quickbase-js 1.0.1-beta.0 → 1.1.0-beta.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 (47) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/dist/{quickbaseClient.d.ts → quickbase.d.ts} +344 -339
  3. package/dist/{quickbaseClient.js → quickbase.js} +350 -266
  4. package/dist/quickbase.js.map +1 -0
  5. package/log-gen.yaml +3565 -0
  6. package/package.json +11 -7
  7. package/rollup.config.js +2 -2
  8. package/src/code-generation/fix-spec-definitions.ts +417 -68
  9. package/src/code-generation/fix-spec-paths.ts +207 -2
  10. package/src/code-generation/output/quickbase-fixed.json +646 -1122
  11. package/src/generated-unified/QuickbaseClient.ts +9 -8
  12. package/src/log-gen.ts +82 -35
  13. package/src/quickbaseClient.ts +39 -42
  14. package/test-artifacts/test-results.json +173 -1145
  15. package/tests/playwright/qb/auth/cacheSwitching.test.ts +2 -2
  16. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +2 -2
  17. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +2 -2
  18. package/tests/playwright/qb/auth/getTempToken.test.ts +2 -2
  19. package/tests/playwright/qb/auth/tokenPrefetch.test.ts +2 -2
  20. package/tests/playwright/qb/auth/tokenRenewal.test.ts +2 -2
  21. package/tests/setup.ts +16 -8
  22. package/tests/vitest/qb/apps/getApp.test.ts +37 -43
  23. package/tests/vitest/qb/records/deleteRecords.test.ts +78 -0
  24. package/tests/vitest/qb/records/upsert.test.ts +72 -0
  25. package/tests/vitest/qb/tables/createTable.test.ts +55 -0
  26. package/tests/vitest/qb/tables/deleteTable.test.ts +50 -0
  27. package/tests/vitest/qb/tables/getAppTables.test.ts +43 -64
  28. package/tests/vitest/qb/tables/getTable.test.ts +26 -0
  29. package/tests/vitest/qb/tables/updateTable.test.ts +48 -0
  30. package/tests/vitest/unit/apps/getApp.test.ts +1 -1
  31. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +4 -3
  32. package/tests/vitest/unit/auth/getTempToken.test.ts +8 -9
  33. package/tests/vitest/unit/auth/retryOn401.test.ts +1 -1
  34. package/tests/vitest/unit/auth/two401s.test.ts +1 -1
  35. package/tests/vitest/unit/fields/getFields.test.ts +1 -1
  36. package/tests/vitest/unit/records/deleteRecords.test.ts +118 -0
  37. package/tests/vitest/unit/records/upsert.test.ts +228 -0
  38. package/tests/vitest/unit/tables/createTable.test.ts +62 -0
  39. package/tests/vitest/unit/tables/deleteTable.test.ts +68 -0
  40. package/tests/vitest/unit/tables/getAppTables.test.ts +1 -1
  41. package/tests/vitest/unit/tables/getTable.test.ts +212 -0
  42. package/tests/vitest/unit/tables/updateTable.test.ts +74 -0
  43. package/tsconfig.json +3 -2
  44. package/vitest.config.ts +3 -2
  45. package/dist/quickbaseClient.js.map +0 -1
  46. package/logGen.yaml +0 -1820
  47. package/src/utils.ts +0 -5
@@ -0,0 +1,212 @@
1
+ import { describe, it, expect, beforeEach, vi } from "vitest";
2
+ import { createClient, mockFetch } from "@tests/setup.ts";
3
+
4
+ describe("QuickbaseClient - getTable (Unit)", () => {
5
+ let client: ReturnType<typeof createClient>;
6
+
7
+ beforeEach(() => {
8
+ mockFetch.mockClear();
9
+ client = createClient(mockFetch, { debug: true });
10
+ });
11
+
12
+ it("calls getTable successfully with user token", async () => {
13
+ const mockAppId = "buwai2zpe";
14
+ const mockTableId = "buwai2zr4";
15
+ const mockResponse = {
16
+ id: mockTableId,
17
+ name: "Root",
18
+ alias: "_DBID_ROOT",
19
+ description: "",
20
+ created: new Date("2025-02-13T18:22:33.000Z"),
21
+ updated: new Date("2025-02-13T18:22:34.000Z"),
22
+ nextRecordId: 1,
23
+ nextFieldId: 6,
24
+ defaultSortFieldId: 2,
25
+ defaultSortOrder: "DESC",
26
+ keyFieldId: 3,
27
+ singleRecordName: "Root",
28
+ pluralRecordName: "Roots",
29
+ sizeLimit: "500 MB",
30
+ spaceUsed: "0 KB",
31
+ spaceRemaining: "500 MB",
32
+ };
33
+
34
+ mockFetch.mockResolvedValueOnce({
35
+ ok: true,
36
+ status: 200,
37
+ json: () => Promise.resolve(mockResponse),
38
+ });
39
+
40
+ const response = await client.getTable({
41
+ tableId: mockTableId,
42
+ appId: mockAppId,
43
+ });
44
+ expect(response).toEqual(mockResponse);
45
+ expect(mockFetch).toHaveBeenCalledWith(
46
+ `https://api.quickbase.com/v1/tables/${mockTableId}?appId=${mockAppId}`,
47
+ expect.objectContaining({
48
+ method: "GET",
49
+ headers: expect.objectContaining({
50
+ Authorization:
51
+ "QB-USER-TOKEN b9f3pk_q4jd_0_b4qu5eebyvuix3xs57ysd7zn3",
52
+ }),
53
+ })
54
+ );
55
+ });
56
+
57
+ it("calls getTable successfully with temp token", async () => {
58
+ client = createClient(mockFetch, { debug: true, useTempTokens: true });
59
+ const mockAppId = "buwai2zpe";
60
+ const mockTableId = "buwai2zr4";
61
+ const mockResponse = {
62
+ id: mockTableId,
63
+ name: "Root",
64
+ alias: "_DBID_ROOT",
65
+ description: "",
66
+ created: new Date("2025-02-13T18:22:33.000Z"),
67
+ updated: new Date("2025-02-13T18:22:34.000Z"),
68
+ nextRecordId: 1,
69
+ nextFieldId: 6,
70
+ defaultSortFieldId: 2,
71
+ defaultSortOrder: "DESC",
72
+ keyFieldId: 3,
73
+ singleRecordName: "Root",
74
+ pluralRecordName: "Roots",
75
+ sizeLimit: "500 MB",
76
+ spaceUsed: "0 KB",
77
+ spaceRemaining: "500 MB",
78
+ };
79
+
80
+ mockFetch
81
+ .mockResolvedValueOnce({
82
+ ok: true,
83
+ status: 200,
84
+ json: () => Promise.resolve({ temporaryAuthorization: "temp_token" }),
85
+ })
86
+ .mockResolvedValueOnce({
87
+ ok: true,
88
+ status: 200,
89
+ json: () => Promise.resolve(mockResponse),
90
+ });
91
+
92
+ const response = await client.getTable({
93
+ tableId: mockTableId,
94
+ appId: mockAppId,
95
+ });
96
+ expect(response).toEqual(mockResponse);
97
+ expect(mockFetch).toHaveBeenCalledTimes(2);
98
+ expect(mockFetch).toHaveBeenCalledWith(
99
+ `https://api.quickbase.com/v1/auth/temporary/${mockTableId}`,
100
+ expect.any(Object)
101
+ );
102
+ expect(mockFetch).toHaveBeenCalledWith(
103
+ `https://api.quickbase.com/v1/tables/${mockTableId}?appId=${mockAppId}`,
104
+ expect.objectContaining({
105
+ headers: expect.objectContaining({
106
+ Authorization: "QB-TEMP-TOKEN temp_token",
107
+ }),
108
+ })
109
+ );
110
+ });
111
+
112
+ it("retries successfully after 401 with temp token", async () => {
113
+ client = createClient(mockFetch, { debug: true, useTempTokens: true });
114
+ const mockAppId = "buwai2zpe";
115
+ const mockTableId = "buwai2zr4";
116
+ const mockResponse = {
117
+ id: mockTableId,
118
+ name: "Root",
119
+ alias: "_DBID_ROOT",
120
+ description: "",
121
+ created: new Date("2025-02-13T18:22:33.000Z"),
122
+ updated: new Date("2025-02-13T18:22:34.000Z"),
123
+ nextRecordId: 1,
124
+ nextFieldId: 6,
125
+ defaultSortFieldId: 2,
126
+ defaultSortOrder: "DESC",
127
+ keyFieldId: 3,
128
+ singleRecordName: "Root",
129
+ pluralRecordName: "Roots",
130
+ sizeLimit: "500 MB",
131
+ spaceUsed: "0 KB",
132
+ spaceRemaining: "500 MB",
133
+ };
134
+
135
+ mockFetch
136
+ .mockResolvedValueOnce({
137
+ ok: true,
138
+ status: 200,
139
+ json: () =>
140
+ Promise.resolve({ temporaryAuthorization: "initial_token" }),
141
+ })
142
+ .mockResolvedValueOnce({
143
+ ok: false,
144
+ status: 401,
145
+ json: () => Promise.resolve({ message: "Unauthorized" }),
146
+ })
147
+ .mockResolvedValueOnce({
148
+ ok: true,
149
+ status: 200,
150
+ json: () => Promise.resolve({ temporaryAuthorization: "new_token" }),
151
+ })
152
+ .mockResolvedValueOnce({
153
+ ok: true,
154
+ status: 200,
155
+ json: () => Promise.resolve(mockResponse),
156
+ });
157
+
158
+ const response = await client.getTable({
159
+ tableId: mockTableId,
160
+ appId: mockAppId,
161
+ });
162
+ expect(response).toEqual(mockResponse);
163
+ expect(mockFetch).toHaveBeenCalledTimes(4); // Initial token, 401, retry token, success
164
+ });
165
+
166
+ it("handles 401 with failed temp token retry", async () => {
167
+ client = createClient(mockFetch, { debug: true, useTempTokens: true });
168
+ const mockAppId = "buwai2zpe";
169
+ const mockTableId = "buwai2zr4";
170
+
171
+ mockFetch
172
+ .mockResolvedValueOnce({
173
+ ok: true,
174
+ status: 200,
175
+ json: () =>
176
+ Promise.resolve({ temporaryAuthorization: "initial_token" }),
177
+ })
178
+ .mockResolvedValueOnce({
179
+ ok: false,
180
+ status: 401,
181
+ json: () => Promise.resolve({ message: "Unauthorized" }),
182
+ })
183
+ .mockResolvedValueOnce({
184
+ ok: false,
185
+ status: 401,
186
+ json: () =>
187
+ Promise.resolve({ message: "Unauthorized in fetchTempToken" }),
188
+ });
189
+
190
+ await expect(
191
+ client.getTable({ tableId: mockTableId, appId: mockAppId })
192
+ ).rejects.toThrow(
193
+ "API Error: Unauthorized in fetchTempToken (Status: 401)"
194
+ );
195
+ expect(mockFetch).toHaveBeenCalledTimes(3);
196
+ });
197
+
198
+ it("handles 404 Not Found", async () => {
199
+ const mockAppId = "buwai2zpe";
200
+ const mockTableId = "invalidTableId";
201
+
202
+ mockFetch.mockResolvedValueOnce({
203
+ ok: false,
204
+ status: 404,
205
+ json: () => Promise.resolve({ message: "Table not found" }),
206
+ });
207
+
208
+ await expect(
209
+ client.getTable({ tableId: mockTableId, appId: mockAppId })
210
+ ).rejects.toThrow("API Error: Table not found (Status: 404)");
211
+ });
212
+ });
@@ -0,0 +1,74 @@
1
+ import { describe, it, expect, beforeEach, vi } from "vitest";
2
+ import { createClient, mockFetch } from "@tests/setup.ts";
3
+
4
+ describe("QuickbaseClient - updateTable (Unit)", () => {
5
+ let client: ReturnType<typeof createClient>;
6
+
7
+ beforeEach(() => {
8
+ mockFetch.mockClear();
9
+ client = createClient(mockFetch, { debug: true });
10
+ });
11
+
12
+ it("calls updateTable successfully with temp token", async () => {
13
+ client = createClient(mockFetch, { debug: true, useTempTokens: true });
14
+ const mockAppId = "buwai2zpe";
15
+ const mockTableId = "buwai2zr4";
16
+ const mockBody = {
17
+ name: "Updated Root",
18
+ description: "Updated description",
19
+ };
20
+ const mockResponse = {
21
+ id: mockTableId,
22
+ name: "Updated Root",
23
+ alias: "_DBID_ROOT",
24
+ description: "Updated description",
25
+ created: new Date("2025-02-13T18:22:33.000Z"),
26
+ updated: new Date("2025-03-10T12:00:00.000Z"),
27
+ nextRecordId: 1,
28
+ nextFieldId: 6,
29
+ defaultSortFieldId: 2,
30
+ defaultSortOrder: "DESC",
31
+ keyFieldId: 3,
32
+ singleRecordName: "Root",
33
+ pluralRecordName: "Roots",
34
+ sizeLimit: "500 MB",
35
+ spaceUsed: "0 KB",
36
+ spaceRemaining: "500 MB",
37
+ };
38
+
39
+ mockFetch
40
+ .mockResolvedValueOnce({
41
+ ok: true,
42
+ status: 200,
43
+ json: () => Promise.resolve({ temporaryAuthorization: "temp_token" }),
44
+ })
45
+ .mockResolvedValueOnce({
46
+ ok: true,
47
+ status: 200,
48
+ json: () => Promise.resolve(mockResponse),
49
+ });
50
+
51
+ const response = await client.updateTable({
52
+ tableId: mockTableId,
53
+ appId: mockAppId,
54
+ body: mockBody,
55
+ });
56
+ expect(response).toEqual(mockResponse);
57
+ expect(mockFetch).toHaveBeenCalledTimes(2);
58
+ expect(mockFetch).toHaveBeenCalledWith(
59
+ `https://api.quickbase.com/v1/auth/temporary/${mockTableId}`,
60
+ expect.any(Object)
61
+ );
62
+ expect(mockFetch).toHaveBeenCalledWith(
63
+ `https://api.quickbase.com/v1/tables/${mockTableId}?appId=${mockAppId}`,
64
+ expect.objectContaining({
65
+ method: "POST", // Updated to match QuickBase API spec
66
+ headers: expect.objectContaining({
67
+ Authorization: "QB-TEMP-TOKEN temp_token",
68
+ "Content-Type": "application/json",
69
+ }),
70
+ body: JSON.stringify(mockBody),
71
+ })
72
+ );
73
+ });
74
+ });
package/tsconfig.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "module": "ESNext",
5
5
  "moduleResolution": "bundler",
6
6
  "strict": true,
7
- "lib": ["ES2015", "ESNext", "DOM"], // Explicitly include ES2015 for Record
7
+ "lib": ["ES2015", "ESNext", "DOM"],
8
8
  "types": ["node", "playwright/test"],
9
9
  "esModuleInterop": true,
10
10
  "resolveJsonModule": true,
@@ -16,7 +16,8 @@
16
16
  "sourceMap": true,
17
17
  "baseUrl": ".",
18
18
  "paths": {
19
- "@/*": ["./*"]
19
+ "@/*": ["src/*"], // Matches Vite's @ -> src/
20
+ "@tests/*": ["tests/*"] // Matches Vite's @tests -> tests/
20
21
  }
21
22
  },
22
23
  "include": ["src/**/*", "tests/**/*"],
package/vitest.config.ts CHANGED
@@ -5,7 +5,7 @@ export default defineConfig({
5
5
  test: {
6
6
  environment: "jsdom",
7
7
  include: ["tests/vitest/**/**/*.test.ts"],
8
- setupFiles: ["tests/setup.ts"],
8
+ setupFiles: ["tests/setup.ts"], // Relative path from root
9
9
  pool: "forks",
10
10
  poolOptions: {
11
11
  forks: {
@@ -15,7 +15,8 @@ export default defineConfig({
15
15
  },
16
16
  resolve: {
17
17
  alias: {
18
- "@": path.resolve(__dirname, "./"),
18
+ "@": path.resolve(__dirname, "./src"), // For src/ imports
19
+ "@tests": path.resolve(__dirname, "./tests"), // For tests/ imports
19
20
  },
20
21
  },
21
22
  });