quickbase-js 1.1.0-beta.0 → 1.1.0-beta.2
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 +16 -0
- package/dist/quickbase.d.ts +356 -6
- package/dist/quickbase.js +363 -20
- package/dist/quickbase.js.map +1 -1
- package/examples/react.js +42 -16
- package/examples/vanillajs.html +32 -8
- package/log-gen.yaml +146 -198
- package/package.json +4 -4
- package/src/code-generation/fix-spec-definitions.ts +99 -41
- package/src/code-generation/fix-spec-paths.ts +6 -19
- package/src/code-generation/generate-unified-interface.ts +1 -8
- package/src/code-generation/output/quickbase-fixed.json +142 -21
- package/src/generated-unified/QuickbaseClient.ts +3 -3
- package/tests/playwright/qb/auth/cacheSwitching.test.ts +2 -2
- package/tests/setup.ts +29 -9
- package/tests/vitest/qb/fields/getFields.test.ts +3 -5
- package/tests/vitest/qb/records/runQuery.test.ts +82 -0
- package/tests/vitest/unit/apps/getApp.test.ts +17 -12
- package/tests/vitest/unit/auth/fetchTempToken401.test.ts +29 -4
- package/tests/vitest/unit/auth/getTempToken.test.ts +30 -17
- package/tests/vitest/unit/auth/retryOn401.test.ts +39 -5
- package/tests/vitest/unit/fields/getFields.test.ts +14 -7
- package/tests/vitest/unit/records/deleteRecords.test.ts +28 -34
- package/tests/vitest/unit/records/runQuery.test.ts +102 -0
- package/tests/vitest/unit/records/upsert.test.ts +31 -41
- package/tests/vitest/unit/tables/createTable.test.ts +18 -10
- package/tests/vitest/unit/tables/deleteTable.test.ts +28 -19
- package/tests/vitest/unit/tables/getAppTables.test.ts +41 -28
- package/tests/vitest/unit/tables/getTable.test.ts +53 -32
- package/tests/vitest/unit/tables/updateTable.test.ts +17 -11
- package/vitest.config.ts +5 -0
package/examples/react.js
CHANGED
|
@@ -1,22 +1,48 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import React, { useState, useEffect } from "react";
|
|
2
|
+
import { quickbase } from "quickbase-js";
|
|
3
3
|
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
});
|
|
8
|
-
|
|
9
|
-
function App() {
|
|
10
|
-
const [app, setApp] = useState < any > null;
|
|
4
|
+
const App = () => {
|
|
5
|
+
const [appName, setAppName] = useState < string > "Loading...";
|
|
6
|
+
const [error, setError] = (useState < string) | (null > null);
|
|
11
7
|
|
|
12
8
|
useEffect(() => {
|
|
13
|
-
client
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
// Initialize the QuickBase client
|
|
10
|
+
const qb = quickbase({
|
|
11
|
+
realm: "your-realm", // Replace with actual QuickBase realm
|
|
12
|
+
// ------------------------------
|
|
13
|
+
// Authentication Options
|
|
14
|
+
// ------------------------------
|
|
15
|
+
// OPTION 1: User Token Authentication
|
|
16
|
+
// - Use this if you have a QuickBase user token (get it from "My Profile" > "Manage User Tokens")
|
|
17
|
+
// - Works in Node.js or browsers, ideal for standalone apps or testing outside QuickBase
|
|
18
|
+
// - Use the line below and replace with your token; comment out 'useTempTokens'
|
|
19
|
+
// userToken: "your-user-token",
|
|
20
|
+
|
|
21
|
+
// ------------------------------
|
|
22
|
+
// OPTION 2: Temporary Token Authentication
|
|
23
|
+
// - Use this for QuickBase code pages, leveraging the browser’s authenticated session
|
|
24
|
+
// - No user token needed; requires running in a QuickBase browser context
|
|
25
|
+
// - Uncomment the line below and comment out 'userToken' if using this option
|
|
26
|
+
// useTempTokens: true,
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
// Fetch the app
|
|
30
|
+
qb.getApp({ appId: "your-app-id" }) // Replace with actual app ID
|
|
31
|
+
.then((app) => {
|
|
32
|
+
setAppName(app.name);
|
|
33
|
+
})
|
|
34
|
+
.catch((err) => {
|
|
35
|
+
console.error("Error fetching app:", err);
|
|
36
|
+
setError("Failed to load app");
|
|
37
|
+
});
|
|
38
|
+
}, []); // Empty dependency array to run once on mount
|
|
18
39
|
|
|
19
|
-
return
|
|
20
|
-
|
|
40
|
+
return (
|
|
41
|
+
<div>
|
|
42
|
+
<h1>Quickbase Test</h1>
|
|
43
|
+
{error ? <p>{error}</p> : <p>App Name: {appName}</p>}
|
|
44
|
+
</div>
|
|
45
|
+
);
|
|
46
|
+
};
|
|
21
47
|
|
|
22
48
|
export default App;
|
package/examples/vanillajs.html
CHANGED
|
@@ -1,23 +1,47 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html>
|
|
3
|
+
|
|
3
4
|
<head>
|
|
4
5
|
<title>Quickbase Test</title>
|
|
5
6
|
</head>
|
|
7
|
+
|
|
6
8
|
<body>
|
|
7
|
-
<div
|
|
9
|
+
<div>
|
|
10
|
+
<h1>Quickbase Test</h1>
|
|
11
|
+
<p id="result">Loading...</p>
|
|
12
|
+
</div>
|
|
8
13
|
<script type="module">
|
|
9
|
-
import {
|
|
14
|
+
import { quickbase } from 'quickbase-js';
|
|
15
|
+
// Initalize the QuickBase client
|
|
16
|
+
const qb = quickbase({
|
|
17
|
+
realm: 'your-realm', // Replace with actual QuickBase realm
|
|
18
|
+
// ------------------------------
|
|
19
|
+
// Authentication Options
|
|
20
|
+
// ----------------------------
|
|
21
|
+
// OPTION 1: User Token Authentication
|
|
22
|
+
// - Use this if you have a QuickBase user token (get it from "My Profile" > "Manage User Tokens")
|
|
23
|
+
// - Works in Node.js or browsers, ideal for standalone apps or testing outside QuickBase
|
|
24
|
+
// - Uncomment the line below and replace with your token; comment out 'useTempTokens'
|
|
25
|
+
// userToken: "your-user-token",
|
|
10
26
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
27
|
+
// ----------------------------
|
|
28
|
+
// OPTION 2: Temporary Token Authentication
|
|
29
|
+
// - Use this for QuickBase code pages, leveraging the browser’s authenticated session
|
|
30
|
+
// - No user token needed; requires running in a QuickBase browser context
|
|
31
|
+
// - Uncomment the line below and comment out 'userToken' if using this option
|
|
32
|
+
// useTempTokens: true,
|
|
14
33
|
});
|
|
15
34
|
|
|
16
|
-
|
|
35
|
+
// Fetch the app
|
|
36
|
+
qb.getApp({ appId: 'your-app-id' }) // Replace with actual app ID
|
|
17
37
|
.then((app) => {
|
|
18
|
-
document.getElementById('
|
|
38
|
+
document.getElementById('result').textContent = `App Name: ${app.name}`;
|
|
19
39
|
})
|
|
20
|
-
.catch((err) =>
|
|
40
|
+
.catch((err) => {
|
|
41
|
+
console.error('Error fetching app:', err);
|
|
42
|
+
document.getElementById('result').textContent = err.message || 'Failed to load app';
|
|
43
|
+
});
|
|
21
44
|
</script>
|
|
22
45
|
</body>
|
|
46
|
+
|
|
23
47
|
</html>
|
package/log-gen.yaml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
project: quickbase-js
|
|
2
|
-
date: 3/
|
|
2
|
+
date: 3/11/2025
|
|
3
3
|
root: /home/drew/Projects/quickbase-js
|
|
4
4
|
goals:
|
|
5
5
|
- A library for interacting with the QuickBase RESTful API.
|
|
@@ -291,184 +291,6 @@ tree:
|
|
|
291
291
|
type: file
|
|
292
292
|
- name: runtime.ts
|
|
293
293
|
type: file
|
|
294
|
-
- name: generated-old
|
|
295
|
-
type: directory
|
|
296
|
-
children:
|
|
297
|
-
- name: .openapi-generator
|
|
298
|
-
type: directory
|
|
299
|
-
children:
|
|
300
|
-
- name: FILES
|
|
301
|
-
type: file
|
|
302
|
-
- name: VERSION
|
|
303
|
-
type: file
|
|
304
|
-
- name: .openapi-generator-ignore
|
|
305
|
-
type: file
|
|
306
|
-
- name: apis
|
|
307
|
-
type: directory
|
|
308
|
-
children:
|
|
309
|
-
- name: AppsApi.ts
|
|
310
|
-
type: file
|
|
311
|
-
- name: AuditApi.ts
|
|
312
|
-
type: file
|
|
313
|
-
- name: AuthApi.ts
|
|
314
|
-
type: file
|
|
315
|
-
- name: DocumentTemplatesApi.ts
|
|
316
|
-
type: file
|
|
317
|
-
- name: FieldsApi.ts
|
|
318
|
-
type: file
|
|
319
|
-
- name: FilesApi.ts
|
|
320
|
-
type: file
|
|
321
|
-
- name: FormulasApi.ts
|
|
322
|
-
type: file
|
|
323
|
-
- name: PlatformAnalyticsApi.ts
|
|
324
|
-
type: file
|
|
325
|
-
- name: RecordsApi.ts
|
|
326
|
-
type: file
|
|
327
|
-
- name: ReportsApi.ts
|
|
328
|
-
type: file
|
|
329
|
-
- name: SolutionsApi.ts
|
|
330
|
-
type: file
|
|
331
|
-
- name: TablesApi.ts
|
|
332
|
-
type: file
|
|
333
|
-
- name: UserTokenApi.ts
|
|
334
|
-
type: file
|
|
335
|
-
- name: UsersApi.ts
|
|
336
|
-
type: file
|
|
337
|
-
- name: index.ts
|
|
338
|
-
type: file
|
|
339
|
-
- name: index.ts
|
|
340
|
-
type: file
|
|
341
|
-
- name: models
|
|
342
|
-
type: directory
|
|
343
|
-
children:
|
|
344
|
-
- name: AddMembersToGroup200Response.ts
|
|
345
|
-
type: file
|
|
346
|
-
- name: AddSubgroupsToGroup200Response.ts
|
|
347
|
-
type: file
|
|
348
|
-
- name: App.ts
|
|
349
|
-
type: file
|
|
350
|
-
- name: AppMemoryInfo.ts
|
|
351
|
-
type: file
|
|
352
|
-
- name: AppSecurityProperties.ts
|
|
353
|
-
type: file
|
|
354
|
-
- name: Audit200Response.ts
|
|
355
|
-
type: file
|
|
356
|
-
- name: Audit202Response.ts
|
|
357
|
-
type: file
|
|
358
|
-
- name: AuditRequest.ts
|
|
359
|
-
type: file
|
|
360
|
-
- name: CloneUserToken200Response.ts
|
|
361
|
-
type: file
|
|
362
|
-
- name: CloneUserTokenRequest.ts
|
|
363
|
-
type: file
|
|
364
|
-
- name: CopyApp200Response.ts
|
|
365
|
-
type: file
|
|
366
|
-
- name: CopyAppRequest.ts
|
|
367
|
-
type: file
|
|
368
|
-
- name: CreateApp200Response.ts
|
|
369
|
-
type: file
|
|
370
|
-
- name: CreateAppRequest.ts
|
|
371
|
-
type: file
|
|
372
|
-
- name: CreateField200Response.ts
|
|
373
|
-
type: file
|
|
374
|
-
- name: CreateRelationship200Response.ts
|
|
375
|
-
type: file
|
|
376
|
-
- name: CreateRelationshipRequest.ts
|
|
377
|
-
type: file
|
|
378
|
-
- name: DeactivateUserToken200Response.ts
|
|
379
|
-
type: file
|
|
380
|
-
- name: DeleteApp200Response.ts
|
|
381
|
-
type: file
|
|
382
|
-
- name: DeleteAppRequest.ts
|
|
383
|
-
type: file
|
|
384
|
-
- name: DeleteFields200Response.ts
|
|
385
|
-
type: file
|
|
386
|
-
- name: DeleteFile200Response.ts
|
|
387
|
-
type: file
|
|
388
|
-
- name: DeleteRelationship200Response.ts
|
|
389
|
-
type: file
|
|
390
|
-
- name: DenyUsers200Response.ts
|
|
391
|
-
type: file
|
|
392
|
-
- name: ExchangeSsoToken200Response.ts
|
|
393
|
-
type: file
|
|
394
|
-
- name: ExchangeSsoTokenRequest.ts
|
|
395
|
-
type: file
|
|
396
|
-
- name: Field.ts
|
|
397
|
-
type: file
|
|
398
|
-
- name: FieldPermissionsInner.ts
|
|
399
|
-
type: file
|
|
400
|
-
- name: FieldProperties.ts
|
|
401
|
-
type: file
|
|
402
|
-
- name: GenerateDocument200Response.ts
|
|
403
|
-
type: file
|
|
404
|
-
- name: GetField200Response.ts
|
|
405
|
-
type: file
|
|
406
|
-
- name: GetRelationships200Response.ts
|
|
407
|
-
type: file
|
|
408
|
-
- name: GetReport200Response.ts
|
|
409
|
-
type: file
|
|
410
|
-
- name: GetTempTokenDBID200Response.ts
|
|
411
|
-
type: file
|
|
412
|
-
- name: GetUsers200Response.ts
|
|
413
|
-
type: file
|
|
414
|
-
- name: GetUsersRequest.ts
|
|
415
|
-
type: file
|
|
416
|
-
- name: PlatformAnalyticEventSummaries200Response.ts
|
|
417
|
-
type: file
|
|
418
|
-
- name: PlatformAnalyticEventSummaries200ResponseMetadata.ts
|
|
419
|
-
type: file
|
|
420
|
-
- name: PlatformAnalyticEventSummaries200ResponseResultsInner.ts
|
|
421
|
-
type: file
|
|
422
|
-
- name: PlatformAnalyticEventSummaries200ResponseResultsInnerEventTypesInner.ts
|
|
423
|
-
type: file
|
|
424
|
-
- name: PlatformAnalyticEventSummaries200ResponseResultsInnerTotals.ts
|
|
425
|
-
type: file
|
|
426
|
-
- name: PlatformAnalyticEventSummaries200ResponseTotals.ts
|
|
427
|
-
type: file
|
|
428
|
-
- name: PlatformAnalyticEventSummaries200ResponseWhereInner.ts
|
|
429
|
-
type: file
|
|
430
|
-
- name: PlatformAnalyticEventSummariesRequest.ts
|
|
431
|
-
type: file
|
|
432
|
-
- name: PlatformAnalyticEventSummariesRequestWhereInner.ts
|
|
433
|
-
type: file
|
|
434
|
-
- name: PlatformAnalyticReads200Response.ts
|
|
435
|
-
type: file
|
|
436
|
-
- name: RemoveMembersFromGroup200Response.ts
|
|
437
|
-
type: file
|
|
438
|
-
- name: RemoveSubgroupsFromGroup200Response.ts
|
|
439
|
-
type: file
|
|
440
|
-
- name: RunFormula200Response.ts
|
|
441
|
-
type: file
|
|
442
|
-
- name: RunFormulaRequest.ts
|
|
443
|
-
type: file
|
|
444
|
-
- name: RunQuery200Response.ts
|
|
445
|
-
type: file
|
|
446
|
-
- name: RunQueryRequest.ts
|
|
447
|
-
type: file
|
|
448
|
-
- name: RunReport200Response.ts
|
|
449
|
-
type: file
|
|
450
|
-
- name: Table.ts
|
|
451
|
-
type: file
|
|
452
|
-
- name: TransferUserToken200Response.ts
|
|
453
|
-
type: file
|
|
454
|
-
- name: TransferUserTokenRequest.ts
|
|
455
|
-
type: file
|
|
456
|
-
- name: UndenyUsers200Response.ts
|
|
457
|
-
type: file
|
|
458
|
-
- name: UpdateApp200Response.ts
|
|
459
|
-
type: file
|
|
460
|
-
- name: UpdateAppRequest.ts
|
|
461
|
-
type: file
|
|
462
|
-
- name: UpdateFieldRequest.ts
|
|
463
|
-
type: file
|
|
464
|
-
- name: UpdateRelationshipRequest.ts
|
|
465
|
-
type: file
|
|
466
|
-
- name: Upsert200Response.ts
|
|
467
|
-
type: file
|
|
468
|
-
- name: index.ts
|
|
469
|
-
type: file
|
|
470
|
-
- name: runtime.ts
|
|
471
|
-
type: file
|
|
472
294
|
- name: generated-unified
|
|
473
295
|
type: directory
|
|
474
296
|
children:
|
|
@@ -1901,36 +1723,157 @@ tree:
|
|
|
1901
1723
|
type: file
|
|
1902
1724
|
contents: |
|
|
1903
1725
|
// tests/vitest/qb/records/deleteRecords.test.ts
|
|
1904
|
-
import { describe, test, expect } from "vitest";
|
|
1726
|
+
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
1905
1727
|
import { quickbase } from "@/quickbaseClient.ts";
|
|
1906
1728
|
|
|
1907
|
-
|
|
1908
|
-
|
|
1729
|
+
const TABLE_ID = "buwai2zws";
|
|
1730
|
+
const UNIQUE_FIELD_ID = 3; // Record ID field
|
|
1731
|
+
const MARKER_FIELD_ID = 6; // Text field for marking test records
|
|
1732
|
+
|
|
1733
|
+
describe("QuickbaseClient - DeleteRecords Integration", () => {
|
|
1909
1734
|
const qb = quickbase({
|
|
1910
1735
|
realm: "builderprogram-dbradford6815",
|
|
1911
1736
|
userToken: process.env.QB_USER_TOKEN,
|
|
1912
1737
|
debug: true,
|
|
1913
1738
|
});
|
|
1914
1739
|
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
|
|
1918
|
-
|
|
1919
|
-
|
|
1740
|
+
beforeEach(async () => {
|
|
1741
|
+
try {
|
|
1742
|
+
await qb.deleteRecords({
|
|
1743
|
+
body: {
|
|
1744
|
+
from: TABLE_ID,
|
|
1745
|
+
where: `{${MARKER_FIELD_ID}.CT.'test-marker-delete'}`,
|
|
1746
|
+
},
|
|
1747
|
+
});
|
|
1748
|
+
} catch (e) {
|
|
1749
|
+
// Ignore if no records exist
|
|
1750
|
+
}
|
|
1751
|
+
});
|
|
1920
1752
|
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1753
|
+
afterEach(async () => {
|
|
1754
|
+
try {
|
|
1755
|
+
await qb.deleteRecords({
|
|
1756
|
+
body: {
|
|
1757
|
+
from: TABLE_ID,
|
|
1758
|
+
where: `{${MARKER_FIELD_ID}.CT.'test-marker-delete'}`,
|
|
1759
|
+
},
|
|
1760
|
+
});
|
|
1761
|
+
} catch (e) {}
|
|
1762
|
+
});
|
|
1763
|
+
|
|
1764
|
+
test(
|
|
1765
|
+
"deletes a newly upserted record",
|
|
1766
|
+
async () => {
|
|
1767
|
+
const upsertResponse = await qb.upsert({
|
|
1768
|
+
body: {
|
|
1769
|
+
to: TABLE_ID,
|
|
1770
|
+
data: [{ [MARKER_FIELD_ID]: { value: "test-marker-delete" } }],
|
|
1771
|
+
fieldsToReturn: [UNIQUE_FIELD_ID], // Return record ID
|
|
1772
|
+
},
|
|
1773
|
+
});
|
|
1774
|
+
const recordId = upsertResponse.metadata.createdRecordIds[0];
|
|
1775
|
+
expect(recordId).toBeDefined();
|
|
1776
|
+
expect(upsertResponse.data[0][UNIQUE_FIELD_ID].value).toBe(recordId);
|
|
1777
|
+
|
|
1778
|
+
const deleteResponse = await qb.deleteRecords({
|
|
1779
|
+
body: { from: TABLE_ID, where: `{${UNIQUE_FIELD_ID}.EX.${recordId}}` },
|
|
1780
|
+
});
|
|
1781
|
+
|
|
1782
|
+
expect(deleteResponse).toEqual({ numberDeleted: 1 });
|
|
1783
|
+
|
|
1784
|
+
const checkResponse = await qb.deleteRecords({
|
|
1785
|
+
body: { from: TABLE_ID, where: `{${UNIQUE_FIELD_ID}.EX.${recordId}}` },
|
|
1786
|
+
});
|
|
1787
|
+
expect(checkResponse.numberDeleted).toBe(0);
|
|
1788
|
+
},
|
|
1789
|
+
{ timeout: 10000 }
|
|
1790
|
+
);
|
|
1791
|
+
|
|
1792
|
+
test(
|
|
1793
|
+
"handles empty result when no records match",
|
|
1794
|
+
async () => {
|
|
1795
|
+
const response = await qb.deleteRecords({
|
|
1796
|
+
body: { from: TABLE_ID, where: "{3.EX.'999999'}" },
|
|
1797
|
+
});
|
|
1798
|
+
expect(response).toEqual({ numberDeleted: 0 });
|
|
1799
|
+
},
|
|
1800
|
+
{ timeout: 10000 }
|
|
1801
|
+
);
|
|
1802
|
+
});
|
|
1803
|
+
- name: upsert.test.ts
|
|
1804
|
+
type: file
|
|
1805
|
+
contents: |
|
|
1806
|
+
// tests/vitest/qb/records/upsert.test.ts
|
|
1807
|
+
import { describe, test, expect, beforeEach, afterEach } from "vitest";
|
|
1808
|
+
import { quickbase } from "@/quickbaseClient.ts";
|
|
1809
|
+
|
|
1810
|
+
const TABLE_ID = "buwai2zws";
|
|
1811
|
+
const MARKER_FIELD_ID = 6; // Text field for marking test records
|
|
1812
|
+
|
|
1813
|
+
describe("QuickbaseClient - Upsert Integration", () => {
|
|
1814
|
+
const qb = quickbase({
|
|
1815
|
+
realm: "builderprogram-dbradford6815",
|
|
1816
|
+
userToken: process.env.QB_USER_TOKEN,
|
|
1817
|
+
debug: true,
|
|
1818
|
+
});
|
|
1924
1819
|
|
|
1925
|
-
|
|
1820
|
+
beforeEach(async () => {
|
|
1821
|
+
try {
|
|
1822
|
+
await qb.deleteRecords({
|
|
1823
|
+
body: {
|
|
1824
|
+
from: TABLE_ID,
|
|
1825
|
+
where: `{${MARKER_FIELD_ID}.CT.'test-marker-upsert'}`,
|
|
1826
|
+
},
|
|
1827
|
+
});
|
|
1828
|
+
} catch (e) {
|
|
1829
|
+
// Ignore if no records exist
|
|
1830
|
+
}
|
|
1926
1831
|
});
|
|
1927
1832
|
|
|
1928
|
-
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1833
|
+
afterEach(async () => {
|
|
1834
|
+
try {
|
|
1835
|
+
await qb.deleteRecords({
|
|
1836
|
+
body: {
|
|
1837
|
+
from: TABLE_ID,
|
|
1838
|
+
where: `{${MARKER_FIELD_ID}.CT.'test-marker-upsert'}`,
|
|
1839
|
+
},
|
|
1840
|
+
});
|
|
1841
|
+
} catch (e) {}
|
|
1933
1842
|
});
|
|
1843
|
+
|
|
1844
|
+
test(
|
|
1845
|
+
"creates a new record successfully",
|
|
1846
|
+
async () => {
|
|
1847
|
+
const response = await qb.upsert({
|
|
1848
|
+
body: {
|
|
1849
|
+
to: TABLE_ID,
|
|
1850
|
+
data: [{ [MARKER_FIELD_ID]: { value: "test-marker-upsert" } }],
|
|
1851
|
+
fieldsToReturn: [MARKER_FIELD_ID, 3], // Return marker and record ID
|
|
1852
|
+
},
|
|
1853
|
+
});
|
|
1854
|
+
|
|
1855
|
+
expect(response.metadata.createdRecordIds.length).toBe(1);
|
|
1856
|
+
expect(response.data).toHaveLength(1);
|
|
1857
|
+
expect(response.data[0][MARKER_FIELD_ID].value).toBe(
|
|
1858
|
+
"test-marker-upsert"
|
|
1859
|
+
);
|
|
1860
|
+
expect(response.data[0][3].value).toBeDefined(); // Record ID assigned by QuickBase
|
|
1861
|
+
expect(response.metadata.totalNumberOfRecordsProcessed).toBe(1);
|
|
1862
|
+
},
|
|
1863
|
+
{ timeout: 10000 }
|
|
1864
|
+
);
|
|
1865
|
+
|
|
1866
|
+
test(
|
|
1867
|
+
"handles empty data gracefully",
|
|
1868
|
+
async () => {
|
|
1869
|
+
await expect(
|
|
1870
|
+
qb.upsert({
|
|
1871
|
+
body: { to: TABLE_ID, data: [] },
|
|
1872
|
+
})
|
|
1873
|
+
).rejects.toThrow("API Error: Bad Request (Status: 400)");
|
|
1874
|
+
},
|
|
1875
|
+
{ timeout: 10000 }
|
|
1876
|
+
);
|
|
1934
1877
|
});
|
|
1935
1878
|
- name: tables
|
|
1936
1879
|
type: directory
|
|
@@ -2831,6 +2774,7 @@ tree:
|
|
|
2831
2774
|
import { createClient, mockFetch } from "@tests/setup.ts";
|
|
2832
2775
|
import { vi } from "vitest";
|
|
2833
2776
|
|
|
2777
|
+
// Note: Type augmentation moved to src/types.d.ts
|
|
2834
2778
|
describe("QuickbaseClient - upsert (Unit)", () => {
|
|
2835
2779
|
beforeEach(() => {
|
|
2836
2780
|
vi.resetModules(); // Reset module cache
|
|
@@ -2961,7 +2905,7 @@ tree:
|
|
|
2961
2905
|
const result = await qb.upsert({
|
|
2962
2906
|
body: { to: "test-table-id", data: [{ "7": { value: "value2" } }] },
|
|
2963
2907
|
dbid: "test-dbid",
|
|
2964
|
-
});
|
|
2908
|
+
} as any); // Temporary type assertion until types.d.ts is applied
|
|
2965
2909
|
|
|
2966
2910
|
expect(mockFetch).toHaveBeenCalledTimes(2);
|
|
2967
2911
|
expect(mockFetch).toHaveBeenNthCalledWith(
|
|
@@ -3046,7 +2990,11 @@ tree:
|
|
|
3046
2990
|
})
|
|
3047
2991
|
);
|
|
3048
2992
|
|
|
3049
|
-
|
|
2993
|
+
if (result.data && result.data.length > 0) {
|
|
2994
|
+
expect((result.data[0]["6"] as { value: any }).value).toBe("value1");
|
|
2995
|
+
} else {
|
|
2996
|
+
throw new Error("Expected data array to have at least one element");
|
|
2997
|
+
}
|
|
3050
2998
|
});
|
|
3051
2999
|
});
|
|
3052
3000
|
- name: tables
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "quickbase-js",
|
|
3
3
|
"main": "dist/quickbase.js",
|
|
4
4
|
"types": "dist/quickbase.d.ts",
|
|
5
|
-
"version": "1.1.0-beta.
|
|
5
|
+
"version": "1.1.0-beta.2",
|
|
6
6
|
"publishConfig": {
|
|
7
7
|
"access": "public"
|
|
8
8
|
},
|
|
@@ -22,9 +22,9 @@
|
|
|
22
22
|
"release:push": "npm run release:beta && git push --follow-tags origin main",
|
|
23
23
|
"release:publish": "npm run release:push && npm publish --tag beta",
|
|
24
24
|
"fix-spec": "node --loader ts-node/esm src/code-generation/fix-spec-main.ts",
|
|
25
|
-
"regenerate": "node --loader ts-node/esm src/code-generation/regenerate-client.ts",
|
|
26
|
-
"
|
|
27
|
-
"
|
|
25
|
+
"regenerate": "rimraf src/generated && node --loader ts-node/esm src/code-generation/regenerate-client.ts",
|
|
26
|
+
"regenerate-unified": "node --loader ts-node/esm src/code-generation/generate-unified-interface.ts",
|
|
27
|
+
"regenerate-all": "npm run fix-spec && npm run regenerate && npm run regenerate-unified",
|
|
28
28
|
"log-gen": "node --loader ts-node/esm src/log-gen.ts",
|
|
29
29
|
"build": "rimraf dist && rollup -c",
|
|
30
30
|
"build:prod": "rm -rf dist/* && NODE_ENV=production rollup -c",
|