quickbase-js 1.1.0-beta.3 → 1.1.0-beta.4

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 (46) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +61 -5
  3. package/dist/quickbase.d.ts +1108 -349
  4. package/dist/quickbase.js +828 -263
  5. package/dist/quickbase.js.map +1 -1
  6. package/examples/react.js +12 -12
  7. package/examples/vanillajs.html +12 -12
  8. package/log-gen.yaml +4622 -759
  9. package/package.json +12 -14
  10. package/playwright-results.txt/.last-run.json +4 -0
  11. package/playwright.config.ts +1 -1
  12. package/src/code-generation/definitions/apps.ts +274 -0
  13. package/src/code-generation/definitions/auth.ts +10 -0
  14. package/src/code-generation/definitions/fields.ts +751 -0
  15. package/src/code-generation/definitions/index.ts +18 -0
  16. package/src/code-generation/definitions/records.ts +269 -0
  17. package/src/code-generation/definitions/relationships.ts +90 -0
  18. package/src/code-generation/definitions/reports.ts +10 -0
  19. package/src/code-generation/definitions/tables.ts +112 -0
  20. package/src/code-generation/fix-spec-main.ts +2 -2
  21. package/src/code-generation/output/quickbase-fixed.json +3244 -4586
  22. package/src/code-generation/paths/apps.ts +100 -0
  23. package/src/code-generation/paths/auth.ts +25 -0
  24. package/src/code-generation/paths/fields.ts +207 -0
  25. package/src/code-generation/paths/index.ts +17 -0
  26. package/src/code-generation/paths/records.ts +68 -0
  27. package/src/code-generation/paths/relationships.ts +32 -0
  28. package/src/code-generation/paths/reports.ts +34 -0
  29. package/src/code-generation/paths/tables.ts +162 -0
  30. package/src/generated-unified/QuickbaseClient.ts +7 -6
  31. package/src/log-gen.ts +8 -6
  32. package/tests/vitest/qb/fields/createField.test.ts +78 -0
  33. package/tests/vitest/qb/fields/deleteFields.test.ts +89 -0
  34. package/tests/vitest/qb/fields/getField.test.ts +85 -0
  35. package/tests/vitest/qb/fields/getFieldUsage.test.ts +174 -0
  36. package/tests/vitest/qb/fields/getFieldsUsage.test.ts +77 -0
  37. package/tests/vitest/qb/index.ts +25 -1
  38. package/tests/vitest/unit/fields/createField.test.ts +391 -0
  39. package/tests/vitest/unit/fields/deleteFields.test.ts +141 -0
  40. package/tests/vitest/unit/fields/getField.test.ts +189 -0
  41. package/tests/vitest/unit/fields/getFieldUsage.test.ts +147 -0
  42. package/tests/vitest/unit/fields/getFieldsUsage.test.ts +160 -0
  43. package/tests/vitest/unit/index.ts +30 -1
  44. package/src/code-generation/fix-spec-definitions.ts +0 -809
  45. package/src/code-generation/fix-spec-paths.ts +0 -439
  46. package/test-artifacts/test-results.json +0 -829
@@ -0,0 +1,147 @@
1
+ // tests/vitest/unit/fields/getFieldUsage.test.ts
2
+ import { describe, it, expect, beforeEach } from "vitest";
3
+ import {
4
+ createClient,
5
+ mockFetch,
6
+ QB_REALM,
7
+ QB_USER_TOKEN,
8
+ QB_TABLE_ID_1,
9
+ } from "@tests/setup.ts";
10
+ import { FieldUsage } from "@/generated/models";
11
+
12
+ describe("QuickbaseClient Unit - getFieldUsage", () => {
13
+ let client: ReturnType<typeof createClient>;
14
+
15
+ beforeEach(() => {
16
+ mockFetch.mockClear();
17
+ client = createClient(mockFetch, { realm: QB_REALM, debug: true });
18
+ });
19
+
20
+ it("initializes without errors and has getFieldUsage method", () => {
21
+ expect(client).toBeDefined();
22
+ expect(typeof client.getFieldUsage).toBe("function");
23
+ });
24
+
25
+ it("calls getFieldUsage successfully with user token", async () => {
26
+ const mockResponse: FieldUsage = {
27
+ field: {
28
+ id: 6,
29
+ name: "name",
30
+ type: "text", // Match QuickBase's lowercase response
31
+ },
32
+ usage: {
33
+ actions: { count: 0 },
34
+ appHomePages: { count: 0 },
35
+ dashboards: { count: 2 },
36
+ defaultReports: { count: 1 },
37
+ exactForms: { count: 0 },
38
+ fields: { count: 0 },
39
+ forms: { count: 1 },
40
+ notifications: { count: 0 },
41
+ personalReports: { count: 0 },
42
+ pipelines: { count: 1 },
43
+ relationships: { count: 0 },
44
+ reminders: { count: 0 },
45
+ reports: { count: 2 },
46
+ roles: { count: 2 },
47
+ tableImports: { count: 2 },
48
+ tableRules: { count: 1 },
49
+ webhooks: { count: 0 },
50
+ },
51
+ };
52
+
53
+ // Mock the response as an array to match the updated API behavior
54
+ mockFetch.mockResolvedValueOnce(
55
+ new Response(JSON.stringify([mockResponse]), {
56
+ status: 200,
57
+ statusText: "OK",
58
+ headers: { "Content-Type": "application/json" },
59
+ })
60
+ );
61
+
62
+ const result = await client.getFieldUsage({
63
+ fieldId: 6,
64
+ tableId: QB_TABLE_ID_1,
65
+ });
66
+
67
+ // Expect an array and unwrap the first item
68
+ expect(result).toBeInstanceOf(Array);
69
+ expect(result).toHaveLength(1);
70
+ const fieldUsage = result[0];
71
+
72
+ expect(fieldUsage).toEqual(mockResponse);
73
+ expect(mockFetch).toHaveBeenCalledWith(
74
+ `https://api.quickbase.com/v1/fields/usage/6?tableId=${QB_TABLE_ID_1}`,
75
+ expect.objectContaining({
76
+ method: "GET",
77
+ headers: expect.objectContaining({
78
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
79
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
80
+ "Content-Type": "application/json",
81
+ }),
82
+ })
83
+ );
84
+ expect(fieldUsage.field.id).toBe(6);
85
+ expect(fieldUsage.field.name).toBe("name");
86
+ expect(fieldUsage.usage.dashboards.count).toBe(2);
87
+ });
88
+
89
+ it("handles 404 error for non-existent field", async () => {
90
+ mockFetch.mockResolvedValueOnce(
91
+ new Response(JSON.stringify({ message: "Field not found" }), {
92
+ status: 404,
93
+ statusText: "Not Found",
94
+ headers: { "Content-Type": "application/json" },
95
+ })
96
+ );
97
+
98
+ await expect(
99
+ client.getFieldUsage({
100
+ fieldId: 999,
101
+ tableId: QB_TABLE_ID_1,
102
+ })
103
+ ).rejects.toThrow("API Error: Field not found (Status: 404)");
104
+
105
+ expect(mockFetch).toHaveBeenCalledWith(
106
+ `https://api.quickbase.com/v1/fields/usage/999?tableId=${QB_TABLE_ID_1}`,
107
+ expect.objectContaining({
108
+ method: "GET",
109
+ headers: expect.objectContaining({
110
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
111
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
112
+ "Content-Type": "application/json",
113
+ }),
114
+ })
115
+ );
116
+ });
117
+
118
+ it("handles 401 error and does not retry with user token", async () => {
119
+ mockFetch.mockResolvedValueOnce(
120
+ new Response(JSON.stringify({ message: "Unauthorized" }), {
121
+ status: 401,
122
+ statusText: "Unauthorized",
123
+ headers: { "Content-Type": "application/json" },
124
+ })
125
+ );
126
+
127
+ await expect(
128
+ client.getFieldUsage({
129
+ fieldId: 6,
130
+ tableId: QB_TABLE_ID_1,
131
+ })
132
+ ).rejects.toThrow("API Error: Unauthorized (Status: 401)");
133
+
134
+ expect(mockFetch).toHaveBeenCalledTimes(1); // No retry with user token
135
+ expect(mockFetch).toHaveBeenCalledWith(
136
+ `https://api.quickbase.com/v1/fields/usage/6?tableId=${QB_TABLE_ID_1}`,
137
+ expect.objectContaining({
138
+ method: "GET",
139
+ headers: expect.objectContaining({
140
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
141
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
142
+ "Content-Type": "application/json",
143
+ }),
144
+ })
145
+ );
146
+ });
147
+ });
@@ -0,0 +1,160 @@
1
+ // tests/vitest/unit/fields/getFieldsUsage.test.ts
2
+ import { describe, it, expect, beforeEach } from "vitest";
3
+ import {
4
+ createClient,
5
+ mockFetch,
6
+ QB_REALM,
7
+ QB_TABLE_ID_1,
8
+ QB_USER_TOKEN,
9
+ } from "@tests/setup.ts";
10
+ import { FieldUsage } from "@/generated/models";
11
+
12
+ describe("QuickbaseClient Unit - getFieldsUsage", () => {
13
+ let client: ReturnType<typeof createClient>;
14
+
15
+ beforeEach(() => {
16
+ mockFetch.mockClear();
17
+ client = createClient(mockFetch, { debug: true });
18
+ });
19
+
20
+ it("initializes without errors and has getFieldsUsage method", () => {
21
+ expect(client).toBeDefined();
22
+ expect(typeof client.getFieldsUsage).toBe("function");
23
+ });
24
+
25
+ it("calls getFieldsUsage successfully with user token", async () => {
26
+ const mockResponse: FieldUsage[] = [
27
+ {
28
+ field: {
29
+ id: 6,
30
+ name: "name",
31
+ type: "Text",
32
+ },
33
+ usage: {
34
+ actions: { count: 0 },
35
+ appHomePages: { count: 0 },
36
+ dashboards: { count: 2 },
37
+ defaultReports: { count: 1 },
38
+ exactForms: { count: 0 },
39
+ fields: { count: 0 },
40
+ forms: { count: 1 },
41
+ notifications: { count: 0 },
42
+ personalReports: { count: 0 },
43
+ pipelines: { count: 1 },
44
+ relationships: { count: 0 },
45
+ reminders: { count: 0 },
46
+ reports: { count: 2 },
47
+ roles: { count: 2 },
48
+ tableImports: { count: 3 },
49
+ tableRules: { count: 1 },
50
+ webhooks: { count: 0 },
51
+ },
52
+ },
53
+ ];
54
+
55
+ mockFetch.mockResolvedValueOnce({
56
+ ok: true,
57
+ status: 200,
58
+ json: () => Promise.resolve(mockResponse),
59
+ });
60
+
61
+ const result = await client.getFieldsUsage({
62
+ tableId: QB_TABLE_ID_1,
63
+ });
64
+
65
+ expect(result).toEqual(mockResponse);
66
+ expect(mockFetch).toHaveBeenCalledWith(
67
+ `https://api.quickbase.com/v1/fields/usage?tableId=${QB_TABLE_ID_1}`,
68
+ expect.objectContaining({
69
+ method: "GET",
70
+ headers: expect.objectContaining({
71
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
72
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
73
+ "Content-Type": "application/json",
74
+ }),
75
+ })
76
+ );
77
+ });
78
+
79
+ it("calls getFieldsUsage with skip and top parameters", async () => {
80
+ const mockResponse: FieldUsage[] = [
81
+ {
82
+ field: {
83
+ id: 7,
84
+ name: "priority",
85
+ type: "Text",
86
+ },
87
+ usage: {
88
+ actions: { count: 1 },
89
+ appHomePages: { count: 0 },
90
+ dashboards: { count: 0 },
91
+ defaultReports: { count: 0 },
92
+ exactForms: { count: 0 },
93
+ fields: { count: 1 },
94
+ forms: { count: 0 },
95
+ notifications: { count: 0 },
96
+ personalReports: { count: 0 },
97
+ pipelines: { count: 0 },
98
+ relationships: { count: 0 },
99
+ reminders: { count: 0 },
100
+ reports: { count: 1 },
101
+ roles: { count: 1 },
102
+ tableImports: { count: 0 },
103
+ tableRules: { count: 0 },
104
+ webhooks: { count: 0 },
105
+ },
106
+ },
107
+ ];
108
+
109
+ mockFetch.mockResolvedValueOnce({
110
+ ok: true,
111
+ status: 200,
112
+ json: () => Promise.resolve(mockResponse),
113
+ });
114
+
115
+ const result = await client.getFieldsUsage({
116
+ tableId: QB_TABLE_ID_1,
117
+ skip: 1,
118
+ top: 1,
119
+ });
120
+
121
+ expect(result).toEqual(mockResponse);
122
+ expect(mockFetch).toHaveBeenCalledWith(
123
+ `https://api.quickbase.com/v1/fields/usage?tableId=${QB_TABLE_ID_1}&skip=1&top=1`,
124
+ expect.objectContaining({
125
+ method: "GET",
126
+ headers: expect.objectContaining({
127
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
128
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
129
+ "Content-Type": "application/json",
130
+ }),
131
+ })
132
+ );
133
+ });
134
+
135
+ it("handles 404 error for non-existent table", async () => {
136
+ const nonExistentTableId = "nonexistent_dbid";
137
+
138
+ mockFetch.mockResolvedValueOnce({
139
+ ok: false,
140
+ status: 404,
141
+ json: () => Promise.resolve({ message: "Table not found" }),
142
+ });
143
+
144
+ await expect(
145
+ client.getFieldsUsage({ tableId: nonExistentTableId })
146
+ ).rejects.toThrow("API Error: Table not found (Status: 404)");
147
+
148
+ expect(mockFetch).toHaveBeenCalledWith(
149
+ `https://api.quickbase.com/v1/fields/usage?tableId=${nonExistentTableId}`,
150
+ expect.objectContaining({
151
+ method: "GET",
152
+ headers: expect.objectContaining({
153
+ "QB-Realm-Hostname": `${QB_REALM}.quickbase.com`,
154
+ Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
155
+ "Content-Type": "application/json",
156
+ }),
157
+ })
158
+ );
159
+ });
160
+ });
@@ -1,4 +1,33 @@
1
- // tests/unit/index.ts
1
+ // tests/vitest/unit/index.ts
2
+ // Apps
3
+ export * from "./apps/copyApp.test.ts";
4
+ export * from "./apps/createApp.test.ts";
5
+ export * from "./apps/deleteApp.test.ts";
2
6
  export * from "./apps/getApp.test.ts";
7
+
8
+ // Auth
9
+ export * from "./auth/fetchTempToken401.test.ts";
10
+ export * from "./auth/getTempToken.test.ts";
11
+ export * from "./auth/retryOn401.test.ts";
12
+ export * from "./auth/two401s.test.ts";
13
+
14
+ // Fields
3
15
  export * from "./fields/getFields.test.ts";
16
+ export * from "./fields/getField.test.ts";
17
+ export * from "./fields/createField.test.ts";
18
+ export * from "./fields/deleteFields.test.ts";
19
+ export * from "./fields/getFieldsUsage.test.ts";
20
+ export * from "./fields/getFieldUsage.test.ts";
21
+
22
+ // Records
23
+ export * from "./records/deleteRecords.test.ts";
24
+ export * from "./records/runQuery.test.ts";
25
+ export * from "./records/upsert.test.ts";
26
+
27
+ // Tables
28
+ export * from "./tables/createTable.test.ts";
29
+ export * from "./tables/deleteTable.test.ts";
4
30
  export * from "./tables/getAppTables.test.ts";
31
+ export * from "./tables/getRelationships.test.ts";
32
+ export * from "./tables/getTable.test.ts";
33
+ export * from "./tables/updateTable.test.ts";