quickbase-js 1.1.0-beta.6 → 1.1.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 (111) hide show
  1. package/README.md +253 -135
  2. package/dist/esm/quickbase.d.ts +5614 -2861
  3. package/dist/esm/quickbase.js +3204 -2116
  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 +3533 -2325
  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 +49 -32
  12. package/CHANGELOG.md +0 -93
  13. package/build.js +0 -186
  14. package/dist/umd/quickbase.umd.d.ts +0 -5341
  15. package/examples/react.js +0 -48
  16. package/examples/vanillajs.html +0 -47
  17. package/examples/vanillatest.html +0 -49
  18. package/log-gen.yaml +0 -1372
  19. package/open-api/definitions/apps.ts +0 -274
  20. package/open-api/definitions/auth.ts +0 -10
  21. package/open-api/definitions/fields.ts +0 -751
  22. package/open-api/definitions/index.ts +0 -18
  23. package/open-api/definitions/records.ts +0 -269
  24. package/open-api/definitions/relationships.ts +0 -90
  25. package/open-api/definitions/reports.ts +0 -10
  26. package/open-api/definitions/tables.ts +0 -112
  27. package/open-api/fix-spec-main.ts +0 -176
  28. package/open-api/generate-unified-interface.ts +0 -170
  29. package/open-api/output/quickbase-fixed.json +0 -6760
  30. package/open-api/paths/apps.ts +0 -100
  31. package/open-api/paths/auth.ts +0 -25
  32. package/open-api/paths/fields.ts +0 -207
  33. package/open-api/paths/index.ts +0 -17
  34. package/open-api/paths/records.ts +0 -68
  35. package/open-api/paths/relationships.ts +0 -32
  36. package/open-api/paths/reports.ts +0 -34
  37. package/open-api/paths/tables.ts +0 -162
  38. package/open-api/regenerate-client.ts +0 -110
  39. package/playwright-results.txt/.last-run.json +0 -4
  40. package/playwright.config.ts +0 -37
  41. package/rollup.config.mjs +0 -114
  42. package/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +0 -46878
  43. package/src/generated-unified/QuickbaseClient.ts +0 -62
  44. package/src/index.ts +0 -1
  45. package/src/quickbaseClient.ts +0 -313
  46. package/src/tokenCache.ts +0 -51
  47. package/test-artifacts/.last-run.json +0 -6
  48. package/test-esm.js +0 -1
  49. package/test-results.json +0 -2050
  50. package/test-umd.js +0 -1
  51. package/test.ts +0 -1
  52. package/tests/playwright/qb/auth/cacheSwitching.test.ts +0 -189
  53. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +0 -217
  54. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +0 -151
  55. package/tests/playwright/qb/auth/getTempToken.test.ts +0 -180
  56. package/tests/playwright/qb/auth/tokenPrefetch.test.ts +0 -192
  57. package/tests/playwright/qb/auth/tokenRenewal.test.ts +0 -110
  58. package/tests/playwright/qb/auth/umd.test.ts +0 -10
  59. package/tests/setup.ts +0 -51
  60. package/tests/vitest/qb/apps/copyApp.test.ts +0 -76
  61. package/tests/vitest/qb/apps/createApp.test.ts +0 -64
  62. package/tests/vitest/qb/apps/deleteApp.test.ts +0 -76
  63. package/tests/vitest/qb/apps/getApp.test.ts +0 -40
  64. package/tests/vitest/qb/fields/createField.test.ts +0 -78
  65. package/tests/vitest/qb/fields/deleteFields.test.ts +0 -89
  66. package/tests/vitest/qb/fields/getField.test.ts +0 -85
  67. package/tests/vitest/qb/fields/getFieldUsage.test.ts +0 -174
  68. package/tests/vitest/qb/fields/getFields.test.ts +0 -232
  69. package/tests/vitest/qb/fields/getFieldsUsage.test.ts +0 -77
  70. package/tests/vitest/qb/index.ts +0 -28
  71. package/tests/vitest/qb/records/deleteRecords.test.ts +0 -110
  72. package/tests/vitest/qb/records/runQuery.test.ts +0 -146
  73. package/tests/vitest/qb/records/upsert.test.ts +0 -102
  74. package/tests/vitest/qb/tables/createTable.test.ts +0 -55
  75. package/tests/vitest/qb/tables/deleteTable.test.ts +0 -50
  76. package/tests/vitest/qb/tables/getAppTables.test.ts +0 -46
  77. package/tests/vitest/qb/tables/getRelationships.test.ts +0 -80
  78. package/tests/vitest/qb/tables/getTable.test.ts +0 -26
  79. package/tests/vitest/qb/tables/updateTable.test.ts +0 -48
  80. package/tests/vitest/unit/apps/copyApp.test.ts +0 -282
  81. package/tests/vitest/unit/apps/createApp.test.ts +0 -125
  82. package/tests/vitest/unit/apps/deleteApp.test.ts +0 -215
  83. package/tests/vitest/unit/apps/getApp.test.ts +0 -86
  84. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +0 -85
  85. package/tests/vitest/unit/auth/getTempToken.test.ts +0 -95
  86. package/tests/vitest/unit/auth/retryOn401.test.ts +0 -106
  87. package/tests/vitest/unit/auth/two401s.test.ts +0 -77
  88. package/tests/vitest/unit/fields/createField.test.ts +0 -391
  89. package/tests/vitest/unit/fields/deleteFields.test.ts +0 -141
  90. package/tests/vitest/unit/fields/getField.test.ts +0 -189
  91. package/tests/vitest/unit/fields/getFieldUsage.test.ts +0 -147
  92. package/tests/vitest/unit/fields/getFields.test.ts +0 -122
  93. package/tests/vitest/unit/fields/getFieldsUsage.test.ts +0 -160
  94. package/tests/vitest/unit/index.ts +0 -33
  95. package/tests/vitest/unit/records/deleteRecords.test.ts +0 -112
  96. package/tests/vitest/unit/records/runQuery.test.ts +0 -102
  97. package/tests/vitest/unit/records/upsert.test.ts +0 -218
  98. package/tests/vitest/unit/tables/createTable.test.ts +0 -70
  99. package/tests/vitest/unit/tables/deleteTable.test.ts +0 -77
  100. package/tests/vitest/unit/tables/getAppTables.test.ts +0 -85
  101. package/tests/vitest/unit/tables/getRelationships.test.ts +0 -259
  102. package/tests/vitest/unit/tables/getTable.test.ts +0 -233
  103. package/tests/vitest/unit/tables/updateTable.test.ts +0 -80
  104. package/tests/vitest/unit/umd.test.ts +0 -8
  105. package/text.txt +0 -104
  106. package/tools/log-gen.ts +0 -175
  107. package/tools/openapi-jars/openapi-generator-cli-7.12.0.jar +0 -0
  108. package/tsconfig.build.json +0 -17
  109. package/tsconfig.json +0 -29
  110. package/versionrc.json +0 -9
  111. package/vitest.config.ts +0 -27
package/README.md CHANGED
@@ -1,212 +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
- ## Example
23
+ #### CDN install.
24
+
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
10
28
 
11
29
  ```html
12
30
  <!DOCTYPE html>
13
31
  <html>
14
32
  <head>
15
- <title>Quickbase Test</title>
33
+ <title>Quickbase</title>
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>
16
36
  </head>
17
-
18
37
  <body>
19
- <div>
20
- <h1>Quickbase Test</h1>
21
- <p id="result">Loading...</p>
22
- </div>
23
- <script type="module">
24
- import { quickbase } from "quickbase-js";
25
- // Initalize the QuickBase client
26
- const qb = quickbase({
27
- realm: "your-realm", // Replace with actual QuickBase realm
28
- // ## ------------------------------
29
- // ## Authentication Options
30
- // ## ----------------------------
31
- // ## OPTION 1: User Token Authentication
32
- // ## - Use this if you have a QuickBase user token.
33
- // ## - Works in Node.js or browsers, ideal for standalone apps or testing outside QuickBase
34
- // ## - Uncomment the line below and replace with your token; comment out 'useTempTokens'
35
- // userToken: "your-user-token",
36
-
37
- // ## ----------------------------
38
- // ## OPTION 2: Temporary Token Authentication
39
- // ## - Use this for QuickBase code pages, leveraging the browser’s authenticated session
40
- // ## - No user token needed; requires running in a QuickBase browser context
41
- // ## - Uncomment the line below and comment out 'userToken' if using this option
42
- // useTempTokens: true,
38
+ <script>
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,
43
45
  });
44
46
 
45
- // Fetch the app
46
- qb.getApp({ appId: "your-app-id" }) // Replace with actual app ID
47
- .then((app) => {
48
- document.getElementById(
49
- "result"
50
- ).textContent = `App Name: ${app.name}`;
51
- })
52
- .catch((err) => {
53
- console.error("Error fetching app:", err);
54
- document.getElementById("result").textContent =
55
- err.message || "Failed to load app";
56
- });
47
+ qb.getApp({ appId })
48
+ .then((app) => console.log(app.name))
49
+ .catch((err) => console.log(err.message));
57
50
  </script>
58
51
  </body>
59
52
  </html>
60
53
  ```
61
54
 
62
- # Development workflow
63
-
64
- ```bash
65
- npm run regenerate:all
66
- npm run build
67
- npm run test:all
68
- ```
55
+ ## Authentication Examples
69
56
 
70
- ## Usage
57
+ ### User Token
71
58
 
72
- ### Node.js (ESM - Recommended)
59
+ ```javascript
60
+ import { quickbase } from "quickbase-js"; // Adjust the import path as needed
73
61
 
74
- 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')
75
66
 
76
- ```javascript
77
- // ESM (Node.js) - Recommended
78
- import { quickbase } from "quickbase-js";
79
- const qb = quickbase({ realm: "example", userToken: "your-token" });
80
-
81
- // Example: Fetching an app
82
- const app = await qb.getApp({ appId: "your-app-id" });
83
- console.log(app);
84
-
85
- // Example: Creating a record with temporary token
86
- const qbTemp = quickbase({ realm: "example", useTempTokens: true });
87
- const record = await qbTemp.upsert({
88
- body: {
89
- to: "your-table-id",
90
- data: [
91
- {
92
- /* record data */
93
- },
94
- ],
95
- },
67
+ const qb = quickbase({
68
+ realm: QB_REALM,
69
+ userToken: QB_USER_TOKEN,
96
70
  });
97
- 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();
98
84
  ```
99
85
 
86
+ ### Temporary Tokens (Code Pages)
87
+
100
88
  ```javascript
101
- // Example: TypeScript ESM (Recommended)
102
- import { quickbase } from "quickbase-js";
103
- const qbTyped: QuickbaseClient = quickbase({
104
- realm: "example",
105
- 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,
106
98
  });
107
- const typedApp = await qbTyped.getApp({ appId: "your-app-id" });
108
- 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();
109
112
  ```
110
113
 
114
+ ### SSO Token
115
+
111
116
  ```javascript
112
- // Example: UMD via CDN (QuickBase Code Pages)
113
- // 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
114
118
 
115
- <script src="https://cdn.jsdelivr.net/npm/quickbase-js@1.1.0-beta.4/dist/umd/quickbase.umd.js"></script>
116
- <script>
117
- const qb = new QuickbaseJS({ realm: 'example', useTempTokens: true });
118
- // Example: Fetching an app
119
- qb.getApp({ appId: 'your-app-id' }).then(app => console.log(app));
120
- </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')
121
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();
122
142
  ```
123
143
 
124
- ## In QuickBase Code Pages (Browser Environment)
144
+ ## Configuration
145
+
146
+ The `quickbase` function accepts a `QuickbaseConfig` object with the following options:
147
+
148
+ ### User Options
125
149
 
126
- ### useTempTokens: true:
150
+ - **`realm`** (`string`): Your QuickBase realm (e.g., "company"). This is required and has no default value.
127
151
 
128
- Token Fetch: Auto-fetches temporary tokens using the provided fetchApi (or window.fetch by default) with cookies (withCredentials: true in the internal tokenClient).
152
+ - **`userToken`** (`string`, optional): A QuickBase user token for authentication. No default is provided.
129
153
 
130
- 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.
154
+ - **`useTempTokens`** (`boolean`, optional): Enables temporary token authentication. Defaults to `false`.
131
155
 
132
- 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.
156
+ - **`useSso`** (`boolean`, optional): Enables SSO authentication. Defaults to `false`.
133
157
 
134
- 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.
158
+ - **`samlToken`** (`string`, optional): A SAML token for SSO authentication. No default is provided.
135
159
 
136
- ### userToken:
160
+ ### Advanced User Options
137
161
 
138
- All Calls: Uses the provided fetchApi (or window.fetch by default) with the QB-USER-TOKEN {TOKEN} header. No session cookies needed (credentials: "omit").
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 }`.
139
163
 
140
- How It Works: The user token authenticates directly, independent of the browser session, making it straightforward and reliable.
164
+ - **`type`** (`string`): Throttle strategy. _Setting type without rate or burst enables default settings for that throttle type._
141
165
 
142
- Test Output: Confirms this with page.evaluate sending QB-USER-TOKEN.
166
+ - `'flow'` (default): Uses `FlowThrottleBucket` for a QuickBase-agnostic burst-then-rate flow. Ideal for steady request pacing.
143
167
 
144
- ## In Node.js (Non-Browser Environment)
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.
145
169
 
146
- ### userToken:
170
+ _Set rate and burst if changing defaults._
147
171
 
148
- All Calls: Works with a provided fetchApi (e.g., fetchApi: node-fetch). Sets QB-USER-TOKEN {TOKEN} header.
172
+ - **`rate`** (`number`): Requests per second after the initial burst (for `'flow'` only). Default is `5`. Meaning 5 request tokens get created each second.
149
173
 
150
- How It Works: Fully functional as long as fetchApi is supplied (e.g., node-fetch), since user tokens don’t require a browser session.
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).
151
178
 
152
- Requirement: Must provide fetchApi explicitly (no default in Node.js).
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).
153
182
 
154
- ### useTempTokens: true:
183
+ - **`maxRetries`** (`number`, optional): Maximum retries for failed requests. Defaults to `3`.
155
184
 
156
- Behavior: Fails with a clear error unless a browser-like fetchApi is provided:
185
+ - **`retryDelay`** (`number`, optional): Base delay (in milliseconds) between retries, increases exponentially. Defaults to `1000`.
157
186
 
158
- "Temporary tokens require a browser environment or a custom fetchApi with browser-like session support"
187
+ - **`tempTokenLifespan`** (`number`, optional): Lifespan (in milliseconds) of temporary tokens in the cache. Defaults to 4 minutes 50 seconds (290000 ms).
159
188
 
160
- 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.
189
+ - **`convertDates`** (`boolean`, optional): Converts ISO date strings to `Date` objects in responses. Defaults to `true`.
161
190
 
162
- Practicality: Effectively unusable in Node.js without external browser support, aligning with QuickBase’s temp token requirement.
191
+ - **`autoPaginate`** (`boolean`, optional): Enables automatic pagination of multi-page API responses. Defaults to `true`.
163
192
 
164
- ## getTempTokenDBID
193
+ ### Overrides and Development Options
165
194
 
166
- Temporary Token Handling with getTempTokenDBID
167
- 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.
168
- In quickbaseClient.ts, we enhance getTempTokenDBID when useTempTokens: true is enabled, wrapping it with intelligent token management:
169
- 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.
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.
170
196
 
171
- 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.
197
+ - **`baseUrl`** (`string`, optional): Base URL for the QuickBase API. Defaults to `"https://api.quickbase.com/v1"`.
172
198
 
173
- 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.
199
+ - **`debug`** (`boolean`, optional): Enables debug logging to the console. Defaults to `false`.
174
200
 
175
- Why This Matters
176
- Efficiency: Caching reduces API requests, crucial for performance in browser environments where temp tokens are fetched frequently but don’t change within their lifespan.
201
+ - **`tempToken`** (`string`, optional): Overrides default tempToken behavior by providing your own token.
177
202
 
178
- 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.
203
+ - **`tokenCache`** (`TokenCache`, optional): Allows use of a custom token cache instance.
179
204
 
180
- 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.
205
+ ---
181
206
 
182
- How It Works
183
- When you call client.getTempTokenDBID({ dbid: "someDbid" }) with useTempTokens: true:
184
- Cache Check: Looks for an existing token in tokenCache for the given dbid.
207
+ #### Configuration Notes
185
208
 
186
- Fetch if Needed: If no cached token exists, fetchTempToken requests a new one from /v1/auth/temporary/{dbid} and caches it.
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.
187
211
 
188
- Return Early: Returns { temporaryAuthorization: token } immediately, skipping the generated method’s execution.
212
+ ---
189
213
 
190
- For other methods (e.g., getFields), the fetched temp token is applied to the Authorization header, ensuring authenticated API calls without re-fetching.
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
+ ```
191
310
 
192
- ## 401 Unauthorized Error Behavior
311
+ ---
193
312
 
194
- 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
195
314
 
196
- 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).
197
317
 
198
- It gets the new token using fetchTempToken and retries the call.
318
+ ---
199
319
 
200
- If the retry fails with another 401, it stops and throws an error like API Error: Unauthorized (Status: 401).
320
+ ### Contributing
201
321
 
202
- Fetching a New Token:
203
- 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.
204
323
 
205
- It throws an error right away: API Error: Unauthorized (Status: 401).
324
+ ---
206
325
 
207
- Why It’s Like This
208
- One Retry: Retries once to fix expired tokens, but stops to avoid endless tries.
326
+ ### License
209
327
 
210
- Fast Fail: No retry on fetchTempToken 401s means you know quickly if login is broken.
328
+ MIT License - see LICENSE for details.
211
329
 
212
- No Loops: Built to never get stuck retrying forever.
330
+ ---