quickbase-js 0.1.0-beta.13 → 0.1.0-beta.14

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 (167) hide show
  1. package/README.md +1 -1
  2. package/dist/esm/quickbase.d.ts +2 -1
  3. package/package.json +9 -4
  4. package/CHANGELOG.md +0 -239
  5. package/build-common.js +0 -131
  6. package/build-esm.js +0 -71
  7. package/build-umd.js +0 -69
  8. package/docs/.vitepress/cache/deps/@theme_index.js +0 -275
  9. package/docs/.vitepress/cache/deps/@theme_index.js.map +0 -7
  10. package/docs/.vitepress/cache/deps/_metadata.json +0 -40
  11. package/docs/.vitepress/cache/deps/chunk-5A67QEFC.js +0 -12542
  12. package/docs/.vitepress/cache/deps/chunk-5A67QEFC.js.map +0 -7
  13. package/docs/.vitepress/cache/deps/chunk-7D4P4MMP.js +0 -9719
  14. package/docs/.vitepress/cache/deps/chunk-7D4P4MMP.js.map +0 -7
  15. package/docs/.vitepress/cache/deps/package.json +0 -3
  16. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js +0 -4504
  17. package/docs/.vitepress/cache/deps/vitepress___@vue_devtools-api.js.map +0 -7
  18. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js +0 -583
  19. package/docs/.vitepress/cache/deps/vitepress___@vueuse_core.js.map +0 -7
  20. package/docs/.vitepress/cache/deps/vue.js +0 -343
  21. package/docs/.vitepress/cache/deps/vue.js.map +0 -7
  22. package/docs/.vitepress/config.mts +0 -26
  23. package/docs/api-examples.md +0 -49
  24. package/docs/index.md +0 -59
  25. package/docs/markdown-examples.md +0 -85
  26. package/docs-data/api-docs.json +0 -4143
  27. package/examples/quicbase-jsCDN.html +0 -36
  28. package/examples/react.js +0 -48
  29. package/examples/vanillajs.html +0 -47
  30. package/index.md +0 -25
  31. package/open-api/fix-spec-main.ts +0 -133
  32. package/open-api/generate-unified-interface.ts +0 -104
  33. package/open-api/generateDocsJson.ts +0 -24
  34. package/open-api/output/quickbase-fixed.json +0 -11191
  35. package/open-api/post-process-generated.ts +0 -226
  36. package/open-api/regenerate-client.ts +0 -117
  37. package/open-api/schema/enhance-general.ts +0 -111
  38. package/open-api/schema/fix-arrays.ts +0 -68
  39. package/open-api/schema/tags/apps.ts +0 -90
  40. package/open-api/schema/tags/fields.ts +0 -471
  41. package/open-api/schema/tags/groups.ts +0 -51
  42. package/open-api/schema/tags/index.ts +0 -66
  43. package/open-api/schema/tags/records.ts +0 -115
  44. package/open-api/schema/tags/tables.ts +0 -211
  45. package/open-api/schema/tags/users.ts +0 -47
  46. package/open-api/types/spec.ts +0 -42
  47. package/open-api/utils/common.ts +0 -29
  48. package/open-api/utils/generateJsDoc.ts +0 -74
  49. package/open-api/utils/infer-schema.ts +0 -40
  50. package/open-api/utils/naming.ts +0 -10
  51. package/open-api/utils/sharedUtils.ts +0 -352
  52. package/playwright.config.ts +0 -37
  53. package/rollup.config.js +0 -114
  54. package/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +0 -46878
  55. package/specs/split/apps.json +0 -1315
  56. package/specs/split/auth.json +0 -191
  57. package/specs/split/fields.json +0 -3869
  58. package/specs/split/records.json +0 -754
  59. package/specs/split/reports.json +0 -619
  60. package/specs/split/tables.json +0 -1605
  61. package/src/BurstAwareThrottleBucket.ts +0 -57
  62. package/src/FlowThrottleBucket.ts +0 -47
  63. package/src/RateLimitError.ts +0 -12
  64. package/src/RateThrottleBucket.ts +0 -5
  65. package/src/Semaphore.ts +0 -33
  66. package/src/authorizationStrategy.ts +0 -321
  67. package/src/generated-unified/QuickbaseClient.ts +0 -1135
  68. package/src/generated-unified/missing-types-report.json +0 -3
  69. package/src/index.ts +0 -1
  70. package/src/invokeMethod.ts +0 -290
  71. package/src/pagination.ts +0 -429
  72. package/src/quickbaseClient.ts +0 -227
  73. package/src/rateLimiter.ts +0 -30
  74. package/src/tokenCache.ts +0 -39
  75. package/src/utils.ts +0 -50
  76. package/tests/playwright/qb/auth/cacheSwitching.test.ts +0 -159
  77. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +0 -219
  78. package/tests/playwright/qb/auth/getAppWithTempToken.test.ts +0 -162
  79. package/tests/playwright/qb/auth/getAppWithTempTokenConcurrency.test.ts +0 -208
  80. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +0 -153
  81. package/tests/playwright/qb/auth/getTempToken.test.ts +0 -152
  82. package/tests/playwright/qb/auth/tempTokenPrefetch.test.ts +0 -179
  83. package/tests/playwright/qb/auth/tempTokenRenewal.test.ts +0 -133
  84. package/tests/setup.ts +0 -53
  85. package/tests/vitest/qb/apps/copyApp.test.ts +0 -76
  86. package/tests/vitest/qb/apps/createApp.test.ts +0 -64
  87. package/tests/vitest/qb/apps/deleteApp.test.ts +0 -76
  88. package/tests/vitest/qb/apps/getApp.test.ts +0 -44
  89. package/tests/vitest/qb/apps/getAppEvents.test.ts +0 -67
  90. package/tests/vitest/qb/apps/updateApp.test.ts +0 -58
  91. package/tests/vitest/qb/auth/mockQuickbaseServer.ts +0 -60
  92. package/tests/vitest/qb/auth/retryUserToken401.test.ts +0 -73
  93. package/tests/vitest/qb/auth/ssoTokenConcurrency.test.ts +0 -68
  94. package/tests/vitest/qb/auth/ssoTokenIntegrationWithServer.test.ts +0 -65
  95. package/tests/vitest/qb/auth/userTokenConcurrency.test.ts +0 -63
  96. package/tests/vitest/qb/fields/createField.test.ts +0 -77
  97. package/tests/vitest/qb/fields/deleteFields.test.ts +0 -83
  98. package/tests/vitest/qb/fields/getField.test.ts +0 -85
  99. package/tests/vitest/qb/fields/getFieldUsage.test.ts +0 -82
  100. package/tests/vitest/qb/fields/getFields.test.ts +0 -232
  101. package/tests/vitest/qb/fields/getFieldsUsage.test.ts +0 -77
  102. package/tests/vitest/qb/fields/updateField.test.ts +0 -93
  103. package/tests/vitest/qb/formulas/runFormula.test.ts +0 -96
  104. package/tests/vitest/qb/index.ts +0 -29
  105. package/tests/vitest/qb/quickbase-js/BurstAwareThrottleBucket.test.ts +0 -125
  106. package/tests/vitest/qb/quickbase-js/FlowBucket.test.ts +0 -77
  107. package/tests/vitest/qb/quickbase-js/paginationSkip.test.ts +0 -111
  108. package/tests/vitest/qb/records/deleteRecords.test.ts +0 -110
  109. package/tests/vitest/qb/records/runQuery.test.ts +0 -145
  110. package/tests/vitest/qb/records/upsert.test.ts +0 -102
  111. package/tests/vitest/qb/tables/createRelationship.test.ts +0 -102
  112. package/tests/vitest/qb/tables/createTable.test.ts +0 -55
  113. package/tests/vitest/qb/tables/deleteRelationship.test.ts +0 -143
  114. package/tests/vitest/qb/tables/deleteTable.test.ts +0 -50
  115. package/tests/vitest/qb/tables/getAppTables.test.ts +0 -46
  116. package/tests/vitest/qb/tables/getRelationships.test.ts +0 -80
  117. package/tests/vitest/qb/tables/getTable.test.ts +0 -26
  118. package/tests/vitest/qb/tables/updateRelationship.test.ts +0 -250
  119. package/tests/vitest/qb/tables/updateTable.test.ts +0 -48
  120. package/tests/vitest/unit/apps/copyApp.test.ts +0 -581
  121. package/tests/vitest/unit/apps/createApp.test.ts +0 -186
  122. package/tests/vitest/unit/apps/deleteApp.test.ts +0 -216
  123. package/tests/vitest/unit/apps/getApp.test.ts +0 -128
  124. package/tests/vitest/unit/apps/getAppConcurrency.test.ts +0 -151
  125. package/tests/vitest/unit/apps/getAppEvents.test.ts +0 -193
  126. package/tests/vitest/unit/apps/updateApp.test.ts +0 -412
  127. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +0 -81
  128. package/tests/vitest/unit/auth/getTempToken.test.ts +0 -119
  129. package/tests/vitest/unit/auth/retryTempToken401.test.ts +0 -95
  130. package/tests/vitest/unit/auth/retryTempTokenMaxRetries.test.ts +0 -206
  131. package/tests/vitest/unit/auth/retryUserToken401.test.ts +0 -66
  132. package/tests/vitest/unit/auth/ssoTokenRefresh.test.ts +0 -325
  133. package/tests/vitest/unit/auth/userTokenConcurrency.test.ts +0 -62
  134. package/tests/vitest/unit/fields/createField.test.ts +0 -451
  135. package/tests/vitest/unit/fields/deleteFields.test.ts +0 -141
  136. package/tests/vitest/unit/fields/getField.test.ts +0 -189
  137. package/tests/vitest/unit/fields/getFieldUsage.test.ts +0 -180
  138. package/tests/vitest/unit/fields/getFields.test.ts +0 -122
  139. package/tests/vitest/unit/fields/getFieldsUsage.test.ts +0 -160
  140. package/tests/vitest/unit/fields/updateField.test.ts +0 -285
  141. package/tests/vitest/unit/formulas/runFormula.test.ts +0 -205
  142. package/tests/vitest/unit/index.ts +0 -34
  143. package/tests/vitest/unit/quickbase-js/BurstAwareThrottleBucket.test.ts +0 -108
  144. package/tests/vitest/unit/quickbase-js/FlowBucket.test.ts +0 -101
  145. package/tests/vitest/unit/quickbase-js/pagination.test.ts +0 -251
  146. package/tests/vitest/unit/quickbase-js/quickbaseClientHttpMethods.test.ts +0 -141
  147. package/tests/vitest/unit/quickbase-js/rateLimit.test.ts +0 -191
  148. package/tests/vitest/unit/quickbase-js/tokenLifespan.test.ts +0 -204
  149. package/tests/vitest/unit/records/deleteRecords.test.ts +0 -112
  150. package/tests/vitest/unit/records/runQuery.test.ts +0 -101
  151. package/tests/vitest/unit/records/upsert.test.ts +0 -234
  152. package/tests/vitest/unit/tables/createRelationship.test.ts +0 -212
  153. package/tests/vitest/unit/tables/createTable.test.ts +0 -70
  154. package/tests/vitest/unit/tables/deleteRelationship.test.ts +0 -97
  155. package/tests/vitest/unit/tables/deleteTable.test.ts +0 -77
  156. package/tests/vitest/unit/tables/getAppTables.test.ts +0 -85
  157. package/tests/vitest/unit/tables/getRelationships.test.ts +0 -259
  158. package/tests/vitest/unit/tables/getTable.test.ts +0 -233
  159. package/tests/vitest/unit/tables/updateRelationship.test.ts +0 -307
  160. package/tests/vitest/unit/tables/updateTable.test.ts +0 -80
  161. package/tools/log-gen.ts +0 -251
  162. package/tools/log-gen.yaml +0 -4829
  163. package/tools/openapi-jars/openapi-generator-cli-7.12.0.jar +0 -0
  164. package/tsconfig.build.json +0 -17
  165. package/tsconfig.json +0 -32
  166. package/versionrc.json +0 -9
  167. package/vitest.config.ts +0 -27
@@ -1,77 +0,0 @@
1
- // tests/vitest/qb/ThrottleBucket.test.ts
2
- import { describe, it, expect } from "vitest";
3
- import { quickbase } from "../../../../src/quickbaseClient";
4
-
5
- describe("QuickbaseClient with ConcurrentThrottleBucket Integration Tests", () => {
6
- it("handles concurrent API calls with burst and rate limiting in strict order", async () => {
7
- const mockFetch = async (
8
- url: string,
9
- options: RequestInit
10
- ): Promise<Response> => {
11
- await new Promise((resolve) => setTimeout(resolve, 500));
12
- return new Response(JSON.stringify({ id: "mock-app" }), {
13
- status: 200,
14
- headers: { "Content-Type": "application/json" },
15
- });
16
- };
17
-
18
- const qbClient = quickbase({
19
- realm: "test",
20
- userToken: "mock-token",
21
- throttle: { rate: 5, burst: 3 },
22
- fetchApi: mockFetch,
23
- debug: true,
24
- });
25
-
26
- const throttleTimes: number[] = [];
27
- const startTimes: number[] = new Array(6).fill(0);
28
- const completionTimes: number[] = [];
29
- const recordTime = async (index: number) => {
30
- const preThrottle = Date.now();
31
- throttleTimes[index] = preThrottle;
32
- await qbClient.getApp({
33
- appId: "mock-app-id",
34
- startTime: startTimes[index],
35
- });
36
- completionTimes[index] = Date.now();
37
- startTimes[index] = startTimes[index] || Date.now() - 500;
38
- };
39
-
40
- const startTime = Date.now();
41
- const promises = [];
42
- for (let i = 0; i < 6; i++) {
43
- promises.push(recordTime(i));
44
- await new Promise((resolve) => setTimeout(resolve, 1));
45
- }
46
- await Promise.all(promises);
47
-
48
- const relativeThrottleTimes = throttleTimes.map((t) => t - startTime);
49
- const relativeStartTimes = startTimes.map((t) => t - startTime);
50
- const durations = completionTimes.map((t) => t - startTime);
51
- const timings = completionTimes.map((t, i) => t - startTimes[i]);
52
-
53
- console.log("Relative Throttle Times:", relativeThrottleTimes);
54
- console.log("Relative Start Times (post-throttle):", relativeStartTimes);
55
- console.log("Durations (completion times):", durations);
56
- console.log("Timings (fetch durations):", timings);
57
- console.log("Total Duration:", Date.now() - startTime);
58
-
59
- const totalDuration = Date.now() - startTime;
60
- expect(totalDuration).toBeGreaterThanOrEqual(1000);
61
- expect(totalDuration).toBeLessThan(1200); // Adjusted back to ~1100ms
62
-
63
- expect(durations.length).toBe(6);
64
- expect(durations.slice(0, 3).every((d) => d >= 500 && d < 550)).toBe(true);
65
-
66
- // Sort durations to handle out-of-order completion
67
- const sortedDurations = [...durations].sort((a, b) => a - b);
68
- expect(sortedDurations[3]).toBeGreaterThanOrEqual(650);
69
- expect(sortedDurations[3]).toBeLessThan(750);
70
- expect(sortedDurations[4]).toBeGreaterThanOrEqual(850);
71
- expect(sortedDurations[4]).toBeLessThan(950);
72
- expect(sortedDurations[5]).toBeGreaterThanOrEqual(1050);
73
- expect(sortedDurations[5]).toBeLessThan(1150);
74
-
75
- expect(timings.every((t) => t >= 500 && t < 550)).toBe(true);
76
- });
77
- });
@@ -1,111 +0,0 @@
1
- import { describe, it, expect, beforeAll } from "vitest";
2
- import {
3
- createClient,
4
- QB_TABLE_ID_1,
5
- QB_REALM,
6
- QB_USER_TOKEN,
7
- } from "@tests/setup";
8
- import { QuickbaseClient } from "@/quickbaseClient";
9
- import {
10
- RunQueryRequest,
11
- RunQueryRequestOptions,
12
- RunQuery200Response,
13
- } from "@/generated/models";
14
-
15
- // Extend RunQueryRequestOptions to include sortBy (for reference, not used here)
16
- interface ExtendedRunQueryRequestOptions extends RunQueryRequestOptions {
17
- sortBy?: Array<{ fieldId: number; order: "ASC" | "DESC" }>;
18
- }
19
-
20
- describe("QuickbaseClient Integration - Pagination with Skip", () => {
21
- let qb: QuickbaseClient;
22
-
23
- beforeAll(() => {
24
- qb = createClient(undefined, {
25
- realm: QB_REALM,
26
- userToken: QB_USER_TOKEN,
27
- debug: true,
28
- autoPaginate: true, // Enable library's automatic pagination
29
- });
30
- console.log("[beforeAll] Client initialized");
31
- });
32
-
33
- it(
34
- "fetches full dataset with auto-pagination and heavy data",
35
- { timeout: 30000 }, // 30s for multiple calls
36
- async () => {
37
- const queryOptions: ExtendedRunQueryRequestOptions = {
38
- skip: 0, // Start at beginning, no top specified
39
- // sortBy removed to test without ordering
40
- };
41
-
42
- const queryRequest: RunQueryRequest = {
43
- from: QB_TABLE_ID_1,
44
- select: [3, 822, 823, 824, 825, 6], // FID 3 for Record ID
45
- options: queryOptions,
46
- };
47
-
48
- const startTime = Date.now();
49
- console.log(
50
- "[Test Start] Query request with auto-pagination:",
51
- queryRequest
52
- );
53
-
54
- try {
55
- const response = (await qb.runQuery({
56
- body: queryRequest,
57
- })) as RunQuery200Response & {
58
- data: Array<{ [key: string]: { value: any } }>;
59
- metadata: {
60
- totalRecords: number;
61
- numRecords: number;
62
- numFields: number;
63
- skip: number;
64
- top?: number;
65
- };
66
- };
67
-
68
- const duration = Date.now() - startTime;
69
- console.log(`[Test Complete] Response received in ${duration}ms`, {
70
- recordCount: response.data.length,
71
- totalRecords: response.metadata.totalRecords,
72
- defaultTop: response.metadata.top,
73
- });
74
-
75
- // Assertions
76
- expect(response.data).toBeDefined();
77
- expect(response.data.length).toBeGreaterThan(2429); // More than initial cap, confirming pagination
78
- expect(response.data.length).toEqual(response.metadata.totalRecords); // Full dataset fetched
79
- expect(response.metadata).toBeDefined();
80
- // Removed expect(response.metadata.totalRecords).toBe(5000)
81
- expect(response.metadata.totalRecords).toBeGreaterThanOrEqual(5000); // Flexible minimum, allows growth
82
- expect(response.metadata.numFields).toBe(6); // 6 fields with FID 3
83
- expect(response.metadata.skip).toBe(0); // Initial skip
84
-
85
- const sampleRecord = response.data[0];
86
- console.log("[Debug] Sample record:", sampleRecord);
87
- expect(sampleRecord["6"]?.value).toBeDefined();
88
- expect(typeof sampleRecord["6"]?.value).toBe("string");
89
- expect(sampleRecord["6"]?.value.length).toBeGreaterThan(9000); // ~10KB
90
- expect(sampleRecord["3"]?.value).toBeDefined(); // Check FID 3 exists
91
- expect(typeof sampleRecord["3"]?.value).toBe("number"); // Record ID is numeric
92
-
93
- // Check for duplicates using Record ID (FID 3)
94
- const recordIds = response.data.map(
95
- (record: { [key: string]: { value: any } }) => record["3"]?.value
96
- );
97
- const uniqueRecordIds = new Set(recordIds);
98
- expect(uniqueRecordIds.size).toEqual(response.data.length); // No duplicates
99
- expect(uniqueRecordIds.size).toEqual(response.metadata.totalRecords); // All records unique
100
-
101
- console.log(
102
- `[Integration Test] Fetched ${response.data.length} records in ${duration}ms, totalRecords: ${response.metadata.totalRecords}`
103
- );
104
- } catch (error) {
105
- const duration = Date.now() - startTime;
106
- console.error("[Test Error] Failed after", duration, "ms:", error);
107
- throw error;
108
- }
109
- }
110
- );
111
- });
@@ -1,110 +0,0 @@
1
- // tests/vitest/qb/records/deleteRecords.test.ts
2
- import { describe, test, expect, beforeEach, afterEach } from "vitest";
3
- import { quickbase } from "@/quickbaseClient.ts";
4
- import {
5
- Upsert200Response,
6
- Upsert207Response,
7
- } from "/home/drew/Projects/quickbase-js/src/generated/models";
8
-
9
- const TABLE_ID = "buwai2zws";
10
- const UNIQUE_FIELD_ID = 3; // Record ID field
11
- const MARKER_FIELD_ID = 6; // Text field for marking test records
12
-
13
- describe("QuickbaseClient - DeleteRecords Integration", () => {
14
- const qb = quickbase({
15
- realm: "builderprogram-dbradford6815",
16
- userToken: process.env.QB_USER_TOKEN,
17
- debug: true,
18
- });
19
-
20
- beforeEach(async () => {
21
- try {
22
- await qb.deleteRecords({
23
- body: {
24
- from: TABLE_ID,
25
- where: `{${MARKER_FIELD_ID}.CT.'test-marker-delete'}`,
26
- },
27
- });
28
- } catch (e) {
29
- // Ignore if no records exist
30
- }
31
- });
32
-
33
- afterEach(async () => {
34
- try {
35
- await qb.deleteRecords({
36
- body: {
37
- from: TABLE_ID,
38
- where: `{${MARKER_FIELD_ID}.CT.'test-marker-delete'}`,
39
- },
40
- });
41
- } catch (e) {}
42
- });
43
-
44
- test(
45
- "deletes a newly upserted record",
46
- async () => {
47
- const upsertResponse: Upsert200Response | Upsert207Response =
48
- await qb.upsert({
49
- body: {
50
- to: TABLE_ID,
51
- data: [{ [MARKER_FIELD_ID]: { value: "test-marker-delete" } }],
52
- fieldsToReturn: [UNIQUE_FIELD_ID], // Return record ID
53
- },
54
- });
55
-
56
- // Check metadata and createdRecordIds
57
- expect(
58
- upsertResponse.metadata,
59
- "Expected metadata to be defined"
60
- ).toBeDefined();
61
- expect(
62
- upsertResponse.metadata?.createdRecordIds,
63
- "Expected createdRecordIds to be defined"
64
- ).toBeDefined();
65
-
66
- const createdRecordIds = upsertResponse.metadata?.createdRecordIds;
67
- if (!createdRecordIds || createdRecordIds.length === 0) {
68
- throw new Error("Expected at least one created record ID");
69
- }
70
-
71
- const recordId = createdRecordIds[0];
72
- expect(recordId, "Expected recordId to be defined").toBeDefined();
73
-
74
- // Check data
75
- expect(upsertResponse.data, "Expected data to be defined").toBeDefined();
76
- if (!upsertResponse.data || upsertResponse.data.length === 0) {
77
- throw new Error("Expected at least one data entry");
78
- }
79
-
80
- const recordData = upsertResponse.data[0];
81
- expect(
82
- recordData[UNIQUE_FIELD_ID]?.value,
83
- "Expected record ID in data to match created record ID"
84
- ).toBe(recordId);
85
-
86
- const deleteResponse = await qb.deleteRecords({
87
- body: { from: TABLE_ID, where: `{${UNIQUE_FIELD_ID}.EX.${recordId}}` },
88
- });
89
-
90
- expect(deleteResponse).toEqual({ numberDeleted: 1 });
91
-
92
- const checkResponse = await qb.deleteRecords({
93
- body: { from: TABLE_ID, where: `{${UNIQUE_FIELD_ID}.EX.${recordId}}` },
94
- });
95
- expect(checkResponse.numberDeleted).toBe(0);
96
- },
97
- { timeout: 10000 }
98
- );
99
-
100
- test(
101
- "handles empty result when no records match",
102
- async () => {
103
- const response = await qb.deleteRecords({
104
- body: { from: TABLE_ID, where: "{3.EX.'999999'}" },
105
- });
106
- expect(response).toEqual({ numberDeleted: 0 });
107
- },
108
- { timeout: 10000 }
109
- );
110
- });
@@ -1,145 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { createClient, QB_TABLE_ID_1 } from "../../../setup.ts";
3
- import {
4
- RunQueryRequest,
5
- RunQueryResponse,
6
- Upsert200Response,
7
- Upsert207Response,
8
- } from "@/generated/models";
9
-
10
- // Define a type for field data with a value property (matches generated Record type)
11
- interface FieldData {
12
- value: any; // Adjust type based on your needs (e.g., string | number)
13
- }
14
-
15
- describe("QuickbaseClient Integration - runQuery", () => {
16
- let createdRecordId: number;
17
-
18
- it(
19
- "queries real records from QuickBase",
20
- async () => {
21
- const client = createClient();
22
-
23
- // Upsert a test record to query later
24
- const upsertResponse: Upsert200Response | Upsert207Response =
25
- await client.upsert({
26
- body: {
27
- to: QB_TABLE_ID_1,
28
- data: [
29
- {
30
- "6": { value: "Test Task " + Date.now() }, // Assuming field 6 is a text field
31
- },
32
- ],
33
- fieldsToReturn: [3, 6], // Record ID# and the text field
34
- },
35
- });
36
-
37
- // Check metadata and createdRecordIds with null safety
38
- expect(
39
- upsertResponse.metadata,
40
- "Expected metadata to be defined"
41
- ).toBeDefined();
42
- expect(
43
- upsertResponse.metadata?.createdRecordIds,
44
- "Expected createdRecordIds to be defined"
45
- ).toBeDefined();
46
-
47
- const createdRecordIds = upsertResponse.metadata?.createdRecordIds;
48
- if (!createdRecordIds || createdRecordIds.length === 0) {
49
- throw new Error("Expected at least one created record ID from upsert");
50
- }
51
-
52
- createdRecordId = createdRecordIds[0];
53
- expect(
54
- createdRecordId,
55
- "Expected createdRecordId to be defined"
56
- ).toBeDefined();
57
- console.log("Created test record with ID:", createdRecordId);
58
-
59
- // Query the record
60
- const queryRequest: RunQueryRequest = {
61
- from: QB_TABLE_ID_1,
62
- select: [3, 6], // Query Record ID# and the text field
63
- where: `{3.EX.${createdRecordId}}`, // Filter by the created record
64
- sortBy: [{ fieldId: 6, order: "ASC" }],
65
- options: { skip: 0, top: 1 },
66
- };
67
-
68
- console.log("Config used:", {
69
- realm: process.env.QB_REALM,
70
- userToken: process.env.QB_USER_TOKEN,
71
- tableId: QB_TABLE_ID_1,
72
- });
73
- console.log("Query request:", queryRequest);
74
- const response: RunQueryResponse = await client.runQuery({
75
- body: queryRequest,
76
- });
77
- console.log("Real API response:", response);
78
-
79
- // Assertions with safety checks and type assertion
80
- expect(
81
- response.data,
82
- "Expected response.data to be defined"
83
- ).toBeDefined();
84
- if (!response.data || response.data.length === 0) {
85
- throw new Error(
86
- "Expected response.data to contain at least one record"
87
- );
88
- }
89
-
90
- expect(response.data).toHaveLength(1);
91
- const record = response.data[0] as { [key: string]: FieldData };
92
- expect(
93
- record["3"]?.value,
94
- "Expected field 3 to match createdRecordId"
95
- ).toBe(createdRecordId);
96
- expect(
97
- record["6"]?.value,
98
- "Expected field 6 to contain 'Test Task'"
99
- ).toContain("Test Task");
100
-
101
- expect(
102
- response.fields,
103
- "Expected response.fields to be defined"
104
- ).toBeDefined();
105
- if (!response.fields) {
106
- throw new Error("Expected response.fields to contain field metadata");
107
- }
108
- expect(response.fields).toContainEqual({
109
- id: 3,
110
- label: expect.any(String),
111
- type: expect.any(String),
112
- });
113
- expect(response.fields).toContainEqual({
114
- id: 6,
115
- label: expect.any(String),
116
- type: expect.any(String),
117
- });
118
-
119
- expect(
120
- response.metadata,
121
- "Expected response.metadata to be defined"
122
- ).toBeDefined();
123
- if (!response.metadata) {
124
- throw new Error("Expected response.metadata to be present");
125
- }
126
- expect(response.metadata).toMatchObject({
127
- numFields: 2,
128
- numRecords: 1,
129
- skip: 0,
130
- // Removed top: 1, as it should be undefined in the final response
131
- totalRecords: expect.any(Number),
132
- });
133
-
134
- // Cleanup: Delete the test record
135
- await client.deleteRecords({
136
- body: {
137
- from: QB_TABLE_ID_1,
138
- where: `{3.EX.${createdRecordId}}`, // Assuming field 3 is Record ID#
139
- },
140
- });
141
- console.log("Cleaned up test record with ID:", createdRecordId);
142
- },
143
- { timeout: 10000 }
144
- );
145
- });
@@ -1,102 +0,0 @@
1
- // tests/vitest/qb/records/upsert.test.ts
2
- import { describe, test, expect, beforeEach, afterEach } from "vitest";
3
- import { quickbase } from "@/quickbaseClient.ts";
4
- import {
5
- Upsert200Response,
6
- Upsert207Response,
7
- } from "/home/drew/Projects/quickbase-js/src/generated/models";
8
-
9
- const TABLE_ID = "buwai2zws";
10
- const MARKER_FIELD_ID = 6; // Text field for marking test records
11
-
12
- describe("QuickbaseClient - Upsert Integration", () => {
13
- const qb = quickbase({
14
- realm: "builderprogram-dbradford6815",
15
- userToken: process.env.QB_USER_TOKEN,
16
- debug: true,
17
- });
18
-
19
- beforeEach(async () => {
20
- try {
21
- await qb.deleteRecords({
22
- body: {
23
- from: TABLE_ID,
24
- where: `{${MARKER_FIELD_ID}.CT.'test-marker-upsert'}`,
25
- },
26
- });
27
- } catch (e) {
28
- // Ignore if no records exist
29
- }
30
- });
31
-
32
- afterEach(async () => {
33
- try {
34
- await qb.deleteRecords({
35
- body: {
36
- from: TABLE_ID,
37
- where: `{${MARKER_FIELD_ID}.CT.'test-marker-upsert'}`,
38
- },
39
- });
40
- } catch (e) {}
41
- });
42
-
43
- test(
44
- "creates a new record successfully",
45
- async () => {
46
- const response: Upsert200Response | Upsert207Response = await qb.upsert({
47
- body: {
48
- to: TABLE_ID,
49
- data: [{ [MARKER_FIELD_ID]: { value: "test-marker-upsert" } }],
50
- fieldsToReturn: [MARKER_FIELD_ID, 3], // Return marker and record ID
51
- },
52
- });
53
-
54
- // Check metadata with null safety
55
- expect(
56
- response.metadata,
57
- "Expected metadata to be defined"
58
- ).toBeDefined();
59
- if (!response.metadata) {
60
- throw new Error("Expected metadata to be present in upsert response");
61
- }
62
-
63
- expect(
64
- response.metadata.createdRecordIds,
65
- "Expected createdRecordIds to be defined"
66
- ).toBeDefined();
67
- if (!response.metadata.createdRecordIds) {
68
- throw new Error(
69
- "Expected createdRecordIds to be present in upsert response"
70
- );
71
- }
72
- expect(response.metadata.createdRecordIds.length).toBe(1);
73
-
74
- // Check data with null safety
75
- expect(response.data, "Expected data to be defined").toBeDefined();
76
- if (!response.data || response.data.length === 0) {
77
- throw new Error("Expected at least one record in data");
78
- }
79
- expect(response.data).toHaveLength(1);
80
- expect(response.data[0][MARKER_FIELD_ID]?.value).toBe(
81
- "test-marker-upsert"
82
- );
83
- expect(response.data[0][3]?.value).toBeDefined(); // Record ID assigned by QuickBase
84
-
85
- // Check totalNumberOfRecordsProcessed
86
- expect(response.metadata.totalNumberOfRecordsProcessed).toBe(1);
87
- },
88
- { timeout: 10000 }
89
- );
90
-
91
- test(
92
- "handles empty data gracefully",
93
- async () => {
94
- await expect(
95
- qb.upsert({
96
- body: { to: TABLE_ID, data: [] },
97
- })
98
- ).rejects.toThrow("API Error: Bad Request (Status: 400)");
99
- },
100
- { timeout: 10000 }
101
- );
102
- });
@@ -1,102 +0,0 @@
1
- // tests/vitest/qb/tables/createRelationship.test.ts
2
-
3
- import { test, expect } from "vitest";
4
- import { quickbase } from "/home/drew/Projects/quickbase-js/src/quickbaseClient";
5
- import {
6
- QB_REALM,
7
- QB_USER_TOKEN,
8
- QB_TABLE_ID_1,
9
- QB_TABLE_ID_2,
10
- } from "/home/drew/Projects/quickbase-js/tests/setup.ts";
11
-
12
- test(
13
- "QuickbaseClient Integration - createRelationship > creates a new relationship in QuickBase",
14
- { timeout: 60000 }, // 60 seconds for create and delete
15
- async () => {
16
- // Validate environment variables
17
- if (!QB_REALM) throw new Error("QB_REALM is not defined in .env");
18
- if (!QB_USER_TOKEN) throw new Error("QB_USER_TOKEN is not defined in .env");
19
- if (!QB_TABLE_ID_1) throw new Error("QB_TABLE_ID_1 is not defined in .env");
20
- if (!QB_TABLE_ID_2) throw new Error("QB_TABLE_ID_2 is not defined in .env");
21
-
22
- // Initialize client
23
- const client = quickbase({
24
- realm: QB_REALM,
25
- userToken: QB_USER_TOKEN,
26
- debug: true,
27
- });
28
-
29
- // Define the relationship creation request
30
- const uniqueLabel = `TestRelationship_${Date.now()}`;
31
- const requestBody = {
32
- parentTableId: QB_TABLE_ID_1,
33
- foreignKeyField: { label: uniqueLabel },
34
- lookupFieldIds: [6], // Assuming field 6 exists in QB_TABLE_ID_1
35
- summaryFields: [
36
- {
37
- summaryFid: 6, // Assuming field 6 in QB_TABLE_ID_2 is numeric
38
- label: `Sum_${uniqueLabel}`,
39
- accumulationType: "SUM",
40
- },
41
- ],
42
- };
43
-
44
- console.log("Config used:", {
45
- realm: QB_REALM,
46
- userToken: "[REDACTED]",
47
- parentTableId: QB_TABLE_ID_1,
48
- childTableId: QB_TABLE_ID_2,
49
- });
50
- console.log("Creating relationship with:", requestBody);
51
-
52
- // Create the relationship
53
- const response = await client.createRelationship({
54
- tableId: QB_TABLE_ID_2,
55
- body: requestBody,
56
- });
57
-
58
- console.log("Real API response:", JSON.stringify(response, null, 2));
59
-
60
- // Assertions for creation
61
- expect(response).toBeDefined();
62
- expect(response.id).toBeDefined();
63
- expect(response.parentTableId).toBe(QB_TABLE_ID_1);
64
- expect(response.childTableId).toBe(QB_TABLE_ID_2);
65
- expect(response.foreignKeyField).toBeDefined();
66
- expect(response.foreignKeyField?.label).toBe(uniqueLabel);
67
- expect(response.lookupFields).toHaveLength(1);
68
- expect(response.lookupFields[0].id).toBeGreaterThan(0);
69
- expect(response.summaryFields).toHaveLength(1);
70
- expect(response.summaryFields[0].label).toBe(`Sum_${uniqueLabel}`);
71
-
72
- // Cleanup: Delete the relationship
73
- const relationshipId = response.id;
74
- console.log("Deleting relationship with ID:", relationshipId);
75
- const deleteResponse = await client.deleteRelationship({
76
- tableId: QB_TABLE_ID_2,
77
- relationshipId,
78
- });
79
-
80
- console.log(
81
- "Delete relationship response:",
82
- JSON.stringify(deleteResponse, null, 2)
83
- );
84
-
85
- // Verify deletion
86
- expect(deleteResponse).toBeDefined();
87
- expect(deleteResponse.relationshipId).toBe(relationshipId);
88
-
89
- // Confirm relationship is gone
90
- const relationships = await client.getRelationships({
91
- tableId: QB_TABLE_ID_2,
92
- });
93
- console.log(
94
- "Relationships after deletion:",
95
- JSON.stringify(relationships, null, 2)
96
- );
97
- const deletedRelationship = relationships.relationships.find(
98
- (r) => r.id === relationshipId
99
- );
100
- expect(deletedRelationship).toBeUndefined(); // Should no longer exist
101
- }
102
- );