quickbase-js 0.1.0-beta.8 → 1.0.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 (132) hide show
  1. package/README.md +252 -126
  2. package/dist/esm/quickbase.d.ts +2725 -2689
  3. package/dist/esm/quickbase.js +1763 -3524
  4. package/dist/esm/quickbase.js.map +1 -1
  5. package/dist/esm/quickbase.min.js +1 -1
  6. package/dist/esm/quickbase.min.js.map +1 -1
  7. package/dist/umd/quickbase.umd.js +1762 -3706
  8. package/dist/umd/quickbase.umd.js.map +1 -1
  9. package/dist/umd/quickbase.umd.min.js +1 -1
  10. package/dist/umd/quickbase.umd.min.js.map +1 -1
  11. package/package.json +27 -12
  12. package/CHANGELOG.md +0 -155
  13. package/build-common.js +0 -131
  14. package/build-esm.js +0 -71
  15. package/build-umd.js +0 -69
  16. package/examples/quicbase-jsCDN.html +0 -36
  17. package/examples/react.js +0 -48
  18. package/examples/vanillajs.html +0 -47
  19. package/open-api/fix-spec-main.ts +0 -97
  20. package/open-api/generate-override-report.ts +0 -214
  21. package/open-api/generate-unified-interface.ts +0 -256
  22. package/open-api/output/override-report.html +0 -11
  23. package/open-api/output/override-report.json +0 -14395
  24. package/open-api/output/quickbase-fixed.json +0 -11191
  25. package/open-api/regenerate-client.ts +0 -116
  26. package/open-api/schema/enhance-general.ts +0 -100
  27. package/open-api/schema/fix-arrays.ts +0 -69
  28. package/open-api/schema/tags/apps.ts +0 -90
  29. package/open-api/schema/tags/fields.ts +0 -471
  30. package/open-api/schema/tags/groups.ts +0 -51
  31. package/open-api/schema/tags/index.ts +0 -66
  32. package/open-api/schema/tags/records.ts +0 -115
  33. package/open-api/schema/tags/tables.ts +0 -211
  34. package/open-api/schema/tags/users.ts +0 -47
  35. package/open-api/types/spec.ts +0 -42
  36. package/open-api/utils/infer-schema.ts +0 -40
  37. package/open-api/utils/naming.ts +0 -10
  38. package/playwright.config.ts +0 -37
  39. package/rollup.config.js +0 -114
  40. package/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +0 -46878
  41. package/specs/split/apps.json +0 -1315
  42. package/specs/split/auth.json +0 -191
  43. package/specs/split/fields.json +0 -3869
  44. package/specs/split/records.json +0 -754
  45. package/specs/split/reports.json +0 -619
  46. package/specs/split/tables.json +0 -1605
  47. package/src/RateLimitError.ts +0 -12
  48. package/src/ThrottleBucket.ts +0 -36
  49. package/src/generated-unified/QuickbaseClient.ts +0 -359
  50. package/src/generated-unified/missing-types-report.json +0 -3
  51. package/src/index.ts +0 -1
  52. package/src/invokeMethod.ts +0 -357
  53. package/src/quickbaseClient.ts +0 -244
  54. package/src/tokenCache.ts +0 -51
  55. package/src/utils.ts +0 -7
  56. package/test-esm.js +0 -1
  57. package/test-results.json +0 -2050
  58. package/test-umd.js +0 -1
  59. package/test.ts +0 -1
  60. package/tests/playwright/qb/auth/cacheSwitching.test.ts +0 -159
  61. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +0 -219
  62. package/tests/playwright/qb/auth/getAppWithTempToken.test.ts +0 -162
  63. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +0 -153
  64. package/tests/playwright/qb/auth/getTempToken.test.ts +0 -152
  65. package/tests/playwright/qb/auth/tempTokenPrefetch.test.ts +0 -179
  66. package/tests/playwright/qb/auth/tempTokenRenewal.test.ts +0 -133
  67. package/tests/setup.ts +0 -53
  68. package/tests/vitest/qb/apps/copyApp.test.ts +0 -76
  69. package/tests/vitest/qb/apps/createApp.test.ts +0 -64
  70. package/tests/vitest/qb/apps/deleteApp.test.ts +0 -76
  71. package/tests/vitest/qb/apps/getApp.test.ts +0 -44
  72. package/tests/vitest/qb/apps/getAppEvents.test.ts +0 -67
  73. package/tests/vitest/qb/apps/updateApp.test.ts +0 -58
  74. package/tests/vitest/qb/auth/retryUserToken401.test.ts +0 -56
  75. package/tests/vitest/qb/fields/createField.test.ts +0 -77
  76. package/tests/vitest/qb/fields/deleteFields.test.ts +0 -83
  77. package/tests/vitest/qb/fields/getField.test.ts +0 -85
  78. package/tests/vitest/qb/fields/getFieldUsage.test.ts +0 -174
  79. package/tests/vitest/qb/fields/getFields.test.ts +0 -232
  80. package/tests/vitest/qb/fields/getFieldsUsage.test.ts +0 -77
  81. package/tests/vitest/qb/fields/updateField.test.ts +0 -93
  82. package/tests/vitest/qb/index.ts +0 -29
  83. package/tests/vitest/qb/records/deleteRecords.test.ts +0 -110
  84. package/tests/vitest/qb/records/runQuery.test.ts +0 -146
  85. package/tests/vitest/qb/records/upsert.test.ts +0 -102
  86. package/tests/vitest/qb/tables/createTable.test.ts +0 -55
  87. package/tests/vitest/qb/tables/deleteTable.test.ts +0 -50
  88. package/tests/vitest/qb/tables/getAppTables.test.ts +0 -46
  89. package/tests/vitest/qb/tables/getRelationships.test.ts +0 -80
  90. package/tests/vitest/qb/tables/getTable.test.ts +0 -26
  91. package/tests/vitest/qb/tables/updateRelationship.test.ts +0 -277
  92. package/tests/vitest/qb/tables/updateTable.test.ts +0 -48
  93. package/tests/vitest/unit/apps/copyApp.test.ts +0 -488
  94. package/tests/vitest/unit/apps/createApp.test.ts +0 -186
  95. package/tests/vitest/unit/apps/deleteApp.test.ts +0 -216
  96. package/tests/vitest/unit/apps/getApp.test.ts +0 -128
  97. package/tests/vitest/unit/apps/getAppEvents.test.ts +0 -193
  98. package/tests/vitest/unit/apps/updateApp.test.ts +0 -381
  99. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +0 -62
  100. package/tests/vitest/unit/auth/getTempToken.test.ts +0 -95
  101. package/tests/vitest/unit/auth/retryTempToken401.test.ts +0 -113
  102. package/tests/vitest/unit/auth/retryTempTokenTwo401.test.ts +0 -81
  103. package/tests/vitest/unit/auth/retryUserToken401.test.ts +0 -56
  104. package/tests/vitest/unit/fields/createField.test.ts +0 -387
  105. package/tests/vitest/unit/fields/deleteFields.test.ts +0 -141
  106. package/tests/vitest/unit/fields/getField.test.ts +0 -189
  107. package/tests/vitest/unit/fields/getFieldUsage.test.ts +0 -166
  108. package/tests/vitest/unit/fields/getFields.test.ts +0 -122
  109. package/tests/vitest/unit/fields/getFieldsUsage.test.ts +0 -160
  110. package/tests/vitest/unit/fields/updateField.test.ts +0 -280
  111. package/tests/vitest/unit/index.ts +0 -33
  112. package/tests/vitest/unit/rateLimit.test.ts +0 -189
  113. package/tests/vitest/unit/records/deleteRecords.test.ts +0 -112
  114. package/tests/vitest/unit/records/runQuery.test.ts +0 -102
  115. package/tests/vitest/unit/records/upsert.test.ts +0 -234
  116. package/tests/vitest/unit/tables/createTable.test.ts +0 -70
  117. package/tests/vitest/unit/tables/deleteTable.test.ts +0 -77
  118. package/tests/vitest/unit/tables/getAppTables.test.ts +0 -85
  119. package/tests/vitest/unit/tables/getRelationships.test.ts +0 -259
  120. package/tests/vitest/unit/tables/getTable.test.ts +0 -233
  121. package/tests/vitest/unit/tables/updateRelationship.test.ts +0 -305
  122. package/tests/vitest/unit/tables/updateTable.test.ts +0 -80
  123. package/tests/vitest/unit/tokenLifespan.test.ts +0 -138
  124. package/tests/vitest/unit/umd.test.ts +0 -8
  125. package/text.txt +0 -104
  126. package/tools/log-gen.ts +0 -235
  127. package/tools/log-gen.yaml +0 -4982
  128. package/tools/openapi-jars/openapi-generator-cli-7.12.0.jar +0 -0
  129. package/tsconfig.build.json +0 -17
  130. package/tsconfig.json +0 -32
  131. package/versionrc.json +0 -9
  132. package/vitest.config.ts +0 -27
package/README.md CHANGED
@@ -1,204 +1,330 @@
1
1
  # quickbase-js
2
2
 
3
- # Installation
3
+ A Typescript API client for the [Quickbase JSON RESTful API](https://developer.quickbase.com/).
4
+
5
+ Support for various authentication types (`user token`, `temporary tokens`, `SSO token`), `concurrent rate limiting strategies`, `auto pagination`, `js date conversion`, `429` (rate limit) and `401` (auth) error handling retries. It uses a Proxy to dynamically invoke API methods derived from the OpenAPI specification.
6
+
7
+ Browser and Node.js support. ESM and UMD builds are available.
8
+
9
+ Authentication and throttle methods are opinionated. See configuration options for details and available settings.
10
+
11
+ ## API Documentation
12
+
13
+ <a href="https://quickbase-js.netlify.app/" target="_blank"> Documentation</a> for quickbase-js.
14
+
15
+ ## Installation
16
+
17
+ #### Node.js install
4
18
 
5
19
  ```bash
6
20
  npm install --save quickbase-js
7
21
  ```
8
22
 
9
- ## Examples
23
+ #### CDN install.
10
24
 
11
- ### CDN Code Page
25
+ Find and select the latest version. UMD is recommended for code pages.
26
+
27
+ <a href="https://www.jsdelivr.com/package/npm/quickbase-js?tab=files" target="_blank">CDN Files</a> for quickbase-js
12
28
 
13
29
  ```html
14
30
  <!DOCTYPE html>
15
31
  <html>
16
32
  <head>
17
33
  <title>Quickbase</title>
18
- <script src="https://cdn.jsdelivr.net/npm/quickbase-js@1.1.0-beta.6/dist/umd/quickbase.umd.min.js"></script>
34
+ <!-- Replace xx.xx.xx with the latest version from CDN Files-->
35
+ <script src="https://cdn.jsdelivr.net/npm/quickbase-js@xx.xx.xx/dist/umd/quickbase.umd.min.js"></script>
19
36
  </head>
20
-
21
37
  <body>
22
- <div>
23
- <h1>Quickbase-js CDN Example</h1>
24
- <p id="result">Loading...</p>
25
- </div>
26
38
  <script>
27
- var realm = "xxxxxxxxxxxxxxxxxxxx"; // replace with your realm
28
- var appId = "xxxxxxxxxxxxxxxxxxxx"; // replace with your app ID
29
- if (typeof QuickbaseJS === "undefined") {
30
- document.getElementById("result").textContent =
31
- "Error: Failed to load QuickbaseJS library.";
32
- } else {
33
- var qbClient = QuickbaseJS.quickbase({
34
- realm,
35
- useTempTokens: true,
36
- });
37
-
38
- qbClient
39
- .getApp({ appId })
40
- .then(function (app) {
41
- document.getElementById("result").textContent =
42
- "App Name: " + app.name;
43
- })
44
- .catch(function (err) {
45
- document.getElementById("result").textContent =
46
- "Error: " + (err.message || "Failed to load app");
47
- });
48
- }
39
+ const realm = ""; // Replace with your realm
40
+ const appId = ""; // Replace with your app ID
41
+
42
+ const qb = QuickbaseJS.quickbase({
43
+ realm,
44
+ useTempTokens: true,
45
+ });
46
+
47
+ qb.getApp({ appId })
48
+ .then((app) => console.log(app.name))
49
+ .catch((err) => console.log(err.message));
49
50
  </script>
50
51
  </body>
51
52
  </html>
52
53
  ```
53
54
 
54
- # Development workflow
55
-
56
- ```bash
57
- npm run gen:all
58
- npm run build
59
- npm run test:all
60
- ```
55
+ ## Authentication Examples
61
56
 
62
- ## Usage
57
+ ### User Token
63
58
 
64
- ### Node.js (ESM - Recommended)
59
+ ```javascript
60
+ import { quickbase } from "quickbase-js"; // Adjust the import path as needed
65
61
 
66
- For modern Node.js applications, use ES modules:
62
+ // QuickBase config variables
63
+ const QB_REALM = ""; // Your QuickBase realm (e.g., 'mycompany')
64
+ const QB_USER_TOKEN = ""; // Your QuickBase user token (e.g., 'b12345_abcde...')
65
+ const QB_APP_ID = ""; // Your app ID (e.g., 'bxyz789')
67
66
 
68
- ```javascript
69
- // ESM (Node.js) - Recommended
70
- import { quickbase } from "quickbase-js";
71
- const qb = quickbase({ realm: "example", userToken: "your-token" });
72
-
73
- // Example: Fetching an app
74
- const app = await qb.getApp({ appId: "your-app-id" });
75
- console.log(app);
76
-
77
- // Example: Creating a record with temporary token
78
- const qbTemp = quickbase({ realm: "example", useTempTokens: true });
79
- const record = await qbTemp.upsert({
80
- body: {
81
- to: "your-table-id",
82
- data: [
83
- {
84
- /* record data */
85
- },
86
- ],
87
- },
67
+ const qb = quickbase({
68
+ realm: QB_REALM,
69
+ userToken: QB_USER_TOKEN,
88
70
  });
89
- console.log(record);
71
+
72
+ const getAppDetails = async () => {
73
+ try {
74
+ const response = await qb.getApp({
75
+ appId: QB_APP_ID,
76
+ });
77
+ console.log("App Details:", response);
78
+ } catch (error) {
79
+ console.error("Error fetching app:", error.message);
80
+ }
81
+ };
82
+
83
+ getAppDetails();
90
84
  ```
91
85
 
86
+ ### Temporary Tokens (Code Pages)
87
+
92
88
  ```javascript
93
- // Example: TypeScript ESM (Recommended)
94
- import { quickbase } from "quickbase-js";
95
- const qbTyped: QuickbaseClient = quickbase({
96
- realm: "example",
97
- userToken: "your-token",
89
+ import { quickbase } from "quickbase-js"; // Adjust the import path as needed
90
+
91
+ // QuickBase config variables
92
+ const QB_REALM = ""; // Your QuickBase realm (e.g., 'mycompany')
93
+ const QB_APP_ID = ""; // Your app ID (e.g., 'bxyz789')
94
+
95
+ const qb = quickbase({
96
+ realm: QB_REALM,
97
+ useTempTokens: true,
98
98
  });
99
- const typedApp = await qbTyped.getApp({ appId: "your-app-id" });
100
- console.log(typedApp);
99
+
100
+ const getAppDetails = async () => {
101
+ try {
102
+ const response = await qb.getApp({
103
+ appId: QB_APP_ID,
104
+ });
105
+ console.log("App Details:", response);
106
+ } catch (error) {
107
+ console.error("Error fetching app:", error.message);
108
+ }
109
+ };
110
+
111
+ getAppDetails();
101
112
  ```
102
113
 
114
+ ### SSO Token
115
+
103
116
  ```javascript
104
- // Example: UMD via CDN (QuickBase Code Pages)
105
- // Note: This is HTML, not JavaScript, and should be used in a browser environment
117
+ import { quickbase } from "quickbase-js"; // Adjust the import path as needed
106
118
 
107
- <script src="https://cdn.jsdelivr.net/npm/quickbase-js@1.1.0-beta.4/dist/umd/quickbase.umd.js"></script>
108
- <script>
109
- const qb = new QuickbaseJS({ realm: 'example', useTempTokens: true });
110
- // Example: Fetching an app
111
- qb.getApp({ appId: 'your-app-id' }).then(app => console.log(app));
112
- </script>
119
+ // QuickBase config variables
120
+ const QB_REALM = ""; // Your QuickBase realm (e.g., 'mycompany')
121
+ const QB_SAML_TOKEN = ""; // Your SAML token (e.g., 'saml_xyz789...')
122
+ const QB_APP_ID = ""; // Your app ID (e.g., 'bxyz789')
113
123
 
124
+ const qb = quickbase({
125
+ realm: QB_REALM,
126
+ samlToken: QB_SAML_TOKEN,
127
+ useSso: true,
128
+ });
129
+
130
+ const getAppDetails = async () => {
131
+ try {
132
+ const response = await qb.getApp({
133
+ appId: QB_APP_ID,
134
+ });
135
+ console.log("App Details:", response);
136
+ } catch (error) {
137
+ console.error("Error fetching app:", error.message);
138
+ }
139
+ };
140
+
141
+ getAppDetails();
114
142
  ```
115
143
 
116
- ## In QuickBase Code Pages (Browser Environment)
144
+ ## Configuration
145
+
146
+ The `quickbase` function accepts a `QuickbaseConfig` object with the following options:
117
147
 
118
- ### useTempTokens: true:
148
+ ### User Options
119
149
 
120
- Token Fetch: Auto-fetches temporary tokens using the provided fetchApi (or window.fetch by default) with cookies (withCredentials: true in the internal tokenClient).
150
+ - **`realm`** (`string`): Your QuickBase realm (e.g., "company"). This is required and has no default value.
121
151
 
122
- Subsequent Calls (e.g., getApp): Uses the same fetchApi (or window.fetch) with the QB-TEMP-TOKEN {TOKEN} header. No additional config needed beyond realm and useTempTokens.
152
+ - **`userToken`** (`string`, optional): A QuickBase user token for authentication. No default is provided.
123
153
 
124
- How It Works: Leverages the browser’s session cookies for the initial token fetch, then uses the token for all API calls. In a real code page, window.fetch handles both steps seamlessly.
154
+ - **`useTempTokens`** (`boolean`, optional): Enables temporary token authentication. Defaults to `false`.
125
155
 
126
- Test Output: The test uses page.evaluate for token fetch and node-fetch for getApp to bypass Playwright’s browser fetch issue, but in a code page, it’s all window.fetch.
156
+ - **`useSso`** (`boolean`, optional): Enables SSO authentication. Defaults to `false`.
127
157
 
128
- ### userToken:
158
+ - **`samlToken`** (`string`, optional): A SAML token for SSO authentication. No default is provided.
129
159
 
130
- All Calls: Uses the provided fetchApi (or window.fetch by default) with the QB-USER-TOKEN {TOKEN} header. No session cookies needed (credentials: "omit").
160
+ ### Advanced User Options
131
161
 
132
- How It Works: The user token authenticates directly, independent of the browser session, making it straightforward and reliable.
162
+ - **`throttle`** (`{ type?: 'flow' | 'burst-aware';` `rate?: number;` `burst?: number;` `windowSeconds?: number }`, optional): Configures concurrent rate limiting to manage API request throughput. Defaults to `{ type: 'flow', rate: 5, burst: 50 }`.
133
163
 
134
- Test Output: Confirms this with page.evaluate sending QB-USER-TOKEN.
164
+ - **`type`** (`string`): Throttle strategy. _Setting type without rate or burst enables default settings for that throttle type._
135
165
 
136
- ## In Node.js (Non-Browser Environment)
166
+ - `'flow'` (default): Uses `FlowThrottleBucket` for a QuickBase-agnostic burst-then-rate flow. Ideal for steady request pacing.
137
167
 
138
- ### userToken:
168
+ - `'burst-aware'`: Uses `BurstAwareThrottleBucket` for QuickBase-specific burst throttling with a sliding window (e.g., 100 requests per 10 seconds). Ideal for when you need to use nearly all your allotted API calls immediately, for example on page load.
139
169
 
140
- All Calls: Works with a provided fetchApi (e.g., fetchApi: node-fetch). Sets QB-USER-TOKEN {TOKEN} header.
170
+ _Set rate and burst if changing defaults._
141
171
 
142
- How It Works: Fully functional as long as fetchApi is supplied (e.g., node-fetch), since user tokens don’t require a browser session.
172
+ - **`rate`** (`number`): Requests per second after the initial burst (for `'flow'` only). Default is `5`. Meaning 5 request tokens get created each second.
143
173
 
144
- Requirement: Must provide fetchApi explicitly (no default in Node.js).
174
+ - **`burst`** (`number`): Maximum concurrent requests:
175
+ - For `'flow'`: Initial concurrent burst size (default: 50), followed by `rate`/sec.
176
+ - For `'burst-aware'`: Concurrent burst cap per window (default: 100), waits for window reset if exceeded.
177
+ - **`windowSeconds`** (`number`, `'burst-aware'` only): Sliding window duration in seconds (default: 10). Caps total requests (e.g., 100 requests available every 10s).
145
178
 
146
- ### useTempTokens: true:
179
+ - **Examples**:
180
+ - `{ type: 'flow', rate: 5, burst: 50 }`: **~10s for 100 requests**, (50 instant, and 1 every 200ms. In other words, 50 at 10/sec).
181
+ - `{ type: 'burst-aware', burst: 100, windowSeconds: 10 }`: **~10s for 100 requests**, (100 instant, refreshing every 10s for next burst).
147
182
 
148
- Behavior: Fails with a clear error unless a browser-like fetchApi is provided:
183
+ - **`maxRetries`** (`number`, optional): Maximum retries for failed requests. Defaults to `3`.
149
184
 
150
- "Temporary tokens require a browser environment or a custom fetchApi with browser-like session support"
185
+ - **`retryDelay`** (`number`, optional): Base delay (in milliseconds) between retries, increases exponentially. Defaults to `1000`.
151
186
 
152
- How It Works: Temp tokens need a browser session with cookies, which Node.js can’t provide natively. A custom fetchApi (e.g., via Puppeteer) could work but is impractical for typical Node.js use.
187
+ - **`tempTokenLifespan`** (`number`, optional): Lifespan (in milliseconds) of temporary tokens in the cache. Defaults to 4 minutes 50 seconds (290000 ms).
153
188
 
154
- Practicality: Effectively unusable in Node.js without external browser support, aligning with QuickBase’s temp token requirement.
189
+ - **`convertDates`** (`boolean`, optional): Converts ISO date strings to `Date` objects in responses. Defaults to `true`.
155
190
 
156
- ## getTempTokenDBID
191
+ - **`autoPaginate`** (`boolean`, optional): Enables automatic pagination of multi-page API responses. Defaults to `true`.
157
192
 
158
- Temporary Token Handling with getTempTokenDBID
159
- The QuickBase API provides the getTempTokenDBID method to fetch temporary tokens (QB-TEMP-TOKEN) for browser-based authentication, typically using session credentials (e.g., cookies). These tokens are short-lived (~5 minutes) and intended for secure, client-side API calls. In the generated OpenAPI client, getTempTokenDBID makes a straightforward GET request to /v1/auth/temporary/{dbid} and returns { temporaryAuthorization: string }. However, this raw implementation lacks caching and doesn’t optimize repeated calls, which can lead to unnecessary API requests.
160
- In quickbaseClient.ts, we enhance getTempTokenDBID when useTempTokens: true is enabled, wrapping it with intelligent token management:
161
- Caching: We introduce a TokenCache to store temporary tokens by dbid. Before fetching a new token, the client checks the cache. If a valid token exists, it’s returned immediately, avoiding redundant API calls.
193
+ ### Overrides and Development Options
162
194
 
163
- Custom Fetch Logic: Instead of relying solely on the generated method, we use a custom fetchTempToken function to fetch tokens. This ensures consistency with browser-based session authentication (credentials: "include") and allows us to cache the result.
195
+ - **`fetchApi`** (`typeof fetch`, optional): Defaults to built-in `fetch` in browsers and Node.js >= 18. In older Node.js versions, node-fetch or another compatible library via fetchApi is required.
164
196
 
165
- Early Returns: For getTempTokenDBID, we bypass the generated method’s execution by returning the cached or freshly fetched token directly. This prevents unnecessary calls to the underlying API when the token is already available or just retrieved.
197
+ - **`baseUrl`** (`string`, optional): Base URL for the QuickBase API. Defaults to `"https://api.quickbase.com/v1"`.
166
198
 
167
- Why This Matters
168
- Efficiency: Caching reduces API requests, crucial for performance in browser environments where temp tokens are fetched frequently but don’t change within their lifespan.
199
+ - **`debug`** (`boolean`, optional): Enables debug logging to the console. Defaults to `false`.
169
200
 
170
- Seamless Integration: The wrapper supports both QB-USER-TOKEN (server-side) and QB-TEMP-TOKEN (client-side) workflows, controlled by the useTempTokens config. This makes the client versatile for different use cases.
201
+ - **`tempToken`** (`string`, optional): Overrides default tempToken behavior by providing your own token.
171
202
 
172
- Testability: The enhancement fixes issues in unit tests (e.g., getTempToken.test.ts) by ensuring predictable behavior—fetching once and reusing cached tokens—avoiding unexpected errors from redundant calls.
203
+ - **`tokenCache`** (`TokenCache`, optional): Allows use of a custom token cache instance.
173
204
 
174
- How It Works
175
- When you call client.getTempTokenDBID({ dbid: "someDbid" }) with useTempTokens: true:
176
- Cache Check: Looks for an existing token in tokenCache for the given dbid.
205
+ ---
177
206
 
178
- Fetch if Needed: If no cached token exists, fetchTempToken requests a new one from /v1/auth/temporary/{dbid} and caches it.
207
+ #### Configuration Notes
179
208
 
180
- Return Early: Returns { temporaryAuthorization: token } immediately, skipping the generated method’s execution.
209
+ - **Authentication**: Three mutually exclusive methods: `userToken`, `useTempTokens`, and `useSso` with `samlToken`. Only one may be active at a time.
210
+ - **`tokenCache`**: Temporary tokens are cached here with their `dbid` and `tempTokenLifespan` when `useTempTokens` is enabled.
181
211
 
182
- For other methods (e.g., getFields), the fetched temp token is applied to the Authorization header, ensuring authenticated API calls without re-fetching.
212
+ ---
213
+
214
+ ### Pagination Control
215
+
216
+ The library supports automatic pagination for methods like `runQuery` when `autoPaginate` is enabled (default: `true`). To temporarily disable or constrain pagination for a specific operation without altering the global configuration, use the `withPaginationDisabled()` or `withPaginationLimit()` methods.
217
+
218
+ #### `withPaginationDisabled(callback)`
219
+
220
+ - **Description**: Executes an asynchronous callback with pagination temporarily disabled, restoring the original `autoPaginate` setting afterward. Useful for fetching only the initial page of results without modifying method signatures or global settings.
221
+ - **Parameters**:
222
+ - `callback`: `() => Promise<T>` - An async function containing the API call(s) to execute without pagination.
223
+ - **Returns**: `Promise<T>` - The result of the callback.
224
+ - **Example**:
225
+
226
+ ```javascript
227
+ import { quickbase } from "quickbase-js"; // Adjust the import path as needed
228
+
229
+ const QB_REALM = ""; // Your QuickBase realm (e.g., 'mycompany')
230
+ const QB_USER_TOKEN = ""; // Your QuickBase user token (e.g., 'b12345_abcde...')
231
+ const QB_TABLE_ID = ""; // Your table ID (e.g., 'bxyz789')
232
+
233
+ const qb = quickbase({
234
+ realm: QB_REALM,
235
+ userToken: QB_USER_TOKEN,
236
+ autoPaginate: true, // Pagination enabled by default
237
+ });
238
+
239
+ const runLimitedQuery = async () => {
240
+ try {
241
+ const result = await qb.withPaginationDisabled(async () => {
242
+ return qb.runQuery({
243
+ body: {
244
+ from: QB_TABLE_ID,
245
+ select: [3], // Example field ID
246
+ options: { top: 2 }, // Fetch only 2 records
247
+ },
248
+ });
249
+ });
250
+ console.log("Fetched records:", result.data.length); // Outputs: 2
251
+ } catch (error) {
252
+ console.error("Error running query:", error.message);
253
+ }
254
+ };
255
+
256
+ runLimitedQuery();
257
+ ```
258
+
259
+ #### `withPaginationLimit(limit, callback)`
260
+
261
+ - **Description**: Executes an asynchronous callback with pagination enabled but limited to a specified number of records, restoring the original `autoPaginate` setting afterward. Useful for fetching a precise number of records (e.g., 100) from a larger dataset, stopping pagination once the limit is reached, without modifying method signatures or global settings.
262
+ - **Parameters**:
263
+ - `limit`: `number` - The maximum number of records to fetch across all pages.
264
+ - `callback`: `() => Promise<T>` - An async function containing the API call(s) to execute with the pagination limit.
265
+ - **Returns**: `Promise<T>` - The result of the callback, containing up to `limit` records.
266
+ - **Example**:
267
+
268
+ ```javascript
269
+ import { quickbase } from "quickbase-js"; // Adjust the import path as needed
270
+
271
+ const QB_REALM = ""; // Your QuickBase realm (e.g., 'mycompany')
272
+ const QB_USER_TOKEN = ""; // Your QuickBase user token (e.g., 'b12345_abcde...')
273
+ const QB_TABLE_ID = ""; // Your table ID (e.g., 'bxyz789')
274
+
275
+ const qb = quickbase({
276
+ realm: QB_REALM,
277
+ userToken: QB_USER_TOKEN,
278
+ autoPaginate: true, // Pagination enabled by default
279
+ });
280
+
281
+ const runCappedQuery = async () => {
282
+ try {
283
+ const result = await qb.withPaginationLimit(100, async () => {
284
+ return qb.runQuery({
285
+ body: {
286
+ from: QB_TABLE_ID,
287
+ select: [3], // Example field ID
288
+ options: { top: 25 }, // Fetch 25 records per page
289
+ },
290
+ });
291
+ });
292
+ console.log("Fetched records:", result.data.length); // Outputs: 100
293
+ } catch (error) {
294
+ console.error("Error running query:", error.message);
295
+ }
296
+ };
297
+
298
+ runCappedQuery();
299
+ ```
300
+
301
+ ---
302
+
303
+ ### Development workflow
304
+
305
+ ```bash
306
+ npm run gen:all
307
+ npm run build
308
+ npm run test:all
309
+ ```
183
310
 
184
- ## 401 Unauthorized Error Behavior
311
+ ---
185
312
 
186
- The quickbase-js library manages 401 Unauthorized errors from the QuickBase API when using temporary tokens (useTempTokens: true). Normally, it keeps tokens fresh via a time-managed cache intending to never have a 401 Unauthorized error, but there is added safety measures incase a 401 happens to occur.
313
+ ### Prerequisites
187
314
 
188
- If a 401 happens, the library tries once more with a fresh temporary token.
315
+ - Node.js version >= 18
316
+ - A Quickbase account. [Free tier available](https://www.quickbase.com/builder-program).
189
317
 
190
- It gets the new token using fetchTempToken and retries the call.
318
+ ---
191
319
 
192
- If the retry fails with another 401, it stops and throws an error like API Error: Unauthorized (Status: 401).
320
+ ### Contributing
193
321
 
194
- Fetching a New Token:
195
- If fetchTempToken itself gets a 401 (e.g., no valid login session), it doesn’t retry.
322
+ If you would like to contribute to this project, please fork the repository and submit a pull request.
196
323
 
197
- It throws an error right away: API Error: Unauthorized (Status: 401).
324
+ ---
198
325
 
199
- Why It’s Like This
200
- One Retry: Retries once to fix expired tokens, but stops to avoid endless tries.
326
+ ### License
201
327
 
202
- Fast Fail: No retry on fetchTempToken 401s means you know quickly if login is broken.
328
+ MIT License - see LICENSE for details.
203
329
 
204
- No Loops: Built to never get stuck retrying forever.
330
+ ---