quickbase-js 0.1.0-beta.8 → 0.1.0-beta.9
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.
- package/CHANGELOG.md +29 -0
- package/README.md +46 -130
- package/dist/esm/quickbase.d.ts +822 -119
- package/dist/esm/quickbase.js +373 -236
- package/dist/esm/quickbase.js.map +1 -1
- package/dist/esm/quickbase.min.js +1 -1
- package/dist/esm/quickbase.min.js.map +1 -1
- package/dist/umd/quickbase.umd.js +373 -236
- package/dist/umd/quickbase.umd.js.map +1 -1
- package/dist/umd/quickbase.umd.min.js +1 -1
- package/dist/umd/quickbase.umd.min.js.map +1 -1
- package/open-api/generate-unified-interface.ts +97 -17
- package/open-api/utils/generateJsDoc.ts +96 -0
- package/package.json +3 -1
- package/src/ThrottleBucket.ts +17 -12
- package/src/authorizationStrategy.ts +246 -0
- package/src/generated-unified/QuickbaseClient.ts +809 -119
- package/src/invokeMethod.ts +150 -265
- package/src/quickbaseClient.ts +85 -58
- package/src/rateLimiter.ts +25 -0
- package/src/tokenCache.ts +10 -26
- package/tests/vitest/qb/auth/mockQuickbaseServer.ts +60 -0
- package/tests/vitest/qb/auth/retryUserToken401.test.ts +59 -42
- package/tests/vitest/qb/auth/ssoTokenIntegrationWithServer.test.ts +65 -0
- package/tests/vitest/qb/fields/getFieldUsage.test.ts +58 -150
- package/tests/vitest/qb/formulas/runFormula.test.ts +96 -0
- package/tests/vitest/qb/tables/createRelationship.test.ts +102 -0
- package/tests/vitest/qb/tables/deleteRelationship.test.ts +143 -0
- package/tests/vitest/qb/tables/updateRelationship.test.ts +118 -145
- package/tests/vitest/unit/ThrottleBucket.test.ts +95 -0
- package/tests/vitest/unit/apps/copyApp.test.ts +133 -40
- package/tests/vitest/unit/apps/updateApp.test.ts +42 -11
- package/tests/vitest/unit/auth/fetchTempToken401.test.ts +3 -2
- package/tests/vitest/unit/auth/getTempToken.test.ts +42 -18
- package/tests/vitest/unit/auth/retryTempToken401.test.ts +46 -64
- package/tests/vitest/unit/auth/retryTempTokenMaxRetries.test.ts +235 -0
- package/tests/vitest/unit/auth/retryUserToken401.test.ts +56 -43
- package/tests/vitest/unit/auth/ssoTokenRefresh.test.ts +325 -0
- package/tests/vitest/unit/fields/createField.test.ts +180 -116
- package/tests/vitest/unit/fields/getFieldUsage.test.ts +17 -3
- package/tests/vitest/unit/fields/updateField.test.ts +12 -7
- package/tests/vitest/unit/formulas/runFormula.test.ts +205 -0
- package/tests/vitest/unit/index.ts +2 -1
- package/tests/vitest/unit/inferHttpMethod.test.ts +131 -0
- package/tests/vitest/unit/rateLimit.test.ts +4 -2
- package/tests/vitest/unit/tables/createRelationship.test.ts +212 -0
- package/tests/vitest/unit/tables/deleteRelationship.test.ts +97 -0
- package/tests/vitest/unit/tables/updateRelationship.test.ts +12 -10
- package/tests/vitest/unit/tokenLifespan.test.ts +149 -83
- package/tools/log-gen.ts +14 -5
- package/tools/log-gen.yaml +710 -268
- package/tests/vitest/unit/auth/retryTempTokenTwo401.test.ts +0 -81
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
// tests/vitest/unit/tables/updateRelationship.test.ts
|
|
2
|
-
|
|
3
1
|
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
4
2
|
import {
|
|
5
3
|
createClient,
|
|
@@ -76,7 +74,7 @@ describe("QuickbaseClient Unit - updateRelationship", () => {
|
|
|
76
74
|
|
|
77
75
|
expect(result).toEqual(mockResponse);
|
|
78
76
|
expect(mockFetch).toHaveBeenCalledWith(
|
|
79
|
-
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
77
|
+
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
80
78
|
expect.objectContaining({
|
|
81
79
|
method: "POST",
|
|
82
80
|
headers: expect.objectContaining({
|
|
@@ -156,7 +154,7 @@ describe("QuickbaseClient Unit - updateRelationship", () => {
|
|
|
156
154
|
);
|
|
157
155
|
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
158
156
|
2,
|
|
159
|
-
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
157
|
+
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
160
158
|
expect.objectContaining({
|
|
161
159
|
method: "POST",
|
|
162
160
|
headers: expect.objectContaining({
|
|
@@ -233,7 +231,7 @@ describe("QuickbaseClient Unit - updateRelationship", () => {
|
|
|
233
231
|
);
|
|
234
232
|
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
235
233
|
2,
|
|
236
|
-
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
234
|
+
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
237
235
|
expect.objectContaining({
|
|
238
236
|
headers: expect.objectContaining({
|
|
239
237
|
Authorization: "QB-TEMP-TOKEN initial_token",
|
|
@@ -247,20 +245,24 @@ describe("QuickbaseClient Unit - updateRelationship", () => {
|
|
|
247
245
|
);
|
|
248
246
|
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
249
247
|
4,
|
|
250
|
-
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
248
|
+
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
251
249
|
expect.objectContaining({
|
|
252
250
|
headers: expect.objectContaining({
|
|
253
251
|
Authorization: "QB-TEMP-TOKEN new_token",
|
|
254
252
|
}),
|
|
255
253
|
})
|
|
256
254
|
);
|
|
255
|
+
|
|
256
|
+
// Updated log expectations
|
|
257
257
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
258
|
-
"Authorization error for updateRelationship (temp token), refreshing token:"
|
|
259
|
-
expect.any(String)
|
|
258
|
+
"Authorization error for updateRelationship (temp token), refreshing token:"
|
|
260
259
|
);
|
|
261
260
|
expect(consoleSpy).toHaveBeenCalledWith(
|
|
262
|
-
|
|
261
|
+
expect.stringContaining(
|
|
262
|
+
"[updateRelationship] Retrying with token: new_tok"
|
|
263
|
+
)
|
|
263
264
|
);
|
|
265
|
+
|
|
264
266
|
consoleSpy.mockRestore();
|
|
265
267
|
});
|
|
266
268
|
|
|
@@ -289,7 +291,7 @@ describe("QuickbaseClient Unit - updateRelationship", () => {
|
|
|
289
291
|
).rejects.toThrow("API Error: Invalid field ID (Status: 400)");
|
|
290
292
|
|
|
291
293
|
expect(mockFetch).toHaveBeenCalledWith(
|
|
292
|
-
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
294
|
+
`https://api.quickbase.com/v1/tables/${tableId}/relationship/${relationshipId}`,
|
|
293
295
|
expect.objectContaining({
|
|
294
296
|
method: "POST",
|
|
295
297
|
headers: expect.objectContaining({
|
|
@@ -1,120 +1,184 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, vi } from "vitest";
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
2
|
import { createClient, mockFetch, QB_APP_ID, QB_REALM } from "@tests/setup.ts";
|
|
3
3
|
import { UpdateAppRequest, UpdateApp200Response } from "@/generated/models";
|
|
4
4
|
|
|
5
5
|
describe("QuickbaseClient Unit - Token Lifespan", () => {
|
|
6
6
|
let client: ReturnType<typeof createClient>;
|
|
7
|
+
const request: UpdateAppRequest = { name: "Test App" };
|
|
8
|
+
const mockResponse: UpdateApp200Response = {
|
|
9
|
+
id: QB_APP_ID,
|
|
10
|
+
name: "Test App",
|
|
11
|
+
description: "",
|
|
12
|
+
created: new Date("2020-01-01T00:00:00Z"), // Match deserialized Date object
|
|
13
|
+
updated: new Date("2020-01-01T00:00:00Z"),
|
|
14
|
+
dateFormat: "MM-DD-YYYY",
|
|
15
|
+
timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
|
|
16
|
+
hasEveryoneOnTheInternet: false,
|
|
17
|
+
ancestorId: undefined,
|
|
18
|
+
variables: [],
|
|
19
|
+
securityProperties: {},
|
|
20
|
+
memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
|
|
21
|
+
dataClassification: "None",
|
|
22
|
+
};
|
|
7
23
|
|
|
8
24
|
beforeEach(() => {
|
|
9
25
|
mockFetch.mockClear();
|
|
26
|
+
vi.useFakeTimers();
|
|
27
|
+
console.log("[beforeEach] mockFetch cleared and fake timers enabled");
|
|
10
28
|
});
|
|
11
29
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
realm: QB_REALM,
|
|
16
|
-
useTempTokens: true,
|
|
17
|
-
tokenLifespan: 500, // 0.5 seconds
|
|
18
|
-
debug: true,
|
|
19
|
-
});
|
|
30
|
+
afterEach(() => {
|
|
31
|
+
vi.useRealTimers();
|
|
32
|
+
});
|
|
20
33
|
|
|
21
|
-
|
|
22
|
-
name: "Test App",
|
|
23
|
-
};
|
|
24
|
-
const mockResponse: UpdateApp200Response = {
|
|
25
|
-
id: QB_APP_ID,
|
|
26
|
-
name: "Test App",
|
|
27
|
-
description: "",
|
|
28
|
-
created: new Date("2020-01-01T00:00:00Z"),
|
|
29
|
-
updated: new Date("2020-01-01T00:00:00Z"),
|
|
30
|
-
dateFormat: "MM-DD-YYYY",
|
|
31
|
-
timeZone: "(UTC-08:00) Pacific Time (US & Canada)",
|
|
32
|
-
hasEveryoneOnTheInternet: false,
|
|
33
|
-
ancestorId: null,
|
|
34
|
-
variables: [],
|
|
35
|
-
securityProperties: {},
|
|
36
|
-
memoryInfo: { estMemory: 0, estMemoryInclDependentApps: 0 },
|
|
37
|
-
dataClassification: "None",
|
|
38
|
-
};
|
|
39
|
-
|
|
40
|
-
// First call: Fetch a new token
|
|
34
|
+
const setupMocks = (token: string) => {
|
|
41
35
|
mockFetch
|
|
42
36
|
.mockResolvedValueOnce({
|
|
43
37
|
ok: true,
|
|
44
38
|
status: 200,
|
|
45
|
-
json: () => Promise.resolve({ temporaryAuthorization:
|
|
39
|
+
json: () => Promise.resolve({ temporaryAuthorization: token }),
|
|
46
40
|
})
|
|
47
41
|
.mockResolvedValueOnce({
|
|
48
42
|
ok: true,
|
|
49
43
|
status: 200,
|
|
50
44
|
json: () => Promise.resolve(mockResponse),
|
|
51
45
|
});
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
it("reuses token within custom lifespan and refetches after expiration", async () => {
|
|
49
|
+
client = createClient(mockFetch, {
|
|
50
|
+
realm: QB_REALM,
|
|
51
|
+
useTempTokens: true,
|
|
52
|
+
tempTokenLifespan: 500,
|
|
53
|
+
debug: true,
|
|
54
|
+
});
|
|
52
55
|
|
|
56
|
+
setupMocks("token1");
|
|
53
57
|
await client.updateApp({ appId: QB_APP_ID, body: request });
|
|
54
|
-
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
58
|
+
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
59
|
+
expect(mockFetch.mock.calls[1][1].headers.Authorization).toBe(
|
|
60
|
+
"QB-TEMP-TOKEN token1"
|
|
61
|
+
);
|
|
55
62
|
|
|
56
|
-
// Second call within lifespan: Should reuse token1
|
|
57
63
|
mockFetch.mockResolvedValueOnce({
|
|
58
64
|
ok: true,
|
|
59
65
|
status: 200,
|
|
60
66
|
json: () => Promise.resolve(mockResponse),
|
|
61
67
|
});
|
|
62
68
|
await client.updateApp({ appId: QB_APP_ID, body: request });
|
|
63
|
-
expect(mockFetch).toHaveBeenCalledTimes(3);
|
|
69
|
+
expect(mockFetch).toHaveBeenCalledTimes(3);
|
|
70
|
+
expect(mockFetch.mock.calls[2][1].headers.Authorization).toBe(
|
|
71
|
+
"QB-TEMP-TOKEN token1"
|
|
72
|
+
);
|
|
64
73
|
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
vi.advanceTimersByTime(500);
|
|
75
|
+
console.log("[Test 1] Token expired after 500ms");
|
|
67
76
|
|
|
68
|
-
|
|
69
|
-
mockFetch
|
|
70
|
-
.mockResolvedValueOnce({
|
|
71
|
-
ok: true,
|
|
72
|
-
status: 200,
|
|
73
|
-
json: () => Promise.resolve({ temporaryAuthorization: "token2" }),
|
|
74
|
-
})
|
|
75
|
-
.mockResolvedValueOnce({
|
|
76
|
-
ok: true,
|
|
77
|
-
status: 200,
|
|
78
|
-
json: () => Promise.resolve(mockResponse),
|
|
79
|
-
});
|
|
77
|
+
setupMocks("token2");
|
|
80
78
|
await client.updateApp({ appId: QB_APP_ID, body: request });
|
|
81
|
-
expect(mockFetch).toHaveBeenCalledTimes(5);
|
|
79
|
+
expect(mockFetch).toHaveBeenCalledTimes(5);
|
|
80
|
+
expect(mockFetch.mock.calls[4][1].headers.Authorization).toBe(
|
|
81
|
+
"QB-TEMP-TOKEN token2"
|
|
82
|
+
);
|
|
82
83
|
});
|
|
83
84
|
|
|
84
|
-
it("
|
|
85
|
-
// No tokenLifespan provided, should use default (4:50 = 290,000ms)
|
|
85
|
+
it("reuses token within default lifespan of 4m50s", async () => {
|
|
86
86
|
client = createClient(mockFetch, {
|
|
87
87
|
realm: QB_REALM,
|
|
88
88
|
useTempTokens: true,
|
|
89
89
|
debug: true,
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
};
|
|
110
|
-
|
|
111
|
-
|
|
92
|
+
setupMocks("default_token");
|
|
93
|
+
await client.updateApp({ appId: QB_APP_ID, body: request });
|
|
94
|
+
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
95
|
+
expect(mockFetch.mock.calls[1][1].headers.Authorization).toBe(
|
|
96
|
+
"QB-TEMP-TOKEN default_token"
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
vi.advanceTimersByTime(1000);
|
|
100
|
+
console.log(
|
|
101
|
+
"[Test 2] Advanced time by 1000ms, still within default lifespan"
|
|
102
|
+
);
|
|
103
|
+
|
|
104
|
+
mockFetch.mockResolvedValueOnce({
|
|
105
|
+
ok: true,
|
|
106
|
+
status: 200,
|
|
107
|
+
json: () => Promise.resolve(mockResponse),
|
|
108
|
+
});
|
|
109
|
+
await client.updateApp({ appId: QB_APP_ID, body: request });
|
|
110
|
+
expect(mockFetch).toHaveBeenCalledTimes(3);
|
|
111
|
+
expect(mockFetch.mock.calls[2][1].headers.Authorization).toBe(
|
|
112
|
+
"QB-TEMP-TOKEN default_token"
|
|
113
|
+
);
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
it("handles token fetch failure gracefully", async () => {
|
|
117
|
+
client = createClient(mockFetch, {
|
|
118
|
+
realm: QB_REALM,
|
|
119
|
+
useTempTokens: true,
|
|
120
|
+
tempTokenLifespan: 500,
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
mockFetch.mockResolvedValueOnce({
|
|
124
|
+
ok: false,
|
|
125
|
+
status: 500,
|
|
126
|
+
json: () => Promise.resolve({ message: "Network error" }),
|
|
127
|
+
});
|
|
128
|
+
await expect(
|
|
129
|
+
client.updateApp({ appId: QB_APP_ID, body: request })
|
|
130
|
+
).rejects.toThrow("API Error: Network error (Status: 500)");
|
|
131
|
+
expect(mockFetch).toHaveBeenCalledTimes(1);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
it("fetches new token every call with zero lifespan", async () => {
|
|
135
|
+
client = createClient(mockFetch, {
|
|
136
|
+
realm: QB_REALM,
|
|
137
|
+
useTempTokens: true,
|
|
138
|
+
tempTokenLifespan: 0,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
setupMocks("token1");
|
|
142
|
+
await client.updateApp({ appId: QB_APP_ID, body: request });
|
|
143
|
+
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
144
|
+
|
|
145
|
+
setupMocks("token2");
|
|
146
|
+
await client.updateApp({ appId: QB_APP_ID, body: request });
|
|
147
|
+
expect(mockFetch).toHaveBeenCalledTimes(4);
|
|
148
|
+
expect(mockFetch.mock.calls[3][1].headers.Authorization).toBe(
|
|
149
|
+
"QB-TEMP-TOKEN token2"
|
|
150
|
+
);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it("reuses token across concurrent calls within lifespan", async () => {
|
|
154
|
+
client = createClient(mockFetch, {
|
|
155
|
+
realm: QB_REALM,
|
|
156
|
+
useTempTokens: true,
|
|
157
|
+
tempTokenLifespan: 500,
|
|
158
|
+
debug: true,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Pre-fetch token to ensure it’s cached
|
|
162
|
+
mockFetch.mockResolvedValueOnce({
|
|
163
|
+
ok: true,
|
|
164
|
+
status: 200,
|
|
165
|
+
json: () => Promise.resolve({ temporaryAuthorization: "token1" }),
|
|
166
|
+
});
|
|
167
|
+
mockFetch.mockResolvedValueOnce({
|
|
168
|
+
ok: true,
|
|
169
|
+
status: 200,
|
|
170
|
+
json: () => Promise.resolve(mockResponse),
|
|
171
|
+
});
|
|
172
|
+
await client.updateApp({ appId: QB_APP_ID, body: request }); // Cache token1
|
|
173
|
+
vi.advanceTimersByTime(1);
|
|
174
|
+
|
|
175
|
+
// Reset mocks and set up API responses
|
|
176
|
+
mockFetch.mockClear();
|
|
112
177
|
mockFetch
|
|
113
178
|
.mockResolvedValueOnce({
|
|
114
179
|
ok: true,
|
|
115
180
|
status: 200,
|
|
116
|
-
json: () =>
|
|
117
|
-
Promise.resolve({ temporaryAuthorization: "default_token" }),
|
|
181
|
+
json: () => Promise.resolve(mockResponse),
|
|
118
182
|
})
|
|
119
183
|
.mockResolvedValueOnce({
|
|
120
184
|
ok: true,
|
|
@@ -122,17 +186,19 @@ describe("QuickbaseClient Unit - Token Lifespan", () => {
|
|
|
122
186
|
json: () => Promise.resolve(mockResponse),
|
|
123
187
|
});
|
|
124
188
|
|
|
125
|
-
|
|
126
|
-
|
|
189
|
+
const [call1, call2] = await Promise.all([
|
|
190
|
+
client.updateApp({ appId: QB_APP_ID, body: request }),
|
|
191
|
+
client.updateApp({ appId: QB_APP_ID, body: request }),
|
|
192
|
+
]);
|
|
127
193
|
|
|
128
|
-
|
|
129
|
-
mockFetch.
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
expect(
|
|
194
|
+
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
195
|
+
expect(mockFetch.mock.calls[0][1].headers.Authorization).toBe(
|
|
196
|
+
"QB-TEMP-TOKEN token1"
|
|
197
|
+
);
|
|
198
|
+
expect(mockFetch.mock.calls[1][1].headers.Authorization).toBe(
|
|
199
|
+
"QB-TEMP-TOKEN token1"
|
|
200
|
+
);
|
|
201
|
+
expect(call1).toEqual(mockResponse);
|
|
202
|
+
expect(call2).toEqual(mockResponse);
|
|
137
203
|
});
|
|
138
204
|
});
|
package/tools/log-gen.ts
CHANGED
|
@@ -31,23 +31,32 @@ const includeRecursiveFolders: string[] = [
|
|
|
31
31
|
// prettier-ignore
|
|
32
32
|
const includeFiles: string[] = [
|
|
33
33
|
// "tests/setup.ts",
|
|
34
|
+
// "vitest.config.ts",
|
|
34
35
|
|
|
35
36
|
// "package.json",
|
|
36
37
|
// "tsconfig.json",
|
|
37
38
|
// "tsconfig.build.json",
|
|
38
39
|
// "rollup.config.js",
|
|
39
|
-
// "vitest.config.ts",
|
|
40
40
|
// "build-common.js",
|
|
41
41
|
// "build-umd.js",
|
|
42
42
|
// "build-esm.js",
|
|
43
|
-
|
|
44
|
-
// "src/generated/runtime.ts",
|
|
43
|
+
|
|
45
44
|
// "src/quickbaseClient.ts",
|
|
46
45
|
// "src/invokeMethod.ts",
|
|
47
46
|
// "src/generated-unified/QuickbaseClient.ts",
|
|
48
|
-
|
|
47
|
+
// "src/authorizationStrategy.ts",
|
|
48
|
+
// "src/rateLimiter.ts",
|
|
49
49
|
// "src/RateLimitError.ts",
|
|
50
|
-
// "src/
|
|
50
|
+
// "src/ThrottleBucket.ts",
|
|
51
|
+
// "src/tokenCache.ts",
|
|
52
|
+
// "src/utils.ts",
|
|
53
|
+
|
|
54
|
+
// "src/generated/runtime.ts",
|
|
55
|
+
// "src/generated/apis/AuthApi.ts",
|
|
56
|
+
// "src/generated/apis/FieldsApi.ts",
|
|
57
|
+
// "src/generated/apis/AppsApi.ts",
|
|
58
|
+
|
|
59
|
+
"test/vitest/unit/fields/createField.test.ts",
|
|
51
60
|
];
|
|
52
61
|
|
|
53
62
|
const projectGoals: string[] = [
|