quickbase-js 0.1.0-beta.8 → 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 (132) hide show
  1. package/README.md +252 -126
  2. package/dist/esm/quickbase.d.ts +2725 -2689
  3. package/dist/esm/quickbase.js +1763 -3524
  4. package/dist/esm/quickbase.js.map +1 -1
  5. package/dist/esm/quickbase.min.js +1 -1
  6. package/dist/esm/quickbase.min.js.map +1 -1
  7. package/dist/umd/quickbase.umd.js +1762 -3706
  8. package/dist/umd/quickbase.umd.js.map +1 -1
  9. package/dist/umd/quickbase.umd.min.js +1 -1
  10. package/dist/umd/quickbase.umd.min.js.map +1 -1
  11. package/package.json +27 -12
  12. package/CHANGELOG.md +0 -155
  13. package/build-common.js +0 -131
  14. package/build-esm.js +0 -71
  15. package/build-umd.js +0 -69
  16. package/examples/quicbase-jsCDN.html +0 -36
  17. package/examples/react.js +0 -48
  18. package/examples/vanillajs.html +0 -47
  19. package/open-api/fix-spec-main.ts +0 -97
  20. package/open-api/generate-override-report.ts +0 -214
  21. package/open-api/generate-unified-interface.ts +0 -256
  22. package/open-api/output/override-report.html +0 -11
  23. package/open-api/output/override-report.json +0 -14395
  24. package/open-api/output/quickbase-fixed.json +0 -11191
  25. package/open-api/regenerate-client.ts +0 -116
  26. package/open-api/schema/enhance-general.ts +0 -100
  27. package/open-api/schema/fix-arrays.ts +0 -69
  28. package/open-api/schema/tags/apps.ts +0 -90
  29. package/open-api/schema/tags/fields.ts +0 -471
  30. package/open-api/schema/tags/groups.ts +0 -51
  31. package/open-api/schema/tags/index.ts +0 -66
  32. package/open-api/schema/tags/records.ts +0 -115
  33. package/open-api/schema/tags/tables.ts +0 -211
  34. package/open-api/schema/tags/users.ts +0 -47
  35. package/open-api/types/spec.ts +0 -42
  36. package/open-api/utils/infer-schema.ts +0 -40
  37. package/open-api/utils/naming.ts +0 -10
  38. package/playwright.config.ts +0 -37
  39. package/rollup.config.js +0 -114
  40. package/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +0 -46878
  41. package/specs/split/apps.json +0 -1315
  42. package/specs/split/auth.json +0 -191
  43. package/specs/split/fields.json +0 -3869
  44. package/specs/split/records.json +0 -754
  45. package/specs/split/reports.json +0 -619
  46. package/specs/split/tables.json +0 -1605
  47. package/src/RateLimitError.ts +0 -12
  48. package/src/ThrottleBucket.ts +0 -36
  49. package/src/generated-unified/QuickbaseClient.ts +0 -359
  50. package/src/generated-unified/missing-types-report.json +0 -3
  51. package/src/index.ts +0 -1
  52. package/src/invokeMethod.ts +0 -357
  53. package/src/quickbaseClient.ts +0 -244
  54. package/src/tokenCache.ts +0 -51
  55. package/src/utils.ts +0 -7
  56. package/test-esm.js +0 -1
  57. package/test-results.json +0 -2050
  58. package/test-umd.js +0 -1
  59. package/test.ts +0 -1
  60. package/tests/playwright/qb/auth/cacheSwitching.test.ts +0 -159
  61. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +0 -219
  62. package/tests/playwright/qb/auth/getAppWithTempToken.test.ts +0 -162
  63. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +0 -153
  64. package/tests/playwright/qb/auth/getTempToken.test.ts +0 -152
  65. package/tests/playwright/qb/auth/tempTokenPrefetch.test.ts +0 -179
  66. package/tests/playwright/qb/auth/tempTokenRenewal.test.ts +0 -133
  67. package/tests/setup.ts +0 -53
  68. package/tests/vitest/qb/apps/copyApp.test.ts +0 -76
  69. package/tests/vitest/qb/apps/createApp.test.ts +0 -64
  70. package/tests/vitest/qb/apps/deleteApp.test.ts +0 -76
  71. package/tests/vitest/qb/apps/getApp.test.ts +0 -44
  72. package/tests/vitest/qb/apps/getAppEvents.test.ts +0 -67
  73. package/tests/vitest/qb/apps/updateApp.test.ts +0 -58
  74. package/tests/vitest/qb/auth/retryUserToken401.test.ts +0 -56
  75. package/tests/vitest/qb/fields/createField.test.ts +0 -77
  76. package/tests/vitest/qb/fields/deleteFields.test.ts +0 -83
  77. package/tests/vitest/qb/fields/getField.test.ts +0 -85
  78. package/tests/vitest/qb/fields/getFieldUsage.test.ts +0 -174
  79. package/tests/vitest/qb/fields/getFields.test.ts +0 -232
  80. package/tests/vitest/qb/fields/getFieldsUsage.test.ts +0 -77
  81. package/tests/vitest/qb/fields/updateField.test.ts +0 -93
  82. package/tests/vitest/qb/index.ts +0 -29
  83. package/tests/vitest/qb/records/deleteRecords.test.ts +0 -110
  84. package/tests/vitest/qb/records/runQuery.test.ts +0 -146
  85. package/tests/vitest/qb/records/upsert.test.ts +0 -102
  86. package/tests/vitest/qb/tables/createTable.test.ts +0 -55
  87. package/tests/vitest/qb/tables/deleteTable.test.ts +0 -50
  88. package/tests/vitest/qb/tables/getAppTables.test.ts +0 -46
  89. package/tests/vitest/qb/tables/getRelationships.test.ts +0 -80
  90. package/tests/vitest/qb/tables/getTable.test.ts +0 -26
  91. package/tests/vitest/qb/tables/updateRelationship.test.ts +0 -277
  92. package/tests/vitest/qb/tables/updateTable.test.ts +0 -48
  93. package/tests/vitest/unit/apps/copyApp.test.ts +0 -488
  94. package/tests/vitest/unit/apps/createApp.test.ts +0 -186
  95. package/tests/vitest/unit/apps/deleteApp.test.ts +0 -216
  96. package/tests/vitest/unit/apps/getApp.test.ts +0 -128
  97. package/tests/vitest/unit/apps/getAppEvents.test.ts +0 -193
  98. package/tests/vitest/unit/apps/updateApp.test.ts +0 -381
  99. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +0 -62
  100. package/tests/vitest/unit/auth/getTempToken.test.ts +0 -95
  101. package/tests/vitest/unit/auth/retryTempToken401.test.ts +0 -113
  102. package/tests/vitest/unit/auth/retryTempTokenTwo401.test.ts +0 -81
  103. package/tests/vitest/unit/auth/retryUserToken401.test.ts +0 -56
  104. package/tests/vitest/unit/fields/createField.test.ts +0 -387
  105. package/tests/vitest/unit/fields/deleteFields.test.ts +0 -141
  106. package/tests/vitest/unit/fields/getField.test.ts +0 -189
  107. package/tests/vitest/unit/fields/getFieldUsage.test.ts +0 -166
  108. package/tests/vitest/unit/fields/getFields.test.ts +0 -122
  109. package/tests/vitest/unit/fields/getFieldsUsage.test.ts +0 -160
  110. package/tests/vitest/unit/fields/updateField.test.ts +0 -280
  111. package/tests/vitest/unit/index.ts +0 -33
  112. package/tests/vitest/unit/rateLimit.test.ts +0 -189
  113. package/tests/vitest/unit/records/deleteRecords.test.ts +0 -112
  114. package/tests/vitest/unit/records/runQuery.test.ts +0 -102
  115. package/tests/vitest/unit/records/upsert.test.ts +0 -234
  116. package/tests/vitest/unit/tables/createTable.test.ts +0 -70
  117. package/tests/vitest/unit/tables/deleteTable.test.ts +0 -77
  118. package/tests/vitest/unit/tables/getAppTables.test.ts +0 -85
  119. package/tests/vitest/unit/tables/getRelationships.test.ts +0 -259
  120. package/tests/vitest/unit/tables/getTable.test.ts +0 -233
  121. package/tests/vitest/unit/tables/updateRelationship.test.ts +0 -305
  122. package/tests/vitest/unit/tables/updateTable.test.ts +0 -80
  123. package/tests/vitest/unit/tokenLifespan.test.ts +0 -138
  124. package/tests/vitest/unit/umd.test.ts +0 -8
  125. package/text.txt +0 -104
  126. package/tools/log-gen.ts +0 -235
  127. package/tools/log-gen.yaml +0 -4982
  128. package/tools/openapi-jars/openapi-generator-cli-7.12.0.jar +0 -0
  129. package/tsconfig.build.json +0 -17
  130. package/tsconfig.json +0 -32
  131. package/versionrc.json +0 -9
  132. package/vitest.config.ts +0 -27
@@ -1,4982 +0,0 @@
1
- project: >-
2
- quickbase-js
3
- date: >-
4
- 3/17/2025
5
- root: >-
6
- /home/drew/Projects/quickbase-js
7
- goals:
8
- - >-
9
- A
10
- library
11
- for
12
- interacting
13
- with
14
- the
15
- QuickBase
16
- RESTful
17
- API.
18
- - >-
19
- Use
20
- OpenAPI
21
- to
22
- generate
23
- types
24
- and
25
- methods
26
- using
27
- a
28
- proxy.
29
- Validate
30
- with
31
- tests.
32
- - >-
33
- Provide
34
- robust
35
- and
36
- intuitive
37
- temporary
38
- token
39
- support
40
- for
41
- browser
42
- environments.
43
- - >-
44
- User
45
- Tokens
46
- support
47
- both
48
- Node.js
49
- and
50
- browser
51
- environments.
52
- - >-
53
- Use
54
- case:
55
- JS
56
- frameworks
57
- like
58
- React,
59
- Vue,
60
- and
61
- Angular
62
- hosted
63
- in
64
- QuickBase
65
- code
66
- pages.
67
- - >-
68
- Enable
69
- a
70
- flexible
71
- or
72
- native
73
- fetch
74
- in
75
- the
76
- browser.
77
- - >-
78
- Enable
79
- a
80
- flexible
81
- fetch
82
- framework
83
- in
84
- Node.js.
85
- - >-
86
- #
87
- - >-
88
- No
89
- manual
90
- updating
91
- methods
92
- when
93
- the
94
- QuickBase
95
- API
96
- changes.
97
- - >-
98
- The
99
- proxy
100
- magic
101
- dynamically
102
- maps
103
- generated
104
- methods
105
- and
106
- types.
107
- - >-
108
- #
109
- - >-
110
- TokenCache
111
- is
112
- defined
113
- per
114
- quickbaseClient
115
- call,
116
- so
117
- each
118
- instance
119
- has
120
- its
121
- own
122
- isolated
123
- TokenCache.
124
- - >-
125
- Each
126
- quickbase
127
- client
128
- instance
129
- has
130
- an
131
- isolated
132
- and
133
- individual
134
- token
135
- cache.
136
- pipelineOverview:
137
- - >-
138
- What
139
- I’m
140
- Trying
141
- to
142
- Do
143
- - >-
144
- My
145
- approach
146
- is
147
- to
148
- ensure
149
- AppsApi.ts
150
- is
151
- generated
152
- with
153
- getAppById
154
- so
155
- QuickbaseClient.ts
156
- can
157
- map
158
- it
159
- to
160
- client.getApp.
161
- Steps
162
- include:
163
- - >-
164
- Fix
165
- fix-spec.ts:
166
- - >-
167
- Add
168
- tags:
169
- ["Apps"]
170
- to
171
- /apps/*
172
- endpoints
173
- to
174
- group
175
- them
176
- into
177
- AppsApi.ts.
178
- - >-
179
- Ensure
180
- all
181
- endpoints
182
- and
183
- models
184
- are
185
- correctly
186
- defined
187
- and
188
- typed.
189
- - >-
190
- Debug
191
- regenerate-client.ts:
192
- - >-
193
- Enhance
194
- logging
195
- to
196
- catch
197
- why
198
- AppsApi.ts
199
- isn’t
200
- generated.
201
- - >-
202
- Test
203
- if
204
- getAppById
205
- appears
206
- in
207
- another
208
- file
209
- (e.g.,
210
- DefaultApi.ts).
211
- - >-
212
- Update
213
- QuickbaseClient.ts:
214
- - >-
215
- Adjust
216
- imports
217
- to
218
- use
219
- the
220
- correct
221
- API
222
- class
223
- once
224
- generated.
225
- - >-
226
- Test
227
- and
228
- Iterate:
229
- - >-
230
- Run
231
- npm
232
- run
233
- fix-spec,
234
- npm
235
- run
236
- regenerate,
237
- and
238
- npm
239
- run
240
- test
241
- to
242
- verify
243
- AppsApi.ts
244
- exists
245
- and
246
- test.ts
247
- works.
248
- - >-
249
- The
250
- latest
251
- fix-spec.ts
252
- with
253
- tags
254
- aims
255
- to
256
- force
257
- the
258
- generator
259
- to
260
- create
261
- AppsApi.ts,
262
- addressing
263
- the
264
- missing
265
- file
266
- issue.
267
- - >-
268
- Relevant
269
- Project
270
- Files
271
- - >-
272
- Here’s
273
- a
274
- list
275
- of
276
- files
277
- that
278
- would
279
- help
280
- understand
281
- and
282
- resolve
283
- this
284
- problem,
285
- along
286
- with
287
- their
288
- roles:
289
- - >-
290
- src/code-generation/fix-spec.ts:
291
- - >-
292
- Role:
293
- Modifies
294
- the
295
- original
296
- QuickBase
297
- spec
298
- (e.g.,
299
- QuickBase_RESTful_*.json)
300
- to
301
- create
302
- quickbase-fixed.json
303
- with
304
- required
305
- endpoints
306
- (e.g.,
307
- /apps/{appId}).
308
- - >-
309
- Relevance:
310
- Defines
311
- the
312
- spec
313
- fed
314
- to
315
- the
316
- generator;
317
- errors
318
- here
319
- affect
320
- generation.
321
- - >-
322
- src/code-generation/quickbase-fixed.json:
323
- - >-
324
- Role:
325
- The
326
- processed
327
- OpenAPI
328
- spec
329
- used
330
- by
331
- regenerate-client.ts
332
- to
333
- generate
334
- code.
335
- - >-
336
- Relevance:
337
- Confirms
338
- if
339
- /apps/{appId}
340
- is
341
- correctly
342
- structured
343
- with
344
- operationId:
345
- "getAppById".
346
- - >-
347
- src/code-generation/regenerate-client.ts:
348
- - >-
349
- Role:
350
- Runs
351
- OpenAPI
352
- Generator
353
- to
354
- produce
355
- src/generated/
356
- files
357
- (APIs
358
- and
359
- models)
360
- and
361
- fixes
362
- .ts
363
- extensions
364
- with
365
- ts-morph.
366
- - >-
367
- Relevance:
368
- Controls
369
- the
370
- generation
371
- process;
372
- logs
373
- reveal
374
- why
375
- AppsApi.ts
376
- is
377
- missing.
378
- - >-
379
- src/generated/apis/AppsApi.ts
380
- (if
381
- exists):
382
- - >-
383
- Role:
384
- Should
385
- contain
386
- getAppById
387
- method
388
- for
389
- /apps/{appId}
390
- GET.
391
- - >-
392
- Relevance:
393
- Missing
394
- file
395
- is
396
- the
397
- core
398
- issue;
399
- its
400
- absence
401
- breaks
402
- QuickbaseClient.ts.
403
- - >-
404
- src/generated/apis/DefaultApi.ts:
405
- - >-
406
- Role:
407
- Default
408
- API
409
- class
410
- for
411
- untagged
412
- operations.
413
- - >-
414
- Relevance:
415
- Might
416
- contain
417
- getAppById
418
- if
419
- tags
420
- are
421
- misconfigured.
422
- - >-
423
- src/QuickbaseClient.ts:
424
- - >-
425
- Role:
426
- Wraps
427
- generated
428
- API
429
- classes
430
- (e.g.,
431
- AppsApi)
432
- in
433
- a
434
- Proxy
435
- for
436
- ergonomic
437
- calls
438
- (e.g.,
439
- client.getApp).
440
- - >-
441
- Relevance:
442
- Fails
443
- to
444
- import
445
- AppsApi.ts,
446
- causing
447
- the
448
- runtime
449
- error.
450
- - >-
451
- src/test.ts:
452
- - >-
453
- Role:
454
- Test
455
- script
456
- calling
457
- client.getApp({
458
- appId
459
- }).
460
- - >-
461
- Relevance:
462
- Final
463
- validation
464
- point;
465
- shows
466
- if
467
- the
468
- fix
469
- works.
470
- - >-
471
- .env.development:
472
- - >-
473
- Role:
474
- Stores
475
- QB_REALM,
476
- QB_USER_TOKEN,
477
- QB_APP_ID
478
- for
479
- API
480
- authentication.
481
- - >-
482
- Relevance:
483
- Ensures
484
- the
485
- API
486
- call
487
- has
488
- valid
489
- credentials
490
- (not
491
- the
492
- current
493
- issue,
494
- but
495
- critical
496
- for
497
- success).
498
- - >-
499
- src/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json
500
- (or
501
- similar):
502
- - >-
503
- Role:
504
- Original
505
- QuickBase
506
- API
507
- spec
508
- before
509
- fix-spec.ts
510
- processing.
511
- - >-
512
- Relevance:
513
- Shows
514
- how
515
- /apps/{appId}
516
- was
517
- originally
518
- defined,
519
- helping
520
- identify
521
- conflicts.
522
- - >-
523
- package.json:
524
- - >-
525
- Role:
526
- Defines
527
- scripts
528
- (fix-spec,
529
- regenerate,
530
- test)
531
- and
532
- dependencies
533
- (e.g.,
534
- ts-node,
535
- openapi-generator-cli).
536
- - >-
537
- Relevance:
538
- Confirms
539
- script
540
- commands
541
- and
542
- versions
543
- align
544
- with
545
- our
546
- process.
547
- - >-
548
- What
549
- We
550
- Achieved
551
- - >-
552
- Goal
553
- Met:
554
- You
555
- can
556
- now
557
- call
558
- client.getApp({
559
- appId:
560
- "buwai2zpe"
561
- })
562
- and
563
- get
564
- the
565
- app
566
- details
567
- {
568
- id:
569
- 'buwai2zpe',
570
- name:
571
- 'qb-copy'
572
- }.
573
- - >-
574
- Fixes
575
- Applied:
576
- - >-
577
- Added
578
- tags:
579
- ["Apps"]
580
- in
581
- fix-spec.ts
582
- to
583
- ensure
584
- AppsApi.ts
585
- is
586
- generated
587
- with
588
- getAppById.
589
- - >-
590
- Updated
591
- QuickbaseClient.ts
592
- to:
593
- - >-
594
- Use
595
- prototype
596
- methods
597
- via
598
- Object.getOwnPropertyNames.
599
- - >-
600
- Bind
601
- methods
602
- to
603
- preserve
604
- context
605
- with
606
- .bind(api).
607
- - >-
608
- Handle
609
- getAppById’s
610
- direct
611
- JSON
612
- return
613
- instead
614
- of
615
- a
616
- Response
617
- object.
618
- - >-
619
- Result:
620
- The
621
- ergonomic
622
- API
623
- you
624
- wanted
625
- (client.getApp)
626
- works
627
- seamlessly
628
- with
629
- the
630
- generated
631
- AppsApi.ts.
632
- - >-
633
- Why
634
- It
635
- Works
636
- Now
637
- - >-
638
- fix-spec.ts:
639
- - >-
640
- Correctly
641
- defined
642
- /apps/{appId}
643
- with
644
- operationId:
645
- "getAppById"
646
- and
647
- tags:
648
- ["Apps"],
649
- ensuring
650
- AppsApi.ts
651
- generation.
652
- - >-
653
- regenerate-client.ts:
654
- - >-
655
- Successfully
656
- ran
657
- OpenAPI
658
- Generator
659
- to
660
- produce
661
- AppsApi.ts
662
- with
663
- getAppById.
664
- - >-
665
- QuickbaseClient.ts:
666
- - >-
667
- buildMethodMap
668
- now
669
- captures
670
- getAppById
671
- and
672
- maps
673
- it
674
- to
675
- getApp.
676
- - >-
677
- invokeMethod
678
- passes
679
- {
680
- appId:
681
- 'buwai2zpe'
682
- }
683
- as
684
- requestParameters
685
- and
686
- handles
687
- the
688
- JSON
689
- response
690
- directly.
691
- - >-
692
- test.ts:
693
- - >-
694
- Calls
695
- client.getApp
696
- and
697
- logs
698
- the
699
- result,
700
- proving
701
- the
702
- end-to-end
703
- flow.
704
- tree:
705
- name: >-
706
- .
707
- type: >-
708
- directory
709
- children:
710
- - name: >-
711
- .env
712
- type: >-
713
- file
714
- - name: >-
715
- .gitignore
716
- type: >-
717
- file
718
- - name: >-
719
- CHANGELOG.md
720
- type: >-
721
- file
722
- - name: >-
723
- LICENSE
724
- type: >-
725
- file
726
- - name: >-
727
- README.md
728
- type: >-
729
- file
730
- - name: >-
731
- build-common.js
732
- type: >-
733
- file
734
- - name: >-
735
- build-esm.js
736
- type: >-
737
- file
738
- - name: >-
739
- build-umd.js
740
- type: >-
741
- file
742
- - name: >-
743
- dist
744
- type: >-
745
- directory
746
- children:
747
- - name: >-
748
- esm
749
- type: >-
750
- directory
751
- children:
752
- - name: >-
753
- quickbase.d.ts
754
- type: >-
755
- file
756
- - name: >-
757
- quickbase.js
758
- type: >-
759
- file
760
- - name: >-
761
- quickbase.js.map
762
- type: >-
763
- file
764
- - name: >-
765
- quickbase.min.js
766
- type: >-
767
- file
768
- - name: >-
769
- quickbase.min.js.map
770
- type: >-
771
- file
772
- - name: >-
773
- umd
774
- type: >-
775
- directory
776
- children:
777
- - name: >-
778
- quickbase.umd.js
779
- type: >-
780
- file
781
- - name: >-
782
- quickbase.umd.js.map
783
- type: >-
784
- file
785
- - name: >-
786
- quickbase.umd.min.js
787
- type: >-
788
- file
789
- - name: >-
790
- quickbase.umd.min.js.map
791
- type: >-
792
- file
793
- - name: >-
794
- examples
795
- type: >-
796
- directory
797
- children:
798
- - name: >-
799
- quicbase-jsCDN.html
800
- type: >-
801
- file
802
- - name: >-
803
- react.js
804
- type: >-
805
- file
806
- - name: >-
807
- vanillajs.html
808
- type: >-
809
- file
810
- - name: >-
811
- open-api
812
- type: >-
813
- directory
814
- children:
815
- - name: >-
816
- fix-spec-main.ts
817
- type: >-
818
- file
819
- - name: >-
820
- generate-override-report.ts
821
- type: >-
822
- file
823
- - name: >-
824
- generate-unified-interface.ts
825
- type: >-
826
- file
827
- - name: >-
828
- regenerate-client.ts
829
- type: >-
830
- file
831
- - name: >-
832
- schema
833
- type: >-
834
- directory
835
- children:
836
- - name: >-
837
- enhance-general.ts
838
- type: >-
839
- file
840
- - name: >-
841
- fix-arrays.ts
842
- type: >-
843
- file
844
- - name: >-
845
- tags
846
- type: >-
847
- directory
848
- children:
849
- - name: >-
850
- apps.ts
851
- type: >-
852
- file
853
- - name: >-
854
- fields.ts
855
- type: >-
856
- file
857
- - name: >-
858
- groups.ts
859
- type: >-
860
- file
861
- - name: >-
862
- index.ts
863
- type: >-
864
- file
865
- - name: >-
866
- records.ts
867
- type: >-
868
- file
869
- - name: >-
870
- tables.ts
871
- type: >-
872
- file
873
- - name: >-
874
- users.ts
875
- type: >-
876
- file
877
- - name: >-
878
- types
879
- type: >-
880
- directory
881
- children:
882
- - name: >-
883
- spec.ts
884
- type: >-
885
- file
886
- - name: >-
887
- utils
888
- type: >-
889
- directory
890
- children:
891
- - name: >-
892
- infer-schema.ts
893
- type: >-
894
- file
895
- - name: >-
896
- naming.ts
897
- type: >-
898
- file
899
- - name: >-
900
- openapitools.json
901
- type: >-
902
- file
903
- - name: >-
904
- package-lock.json
905
- type: >-
906
- file
907
- - name: >-
908
- package.json
909
- type: >-
910
- file
911
- - name: >-
912
- playwright.config.ts
913
- type: >-
914
- file
915
- - name: >-
916
- rollup.config.js
917
- type: >-
918
- file
919
- - name: >-
920
- src
921
- type: >-
922
- directory
923
- children:
924
- - name: >-
925
- RateLimitError.ts
926
- type: >-
927
- file
928
- - name: >-
929
- ThrottleBucket.ts
930
- type: >-
931
- file
932
- - name: >-
933
- generated
934
- type: >-
935
- directory
936
- children:
937
- - name: >-
938
- .openapi-generator
939
- type: >-
940
- directory
941
- children:
942
- - name: >-
943
- FILES
944
- type: >-
945
- file
946
- - name: >-
947
- VERSION
948
- type: >-
949
- file
950
- - name: >-
951
- .openapi-generator-ignore
952
- type: >-
953
- file
954
- - name: >-
955
- apis
956
- type: >-
957
- directory
958
- children:
959
- - name: >-
960
- AppsApi.ts
961
- type: >-
962
- file
963
- - name: >-
964
- AuditApi.ts
965
- type: >-
966
- file
967
- - name: >-
968
- AuthApi.ts
969
- type: >-
970
- file
971
- - name: >-
972
- DocumentTemplatesApi.ts
973
- type: >-
974
- file
975
- - name: >-
976
- FieldsApi.ts
977
- type: >-
978
- file
979
- - name: >-
980
- FilesApi.ts
981
- type: >-
982
- file
983
- - name: >-
984
- FormulasApi.ts
985
- type: >-
986
- file
987
- - name: >-
988
- PlatformAnalyticsApi.ts
989
- type: >-
990
- file
991
- - name: >-
992
- RecordsApi.ts
993
- type: >-
994
- file
995
- - name: >-
996
- ReportsApi.ts
997
- type: >-
998
- file
999
- - name: >-
1000
- SolutionsApi.ts
1001
- type: >-
1002
- file
1003
- - name: >-
1004
- TablesApi.ts
1005
- type: >-
1006
- file
1007
- - name: >-
1008
- UserTokenApi.ts
1009
- type: >-
1010
- file
1011
- - name: >-
1012
- UsersApi.ts
1013
- type: >-
1014
- file
1015
- - name: >-
1016
- index.ts
1017
- type: >-
1018
- file
1019
- - name: >-
1020
- index.ts
1021
- type: >-
1022
- file
1023
- - name: >-
1024
- models
1025
- type: >-
1026
- directory
1027
- children:
1028
- - name: >-
1029
- AddManagersToGroup200Response.ts
1030
- type: >-
1031
- file
1032
- - name: >-
1033
- AddManagersToGroupRequest.ts
1034
- type: >-
1035
- file
1036
- - name: >-
1037
- AddMembersToGroup200Response.ts
1038
- type: >-
1039
- file
1040
- - name: >-
1041
- AddMembersToGroupRequest.ts
1042
- type: >-
1043
- file
1044
- - name: >-
1045
- AddSubgroupsToGroup200Response.ts
1046
- type: >-
1047
- file
1048
- - name: >-
1049
- AddSubgroupsToGroupRequest.ts
1050
- type: >-
1051
- file
1052
- - name: >-
1053
- Audit200Response.ts
1054
- type: >-
1055
- file
1056
- - name: >-
1057
- Audit202Response.ts
1058
- type: >-
1059
- file
1060
- - name: >-
1061
- AuditRequest.ts
1062
- type: >-
1063
- file
1064
- - name: >-
1065
- ChangesetSolution200Response.ts
1066
- type: >-
1067
- file
1068
- - name: >-
1069
- ChangesetSolution200ResponseInner.ts
1070
- type: >-
1071
- file
1072
- - name: >-
1073
- ChangesetSolution200ResponseInnerChangesInnerInner.ts
1074
- type: >-
1075
- file
1076
- - name: >-
1077
- ChangesetSolution400Response.ts
1078
- type: >-
1079
- file
1080
- - name: >-
1081
- ChangesetSolution401403Response.ts
1082
- type: >-
1083
- file
1084
- - name: >-
1085
- ChangesetSolution404Response.ts
1086
- type: >-
1087
- file
1088
- - name: >-
1089
- ChangesetSolution4xx5xxResponse.ts
1090
- type: >-
1091
- file
1092
- - name: >-
1093
- ChangesetSolutionFromRecord200Response.ts
1094
- type: >-
1095
- file
1096
- - name: >-
1097
- ChangesetSolutionFromRecord400Response.ts
1098
- type: >-
1099
- file
1100
- - name: >-
1101
- ChangesetSolutionFromRecord401403Response.ts
1102
- type: >-
1103
- file
1104
- - name: >-
1105
- ChangesetSolutionFromRecord404Response.ts
1106
- type: >-
1107
- file
1108
- - name: >-
1109
- ChangesetSolutionFromRecord4xx5xxResponse.ts
1110
- type: >-
1111
- file
1112
- - name: >-
1113
- CloneUserToken200Response.ts
1114
- type: >-
1115
- file
1116
- - name: >-
1117
- CloneUserTokenRequest.ts
1118
- type: >-
1119
- file
1120
- - name: >-
1121
- CopyApp200Response.ts
1122
- type: >-
1123
- file
1124
- - name: >-
1125
- CopyAppRequest.ts
1126
- type: >-
1127
- file
1128
- - name: >-
1129
- CopyAppRequestProperties.ts
1130
- type: >-
1131
- file
1132
- - name: >-
1133
- CreateApp200Response.ts
1134
- type: >-
1135
- file
1136
- - name: >-
1137
- CreateAppRequest.ts
1138
- type: >-
1139
- file
1140
- - name: >-
1141
- CreateField200Response.ts
1142
- type: >-
1143
- file
1144
- - name: >-
1145
- CreateFieldRequest.ts
1146
- type: >-
1147
- file
1148
- - name: >-
1149
- CreateFieldRequestProperties.ts
1150
- type: >-
1151
- file
1152
- - name: >-
1153
- CreateRelationship200Response.ts
1154
- type: >-
1155
- file
1156
- - name: >-
1157
- CreateRelationshipRequest.ts
1158
- type: >-
1159
- file
1160
- - name: >-
1161
- CreateSolution200Response.ts
1162
- type: >-
1163
- file
1164
- - name: >-
1165
- CreateSolution400Response.ts
1166
- type: >-
1167
- file
1168
- - name: >-
1169
- CreateSolution401403Response.ts
1170
- type: >-
1171
- file
1172
- - name: >-
1173
- CreateSolution4xx5xxResponse.ts
1174
- type: >-
1175
- file
1176
- - name: >-
1177
- CreateSolutionFromRecord200Response.ts
1178
- type: >-
1179
- file
1180
- - name: >-
1181
- CreateSolutionFromRecord200ResponseInner.ts
1182
- type: >-
1183
- file
1184
- - name: >-
1185
- CreateSolutionFromRecord200ResponseInnerCreatedResourcesInner.ts
1186
- type: >-
1187
- file
1188
- - name: >-
1189
- CreateSolutionFromRecord200ResponseInnerCreatedResourcesInnerAppsInner.ts
1190
- type: >-
1191
- file
1192
- - name: >-
1193
- CreateSolutionFromRecord400Response.ts
1194
- type: >-
1195
- file
1196
- - name: >-
1197
- CreateSolutionFromRecord401403Response.ts
1198
- type: >-
1199
- file
1200
- - name: >-
1201
- CreateSolutionFromRecord404Response.ts
1202
- type: >-
1203
- file
1204
- - name: >-
1205
- CreateSolutionFromRecord4xx5xxResponse.ts
1206
- type: >-
1207
- file
1208
- - name: >-
1209
- CreateTable200Response.ts
1210
- type: >-
1211
- file
1212
- - name: >-
1213
- CreateTableRequest.ts
1214
- type: >-
1215
- file
1216
- - name: >-
1217
- DeactivateUserToken200Response.ts
1218
- type: >-
1219
- file
1220
- - name: >-
1221
- DeleteApp200Response.ts
1222
- type: >-
1223
- file
1224
- - name: >-
1225
- DeleteAppRequest.ts
1226
- type: >-
1227
- file
1228
- - name: >-
1229
- DeleteFields200Response.ts
1230
- type: >-
1231
- file
1232
- - name: >-
1233
- DeleteFieldsRequest.ts
1234
- type: >-
1235
- file
1236
- - name: >-
1237
- DeleteFile200Response.ts
1238
- type: >-
1239
- file
1240
- - name: >-
1241
- DeleteRecords200Response.ts
1242
- type: >-
1243
- file
1244
- - name: >-
1245
- DeleteRecordsRequest.ts
1246
- type: >-
1247
- file
1248
- - name: >-
1249
- DeleteRelationship200Response.ts
1250
- type: >-
1251
- file
1252
- - name: >-
1253
- DeleteTable200Response.ts
1254
- type: >-
1255
- file
1256
- - name: >-
1257
- DeleteUserToken200Response.ts
1258
- type: >-
1259
- file
1260
- - name: >-
1261
- DenyUsers200Response.ts
1262
- type: >-
1263
- file
1264
- - name: >-
1265
- DenyUsersAndGroups200Response.ts
1266
- type: >-
1267
- file
1268
- - name: >-
1269
- DenyUsersAndGroupsRequest.ts
1270
- type: >-
1271
- file
1272
- - name: >-
1273
- DenyUsersRequest.ts
1274
- type: >-
1275
- file
1276
- - name: >-
1277
- DownloadFile200Response.ts
1278
- type: >-
1279
- file
1280
- - name: >-
1281
- ExchangeSsoToken200Response.ts
1282
- type: >-
1283
- file
1284
- - name: >-
1285
- ExchangeSsoTokenRequest.ts
1286
- type: >-
1287
- file
1288
- - name: >-
1289
- ExportSolution200Response.ts
1290
- type: >-
1291
- file
1292
- - name: >-
1293
- ExportSolution400Response.ts
1294
- type: >-
1295
- file
1296
- - name: >-
1297
- ExportSolution401403Response.ts
1298
- type: >-
1299
- file
1300
- - name: >-
1301
- ExportSolution404Response.ts
1302
- type: >-
1303
- file
1304
- - name: >-
1305
- ExportSolution4xx5xxResponse.ts
1306
- type: >-
1307
- file
1308
- - name: >-
1309
- ExportSolutionToRecord200Response.ts
1310
- type: >-
1311
- file
1312
- - name: >-
1313
- ExportSolutionToRecord200ResponseInner.ts
1314
- type: >-
1315
- file
1316
- - name: >-
1317
- ExportSolutionToRecord400Response.ts
1318
- type: >-
1319
- file
1320
- - name: >-
1321
- ExportSolutionToRecord401403Response.ts
1322
- type: >-
1323
- file
1324
- - name: >-
1325
- ExportSolutionToRecord404Response.ts
1326
- type: >-
1327
- file
1328
- - name: >-
1329
- ExportSolutionToRecord4xx5xxResponse.ts
1330
- type: >-
1331
- file
1332
- - name: >-
1333
- GenerateDocument200Response.ts
1334
- type: >-
1335
- file
1336
- - name: >-
1337
- GetApp200Response.ts
1338
- type: >-
1339
- file
1340
- - name: >-
1341
- GetAppEvents200Response.ts
1342
- type: >-
1343
- file
1344
- - name: >-
1345
- GetAppTables200Response.ts
1346
- type: >-
1347
- file
1348
- - name: >-
1349
- GetField200Response.ts
1350
- type: >-
1351
- file
1352
- - name: >-
1353
- GetFieldUsage200Response.ts
1354
- type: >-
1355
- file
1356
- - name: >-
1357
- GetFields200Response.ts
1358
- type: >-
1359
- file
1360
- - name: >-
1361
- GetFieldsUsage200Response.ts
1362
- type: >-
1363
- file
1364
- - name: >-
1365
- GetRelationships200Response.ts
1366
- type: >-
1367
- file
1368
- - name: >-
1369
- GetReport200Response.ts
1370
- type: >-
1371
- file
1372
- - name: >-
1373
- GetTable200Response.ts
1374
- type: >-
1375
- file
1376
- - name: >-
1377
- GetTableReports200Response.ts
1378
- type: >-
1379
- file
1380
- - name: >-
1381
- GetTempTokenDBID200Response.ts
1382
- type: >-
1383
- file
1384
- - name: >-
1385
- GetUsers200Response.ts
1386
- type: >-
1387
- file
1388
- - name: >-
1389
- GetUsersRequest.ts
1390
- type: >-
1391
- file
1392
- - name: >-
1393
- Permission.ts
1394
- type: >-
1395
- file
1396
- - name: >-
1397
- PlatformAnalyticEventSummaries200Response.ts
1398
- type: >-
1399
- file
1400
- - name: >-
1401
- PlatformAnalyticEventSummaries200ResponseMetadata.ts
1402
- type: >-
1403
- file
1404
- - name: >-
1405
- PlatformAnalyticEventSummaries200ResponseResultsInner.ts
1406
- type: >-
1407
- file
1408
- - name: >-
1409
- PlatformAnalyticEventSummaries200ResponseResultsInnerEventTypesInner.ts
1410
- type: >-
1411
- file
1412
- - name: >-
1413
- PlatformAnalyticEventSummaries200ResponseResultsInnerTotals.ts
1414
- type: >-
1415
- file
1416
- - name: >-
1417
- PlatformAnalyticEventSummaries200ResponseTotals.ts
1418
- type: >-
1419
- file
1420
- - name: >-
1421
- PlatformAnalyticEventSummaries200ResponseWhereInner.ts
1422
- type: >-
1423
- file
1424
- - name: >-
1425
- PlatformAnalyticEventSummariesRequest.ts
1426
- type: >-
1427
- file
1428
- - name: >-
1429
- PlatformAnalyticEventSummariesRequestWhereInner.ts
1430
- type: >-
1431
- file
1432
- - name: >-
1433
- PlatformAnalyticReads200Response.ts
1434
- type: >-
1435
- file
1436
- - name: >-
1437
- Record.ts
1438
- type: >-
1439
- file
1440
- - name: >-
1441
- RecordValue.ts
1442
- type: >-
1443
- file
1444
- - name: >-
1445
- RemoveManagersFromGroup200Response.ts
1446
- type: >-
1447
- file
1448
- - name: >-
1449
- RemoveManagersFromGroupRequest.ts
1450
- type: >-
1451
- file
1452
- - name: >-
1453
- RemoveMembersFromGroup200Response.ts
1454
- type: >-
1455
- file
1456
- - name: >-
1457
- RemoveMembersFromGroupRequest.ts
1458
- type: >-
1459
- file
1460
- - name: >-
1461
- RemoveSubgroupsFromGroup200Response.ts
1462
- type: >-
1463
- file
1464
- - name: >-
1465
- RemoveSubgroupsFromGroupRequest.ts
1466
- type: >-
1467
- file
1468
- - name: >-
1469
- RunFormula200Response.ts
1470
- type: >-
1471
- file
1472
- - name: >-
1473
- RunFormulaRequest.ts
1474
- type: >-
1475
- file
1476
- - name: >-
1477
- RunQuery200Response.ts
1478
- type: >-
1479
- file
1480
- - name: >-
1481
- RunQueryRequest.ts
1482
- type: >-
1483
- file
1484
- - name: >-
1485
- RunQueryRequestGroupByInner.ts
1486
- type: >-
1487
- file
1488
- - name: >-
1489
- RunQueryRequestOptions.ts
1490
- type: >-
1491
- file
1492
- - name: >-
1493
- RunQueryRequestSortByInner.ts
1494
- type: >-
1495
- file
1496
- - name: >-
1497
- RunReport200Response.ts
1498
- type: >-
1499
- file
1500
- - name: >-
1501
- TransferUserToken200Response.ts
1502
- type: >-
1503
- file
1504
- - name: >-
1505
- TransferUserTokenRequest.ts
1506
- type: >-
1507
- file
1508
- - name: >-
1509
- UndenyUsers200Response.ts
1510
- type: >-
1511
- file
1512
- - name: >-
1513
- UndenyUsersRequest.ts
1514
- type: >-
1515
- file
1516
- - name: >-
1517
- UpdateApp200Response.ts
1518
- type: >-
1519
- file
1520
- - name: >-
1521
- UpdateAppRequest.ts
1522
- type: >-
1523
- file
1524
- - name: >-
1525
- UpdateField200Response.ts
1526
- type: >-
1527
- file
1528
- - name: >-
1529
- UpdateFieldRequest.ts
1530
- type: >-
1531
- file
1532
- - name: >-
1533
- UpdateRelationship200Response.ts
1534
- type: >-
1535
- file
1536
- - name: >-
1537
- UpdateRelationshipRequest.ts
1538
- type: >-
1539
- file
1540
- - name: >-
1541
- UpdateSolution200Response.ts
1542
- type: >-
1543
- file
1544
- - name: >-
1545
- UpdateSolution200ResponseInner.ts
1546
- type: >-
1547
- file
1548
- - name: >-
1549
- UpdateSolution200ResponseInnerCreatedResourcesInner.ts
1550
- type: >-
1551
- file
1552
- - name: >-
1553
- UpdateSolution400Response.ts
1554
- type: >-
1555
- file
1556
- - name: >-
1557
- UpdateSolution401403Response.ts
1558
- type: >-
1559
- file
1560
- - name: >-
1561
- UpdateSolution4xx5xxResponse.ts
1562
- type: >-
1563
- file
1564
- - name: >-
1565
- UpdateSolutionToRecord200Response.ts
1566
- type: >-
1567
- file
1568
- - name: >-
1569
- UpdateSolutionToRecord200ResponseInner.ts
1570
- type: >-
1571
- file
1572
- - name: >-
1573
- UpdateSolutionToRecord400Response.ts
1574
- type: >-
1575
- file
1576
- - name: >-
1577
- UpdateSolutionToRecord401403Response.ts
1578
- type: >-
1579
- file
1580
- - name: >-
1581
- UpdateSolutionToRecord404Response.ts
1582
- type: >-
1583
- file
1584
- - name: >-
1585
- UpdateSolutionToRecord4xx5xxResponse.ts
1586
- type: >-
1587
- file
1588
- - name: >-
1589
- UpdateTable200Response.ts
1590
- type: >-
1591
- file
1592
- - name: >-
1593
- UpdateTableRequest.ts
1594
- type: >-
1595
- file
1596
- - name: >-
1597
- Upsert200Response.ts
1598
- type: >-
1599
- file
1600
- - name: >-
1601
- Upsert207Response.ts
1602
- type: >-
1603
- file
1604
- - name: >-
1605
- Upsert400Response.ts
1606
- type: >-
1607
- file
1608
- - name: >-
1609
- UpsertRequest.ts
1610
- type: >-
1611
- file
1612
- - name: >-
1613
- index.ts
1614
- type: >-
1615
- file
1616
- - name: >-
1617
- runtime.ts
1618
- type: >-
1619
- file
1620
- - name: >-
1621
- generated-unified
1622
- type: >-
1623
- directory
1624
- children:
1625
- - name: >-
1626
- QuickbaseClient.ts
1627
- type: >-
1628
- file
1629
- - name: >-
1630
- missing-types-report.json
1631
- type: >-
1632
- file
1633
- - name: >-
1634
- index.ts
1635
- type: >-
1636
- file
1637
- - name: >-
1638
- invokeMethod.ts
1639
- type: >-
1640
- file
1641
- - name: >-
1642
- quickbaseClient.ts
1643
- type: >-
1644
- file
1645
- - name: >-
1646
- tokenCache.ts
1647
- type: >-
1648
- file
1649
- - name: >-
1650
- utils.ts
1651
- type: >-
1652
- file
1653
- - name: >-
1654
- test-artifacts
1655
- type: >-
1656
- directory
1657
- children:
1658
- - name: >-
1659
- .last-run.json
1660
- type: >-
1661
- file
1662
- - name: >-
1663
- test-results.json
1664
- type: >-
1665
- file
1666
- - name: >-
1667
- test-esm.js
1668
- type: >-
1669
- file
1670
- - name: >-
1671
- test-results.json
1672
- type: >-
1673
- file
1674
- - name: >-
1675
- test-umd.js
1676
- type: >-
1677
- file
1678
- - name: >-
1679
- test.ts
1680
- type: >-
1681
- file
1682
- - name: >-
1683
- tests
1684
- type: >-
1685
- directory
1686
- children:
1687
- - name: >-
1688
- playwright
1689
- type: >-
1690
- directory
1691
- children:
1692
- - name: >-
1693
- qb
1694
- type: >-
1695
- directory
1696
- children:
1697
- - name: >-
1698
- auth
1699
- type: >-
1700
- directory
1701
- children:
1702
- - name: >-
1703
- cacheSwitching.test.ts
1704
- type: >-
1705
- file
1706
- - name: >-
1707
- fetchTempToken401.test.ts
1708
- type: >-
1709
- file
1710
- - name: >-
1711
- getAppWithTempToken.test.ts
1712
- type: >-
1713
- file
1714
- - name: >-
1715
- getAppWithUserToken.test.ts
1716
- type: >-
1717
- file
1718
- - name: >-
1719
- getTempToken.test.ts
1720
- type: >-
1721
- file
1722
- - name: >-
1723
- tempTokenPrefetch.test.ts
1724
- type: >-
1725
- file
1726
- - name: >-
1727
- tempTokenRenewal.test.ts
1728
- type: >-
1729
- file
1730
- - name: >-
1731
- setup.ts
1732
- type: >-
1733
- file
1734
- - name: >-
1735
- vitest
1736
- type: >-
1737
- directory
1738
- children:
1739
- - name: >-
1740
- qb
1741
- type: >-
1742
- directory
1743
- children:
1744
- - name: >-
1745
- apps
1746
- type: >-
1747
- directory
1748
- children:
1749
- - name: >-
1750
- copyApp.test.ts
1751
- type: >-
1752
- file
1753
- contents: >
1754
- //
1755
- tests/vitest/qb/apps/copyApp.test.ts
1756
-
1757
- import
1758
- {
1759
- test,
1760
- expect
1761
- }
1762
- from
1763
- "vitest";
1764
-
1765
- import
1766
- {
1767
- quickbase
1768
- }
1769
- from
1770
- "../../../../src/quickbaseClient";
1771
-
1772
-
1773
- test(
1774
- "QuickbaseClient Integration - copyApp > creates a new copied app in QuickBase",
1775
- { timeout: 30000 }, // Increased to 30 seconds
1776
- async () => {
1777
- const config = {
1778
- realm: process.env.QB_REALM || "",
1779
- userToken: process.env.QB_USER_TOKEN || "",
1780
- debug: true,
1781
- };
1782
- const client = quickbase(config);
1783
- const appId = process.env.QB_APP_ID || ""; // The source app ID to copy from
1784
-
1785
- const copyAppName = `CopiedApp_${Date.now()}`; // Unique name to avoid conflicts
1786
- const copyBody = {
1787
- name: copyAppName,
1788
- description: "Test copied app",
1789
- properties: {
1790
- keepData: false,
1791
- excludeFiles: true,
1792
- usersAndRoles: false,
1793
- assignUserToken: true,
1794
- },
1795
- };
1796
-
1797
- console.log("Config used:", {
1798
- ...config,
1799
- userToken: config.userToken ? "[REDACTED]" : "", // Avoid logging sensitive token
1800
- });
1801
- console.log("Copying app with:", copyBody);
1802
- const startTime = Date.now();
1803
- let response;
1804
- try {
1805
- response = await client.copyApp({ appId, body: copyBody });
1806
- const duration = Date.now() - startTime;
1807
- console.log(`copyApp completed in ${duration}ms`);
1808
- console.log("Real API response:", response);
1809
-
1810
- expect(response).toBeDefined();
1811
- expect(response.id).toBeDefined();
1812
- expect(response.name).toBe(copyAppName);
1813
- expect(response.description).toBe(copyBody.description);
1814
- expect(response.created).toBeInstanceOf(Date);
1815
- expect(response.updated).toBeInstanceOf(Date);
1816
- expect(response.dateFormat).toMatch(/^\w{2}-\w{2}-\w{4}$/); // e.g., "MM-DD-YYYY"
1817
- expect(typeof response.timeZone).toBe("string"); // Simplified check
1818
- expect(typeof response.hasEveryoneOnTheInternet).toBe("boolean");
1819
- expect(response.ancestorId).toBe(appId); // Should match the source app ID
1820
- expect(
1821
- response.dataClassification === undefined ||
1822
- typeof response.dataClassification === "string"
1823
- ).toBe(true); // Allow undefined or string
1824
- expect(
1825
- response.variables === undefined || Array.isArray(response.variables)
1826
- ).toBe(true); // Allow undefined or array
1827
- } catch (error) {
1828
- const duration = Date.now() - startTime;
1829
- console.error(`copyApp failed after ${duration}ms:`, error);
1830
- throw error; // Re-throw to fail the test
1831
- }
1832
-
1833
- // Cleanup: Delete the copied app using deleteApp
1834
- const deleteStartTime = Date.now();
1835
- const deleteResponse = await client.deleteApp({
1836
- appId: response.id,
1837
- body: { name: copyAppName },
1838
- });
1839
- const deleteDuration = Date.now() - deleteStartTime;
1840
- console.log(`deleteApp completed in ${deleteDuration}ms`);
1841
- console.log("Cleanup - Deleted app:", deleteResponse);
1842
- expect(deleteResponse.deletedAppId).toBe(response.id);
1843
- }
1844
- );
1845
- - name: >-
1846
- createApp.test.ts
1847
- type: >-
1848
- file
1849
- contents: >
1850
- //
1851
- tests/vitest/qb/apps/createApp.test.ts
1852
-
1853
- import
1854
- {
1855
- test,
1856
- expect
1857
- }
1858
- from
1859
- "vitest";
1860
-
1861
- import
1862
- {
1863
- quickbase
1864
- }
1865
- from
1866
- "../../../../src/quickbaseClient";
1867
-
1868
-
1869
- test(
1870
- "QuickbaseClient Integration - createApp > creates a new app in QuickBase",
1871
- { timeout: 30000 },
1872
- async () => {
1873
- const config = {
1874
- realm: process.env.QB_REALM || "",
1875
- userToken: process.env.QB_USER_TOKEN || "",
1876
- debug: true,
1877
- useTempTokens: false,
1878
- };
1879
- const client = quickbase(config);
1880
-
1881
- const appName = `TestApp_${Date.now()}`;
1882
- const createBody = {
1883
- name: appName,
1884
- description: "Test app creation",
1885
- assignToken: true,
1886
- };
1887
-
1888
- console.log("Config used:", {
1889
- ...config,
1890
- userToken: config.userToken ? "[REDACTED]" : "",
1891
- });
1892
- console.log("Creating app with:", createBody);
1893
- const createStartTime = Date.now();
1894
- let response;
1895
- try {
1896
- response = await client.createApp({ body: createBody });
1897
- const createDuration = Date.now() - createStartTime;
1898
- console.log(`createApp completed in ${createDuration}ms`);
1899
- console.log("Real API response:", response);
1900
-
1901
- expect(response).toBeDefined();
1902
- expect(response.id).toBeDefined();
1903
- expect(response.name).toBe(appName);
1904
- expect(response.description).toBe(createBody.description);
1905
- expect(response.created).toBeInstanceOf(Date);
1906
- expect(response.updated).toBeInstanceOf(Date);
1907
- expect(response.dateFormat).toMatch(/^\w{2}-\w{2}-\w{4}$/);
1908
- expect(typeof response.timeZone).toBe("string");
1909
- expect(typeof response.hasEveryoneOnTheInternet).toBe("boolean");
1910
- expect(
1911
- response.dataClassification === undefined ||
1912
- typeof response.dataClassification === "string"
1913
- ).toBe(true);
1914
- expect(
1915
- response.variables === undefined || Array.isArray(response.variables)
1916
- ).toBe(true);
1917
-
1918
- // Cleanup: Delete the app after assertions
1919
- const deleteBody = { name: appName };
1920
- await client.deleteApp({ appId: response.id, body: deleteBody });
1921
- console.log("Cleanup: App deleted:", response.id);
1922
- } catch (error) {
1923
- const createDuration = Date.now() - createStartTime;
1924
- console.error(`createApp failed after ${createDuration}ms:`, error);
1925
- throw error;
1926
- }
1927
- }
1928
- );
1929
- - name: >-
1930
- deleteApp.test.ts
1931
- type: >-
1932
- file
1933
- contents: >
1934
- //
1935
- tests/vitest/qb/apps/deleteApp.test.ts
1936
-
1937
- import
1938
- {
1939
- test,
1940
- expect
1941
- }
1942
- from
1943
- "vitest";
1944
-
1945
- import
1946
- {
1947
- quickbase
1948
- }
1949
- from
1950
- "../../../../src/quickbaseClient";
1951
-
1952
-
1953
- test(
1954
- "QuickbaseClient Integration - deleteApp > deletes an app in QuickBase",
1955
- { timeout: 30000 },
1956
- async () => {
1957
- const config = {
1958
- realm: process.env.QB_REALM || "",
1959
- userToken: process.env.QB_USER_TOKEN || "",
1960
- debug: true,
1961
- useTempTokens: false,
1962
- };
1963
- const client = quickbase(config);
1964
-
1965
- const appName = `TempApp_${Date.now()}`;
1966
- const createBody = {
1967
- name: appName,
1968
- description: "Temporary app for deleteApp test",
1969
- assignToken: true, // Match createApp.test.ts
1970
- };
1971
-
1972
- console.log("Config used:", {
1973
- ...config,
1974
- userToken: config.userToken ? "[REDACTED]" : "",
1975
- });
1976
- console.log("Creating temporary app with:", createBody);
1977
- const createStartTime = Date.now();
1978
- let createResponse;
1979
- try {
1980
- createResponse = await client.createApp({ body: createBody });
1981
- const createDuration = Date.now() - createStartTime;
1982
- console.log(`createApp completed in ${createDuration}ms`);
1983
- console.log("Created app response:", createResponse);
1984
-
1985
- expect(createResponse).toBeDefined();
1986
- expect(createResponse.id).toBeDefined();
1987
- expect(createResponse.name).toBe(appName);
1988
- } catch (error) {
1989
- const createDuration = Date.now() - createStartTime;
1990
- console.error(`createApp failed after ${createDuration}ms:`, error);
1991
- throw error;
1992
- }
1993
-
1994
- const deleteBody = {
1995
- name: appName,
1996
- };
1997
- console.log("Deleting app with:", deleteBody);
1998
- const deleteStartTime = Date.now();
1999
- try {
2000
- const deleteResponse = await client.deleteApp({
2001
- appId: createResponse.id,
2002
- body: deleteBody,
2003
- });
2004
- const deleteDuration = Date.now() - deleteStartTime;
2005
- console.log(`deleteApp completed in ${deleteDuration}ms`);
2006
- console.log("Delete app response:", deleteResponse);
2007
-
2008
- expect(deleteResponse).toBeDefined();
2009
- expect(deleteResponse.deletedAppId).toBe(createResponse.id);
2010
- } catch (error) {
2011
- const deleteDuration = Date.now() - deleteStartTime;
2012
- console.error(`deleteApp failed after ${deleteDuration}ms:`, error);
2013
- if (error instanceof Error && "response" in error) {
2014
- try {
2015
- const errorBody = await (error as any).response.json();
2016
- console.error("Full deleteApp error response:", errorBody);
2017
- } catch (e) {
2018
- console.error("Could not parse error response:", e);
2019
- }
2020
- }
2021
- throw error;
2022
- }
2023
- }
2024
- );
2025
- - name: >-
2026
- getApp.test.ts
2027
- type: >-
2028
- file
2029
- contents: >
2030
- //
2031
- tests/vitest/qb/apps/getApp.test.ts
2032
-
2033
- import
2034
- {
2035
- test,
2036
- expect
2037
- }
2038
- from
2039
- "vitest";
2040
-
2041
- import
2042
- {
2043
- quickbase
2044
- }
2045
- from
2046
- "../../../../src/quickbaseClient";
2047
-
2048
-
2049
- test(
2050
- "QuickbaseClient Integration - getApp > fetches real app data from QuickBase",
2051
- { timeout: 10000 },
2052
- async () => {
2053
- const config = {
2054
- realm: process.env.QB_REALM || "",
2055
- userToken: process.env.QB_USER_TOKEN || "",
2056
- debug: true,
2057
- };
2058
- const client = quickbase(config);
2059
- const getAppId = "buwai2zpe";
2060
-
2061
- console.log("Config used:", config);
2062
- const result = await client.getApp({ appId: getAppId });
2063
- console.log("Real API response:", result);
2064
-
2065
- expect(result).toEqual({
2066
- id: getAppId,
2067
- name: "qb-copy",
2068
- created: expect.any(Date),
2069
- updated: expect.any(Date),
2070
- description: "",
2071
- timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
2072
- dateFormat: "MM-DD-YYYY",
2073
- hasEveryoneOnTheInternet: false,
2074
- memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
2075
- securityProperties: {
2076
- allowClone: false,
2077
- allowExport: true,
2078
- enableAppTokens: true,
2079
- hideFromPublic: false,
2080
- mustBeRealmApproved: false,
2081
- useIPFilter: false,
2082
- },
2083
- ancestorId: undefined,
2084
- dataClassification: undefined,
2085
- variables: [{ name: "TestVar", value: "TestValue" }],
2086
- });
2087
- }
2088
- );
2089
- - name: >-
2090
- getAppEvents.test.ts
2091
- type: >-
2092
- file
2093
- contents: >
2094
- import
2095
- {
2096
- test,
2097
- expect
2098
- }
2099
- from
2100
- "vitest";
2101
-
2102
- import
2103
- {
2104
- quickbase
2105
- }
2106
- from
2107
- "../../../../src/quickbaseClient";
2108
-
2109
-
2110
- test(
2111
- "QuickbaseClient Integration - getAppEvents > fetches real app events from QuickBase",
2112
- { timeout: 10000 },
2113
- async () => {
2114
- const config = {
2115
- realm: process.env.QB_REALM || "",
2116
- userToken: process.env.QB_USER_TOKEN || "",
2117
- debug: true,
2118
- };
2119
- const client = quickbase(config);
2120
- const appId = "buwai2zpe"; // Same app ID as getApp test
2121
-
2122
- console.log("Config used:", config);
2123
- const result = await client.getAppEvents({ appId });
2124
- console.log("Real API response:", result);
2125
-
2126
- // Validate the response is an array of events
2127
- expect(result).toBeInstanceOf(Array);
2128
-
2129
- // Check that each event has the required properties
2130
- result.forEach((event) => {
2131
- expect(event).toHaveProperty("type");
2132
- expect([
2133
- "qb-action",
2134
- "webhook",
2135
- "email-notification",
2136
- "subscription",
2137
- "reminder",
2138
- "automation",
2139
- ]).toContain(event.type);
2140
-
2141
- expect(event).toHaveProperty("owner");
2142
- expect(event.owner).toHaveProperty("email");
2143
- expect(typeof event.owner.email).toBe("string");
2144
- expect(event.owner).toHaveProperty("id");
2145
- expect(typeof event.owner.id).toBe("string");
2146
- expect(event.owner).toHaveProperty("name");
2147
- expect(typeof event.owner.name).toBe("string");
2148
- // userName is optional, so we don't enforce it
2149
-
2150
- expect(event).toHaveProperty("isActive");
2151
- expect(typeof event.isActive).toBe("boolean");
2152
-
2153
- expect(event).toHaveProperty("tableId");
2154
- expect(typeof event.tableId).toBe("string");
2155
-
2156
- // Name is present for all types except automation
2157
- if (event.type !== "automation") {
2158
- expect(event).toHaveProperty("name");
2159
- expect(typeof event.name).toBe("string");
2160
- } else {
2161
- expect(event.name).toBeUndefined();
2162
- }
2163
-
2164
- // URL is only present for automation
2165
- if (event.type === "automation") {
2166
- expect(event).toHaveProperty("url");
2167
- expect(typeof event.url).toBe("string");
2168
- } else {
2169
- expect(event.url).toBeUndefined();
2170
- }
2171
- });
2172
- }
2173
- );
2174
- - name: >-
2175
- updateApp.test.ts
2176
- type: >-
2177
- file
2178
- contents: >
2179
- import
2180
- {
2181
- test,
2182
- expect
2183
- }
2184
- from
2185
- "vitest";
2186
-
2187
- import
2188
- {
2189
- quickbase
2190
- }
2191
- from
2192
- "../../../../src/quickbaseClient";
2193
-
2194
-
2195
- test(
2196
- "QuickbaseClient Integration - updateApp > updates real app data in QuickBase",
2197
- { timeout: 10000 },
2198
- async () => {
2199
- const config = {
2200
- realm: process.env.QB_REALM || "",
2201
- userToken: process.env.QB_USER_TOKEN || "",
2202
- debug: true,
2203
- };
2204
- const client = quickbase(config);
2205
- const appId = "buwai2zpe"; // Same app ID as before
2206
-
2207
- // Original app data (to restore later if needed)
2208
- const originalApp = await client.getApp({ appId });
2209
- console.log("Original app data:", originalApp);
2210
-
2211
- // Update request
2212
- const updateRequest = {
2213
- name: "qb-copy-updated",
2214
- description: "Updated via integration test",
2215
- variables: [{ name: "TestVar", value: "TestValue" }],
2216
- };
2217
-
2218
- console.log("Config used:", config);
2219
- console.log("Update request:", updateRequest);
2220
- const result = await client.updateApp({ appId, body: updateRequest });
2221
- console.log("Real API response:", result);
2222
-
2223
- // Validate the response
2224
- expect(result).toHaveProperty("id", appId);
2225
- expect(result).toHaveProperty("name", "qb-copy-updated");
2226
- expect(result).toHaveProperty(
2227
- "description",
2228
- "Updated via integration test"
2229
- );
2230
- expect(result).toHaveProperty("variables");
2231
- expect(result.variables).toContainEqual({
2232
- name: "TestVar",
2233
- value: "TestValue",
2234
- });
2235
- expect(result).toHaveProperty("created");
2236
- expect(result.created).toBeInstanceOf(Date);
2237
- expect(result).toHaveProperty("updated");
2238
- expect(result.updated).toBeInstanceOf(Date);
2239
-
2240
- // Optional: Restore original name to avoid permanent changes
2241
- const restoreRequest = {
2242
- name: originalApp.name,
2243
- description: originalApp.description,
2244
- variables: originalApp.variables,
2245
- };
2246
- await client.updateApp({ appId, body: restoreRequest });
2247
- console.log("Restored app to:", originalApp.name);
2248
- }
2249
- );
2250
- - name: >-
2251
- auth
2252
- type: >-
2253
- directory
2254
- children:
2255
- - name: >-
2256
- retryUserToken401.test.ts
2257
- type: >-
2258
- file
2259
- contents: >
2260
- import
2261
- {
2262
- describe,
2263
- it,
2264
- vi,
2265
- expect,
2266
- beforeEach
2267
- }
2268
- from
2269
- "vitest";
2270
-
2271
- import
2272
- {
2273
- quickbase,
2274
- QuickbaseClient
2275
- }
2276
- from
2277
- "../../../../src/quickbaseClient";
2278
-
2279
- import
2280
- {
2281
- ResponseError
2282
- }
2283
- from
2284
- "../../../../src/generated/runtime";
2285
-
2286
-
2287
- describe("QuickbaseClient
2288
- Integration
2289
- -
2290
- User
2291
- Token
2292
- Retry
2293
- on
2294
- 401",
2295
- ()
2296
- =>
2297
- {
2298
- let client: QuickbaseClient;
2299
- const mockFetch = vi.fn();
2300
-
2301
- beforeEach(() => {
2302
- const config = {
2303
- realm: process.env.QB_REALM || "builderprogram-dbradford6815",
2304
- userToken: "mock-user-token",
2305
- debug: true,
2306
- fetchApi: mockFetch,
2307
- };
2308
- console.log("[quickbaseTest] Config:", config);
2309
- client = quickbase(config);
2310
- });
2311
-
2312
- it("retries on transient 401 with user token and succeeds", async () => {
2313
- const consoleSpy = vi.spyOn(console, "log");
2314
-
2315
- mockFetch
2316
- .mockImplementationOnce(() => {
2317
- const response = new Response(null, {
2318
- status: 401,
2319
- statusText: "Unauthorized",
2320
- });
2321
- console.log("[mockFetch] Throwing 401 ResponseError");
2322
- return Promise.reject(new ResponseError(response));
2323
- })
2324
- .mockResolvedValueOnce({
2325
- ok: true,
2326
- status: 200,
2327
- json: async () => [{ id: 1, label: "Mock Field", fieldType: "text" }],
2328
- });
2329
-
2330
- const fields = await client.getFields({ tableId: "mock-table-id" });
2331
-
2332
- expect(fields).toBeInstanceOf(Array);
2333
- expect(fields.length).toBeGreaterThan(0);
2334
- expect(fields[0]).toHaveProperty("id");
2335
- expect(fields[0]).toHaveProperty("label");
2336
-
2337
- expect(consoleSpy).toHaveBeenCalledWith(
2338
- "Authorization error for getFields (user token), retrying with same token:",
2339
- "" // Matches empty ResponseError message from mock
2340
- );
2341
- expect(consoleSpy).toHaveBeenCalledWith(
2342
- "Retrying getFields with user token"
2343
- );
2344
- expect(mockFetch).toHaveBeenCalledTimes(2);
2345
-
2346
- consoleSpy.mockRestore();
2347
- });
2348
- });
2349
- - name: >-
2350
- fields
2351
- type: >-
2352
- directory
2353
- children:
2354
- - name: >-
2355
- createField.test.ts
2356
- type: >-
2357
- file
2358
- contents: >
2359
- import
2360
- {
2361
- describe,
2362
- it,
2363
- expect,
2364
- afterAll
2365
- }
2366
- from
2367
- "vitest";
2368
-
2369
- import
2370
- {
2371
- createClient,
2372
- QB_TABLE_ID_1
2373
- }
2374
- from
2375
- "../../../setup.ts";
2376
-
2377
-
2378
- describe("QuickbaseClient
2379
- Integration
2380
- -
2381
- createField",
2382
- ()
2383
- =>
2384
- {
2385
- const client = createClient();
2386
-
2387
- const createdFieldIds: number[] = [];
2388
-
2389
- afterAll(async () => {
2390
- if (createdFieldIds.length > 0) {
2391
- try {
2392
- const response = await client.deleteFields({
2393
- tableId: QB_TABLE_ID_1,
2394
- body: { fieldIds: createdFieldIds },
2395
- });
2396
- console.log(
2397
- `Cleaned up fields: ${JSON.stringify(response.deletedFieldIds)}`,
2398
- response.errors && response.errors.length > 0
2399
- ? `Errors: ${response.errors}`
2400
- : ""
2401
- );
2402
- } catch (error) {
2403
- console.error("Cleanup failed:", error);
2404
- console.log(`Fields left in table: ${createdFieldIds}`);
2405
- }
2406
- } else {
2407
- console.log("No fields to clean up.");
2408
- }
2409
- });
2410
-
2411
- it("creates a field with user token", async () => {
2412
- const uniqueLabel = `TestField_${Date.now()}`;
2413
- const response = await client.createField({
2414
- tableId: QB_TABLE_ID_1,
2415
- body: {
2416
- label: uniqueLabel,
2417
- fieldType: "text",
2418
- fieldHelp: "Created via integration test",
2419
- addToForms: true,
2420
- },
2421
- });
2422
-
2423
- expect(response.id).toBeDefined();
2424
- expect(response.label).toBe(uniqueLabel);
2425
- expect(response.fieldType).toBe("text");
2426
- expect(response.fieldHelp).toBe("Created via integration test");
2427
-
2428
- createdFieldIds.push(response.id);
2429
- console.log(`Created field ${uniqueLabel} with ID ${response.id}`);
2430
- });
2431
-
2432
- it("fails with invalid field type", async () => {
2433
- const uniqueLabel = `InvalidField_${Date.now()}`;
2434
- await expect(
2435
- client.createField({
2436
- tableId: QB_TABLE_ID_1,
2437
- body: {
2438
- label: uniqueLabel,
2439
- fieldType: "invalid_type" as "text", // Type assertion to bypass compile-time check
2440
- fieldHelp: "Should fail",
2441
- },
2442
- })
2443
- ).rejects.toThrow("API Error: Bad Request (Status: 400)");
2444
- }, 10000); // Increased timeout to 10 seconds
2445
-
2446
- it("fails with missing label", async () => {
2447
- await expect(
2448
- client.createField({
2449
- tableId: QB_TABLE_ID_1,
2450
- body: {
2451
- label: "",
2452
- fieldType: "text",
2453
- },
2454
- })
2455
- ).rejects.toThrow("API Error: Invalid input (Status: 400)");
2456
- });
2457
- });
2458
- - name: >-
2459
- deleteFields.test.ts
2460
- type: >-
2461
- file
2462
- contents: >
2463
- //
2464
- tests/vitest/qb/fields/deleteFields.test.ts
2465
-
2466
- import
2467
- {
2468
- describe,
2469
- it,
2470
- expect,
2471
- beforeAll
2472
- }
2473
- from
2474
- "vitest";
2475
-
2476
- import
2477
- {
2478
- createClient,
2479
- QB_TABLE_ID_1
2480
- }
2481
- from
2482
- "../../../setup.ts";
2483
-
2484
-
2485
- describe("QuickbaseClient
2486
- Integration
2487
- -
2488
- deleteFields",
2489
- ()
2490
- =>
2491
- {
2492
- const client = createClient();
2493
- let fieldIdsToDelete: number[] = [];
2494
-
2495
- beforeAll(async () => {
2496
- try {
2497
- const fieldLabels = ["DeleteTest1", "DeleteTest2"];
2498
- for (const label of fieldLabels) {
2499
- const response = await client.createField({
2500
- tableId: QB_TABLE_ID_1,
2501
- body: {
2502
- label,
2503
- fieldType: "text",
2504
- fieldHelp: "Test field for deletion",
2505
- },
2506
- });
2507
- fieldIdsToDelete.push(response.id);
2508
- console.log(`Created field ${label} with ID ${response.id}`);
2509
- }
2510
- if (fieldIdsToDelete.length !== 2) {
2511
- throw new Error("Failed to create all test fields");
2512
- }
2513
- } catch (error) {
2514
- console.error("beforeAll failed:", error);
2515
- throw error;
2516
- }
2517
- });
2518
-
2519
- it("deletes fields successfully with user token", async () => {
2520
- try {
2521
- const response = await client.deleteFields({
2522
- tableId: QB_TABLE_ID_1,
2523
- body: { fieldIds: fieldIdsToDelete },
2524
- });
2525
- console.log("deleteFields response:", JSON.stringify(response, null, 2));
2526
- expect(response).toBeDefined();
2527
- expect(response.deletedFieldIds).toEqual(
2528
- expect.arrayContaining(fieldIdsToDelete)
2529
- );
2530
- expect(response.errors ?? []).toHaveLength(0);
2531
- } catch (error) {
2532
- console.error("deleteFields failed:", error);
2533
- throw error;
2534
- }
2535
- });
2536
-
2537
- it("handles partial success with errors", { timeout: 10000 }, async () => {
2538
- const newField = await client.createField({
2539
- tableId: QB_TABLE_ID_1,
2540
- body: { label: "DeleteTest3", fieldType: "text" },
2541
- });
2542
- console.log(`Created field DeleteTest3 with ID ${newField.id}`);
2543
-
2544
- const invalidFieldId = 999999;
2545
- const fieldIds = [newField.id, invalidFieldId];
2546
-
2547
- console.log("Sending deleteFields request at:", new Date());
2548
- const response = await client.deleteFields({
2549
- tableId: QB_TABLE_ID_1,
2550
- body: { fieldIds },
2551
- });
2552
- console.log("deleteFields response received at:", new Date());
2553
- console.log("Response:", JSON.stringify(response, null, 2));
2554
-
2555
- expect(response.deletedFieldIds).toContain(newField.id);
2556
- expect(response.deletedFieldIds).not.toContain(invalidFieldId);
2557
- expect(response.errors).toHaveLength(1);
2558
- expect(response.errors[0]).toMatch(/Field: 999999 was not found/i);
2559
- });
2560
-
2561
- it("fails with invalid request (empty fieldIds)", async () => {
2562
- await expect(
2563
- client.deleteFields({
2564
- tableId: QB_TABLE_ID_1,
2565
- body: { fieldIds: [] },
2566
- })
2567
- ).rejects.toThrow("API Error: Bad Request (Status: 400)");
2568
- });
2569
- });
2570
- - name: >-
2571
- getField.test.ts
2572
- type: >-
2573
- file
2574
- contents: >
2575
- //
2576
- tests/vitest/qb/fields/getField.test.ts
2577
-
2578
- import
2579
- {
2580
- describe,
2581
- it,
2582
- expect
2583
- }
2584
- from
2585
- "vitest";
2586
-
2587
- import
2588
- {
2589
- createClient,
2590
- QB_TABLE_ID_1
2591
- }
2592
- from
2593
- "../../../setup.ts";
2594
-
2595
-
2596
- describe("QuickbaseClient
2597
- Integration
2598
- -
2599
- getField",
2600
- ()
2601
- =>
2602
- {
2603
- const client = createClient();
2604
-
2605
- it("retrieves an existing field with user token", async () => {
2606
- // Create a field to ensure we have a known field ID to retrieve
2607
- const uniqueLabel = `TestField_${Date.now()}`;
2608
- const createResponse = await client.createField({
2609
- tableId: QB_TABLE_ID_1,
2610
- body: {
2611
- label: uniqueLabel,
2612
- fieldType: "text",
2613
- fieldHelp: "Created for getField integration test",
2614
- addToForms: true,
2615
- },
2616
- });
2617
-
2618
- expect(createResponse.id).toBeDefined();
2619
- const fieldId = createResponse.id;
2620
- console.log(`Created field ${uniqueLabel} with ID ${fieldId} for testing`);
2621
-
2622
- // Test getField with the created field
2623
- const response = await client.getField({
2624
- fieldId: fieldId,
2625
- tableId: QB_TABLE_ID_1,
2626
- includeFieldPerms: true,
2627
- });
2628
-
2629
- expect(response.id).toBe(fieldId);
2630
- expect(response.label).toBe(uniqueLabel);
2631
- expect(response.fieldType).toBe("text");
2632
- expect(response.fieldHelp).toBe("Created for getField integration test");
2633
- expect(response.permissions).toBeDefined();
2634
- expect(Array.isArray(response.permissions)).toBe(true);
2635
- console.log(`Retrieved field ${response.label} with ID ${response.id}`);
2636
-
2637
- // Clean up the created field
2638
- try {
2639
- const deleteResponse = await client.deleteFields({
2640
- tableId: QB_TABLE_ID_1,
2641
- body: { fieldIds: [fieldId] },
2642
- });
2643
- console.log(
2644
- `Cleaned up field ${fieldId}: ${JSON.stringify(deleteResponse)}`
2645
- );
2646
- } catch (error) {
2647
- console.error(`Failed to clean up field ${fieldId}:`, error);
2648
- }
2649
- }, 10000); // Increase timeout to 10 seconds
2650
-
2651
- it("fails with non-existent field ID", async () => {
2652
- const nonExistentFieldId = 999999; // Assuming this ID doesn’t exist
2653
- await expect(
2654
- client.getField({
2655
- fieldId: nonExistentFieldId,
2656
- tableId: QB_TABLE_ID_1,
2657
- })
2658
- ).rejects.toMatchObject({
2659
- message: expect.stringContaining(
2660
- "API Error: No such field (Status: 404)"
2661
- ),
2662
- });
2663
- console.log(
2664
- `Confirmed 404 for non-existent field ID ${nonExistentFieldId}`
2665
- );
2666
- });
2667
-
2668
- it("fails with invalid table ID", async () => {
2669
- const invalidTableId = "invalid_dbid";
2670
- await expect(
2671
- client.getField({
2672
- fieldId: 1, // Arbitrary field ID
2673
- tableId: invalidTableId,
2674
- })
2675
- ).rejects.toMatchObject({
2676
- message: expect.stringContaining(
2677
- "API Error: Invalid request (Status: 400)"
2678
- ),
2679
- });
2680
- console.log(`Confirmed 400 for invalid table ID ${invalidTableId}`);
2681
- });
2682
- });
2683
- - name: >-
2684
- getFieldUsage.test.ts
2685
- type: >-
2686
- file
2687
- contents: >
2688
- //
2689
- tests/vitest/qb/fields/getFieldUsage.test.ts
2690
-
2691
- import
2692
- {
2693
- describe,
2694
- it,
2695
- expect,
2696
- afterAll
2697
- }
2698
- from
2699
- "vitest";
2700
-
2701
- import
2702
- {
2703
- createClient,
2704
- QB_REALM,
2705
- QB_USER_TOKEN,
2706
- QB_TABLE_ID_1,
2707
- }
2708
- from
2709
- "../../../setup.ts";
2710
-
2711
- import
2712
- {
2713
- FieldUsage
2714
- }
2715
- from
2716
- "@/generated/models";
2717
-
2718
-
2719
- describe("QuickbaseClient
2720
- Integration
2721
- -
2722
- getFieldUsage",
2723
- ()
2724
- =>
2725
- {
2726
- const client = createClient();
2727
- const createdFieldIds: number[] = [];
2728
-
2729
- afterAll(async () => {
2730
- if (createdFieldIds.length > 0) {
2731
- try {
2732
- const response = await client.deleteFields({
2733
- tableId: QB_TABLE_ID_1,
2734
- body: { fieldIds: createdFieldIds },
2735
- });
2736
- console.log(
2737
- `Cleaned up fields: ${JSON.stringify(response.deletedFieldIds)}`,
2738
- response.errors && response.errors.length > 0
2739
- ? `Errors: ${response.errors}`
2740
- : ""
2741
- );
2742
- } catch (error) {
2743
- console.error("Cleanup failed:", error);
2744
- console.log(`Fields left in table: ${createdFieldIds}`);
2745
- }
2746
- } else {
2747
- console.log("No fields to clean up.");
2748
- }
2749
- });
2750
-
2751
- it(
2752
- "creates a field, retrieves its usage statistics, and deletes it",
2753
- async () => {
2754
- // Step 1: Create a field
2755
- const uniqueLabel = `TestField_${Date.now()}`;
2756
- console.log("Creating field with label:", uniqueLabel);
2757
- const createResponse = await client.createField({
2758
- tableId: QB_TABLE_ID_1,
2759
- body: {
2760
- label: uniqueLabel,
2761
- fieldType: "text",
2762
- fieldHelp: "Created for getFieldUsage integration test",
2763
- addToForms: true,
2764
- },
2765
- });
2766
-
2767
- expect(createResponse.id).toBeDefined();
2768
- const fieldId = createResponse.id;
2769
- createdFieldIds.push(fieldId);
2770
- console.log(`Created field ${uniqueLabel} with ID ${fieldId}`);
2771
-
2772
- // Brief delay to ensure field is registered
2773
- await new Promise((resolve) => setTimeout(resolve, 1000));
2774
-
2775
- // Step 2: Get field usage with raw response logging
2776
- console.log("Fetching field usage for:", {
2777
- tableId: QB_TABLE_ID_1,
2778
- fieldId,
2779
- });
2780
- const rawResponse = await fetch(
2781
- `https://api.quickbase.com/v1/fields/usage/${fieldId}?tableId=${QB_TABLE_ID_1}`,
2782
- {
2783
- method: "GET",
2784
- headers: {
2785
- "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
2786
- Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
2787
- "Content-Type": "application/json",
2788
- },
2789
- }
2790
- );
2791
- const rawBody = await rawResponse.text();
2792
- console.log("Raw API response:", {
2793
- status: rawResponse.status,
2794
- statusText: rawResponse.statusText,
2795
- body: rawBody,
2796
- });
2797
-
2798
- const responseArray: FieldUsage[] = await client.getFieldUsage({
2799
- fieldId,
2800
- tableId: QB_TABLE_ID_1,
2801
- });
2802
- console.log("Parsed API response (array):", responseArray);
2803
-
2804
- // Validate response structure (unwrap the array)
2805
- expect(responseArray).toBeDefined();
2806
- expect(responseArray).toHaveLength(1); // Expect a single-item array
2807
- const response = responseArray[0];
2808
-
2809
- expect(response).toBeDefined();
2810
- expect(response.field).toHaveProperty("id", fieldId);
2811
- expect(response.field).toHaveProperty("name", uniqueLabel);
2812
- expect(response.field).toHaveProperty("type", "text");
2813
- expect(typeof response.field.name).toBe("string");
2814
- expect(typeof response.field.type).toBe("string");
2815
-
2816
- expect(response.usage).toBeDefined();
2817
- expect(typeof response.usage).toBe("object");
2818
- expect(response.usage).toHaveProperty("actions");
2819
- expect(response.usage.actions).toHaveProperty("count");
2820
- expect(typeof response.usage.actions.count).toBe("number");
2821
- expect(response.usage).toHaveProperty("appHomePages");
2822
- expect(response.usage).toHaveProperty("dashboards");
2823
- expect(response.usage).toHaveProperty("defaultReports");
2824
- expect(response.usage).toHaveProperty("exactForms");
2825
- expect(response.usage).toHaveProperty("fields");
2826
- expect(response.usage).toHaveProperty("forms");
2827
- expect(response.usage).toHaveProperty("notifications");
2828
- expect(response.usage).toHaveProperty("personalReports");
2829
- expect(response.usage).toHaveProperty("pipelines");
2830
- expect(response.usage).toHaveProperty("relationships");
2831
- expect(response.usage).toHaveProperty("reminders");
2832
- expect(response.usage).toHaveProperty("reports");
2833
- expect(response.usage).toHaveProperty("roles");
2834
- expect(response.usage).toHaveProperty("tableImports");
2835
- expect(response.usage).toHaveProperty("tableRules");
2836
- expect(response.usage).toHaveProperty("webhooks");
2837
-
2838
- // Since it’s a new field, expect minimal usage
2839
- expect(response.usage.forms.count).toBeGreaterThanOrEqual(0); // May be 1 if addToForms worked
2840
- },
2841
- { timeout: 30000 } // 30-second timeout for create + get + delete
2842
- );
2843
-
2844
- it("fails with non-existent field ID", { timeout: 15000 }, async () => {
2845
- const nonExistentFieldId = 999999;
2846
-
2847
- console.log("Attempting to fetch usage for non-existent field:", {
2848
- tableId: QB_TABLE_ID_1,
2849
- fieldId: nonExistentFieldId,
2850
- });
2851
- await expect(
2852
- client.getFieldUsage({
2853
- fieldId: nonExistentFieldId,
2854
- tableId: QB_TABLE_ID_1,
2855
- })
2856
- ).rejects.toMatchObject({
2857
- message: expect.stringContaining(
2858
- "API Error: No such field (Status: 404)"
2859
- ),
2860
- });
2861
-
2862
- console.log(
2863
- `Confirmed 404 for non-existent field ID ${nonExistentFieldId}`
2864
- );
2865
- });
2866
-
2867
- it("fails with invalid table ID", { timeout: 15000 }, async () => {
2868
- const invalidTableId = "invalid_dbid";
2869
- const fieldId = 6;
2870
-
2871
- console.log("Attempting to fetch usage with invalid table ID:", {
2872
- tableId: invalidTableId,
2873
- fieldId,
2874
- });
2875
- await expect(
2876
- client.getFieldUsage({
2877
- fieldId,
2878
- tableId: invalidTableId,
2879
- })
2880
- ).rejects.toMatchObject({
2881
- message: expect.stringContaining(
2882
- "API Error: Access denied (Status: 401)"
2883
- ),
2884
- });
2885
-
2886
- console.log(`Confirmed 401 for invalid table ID ${invalidTableId}`);
2887
- });
2888
- });
2889
- - name: >-
2890
- getFields.test.ts
2891
- type: >-
2892
- file
2893
- contents: >
2894
- import
2895
- {
2896
- describe,
2897
- it,
2898
- expect
2899
- }
2900
- from
2901
- "vitest";
2902
-
2903
- import
2904
- {
2905
- createClient,
2906
- QB_TABLE_ID_1
2907
- }
2908
- from
2909
- "../../../setup.ts";
2910
-
2911
-
2912
- describe("QuickbaseClient
2913
- Integration
2914
- -
2915
- getFields",
2916
- ()
2917
- =>
2918
- {
2919
- const client = createClient();
2920
-
2921
- it(
2922
- "fetches real field data from QuickBase",
2923
- async () => {
2924
- if (!process.env.QB_REALM)
2925
- throw new Error("QB_REALM is not defined in .env");
2926
- if (!process.env.QB_USER_TOKEN)
2927
- throw new Error("QB_USER_TOKEN is not defined in .env");
2928
-
2929
- console.log("Config used:", {
2930
- realm: process.env.QB_REALM,
2931
- userToken: process.env.QB_USER_TOKEN,
2932
- tableId: QB_TABLE_ID_1,
2933
- });
2934
- const result = await client.getFields({
2935
- tableId: QB_TABLE_ID_1,
2936
- includeFieldPerms: true,
2937
- });
2938
- console.log("Real API response:", result);
2939
- expect(result).toEqual(
2940
- expect.arrayContaining([
2941
- expect.objectContaining({
2942
- id: 1,
2943
- label: "Date Created",
2944
- fieldType: "timestamp",
2945
- noWrap: true,
2946
- bold: false,
2947
- required: false,
2948
- appearsByDefault: false,
2949
- findEnabled: false,
2950
- unique: false,
2951
- doesDataCopy: false,
2952
- fieldHelp: "",
2953
- audited: false,
2954
- properties: expect.objectContaining({
2955
- primaryKey: false,
2956
- foreignKey: false,
2957
- sortAsGiven: true,
2958
- carryChoices: true,
2959
- allowNewChoices: false,
2960
- formula: "",
2961
- defaultValue: "",
2962
- }),
2963
- permissions: expect.arrayContaining([
2964
- expect.objectContaining({
2965
- permissionType: "Modify",
2966
- role: "Viewer",
2967
- roleId: 10,
2968
- }),
2969
- expect.objectContaining({
2970
- permissionType: "Modify",
2971
- role: "Participant",
2972
- roleId: 11,
2973
- }),
2974
- expect.objectContaining({
2975
- permissionType: "Modify",
2976
- role: "Administrator",
2977
- roleId: 12,
2978
- }),
2979
- ]),
2980
- }),
2981
- expect.objectContaining({
2982
- id: 2,
2983
- label: "Date Modified",
2984
- fieldType: "timestamp",
2985
- noWrap: true,
2986
- bold: false,
2987
- required: false,
2988
- appearsByDefault: false,
2989
- findEnabled: false,
2990
- unique: false,
2991
- doesDataCopy: false,
2992
- fieldHelp: "",
2993
- audited: false,
2994
- properties: expect.objectContaining({
2995
- primaryKey: false,
2996
- foreignKey: false,
2997
- sortAsGiven: true,
2998
- carryChoices: true,
2999
- allowNewChoices: false,
3000
- formula: "",
3001
- defaultValue: "",
3002
- }),
3003
- permissions: expect.arrayContaining([
3004
- expect.objectContaining({
3005
- permissionType: "Modify",
3006
- role: "Viewer",
3007
- roleId: 10,
3008
- }),
3009
- expect.objectContaining({
3010
- permissionType: "Modify",
3011
- role: "Participant",
3012
- roleId: 11,
3013
- }),
3014
- expect.objectContaining({
3015
- permissionType: "Modify",
3016
- role: "Administrator",
3017
- roleId: 12,
3018
- }),
3019
- ]),
3020
- }),
3021
- expect.objectContaining({
3022
- id: 3,
3023
- label: "Record ID#",
3024
- fieldType: "recordid",
3025
- noWrap: true,
3026
- bold: false,
3027
- required: false,
3028
- appearsByDefault: false,
3029
- findEnabled: false,
3030
- unique: true,
3031
- doesDataCopy: false,
3032
- fieldHelp: "",
3033
- audited: false,
3034
- properties: expect.objectContaining({
3035
- primaryKey: true,
3036
- foreignKey: false,
3037
- sortAsGiven: true,
3038
- carryChoices: true,
3039
- allowNewChoices: false,
3040
- formula: "",
3041
- defaultValue: "",
3042
- }),
3043
- permissions: expect.arrayContaining([
3044
- expect.objectContaining({
3045
- permissionType: "Modify",
3046
- role: "Viewer",
3047
- roleId: 10,
3048
- }),
3049
- expect.objectContaining({
3050
- permissionType: "Modify",
3051
- role: "Participant",
3052
- roleId: 11,
3053
- }),
3054
- expect.objectContaining({
3055
- permissionType: "Modify",
3056
- role: "Administrator",
3057
- roleId: 12,
3058
- }),
3059
- ]),
3060
- }),
3061
- expect.objectContaining({
3062
- id: 4,
3063
- label: "Record Owner",
3064
- fieldType: "user",
3065
- noWrap: true,
3066
- bold: false,
3067
- required: false,
3068
- appearsByDefault: false,
3069
- findEnabled: true,
3070
- unique: false,
3071
- doesDataCopy: false,
3072
- fieldHelp: "",
3073
- audited: false,
3074
- properties: expect.objectContaining({
3075
- primaryKey: false,
3076
- foreignKey: false,
3077
- sortAsGiven: true,
3078
- carryChoices: true,
3079
- allowNewChoices: true,
3080
- formula: "",
3081
- defaultValue: "",
3082
- }),
3083
- permissions: expect.arrayContaining([
3084
- expect.objectContaining({
3085
- permissionType: "Modify",
3086
- role: "Viewer",
3087
- roleId: 10,
3088
- }),
3089
- expect.objectContaining({
3090
- permissionType: "Modify",
3091
- role: "Participant",
3092
- roleId: 11,
3093
- }),
3094
- expect.objectContaining({
3095
- permissionType: "Modify",
3096
- role: "Administrator",
3097
- roleId: 12,
3098
- }),
3099
- ]),
3100
- }),
3101
- expect.objectContaining({
3102
- id: 5,
3103
- label: "Last Modified By",
3104
- fieldType: "user",
3105
- noWrap: true,
3106
- bold: false,
3107
- required: false,
3108
- appearsByDefault: false,
3109
- findEnabled: true,
3110
- unique: false,
3111
- doesDataCopy: false,
3112
- fieldHelp: "",
3113
- audited: false,
3114
- properties: expect.objectContaining({
3115
- primaryKey: false,
3116
- foreignKey: false,
3117
- sortAsGiven: true,
3118
- carryChoices: true,
3119
- allowNewChoices: true,
3120
- formula: "",
3121
- defaultValue: "",
3122
- }),
3123
- permissions: expect.arrayContaining([
3124
- expect.objectContaining({
3125
- permissionType: "Modify",
3126
- role: "Viewer",
3127
- roleId: 10,
3128
- }),
3129
- expect.objectContaining({
3130
- permissionType: "Modify",
3131
- role: "Participant",
3132
- roleId: 11,
3133
- }),
3134
- expect.objectContaining({
3135
- permissionType: "Modify",
3136
- role: "Administrator",
3137
- roleId: 12,
3138
- }),
3139
- ]),
3140
- }),
3141
- ])
3142
- );
3143
- },
3144
- { timeout: 10000 }
3145
- );
3146
- });
3147
- - name: >-
3148
- getFieldsUsage.test.ts
3149
- type: >-
3150
- file
3151
- contents: >
3152
- //
3153
- tests/vitest/qb/fields/getFieldsUsage.test.ts
3154
-
3155
- import
3156
- {
3157
- describe,
3158
- it,
3159
- expect
3160
- }
3161
- from
3162
- "vitest";
3163
-
3164
- import
3165
- {
3166
- createClient,
3167
- QB_TABLE_ID_1
3168
- }
3169
- from
3170
- "../../../setup.ts";
3171
-
3172
- import
3173
- {
3174
- FieldUsage
3175
- }
3176
- from
3177
- "@/generated/models";
3178
-
3179
-
3180
- describe("QuickbaseClient
3181
- Integration
3182
- -
3183
- getFieldsUsage",
3184
- ()
3185
- =>
3186
- {
3187
- const client = createClient();
3188
-
3189
- it("retrieves field usage statistics for a valid table", async () => {
3190
- console.log("Starting retrieval of full field usage list");
3191
- const response = await client.getFieldsUsage({
3192
- tableId: QB_TABLE_ID_1,
3193
- });
3194
-
3195
- expect(response).toBeInstanceOf(Array);
3196
- expect(response.length).toBeGreaterThan(0); // Assumes the table has fields
3197
- response.forEach((usage: FieldUsage) => {
3198
- expect(usage.field).toHaveProperty("id");
3199
- expect(usage.field).toHaveProperty("name");
3200
- expect(usage.field).toHaveProperty("type");
3201
- expect(usage.usage).toHaveProperty("actions");
3202
- expect(usage.usage.actions).toHaveProperty("count");
3203
- expect(typeof usage.usage.actions.count).toBe("number");
3204
- expect(usage.usage).toHaveProperty("dashboards");
3205
- expect(usage.usage).toHaveProperty("forms");
3206
- expect(usage.usage).toHaveProperty("reports");
3207
- });
3208
- console.log(
3209
- `Retrieved ${response.length} field usage entries for table ${QB_TABLE_ID_1}`
3210
- );
3211
- }, 15000); // 15-second timeout
3212
-
3213
- it("retrieves field usage with skip and top parameters", async () => {
3214
- console.log(
3215
- "Starting retrieval of full field usage list for skip/top test"
3216
- );
3217
- const fullResponse = await client.getFieldsUsage({
3218
- tableId: QB_TABLE_ID_1,
3219
- });
3220
- console.log(`Full list retrieved: ${fullResponse.length} fields`);
3221
-
3222
- const totalFields = fullResponse.length;
3223
- if (totalFields <= 1) {
3224
- console.log("Skipping skip/top test: table has too few fields");
3225
- return; // Skip if not enough fields to test pagination
3226
- }
3227
-
3228
- console.log("Starting retrieval with skip=1 and top=1");
3229
- const response = await client.getFieldsUsage({
3230
- tableId: QB_TABLE_ID_1,
3231
- skip: 1,
3232
- top: 1,
3233
- });
3234
-
3235
- expect(response).toBeInstanceOf(Array);
3236
- expect(response.length).toBe(1); // Should return exactly 1 field
3237
- expect(response[0].field.id).not.toBe(fullResponse[0].field.id); // Should skip the first field
3238
- console.log(
3239
- `Retrieved ${response.length} field usage entries with skip=1 and top=1`
3240
- );
3241
- }, 15000); // 15-second timeout
3242
-
3243
- it("fails with invalid table ID", async () => {
3244
- const invalidTableId = "invalid_dbid";
3245
- console.log(`Starting retrieval with invalid table ID ${invalidTableId}`);
3246
- await expect(
3247
- client.getFieldsUsage({
3248
- tableId: invalidTableId,
3249
- })
3250
- ).rejects.toMatchObject({
3251
- message: expect.stringContaining(
3252
- "API Error: Access denied (Status: 401)"
3253
- ),
3254
- });
3255
- console.log(`Confirmed 401 for invalid table ID ${invalidTableId}`);
3256
- }, 15000); // 15-second timeout
3257
- });
3258
- - name: >-
3259
- updateField.test.ts
3260
- type: >-
3261
- file
3262
- contents: >
3263
- //
3264
- tests/vitest/qb/fields/updateField.test.ts
3265
-
3266
- import
3267
- {
3268
- describe,
3269
- it,
3270
- expect,
3271
- beforeAll,
3272
- afterAll
3273
- }
3274
- from
3275
- "vitest";
3276
-
3277
- import
3278
- {
3279
- createClient,
3280
- QB_TABLE_ID_1
3281
- }
3282
- from
3283
- "../../../setup.ts";
3284
-
3285
-
3286
- describe("QuickbaseClient
3287
- Integration
3288
- -
3289
- updateField",
3290
- ()
3291
- =>
3292
- {
3293
- const client = createClient();
3294
- let fieldIdToUpdate: number;
3295
-
3296
- // Setup: Create a test field to update
3297
- beforeAll(async () => {
3298
- try {
3299
- const response = await client.createField({
3300
- tableId: QB_TABLE_ID_1,
3301
- body: {
3302
- label: "UpdateTestField",
3303
- fieldType: "text",
3304
- fieldHelp: "Test field for updating",
3305
- },
3306
- });
3307
- fieldIdToUpdate = response.id;
3308
- console.log(`Created field UpdateTestField with ID ${fieldIdToUpdate}`);
3309
- } catch (error) {
3310
- console.error("beforeAll failed:", error);
3311
- throw error; // Fail the suite if setup fails
3312
- }
3313
- });
3314
-
3315
- // Teardown: Delete the test field
3316
- afterAll(async () => {
3317
- try {
3318
- if (fieldIdToUpdate) {
3319
- const response = await client.deleteFields({
3320
- tableId: QB_TABLE_ID_1,
3321
- body: { fieldIds: [fieldIdToUpdate] },
3322
- });
3323
- console.log(
3324
- `Deleted field ${fieldIdToUpdate}:`,
3325
- JSON.stringify(response, null, 2)
3326
- );
3327
- }
3328
- } catch (error) {
3329
- console.error("afterAll cleanup failed:", error);
3330
- // Don’t throw here to avoid masking test results
3331
- }
3332
- });
3333
-
3334
- it(
3335
- "updates a field successfully with user token",
3336
- { timeout: 10000 },
3337
- async () => {
3338
- try {
3339
- const updatedLabel = "UpdatedTestField";
3340
- console.log("Sending updateField request at:", new Date());
3341
- const response = await client.updateField({
3342
- tableId: QB_TABLE_ID_1,
3343
- fieldId: fieldIdToUpdate,
3344
- body: {
3345
- label: updatedLabel,
3346
- fieldHelp: "Updated help text",
3347
- },
3348
- });
3349
- console.log("updateField response received at:", new Date());
3350
- console.log("Response:", JSON.stringify(response, null, 2));
3351
-
3352
- // Verify the update was successful
3353
- expect(response).toBeDefined();
3354
- expect(response.id).toBe(fieldIdToUpdate);
3355
- expect(response.label).toBe(updatedLabel);
3356
- expect(response.fieldHelp).toBe("Updated help text");
3357
- } catch (error) {
3358
- console.error("updateField failed:", error);
3359
- throw error; // Re-throw to fail the test with details
3360
- }
3361
- }
3362
- );
3363
-
3364
- it("fails with invalid field ID", { timeout: 10000 }, async () => {
3365
- try {
3366
- await expect(
3367
- client.updateField({
3368
- tableId: QB_TABLE_ID_1,
3369
- fieldId: 999999, // Invalid field ID
3370
- body: {
3371
- label: "InvalidUpdate",
3372
- },
3373
- })
3374
- ).rejects.toThrow("API Error: Item not found (Status: 404)"); // Updated to match actual error
3375
- } catch (error) {
3376
- console.error("updateField with invalid ID failed unexpectedly:", error);
3377
- throw error;
3378
- }
3379
- });
3380
- });
3381
- - name: >-
3382
- index.ts
3383
- type: >-
3384
- file
3385
- contents: >
3386
- //
3387
- tests/vitest/qb/index.ts
3388
-
3389
-
3390
- //
3391
- Apps
3392
-
3393
- export
3394
- *
3395
- from
3396
- "./apps/copyApp.test.ts";
3397
-
3398
- export
3399
- *
3400
- from
3401
- "./apps/createApp.test.ts";
3402
-
3403
- export
3404
- *
3405
- from
3406
- "./apps/deleteApp.test.ts";
3407
-
3408
- export
3409
- *
3410
- from
3411
- "./apps/getApp.test.ts";
3412
-
3413
-
3414
- //
3415
- Fields
3416
-
3417
- export
3418
- *
3419
- from
3420
- "./fields/createField.test.ts";
3421
-
3422
- export
3423
- *
3424
- from
3425
- "./fields/deleteFields.test.ts";
3426
-
3427
- export
3428
- *
3429
- from
3430
- "./fields/getFields.test.ts";
3431
-
3432
- export
3433
- *
3434
- from
3435
- "./fields/getField.test.ts";
3436
- //
3437
- Added
3438
- new
3439
- getField
3440
- test
3441
-
3442
- export
3443
- *
3444
- from
3445
- "./fields/getFieldsUsage.test.ts";
3446
-
3447
- export
3448
- *
3449
- from
3450
- "./fields/getFieldUsage.test.ts";
3451
-
3452
-
3453
- //
3454
- Records
3455
-
3456
- export
3457
- *
3458
- from
3459
- "./records/deleteRecords.test.ts";
3460
-
3461
- export
3462
- *
3463
- from
3464
- "./records/runQuery.test.ts";
3465
-
3466
- export
3467
- *
3468
- from
3469
- "./records/upsert.test.ts";
3470
-
3471
-
3472
- //
3473
- Tables
3474
-
3475
- export
3476
- *
3477
- from
3478
- "./tables/createTable.test.ts";
3479
-
3480
- export
3481
- *
3482
- from
3483
- "./tables/deleteTable.test.ts";
3484
-
3485
- export
3486
- *
3487
- from
3488
- "./tables/getAppTables.test.ts";
3489
-
3490
- export
3491
- *
3492
- from
3493
- "./tables/getRelationships.test.ts";
3494
-
3495
- export
3496
- *
3497
- from
3498
- "./tables/getTable.test.ts";
3499
-
3500
- export
3501
- *
3502
- from
3503
- "./tables/updateTable.test.ts";
3504
-
3505
- export
3506
- *
3507
- from
3508
- "./tables/updateRelationship.test.ts";
3509
- - name: >-
3510
- records
3511
- type: >-
3512
- directory
3513
- children:
3514
- - name: >-
3515
- deleteRecords.test.ts
3516
- type: >-
3517
- file
3518
- contents: >
3519
- //
3520
- tests/vitest/qb/records/deleteRecords.test.ts
3521
-
3522
- import
3523
- {
3524
- describe,
3525
- test,
3526
- expect,
3527
- beforeEach,
3528
- afterEach
3529
- }
3530
- from
3531
- "vitest";
3532
-
3533
- import
3534
- {
3535
- quickbase
3536
- }
3537
- from
3538
- "@/quickbaseClient.ts";
3539
-
3540
- import
3541
- {
3542
- Upsert200Response,
3543
- Upsert207Response,
3544
- }
3545
- from
3546
- "/home/drew/Projects/quickbase-js/src/generated/models";
3547
-
3548
-
3549
- const
3550
- TABLE_ID
3551
- =
3552
- "buwai2zws";
3553
-
3554
- const
3555
- UNIQUE_FIELD_ID
3556
- =
3557
- 3;
3558
- //
3559
- Record
3560
- ID
3561
- field
3562
-
3563
- const
3564
- MARKER_FIELD_ID
3565
- =
3566
- 6;
3567
- //
3568
- Text
3569
- field
3570
- for
3571
- marking
3572
- test
3573
- records
3574
-
3575
-
3576
- describe("QuickbaseClient
3577
- -
3578
- DeleteRecords
3579
- Integration",
3580
- ()
3581
- =>
3582
- {
3583
- const qb = quickbase({
3584
- realm: "builderprogram-dbradford6815",
3585
- userToken: process.env.QB_USER_TOKEN,
3586
- debug: true,
3587
- });
3588
-
3589
- beforeEach(async () => {
3590
- try {
3591
- await qb.deleteRecords({
3592
- body: {
3593
- from: TABLE_ID,
3594
- where: `{${MARKER_FIELD_ID}.CT.'test-marker-delete'}`,
3595
- },
3596
- });
3597
- } catch (e) {
3598
- // Ignore if no records exist
3599
- }
3600
- });
3601
-
3602
- afterEach(async () => {
3603
- try {
3604
- await qb.deleteRecords({
3605
- body: {
3606
- from: TABLE_ID,
3607
- where: `{${MARKER_FIELD_ID}.CT.'test-marker-delete'}`,
3608
- },
3609
- });
3610
- } catch (e) {}
3611
- });
3612
-
3613
- test(
3614
- "deletes a newly upserted record",
3615
- async () => {
3616
- const upsertResponse: Upsert200Response | Upsert207Response =
3617
- await qb.upsert({
3618
- body: {
3619
- to: TABLE_ID,
3620
- data: [{ [MARKER_FIELD_ID]: { value: "test-marker-delete" } }],
3621
- fieldsToReturn: [UNIQUE_FIELD_ID], // Return record ID
3622
- },
3623
- });
3624
-
3625
- // Check metadata and createdRecordIds
3626
- expect(
3627
- upsertResponse.metadata,
3628
- "Expected metadata to be defined"
3629
- ).toBeDefined();
3630
- expect(
3631
- upsertResponse.metadata?.createdRecordIds,
3632
- "Expected createdRecordIds to be defined"
3633
- ).toBeDefined();
3634
-
3635
- const createdRecordIds = upsertResponse.metadata?.createdRecordIds;
3636
- if (!createdRecordIds || createdRecordIds.length === 0) {
3637
- throw new Error("Expected at least one created record ID");
3638
- }
3639
-
3640
- const recordId = createdRecordIds[0];
3641
- expect(recordId, "Expected recordId to be defined").toBeDefined();
3642
-
3643
- // Check data
3644
- expect(upsertResponse.data, "Expected data to be defined").toBeDefined();
3645
- if (!upsertResponse.data || upsertResponse.data.length === 0) {
3646
- throw new Error("Expected at least one data entry");
3647
- }
3648
-
3649
- const recordData = upsertResponse.data[0];
3650
- expect(
3651
- recordData[UNIQUE_FIELD_ID]?.value,
3652
- "Expected record ID in data to match created record ID"
3653
- ).toBe(recordId);
3654
-
3655
- const deleteResponse = await qb.deleteRecords({
3656
- body: { from: TABLE_ID, where: `{${UNIQUE_FIELD_ID}.EX.${recordId}}` },
3657
- });
3658
-
3659
- expect(deleteResponse).toEqual({ numberDeleted: 1 });
3660
-
3661
- const checkResponse = await qb.deleteRecords({
3662
- body: { from: TABLE_ID, where: `{${UNIQUE_FIELD_ID}.EX.${recordId}}` },
3663
- });
3664
- expect(checkResponse.numberDeleted).toBe(0);
3665
- },
3666
- { timeout: 10000 }
3667
- );
3668
-
3669
- test(
3670
- "handles empty result when no records match",
3671
- async () => {
3672
- const response = await qb.deleteRecords({
3673
- body: { from: TABLE_ID, where: "{3.EX.'999999'}" },
3674
- });
3675
- expect(response).toEqual({ numberDeleted: 0 });
3676
- },
3677
- { timeout: 10000 }
3678
- );
3679
- });
3680
- - name: >-
3681
- runQuery.test.ts
3682
- type: >-
3683
- file
3684
- contents: >
3685
- //
3686
- tests/vitest/qb/records/runQuery.test.ts
3687
-
3688
- import
3689
- {
3690
- describe,
3691
- it,
3692
- expect
3693
- }
3694
- from
3695
- "vitest";
3696
-
3697
- import
3698
- {
3699
- createClient,
3700
- QB_TABLE_ID_1
3701
- }
3702
- from
3703
- "../../../setup.ts";
3704
-
3705
- import
3706
- {
3707
- RunQueryRequest,
3708
- RunQueryResponse,
3709
- Upsert200Response,
3710
- Upsert207Response,
3711
- }
3712
- from
3713
- "@/generated/models";
3714
-
3715
-
3716
- //
3717
- Define
3718
- a
3719
- type
3720
- for
3721
- field
3722
- data
3723
- with
3724
- a
3725
- value
3726
- property
3727
- (matches
3728
- generated
3729
- Record
3730
- type)
3731
-
3732
- interface
3733
- FieldData
3734
- {
3735
- value: any; // Adjust type based on your needs (e.g., string | number)
3736
- }
3737
-
3738
-
3739
- describe("QuickbaseClient
3740
- Integration
3741
- -
3742
- runQuery",
3743
- ()
3744
- =>
3745
- {
3746
- let createdRecordId: number;
3747
-
3748
- it(
3749
- "queries real records from QuickBase",
3750
- async () => {
3751
- const client = createClient();
3752
-
3753
- // Upsert a test record to query later
3754
- const upsertResponse: Upsert200Response | Upsert207Response =
3755
- await client.upsert({
3756
- body: {
3757
- to: QB_TABLE_ID_1,
3758
- data: [
3759
- {
3760
- "6": { value: "Test Task " + Date.now() }, // Assuming field 6 is a text field
3761
- },
3762
- ],
3763
- fieldsToReturn: [3, 6], // Record ID# and the text field
3764
- },
3765
- });
3766
-
3767
- // Check metadata and createdRecordIds with null safety
3768
- expect(
3769
- upsertResponse.metadata,
3770
- "Expected metadata to be defined"
3771
- ).toBeDefined();
3772
- expect(
3773
- upsertResponse.metadata?.createdRecordIds,
3774
- "Expected createdRecordIds to be defined"
3775
- ).toBeDefined();
3776
-
3777
- const createdRecordIds = upsertResponse.metadata?.createdRecordIds;
3778
- if (!createdRecordIds || createdRecordIds.length === 0) {
3779
- throw new Error("Expected at least one created record ID from upsert");
3780
- }
3781
-
3782
- createdRecordId = createdRecordIds[0];
3783
- expect(
3784
- createdRecordId,
3785
- "Expected createdRecordId to be defined"
3786
- ).toBeDefined();
3787
- console.log("Created test record with ID:", createdRecordId);
3788
-
3789
- // Query the record
3790
- const queryRequest: RunQueryRequest = {
3791
- from: QB_TABLE_ID_1,
3792
- select: [3, 6], // Query Record ID# and the text field
3793
- where: `{3.EX.${createdRecordId}}`, // Filter by the created record
3794
- sortBy: [{ fieldId: 6, order: "ASC" }],
3795
- options: { skip: 0, top: 1 },
3796
- };
3797
-
3798
- console.log("Config used:", {
3799
- realm: process.env.QB_REALM,
3800
- userToken: process.env.QB_USER_TOKEN,
3801
- tableId: QB_TABLE_ID_1,
3802
- });
3803
- console.log("Query request:", queryRequest);
3804
- const response: RunQueryResponse = await client.runQuery({
3805
- body: queryRequest,
3806
- });
3807
- console.log("Real API response:", response);
3808
-
3809
- // Assertions with safety checks and type assertion
3810
- expect(
3811
- response.data,
3812
- "Expected response.data to be defined"
3813
- ).toBeDefined();
3814
- if (!response.data || response.data.length === 0) {
3815
- throw new Error(
3816
- "Expected response.data to contain at least one record"
3817
- );
3818
- }
3819
-
3820
- expect(response.data).toHaveLength(1);
3821
- const record = response.data[0] as { [key: string]: FieldData };
3822
- expect(
3823
- record["3"]?.value,
3824
- "Expected field 3 to match createdRecordId"
3825
- ).toBe(createdRecordId);
3826
- expect(
3827
- record["6"]?.value,
3828
- "Expected field 6 to contain 'Test Task'"
3829
- ).toContain("Test Task");
3830
-
3831
- expect(
3832
- response.fields,
3833
- "Expected response.fields to be defined"
3834
- ).toBeDefined();
3835
- if (!response.fields) {
3836
- throw new Error("Expected response.fields to contain field metadata");
3837
- }
3838
- expect(response.fields).toContainEqual({
3839
- id: 3,
3840
- label: expect.any(String),
3841
- type: expect.any(String),
3842
- });
3843
- expect(response.fields).toContainEqual({
3844
- id: 6,
3845
- label: expect.any(String),
3846
- type: expect.any(String),
3847
- });
3848
-
3849
- expect(
3850
- response.metadata,
3851
- "Expected response.metadata to be defined"
3852
- ).toBeDefined();
3853
- if (!response.metadata) {
3854
- throw new Error("Expected response.metadata to be present");
3855
- }
3856
- expect(response.metadata).toMatchObject({
3857
- numFields: 2,
3858
- numRecords: 1,
3859
- skip: 0,
3860
- top: 1,
3861
- totalRecords: expect.any(Number),
3862
- });
3863
-
3864
- // Cleanup: Delete the test record
3865
- await client.deleteRecords({
3866
- body: {
3867
- from: QB_TABLE_ID_1,
3868
- where: `{3.EX.${createdRecordId}}`, // Assuming field 3 is Record ID#
3869
- },
3870
- });
3871
- console.log("Cleaned up test record with ID:", createdRecordId);
3872
- },
3873
- { timeout: 10000 }
3874
- );
3875
- });
3876
- - name: >-
3877
- upsert.test.ts
3878
- type: >-
3879
- file
3880
- contents: >
3881
- //
3882
- tests/vitest/qb/records/upsert.test.ts
3883
-
3884
- import
3885
- {
3886
- describe,
3887
- test,
3888
- expect,
3889
- beforeEach,
3890
- afterEach
3891
- }
3892
- from
3893
- "vitest";
3894
-
3895
- import
3896
- {
3897
- quickbase
3898
- }
3899
- from
3900
- "@/quickbaseClient.ts";
3901
-
3902
- import
3903
- {
3904
- Upsert200Response,
3905
- Upsert207Response,
3906
- }
3907
- from
3908
- "/home/drew/Projects/quickbase-js/src/generated/models";
3909
-
3910
-
3911
- const
3912
- TABLE_ID
3913
- =
3914
- "buwai2zws";
3915
-
3916
- const
3917
- MARKER_FIELD_ID
3918
- =
3919
- 6;
3920
- //
3921
- Text
3922
- field
3923
- for
3924
- marking
3925
- test
3926
- records
3927
-
3928
-
3929
- describe("QuickbaseClient
3930
- -
3931
- Upsert
3932
- Integration",
3933
- ()
3934
- =>
3935
- {
3936
- const qb = quickbase({
3937
- realm: "builderprogram-dbradford6815",
3938
- userToken: process.env.QB_USER_TOKEN,
3939
- debug: true,
3940
- });
3941
-
3942
- beforeEach(async () => {
3943
- try {
3944
- await qb.deleteRecords({
3945
- body: {
3946
- from: TABLE_ID,
3947
- where: `{${MARKER_FIELD_ID}.CT.'test-marker-upsert'}`,
3948
- },
3949
- });
3950
- } catch (e) {
3951
- // Ignore if no records exist
3952
- }
3953
- });
3954
-
3955
- afterEach(async () => {
3956
- try {
3957
- await qb.deleteRecords({
3958
- body: {
3959
- from: TABLE_ID,
3960
- where: `{${MARKER_FIELD_ID}.CT.'test-marker-upsert'}`,
3961
- },
3962
- });
3963
- } catch (e) {}
3964
- });
3965
-
3966
- test(
3967
- "creates a new record successfully",
3968
- async () => {
3969
- const response: Upsert200Response | Upsert207Response = await qb.upsert({
3970
- body: {
3971
- to: TABLE_ID,
3972
- data: [{ [MARKER_FIELD_ID]: { value: "test-marker-upsert" } }],
3973
- fieldsToReturn: [MARKER_FIELD_ID, 3], // Return marker and record ID
3974
- },
3975
- });
3976
-
3977
- // Check metadata with null safety
3978
- expect(
3979
- response.metadata,
3980
- "Expected metadata to be defined"
3981
- ).toBeDefined();
3982
- if (!response.metadata) {
3983
- throw new Error("Expected metadata to be present in upsert response");
3984
- }
3985
-
3986
- expect(
3987
- response.metadata.createdRecordIds,
3988
- "Expected createdRecordIds to be defined"
3989
- ).toBeDefined();
3990
- if (!response.metadata.createdRecordIds) {
3991
- throw new Error(
3992
- "Expected createdRecordIds to be present in upsert response"
3993
- );
3994
- }
3995
- expect(response.metadata.createdRecordIds.length).toBe(1);
3996
-
3997
- // Check data with null safety
3998
- expect(response.data, "Expected data to be defined").toBeDefined();
3999
- if (!response.data || response.data.length === 0) {
4000
- throw new Error("Expected at least one record in data");
4001
- }
4002
- expect(response.data).toHaveLength(1);
4003
- expect(response.data[0][MARKER_FIELD_ID]?.value).toBe(
4004
- "test-marker-upsert"
4005
- );
4006
- expect(response.data[0][3]?.value).toBeDefined(); // Record ID assigned by QuickBase
4007
-
4008
- // Check totalNumberOfRecordsProcessed
4009
- expect(response.metadata.totalNumberOfRecordsProcessed).toBe(1);
4010
- },
4011
- { timeout: 10000 }
4012
- );
4013
-
4014
- test(
4015
- "handles empty data gracefully",
4016
- async () => {
4017
- await expect(
4018
- qb.upsert({
4019
- body: { to: TABLE_ID, data: [] },
4020
- })
4021
- ).rejects.toThrow("API Error: Bad Request (Status: 400)");
4022
- },
4023
- { timeout: 10000 }
4024
- );
4025
- });
4026
- - name: >-
4027
- tables
4028
- type: >-
4029
- directory
4030
- children:
4031
- - name: >-
4032
- createTable.test.ts
4033
- type: >-
4034
- file
4035
- contents: >
4036
- import
4037
- {
4038
- test,
4039
- expect
4040
- }
4041
- from
4042
- "vitest";
4043
-
4044
- import
4045
- {
4046
- quickbase
4047
- }
4048
- from
4049
- "../../../../src/quickbaseClient";
4050
-
4051
-
4052
- test(
4053
- "QuickbaseClient Integration - createTable > creates a new table in QuickBase",
4054
- { timeout: 10000 },
4055
- async () => {
4056
- const config = {
4057
- realm: process.env.QB_REALM || "",
4058
- userToken: process.env.QB_USER_TOKEN || "",
4059
- debug: true,
4060
- };
4061
- const client = quickbase(config);
4062
- const appId = "buwai2zpe";
4063
-
4064
- const tableName = `TestTable_${Date.now()}`;
4065
- const createBody = {
4066
- name: tableName,
4067
- description: "Test table creation",
4068
- singleRecordName: "TestRecord",
4069
- pluralRecordName: "TestRecords",
4070
- };
4071
-
4072
- console.log("Config used:", config);
4073
- console.log("Creating table with:", createBody);
4074
- const response = await client.createTable({ appId, body: createBody });
4075
-
4076
- expect(response).toBeDefined();
4077
- expect(response.id).toBeDefined();
4078
- expect(response.name).toBe(tableName);
4079
- expect(response.description).toBe(createBody.description);
4080
- expect(response.singleRecordName).toBe(createBody.singleRecordName);
4081
- expect(response.pluralRecordName).toBe(createBody.pluralRecordName);
4082
- expect(response.alias).toMatch(/^_DBID_/);
4083
- expect(response.created).toBeInstanceOf(Date);
4084
- expect(response.updated).toBeInstanceOf(Date);
4085
- expect(response.nextRecordId).toBeGreaterThanOrEqual(1);
4086
- expect(response.nextFieldId).toBeGreaterThanOrEqual(1);
4087
- expect(response.defaultSortFieldId).toBeGreaterThanOrEqual(0);
4088
- expect(response.keyFieldId).toBeGreaterThanOrEqual(1);
4089
- expect(response.sizeLimit).toMatch(/^\d+\sMB$/); // e.g., "500 MB"
4090
- expect(response.spaceUsed).toMatch(/^\d+\s(KB|MB)$/); // e.g., "0 KB"
4091
- expect(response.spaceRemaining).toMatch(/^\d+\sMB$/); // e.g., "500 MB"
4092
-
4093
- console.log("Real API response:", response);
4094
-
4095
- // Cleanup: Delete the table to avoid clutter
4096
- const deleteResponse = await client.deleteTable({
4097
- tableId: response.id,
4098
- appId,
4099
- });
4100
- expect(deleteResponse.deletedTableId).toBe(response.id);
4101
- console.log("Cleanup - Deleted table:", deleteResponse);
4102
- }
4103
- );
4104
- - name: >-
4105
- deleteTable.test.ts
4106
- type: >-
4107
- file
4108
- contents: >
4109
- import
4110
- {
4111
- test,
4112
- expect
4113
- }
4114
- from
4115
- "vitest";
4116
-
4117
- import
4118
- {
4119
- quickbase
4120
- }
4121
- from
4122
- "../../../../src/quickbaseClient";
4123
-
4124
-
4125
- test(
4126
- "QuickbaseClient Integration - deleteTable > deletes a table in QuickBase",
4127
- { timeout: 20000 },
4128
- async () => {
4129
- const config = {
4130
- realm: process.env.QB_REALM || "",
4131
- userToken: process.env.QB_USER_TOKEN || "",
4132
- debug: true,
4133
- };
4134
- const client = quickbase(config);
4135
- const appId = "buwai2zpe";
4136
-
4137
- // Step 1: Create a temporary table to delete
4138
- const tableName = `DeleteTest_${Date.now()}`;
4139
- const createBody = {
4140
- name: tableName,
4141
- description: "Temporary table for delete test",
4142
- singleRecordName: "DeleteTest",
4143
- pluralRecordName: "DeleteTests",
4144
- };
4145
- console.log("Creating temporary table with:", createBody);
4146
- const createResponse = await client.createTable({
4147
- appId,
4148
- body: createBody,
4149
- });
4150
- expect(createResponse.id).toBeDefined();
4151
- expect(createResponse.name).toBe(tableName);
4152
- console.log("Created table:", createResponse);
4153
- const tableId = createResponse.id;
4154
-
4155
- // Step 2: Delete the table
4156
- console.log("Deleting table:", { tableId, appId });
4157
- const deleteResponse = await client.deleteTable({ tableId, appId });
4158
- expect(deleteResponse).toBeDefined();
4159
- expect(deleteResponse.deletedTableId).toBe(tableId);
4160
- console.log("Delete API response:", deleteResponse);
4161
-
4162
- // Step 3: Verify the table is gone
4163
- try {
4164
- await client.getTable({ tableId, appId });
4165
- throw new Error("Table should not exist after deletion");
4166
- } catch (error) {
4167
- expect(error.message).toMatch(/404|not found/i); // Expect a 404 error
4168
- console.log("Verified table deletion:", error.message);
4169
- }
4170
- }
4171
- );
4172
- - name: >-
4173
- getAppTables.test.ts
4174
- type: >-
4175
- file
4176
- contents: >
4177
- import
4178
- {
4179
- test,
4180
- expect
4181
- }
4182
- from
4183
- "vitest";
4184
-
4185
- import
4186
- {
4187
- quickbase
4188
- }
4189
- from
4190
- "../../../../src/quickbaseClient";
4191
-
4192
-
4193
- test(
4194
- "QuickbaseClient Integration - getAppTables > fetches real table data from QuickBase",
4195
- { timeout: 10000 },
4196
- async () => {
4197
- const config = {
4198
- realm: process.env.QB_REALM || "",
4199
- userToken: process.env.QB_USER_TOKEN || "",
4200
- debug: true,
4201
- };
4202
- const client = quickbase(config);
4203
- const tablesAppId = "buwai2zpe";
4204
-
4205
- console.log("Config used:", config);
4206
- const result = await client.getAppTables({ appId: tablesAppId });
4207
- console.log("Real API response:", result);
4208
-
4209
- expect(result).toBeDefined();
4210
- expect(result).toBeInstanceOf(Array);
4211
- expect(result.length).toBeGreaterThan(0);
4212
- expect(result).toEqual(
4213
- expect.arrayContaining([
4214
- expect.objectContaining({
4215
- id: "buwai2zr4",
4216
- alias: "_DBID_ROOT",
4217
- name: expect.any(String), // Allow dynamic name due to updateTable
4218
- description: expect.any(String), // Allow dynamic description
4219
- created: expect.any(Date),
4220
- updated: expect.any(Date), // Allow varying timestamps
4221
- nextRecordId: expect.any(Number),
4222
- nextFieldId: expect.any(Number),
4223
- defaultSortFieldId: expect.any(Number),
4224
- defaultSortOrder: "DESC",
4225
- keyFieldId: expect.any(Number),
4226
- singleRecordName: "Root",
4227
- pluralRecordName: "Roots",
4228
- sizeLimit: "500 MB",
4229
- spaceUsed: expect.any(String),
4230
- spaceRemaining: "500 MB",
4231
- }),
4232
- ])
4233
- );
4234
- }
4235
- );
4236
- - name: >-
4237
- getRelationships.test.ts
4238
- type: >-
4239
- file
4240
- contents: >
4241
- //
4242
- tests/vitest/qb/tables/getRelationships.test.ts
4243
-
4244
- import
4245
- {
4246
- describe,
4247
- test,
4248
- expect
4249
- }
4250
- from
4251
- "vitest";
4252
-
4253
- import
4254
- {
4255
- quickbase
4256
- }
4257
- from
4258
- "/home/drew/Projects/quickbase-js/src/quickbaseClient.ts";
4259
-
4260
- import
4261
- {
4262
- QB_TABLE_ID_1
4263
- }
4264
- from
4265
- "/home/drew/Projects/quickbase-js/tests/setup.ts";
4266
-
4267
- import
4268
- {
4269
- GetRelationships200Response
4270
- }
4271
- from
4272
- "/home/drew/Projects/quickbase-js/src/generated/models";
4273
-
4274
-
4275
- describe("QuickbaseClient
4276
- Integration
4277
- -
4278
- getRelationships",
4279
- ()
4280
- =>
4281
- {
4282
- const qb = quickbase({
4283
- realm: process.env.QB_REALM || "builderprogram-dbradford6815",
4284
- userToken: process.env.QB_USER_TOKEN || "",
4285
- debug: true,
4286
- });
4287
-
4288
- test("fetches real relationships from QuickBase", async () => {
4289
- // Ensure environment variables are set
4290
- if (!process.env.QB_REALM)
4291
- throw new Error("QB_REALM is not defined in .env");
4292
- if (!process.env.QB_USER_TOKEN)
4293
- throw new Error("QB_USER_TOKEN is not defined in .env");
4294
-
4295
- console.log("Config used:", {
4296
- realm: process.env.QB_REALM,
4297
- userToken: process.env.QB_USER_TOKEN,
4298
- tableId: QB_TABLE_ID_1,
4299
- });
4300
-
4301
- const response: GetRelationships200Response = await qb.getRelationships({
4302
- tableId: QB_TABLE_ID_1, // Query relationships for QB_TABLE_ID_1 (e.g., "buwai2zws")
4303
- skip: 0,
4304
- });
4305
-
4306
- console.log("Real API response:", JSON.stringify(response, null, 2));
4307
-
4308
- // Basic structure validation
4309
- expect(response).toBeDefined();
4310
- expect(response.metadata).toBeDefined();
4311
- expect(response.metadata).toHaveProperty(
4312
- "numRelationships",
4313
- expect.any(Number)
4314
- );
4315
- expect(response.metadata).toHaveProperty("skip", 0);
4316
- expect(response.metadata).toHaveProperty(
4317
- "totalRelationships",
4318
- expect.any(Number)
4319
- );
4320
- expect(response.relationships).toBeDefined();
4321
- expect(Array.isArray(response.relationships)).toBe(true);
4322
-
4323
- // If relationships exist, validate the first one
4324
- if (response.relationships.length > 0) {
4325
- const relationship = response.relationships[0];
4326
- expect(relationship).toHaveProperty("id", expect.any(Number));
4327
- expect(relationship).toHaveProperty("parentTableId", expect.any(String));
4328
- expect(relationship).toHaveProperty("childTableId", QB_TABLE_ID_1);
4329
- expect(relationship).toHaveProperty("foreignKeyField");
4330
- expect(relationship.foreignKeyField).toHaveProperty(
4331
- "id",
4332
- expect.any(Number)
4333
- );
4334
- expect(relationship.foreignKeyField).toHaveProperty(
4335
- "label",
4336
- expect.any(String)
4337
- );
4338
- expect(relationship.foreignKeyField).toHaveProperty(
4339
- "type",
4340
- expect.any(String)
4341
- );
4342
- expect(relationship).toHaveProperty("isCrossApp", expect.any(Boolean));
4343
- expect(relationship).toHaveProperty("lookupFields", expect.any(Array));
4344
-
4345
- // summaryFields is optional; only validate if present
4346
- if (
4347
- "summaryFields" in relationship &&
4348
- relationship.summaryFields !== undefined
4349
- ) {
4350
- expect(Array.isArray(relationship.summaryFields)).toBe(true);
4351
- }
4352
- }
4353
- }, 10000); // Timeout as second argument
4354
- });
4355
- - name: >-
4356
- getTable.test.ts
4357
- type: >-
4358
- file
4359
- contents: >
4360
- import
4361
- {
4362
- test,
4363
- expect
4364
- }
4365
- from
4366
- "vitest";
4367
-
4368
- import
4369
- {
4370
- quickbase
4371
- }
4372
- from
4373
- "../../../../src/quickbaseClient";
4374
-
4375
-
4376
- test(
4377
- "QuickbaseClient Integration - getTable > fetches real table data from QuickBase",
4378
- { timeout: 10000 },
4379
- async () => {
4380
- const config = {
4381
- realm: process.env.QB_REALM || "",
4382
- userToken: process.env.QB_USER_TOKEN || "",
4383
- debug: true,
4384
- };
4385
- const client = quickbase(config);
4386
- const tableId = "buwai2zr4";
4387
- const appId = "buwai2zpe";
4388
-
4389
- console.log("Config used:", config);
4390
- const response = await client.getTable({ tableId, appId });
4391
- expect(response).toBeDefined();
4392
- expect(response.id).toBe(tableId);
4393
- expect(response.name).toBe("Root"); // Expect original name
4394
- expect(response.alias).toBe("_DBID_ROOT");
4395
- expect(response.created).toBeInstanceOf(Date);
4396
- console.log("Real API response:", response);
4397
- }
4398
- );
4399
- - name: >-
4400
- updateRelationship.test.ts
4401
- type: >-
4402
- file
4403
- contents: >
4404
- //
4405
- tests/vitest/qb/tables/updateRelationship.test.ts
4406
-
4407
-
4408
- import
4409
- {
4410
- describe,
4411
- it,
4412
- expect,
4413
- beforeAll,
4414
- afterAll,
4415
- beforeEach
4416
- }
4417
- from
4418
- "vitest";
4419
-
4420
- import
4421
- {
4422
- createClient,
4423
- QB_REALM,
4424
- QB_USER_TOKEN,
4425
- QB_TABLE_ID_1,
4426
- QB_TABLE_ID_2,
4427
- }
4428
- from
4429
- "@tests/setup.ts";
4430
-
4431
- import
4432
- {
4433
- UpdateRelationshipRequest,
4434
- CreateFieldRequest,
4435
- }
4436
- from
4437
- "@/generated/models";
4438
-
4439
-
4440
- describe("QuickbaseClient
4441
- Integration
4442
- -
4443
- updateRelationship",
4444
- ()
4445
- =>
4446
- {
4447
- let client: ReturnType<typeof createClient>;
4448
- let relationshipId: number;
4449
- let newLookupFieldId: number;
4450
- let newChildFieldId: number;
4451
-
4452
- beforeAll(async () => {
4453
- client = createClient(fetch, {
4454
- realm: QB_REALM,
4455
- userToken: QB_USER_TOKEN,
4456
- debug: true,
4457
- });
4458
-
4459
- if (!QB_REALM) throw new Error("QB_REALM is not defined in .env");
4460
- if (!QB_USER_TOKEN) throw new Error("QB_USER_TOKEN is not defined in .env");
4461
-
4462
- // Fetch relationship ID
4463
- const relationshipsResponse = await client.getRelationships({
4464
- tableId: QB_TABLE_ID_2,
4465
- skip: 0,
4466
- });
4467
-
4468
- const relationship = relationshipsResponse.relationships.find(
4469
- (r) => r.parentTableId === QB_TABLE_ID_1
4470
- );
4471
- if (!relationship) {
4472
- throw new Error(
4473
- `No relationship found between parent ${QB_TABLE_ID_1} and child ${QB_TABLE_ID_2}`
4474
- );
4475
- }
4476
- relationshipId = relationship.id;
4477
-
4478
- // Create fields
4479
- const lookupFieldRequest: CreateFieldRequest = {
4480
- label: "Test Lookup Field",
4481
- fieldType: "text",
4482
- };
4483
- const lookupResponse = await client.createField({
4484
- tableId: QB_TABLE_ID_1,
4485
- body: lookupFieldRequest,
4486
- });
4487
- newLookupFieldId = lookupResponse.id;
4488
-
4489
- const childFieldRequest: CreateFieldRequest = {
4490
- label: "Test Child Numeric",
4491
- fieldType: "numeric",
4492
- };
4493
- const childResponse = await client.createField({
4494
- tableId: QB_TABLE_ID_2,
4495
- body: childFieldRequest,
4496
- });
4497
- newChildFieldId = childResponse.id;
4498
-
4499
- console.log(
4500
- `Created lookup field ${newLookupFieldId} in parent ${QB_TABLE_ID_1}`
4501
- );
4502
- console.log(
4503
- `Created child field ${newChildFieldId} in child ${QB_TABLE_ID_2}`
4504
- );
4505
- console.log(
4506
- `Using relationshipId: ${relationshipId} from child ${QB_TABLE_ID_2} to parent ${QB_TABLE_ID_1}`
4507
- );
4508
- }, 30000);
4509
-
4510
- afterAll(async () => {
4511
- if (newLookupFieldId) {
4512
- await client.deleteFields({
4513
- tableId: QB_TABLE_ID_1,
4514
- body: { fieldIds: [newLookupFieldId] },
4515
- });
4516
- console.log(`Deleted field ${newLookupFieldId} from ${QB_TABLE_ID_1}`);
4517
- }
4518
- if (newChildFieldId) {
4519
- await client.deleteFields({
4520
- tableId: QB_TABLE_ID_2,
4521
- body: { fieldIds: [newChildFieldId] },
4522
- });
4523
- console.log(`Deleted field ${newChildFieldId} from ${QB_TABLE_ID_2}`);
4524
- }
4525
- }, 30000);
4526
-
4527
- beforeEach(async () => {
4528
- // Reset relationship to a clean state before each test
4529
- const relationshipsResponse = await client.getRelationships({
4530
- tableId: QB_TABLE_ID_2,
4531
- });
4532
- const relationship = relationshipsResponse.relationships.find(
4533
- (r) => r.id === relationshipId
4534
- );
4535
- const cleanupRequest: UpdateRelationshipRequest = {
4536
- lookupFieldIds: (relationship?.lookupFields || [])
4537
- .map((f) => f.id)
4538
- .filter((id) => id !== newLookupFieldId),
4539
- summaryFields: (relationship?.summaryFields || []).map((f) => ({
4540
- summaryFid: f.id,
4541
- label: f.label,
4542
- accumulationType: "COUNT", // Assuming COUNT for existing fields; adjust if needed
4543
- })),
4544
- };
4545
- await client.updateRelationship({
4546
- tableId: QB_TABLE_ID_2,
4547
- relationshipId,
4548
- body: cleanupRequest,
4549
- });
4550
- console.log(`Reset relationship ${relationshipId} before test`);
4551
- });
4552
-
4553
- it(
4554
- "adds a lookup field to the relationship",
4555
- async ({ expect }) => {
4556
- const tableId = QB_TABLE_ID_2;
4557
-
4558
- // Get current state
4559
- const initialResponse = await client.getRelationships({ tableId });
4560
- const initialRelationship = initialResponse.relationships.find(
4561
- (r) => r.id === relationshipId
4562
- );
4563
- const currentLookupFields = (initialRelationship?.lookupFields || []).map(
4564
- (f) => f.id
4565
- );
4566
-
4567
- const request: UpdateRelationshipRequest = {
4568
- lookupFieldIds: [...currentLookupFields, newLookupFieldId],
4569
- };
4570
-
4571
- const updateResponse = await client.updateRelationship({
4572
- tableId,
4573
- relationshipId,
4574
- body: request,
4575
- });
4576
-
4577
- expect(updateResponse.id).toBe(relationshipId);
4578
- expect(updateResponse.childTableId).toBe(QB_TABLE_ID_2);
4579
- expect(updateResponse.parentTableId).toBe(QB_TABLE_ID_1);
4580
- expect(
4581
- updateResponse.lookupFields.some((f) => f.id === newLookupFieldId)
4582
- ).toBe(true);
4583
-
4584
- const relationshipsResponse = await client.getRelationships({ tableId });
4585
- const updatedRelationship = relationshipsResponse.relationships.find(
4586
- (r) => r.id === relationshipId
4587
- );
4588
- expect(
4589
- updatedRelationship!.lookupFields.some((f) => f.id === newLookupFieldId)
4590
- ).toBe(true);
4591
- },
4592
- { timeout: 30000 }
4593
- );
4594
-
4595
- it(
4596
- "adds a summary field to the parent table",
4597
- async ({ expect }) => {
4598
- const tableId = QB_TABLE_ID_2;
4599
-
4600
- // Get current state
4601
- const initialResponse = await client.getRelationships({ tableId });
4602
- const initialRelationship = initialResponse.relationships.find(
4603
- (r) => r.id === relationshipId
4604
- );
4605
- const currentSummaryFields = (
4606
- initialRelationship?.summaryFields || []
4607
- ).map((f) => ({
4608
- summaryFid: f.id,
4609
- label: f.label,
4610
- accumulationType: "COUNT",
4611
- }));
4612
-
4613
- const request: UpdateRelationshipRequest = {
4614
- summaryFields: [
4615
- ...currentSummaryFields,
4616
- {
4617
- summaryFid: newChildFieldId,
4618
- label: "Test Summary Field",
4619
- accumulationType: "SUM",
4620
- },
4621
- ],
4622
- };
4623
-
4624
- const updateResponse = await client.updateRelationship({
4625
- tableId,
4626
- relationshipId,
4627
- body: request,
4628
- });
4629
-
4630
- expect(updateResponse.id).toBe(relationshipId);
4631
- expect(updateResponse.childTableId).toBe(QB_TABLE_ID_2);
4632
- expect(updateResponse.parentTableId).toBe(QB_TABLE_ID_1);
4633
- expect(
4634
- updateResponse.summaryFields.some(
4635
- (f) => f.label === "Test Summary Field"
4636
- )
4637
- ).toBe(true);
4638
-
4639
- const relationshipsResponse = await client.getRelationships({ tableId });
4640
- const updatedRelationship = relationshipsResponse.relationships.find(
4641
- (r) => r.id === relationshipId
4642
- );
4643
- expect(
4644
- updatedRelationship!.summaryFields.some(
4645
- (f) => f.label === "Test Summary Field"
4646
- )
4647
- ).toBe(true);
4648
- },
4649
- { timeout: 30000 }
4650
- );
4651
-
4652
- it(
4653
- "handles an invalid field ID gracefully",
4654
- async ({ expect }) => {
4655
- const tableId = QB_TABLE_ID_2;
4656
-
4657
- const request: UpdateRelationshipRequest = {
4658
- lookupFieldIds: [999999], // Invalid ID
4659
- };
4660
-
4661
- await expect(
4662
- client.updateRelationship({
4663
- tableId,
4664
- relationshipId,
4665
- body: request,
4666
- })
4667
- ).rejects.toThrow(/API Error:.*400/);
4668
- },
4669
- { timeout: 30000 }
4670
- );
4671
-
4672
- it(
4673
- "succeeds with no changes (idempotent)",
4674
- async ({ expect }) => {
4675
- const tableId = QB_TABLE_ID_2;
4676
-
4677
- // Get current state
4678
- const initialResponse = await client.getRelationships({ tableId });
4679
- const initialRelationship = initialResponse.relationships.find(
4680
- (r) => r.id === relationshipId
4681
- );
4682
- const currentLookupFields = (initialRelationship?.lookupFields || []).map(
4683
- (f) => f.id
4684
- );
4685
- const currentSummaryFields = (
4686
- initialRelationship?.summaryFields || []
4687
- ).map((f) => ({
4688
- summaryFid: f.id,
4689
- label: f.label,
4690
- accumulationType: "COUNT",
4691
- }));
4692
-
4693
- const request: UpdateRelationshipRequest = {
4694
- lookupFieldIds: currentLookupFields,
4695
- summaryFields: currentSummaryFields,
4696
- };
4697
-
4698
- const updateResponse = await client.updateRelationship({
4699
- tableId,
4700
- relationshipId,
4701
- body: request,
4702
- });
4703
-
4704
- expect(updateResponse.id).toBe(relationshipId);
4705
- expect(updateResponse.childTableId).toBe(QB_TABLE_ID_2);
4706
- expect(updateResponse.parentTableId).toBe(QB_TABLE_ID_1);
4707
- expect(updateResponse.lookupFields.map((f) => f.id)).toEqual(
4708
- currentLookupFields
4709
- );
4710
- expect(updateResponse.summaryFields?.map((f) => f.id) || []).toEqual(
4711
- currentSummaryFields.map((f) => f.summaryFid)
4712
- );
4713
- },
4714
- { timeout: 30000 }
4715
- );
4716
- });
4717
- - name: >-
4718
- updateTable.test.ts
4719
- type: >-
4720
- file
4721
- contents: >
4722
- import
4723
- {
4724
- test,
4725
- expect
4726
- }
4727
- from
4728
- "vitest";
4729
-
4730
- import
4731
- {
4732
- quickbase
4733
- }
4734
- from
4735
- "../../../../src/quickbaseClient";
4736
-
4737
-
4738
- test(
4739
- "QuickbaseClient Integration - updateTable > updates real table data in QuickBase",
4740
- { timeout: 10000 },
4741
- async () => {
4742
- const config = {
4743
- realm: process.env.QB_REALM || "",
4744
- userToken: process.env.QB_USER_TOKEN || "",
4745
- debug: true,
4746
- };
4747
- const client = quickbase(config);
4748
- const appId = "buwai2zpe";
4749
- const tableId = "buwai2zr4";
4750
- const updatedBody = {
4751
- name: "Root Updated " + Date.now(),
4752
- description: "Integration test update",
4753
- };
4754
- const originalBody = {
4755
- name: "Root",
4756
- description: "",
4757
- };
4758
-
4759
- console.log("Config used:", config);
4760
- // Update the table
4761
- const response = await client.updateTable({
4762
- tableId,
4763
- appId,
4764
- body: updatedBody,
4765
- });
4766
- expect(response).toBeDefined();
4767
- expect(response.id).toBe(tableId);
4768
- expect(response.name).toBe(updatedBody.name);
4769
- expect(response.description).toBe(updatedBody.description);
4770
- console.log("Real API response:", response);
4771
-
4772
- // Cleanup: Revert the table to original state
4773
- const cleanupResponse = await client.updateTable({
4774
- tableId,
4775
- appId,
4776
- body: originalBody,
4777
- });
4778
- expect(cleanupResponse.name).toBe(originalBody.name);
4779
- expect(cleanupResponse.description).toBe(originalBody.description);
4780
- console.log("Cleanup API response:", cleanupResponse);
4781
- }
4782
- );
4783
- - name: >-
4784
- unit
4785
- type: >-
4786
- directory
4787
- children:
4788
- - name: >-
4789
- apps
4790
- type: >-
4791
- directory
4792
- children:
4793
- - name: >-
4794
- copyApp.test.ts
4795
- type: >-
4796
- file
4797
- - name: >-
4798
- createApp.test.ts
4799
- type: >-
4800
- file
4801
- - name: >-
4802
- deleteApp.test.ts
4803
- type: >-
4804
- file
4805
- - name: >-
4806
- getApp.test.ts
4807
- type: >-
4808
- file
4809
- - name: >-
4810
- getAppEvents.test.ts
4811
- type: >-
4812
- file
4813
- - name: >-
4814
- updateApp.test.ts
4815
- type: >-
4816
- file
4817
- - name: >-
4818
- auth
4819
- type: >-
4820
- directory
4821
- children:
4822
- - name: >-
4823
- fetchTempToken401.test.ts
4824
- type: >-
4825
- file
4826
- - name: >-
4827
- getTempToken.test.ts
4828
- type: >-
4829
- file
4830
- - name: >-
4831
- retryTempToken401.test.ts
4832
- type: >-
4833
- file
4834
- - name: >-
4835
- retryTempTokenTwo401.test.ts
4836
- type: >-
4837
- file
4838
- - name: >-
4839
- retryUserToken401.test.ts
4840
- type: >-
4841
- file
4842
- - name: >-
4843
- fields
4844
- type: >-
4845
- directory
4846
- children:
4847
- - name: >-
4848
- createField.test.ts
4849
- type: >-
4850
- file
4851
- - name: >-
4852
- deleteFields.test.ts
4853
- type: >-
4854
- file
4855
- - name: >-
4856
- getField.test.ts
4857
- type: >-
4858
- file
4859
- - name: >-
4860
- getFieldUsage.test.ts
4861
- type: >-
4862
- file
4863
- - name: >-
4864
- getFields.test.ts
4865
- type: >-
4866
- file
4867
- - name: >-
4868
- getFieldsUsage.test.ts
4869
- type: >-
4870
- file
4871
- - name: >-
4872
- updateField.test.ts
4873
- type: >-
4874
- file
4875
- - name: >-
4876
- index.ts
4877
- type: >-
4878
- file
4879
- - name: >-
4880
- rateLimit.test.ts
4881
- type: >-
4882
- file
4883
- - name: >-
4884
- records
4885
- type: >-
4886
- directory
4887
- children:
4888
- - name: >-
4889
- deleteRecords.test.ts
4890
- type: >-
4891
- file
4892
- - name: >-
4893
- runQuery.test.ts
4894
- type: >-
4895
- file
4896
- - name: >-
4897
- upsert.test.ts
4898
- type: >-
4899
- file
4900
- - name: >-
4901
- tables
4902
- type: >-
4903
- directory
4904
- children:
4905
- - name: >-
4906
- createTable.test.ts
4907
- type: >-
4908
- file
4909
- - name: >-
4910
- deleteTable.test.ts
4911
- type: >-
4912
- file
4913
- - name: >-
4914
- getAppTables.test.ts
4915
- type: >-
4916
- file
4917
- - name: >-
4918
- getRelationships.test.ts
4919
- type: >-
4920
- file
4921
- - name: >-
4922
- getTable.test.ts
4923
- type: >-
4924
- file
4925
- - name: >-
4926
- updateRelationship.test.ts
4927
- type: >-
4928
- file
4929
- - name: >-
4930
- updateTable.test.ts
4931
- type: >-
4932
- file
4933
- - name: >-
4934
- tokenLifespan.test.ts
4935
- type: >-
4936
- file
4937
- - name: >-
4938
- umd.test.ts
4939
- type: >-
4940
- file
4941
- - name: >-
4942
- text.txt
4943
- type: >-
4944
- file
4945
- - name: >-
4946
- tools
4947
- type: >-
4948
- directory
4949
- children:
4950
- - name: >-
4951
- log-gen.ts
4952
- type: >-
4953
- file
4954
- - name: >-
4955
- log-gen.yaml
4956
- type: >-
4957
- file
4958
- - name: >-
4959
- openapi-jars
4960
- type: >-
4961
- directory
4962
- children:
4963
- - name: >-
4964
- openapi-generator-cli-7.12.0.jar
4965
- type: >-
4966
- file
4967
- - name: >-
4968
- tsconfig.build.json
4969
- type: >-
4970
- file
4971
- - name: >-
4972
- tsconfig.json
4973
- type: >-
4974
- file
4975
- - name: >-
4976
- versionrc.json
4977
- type: >-
4978
- file
4979
- - name: >-
4980
- vitest.config.ts
4981
- type: >-
4982
- file