quickbase-js 1.2.0 → 2.0.0-alpha.3
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/README.md +351 -227
- package/dist/auth/index.d.ts +15 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +29 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/sso-token.d.ts +28 -0
- package/dist/auth/sso-token.d.ts.map +1 -0
- package/dist/auth/sso-token.js +108 -0
- package/dist/auth/sso-token.js.map +1 -0
- package/dist/auth/temp-token.d.ts +31 -0
- package/dist/auth/temp-token.d.ts.map +1 -0
- package/dist/auth/temp-token.js +121 -0
- package/dist/auth/temp-token.js.map +1 -0
- package/dist/auth/token-cache.d.ts +44 -0
- package/dist/auth/token-cache.d.ts.map +1 -0
- package/dist/auth/token-cache.js +84 -0
- package/dist/auth/token-cache.js.map +1 -0
- package/dist/auth/types.d.ts +44 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +5 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/auth/user-token.d.ts +17 -0
- package/dist/auth/user-token.d.ts.map +1 -0
- package/dist/auth/user-token.js +30 -0
- package/dist/auth/user-token.js.map +1 -0
- package/dist/client/index.d.ts +12 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/pagination.d.ts +131 -0
- package/dist/client/pagination.d.ts.map +1 -0
- package/dist/client/pagination.js +232 -0
- package/dist/client/pagination.js.map +1 -0
- package/dist/client/request.d.ts +45 -0
- package/dist/client/request.d.ts.map +1 -0
- package/dist/client/request.js +232 -0
- package/dist/client/request.js.map +1 -0
- package/dist/client/retry.d.ts +41 -0
- package/dist/client/retry.d.ts.map +1 -0
- package/dist/client/retry.js +122 -0
- package/dist/client/retry.js.map +1 -0
- package/dist/client/throttle.d.ts +46 -0
- package/dist/client/throttle.d.ts.map +1 -0
- package/dist/client/throttle.js +85 -0
- package/dist/client/throttle.js.map +1 -0
- package/dist/core/config.d.ts +13 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +120 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/dates.d.ts +18 -0
- package/dist/core/dates.d.ts.map +1 -0
- package/dist/core/dates.js +58 -0
- package/dist/core/dates.js.map +1 -0
- package/dist/core/errors.d.ts +134 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +185 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +41 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +96 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/types.d.ts +154 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +23 -0
- package/dist/core/types.js.map +1 -0
- package/dist/generated/client.d.ts +18 -0
- package/dist/generated/client.d.ts.map +1 -0
- package/dist/generated/client.js +1390 -0
- package/dist/generated/client.js.map +1 -0
- package/dist/generated/types.d.ts +3827 -0
- package/dist/generated/types.d.ts.map +1 -0
- package/dist/generated/types.js +8 -0
- package/dist/generated/types.js.map +1 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -0
- package/dist/quickbase.esm.js +7 -0
- package/dist/quickbase.esm.js.map +7 -0
- package/dist/quickbase.min.js +7 -0
- package/dist/quickbase.min.js.map +7 -0
- package/package.json +60 -86
- package/dist/esm/quickbase.d.ts +0 -8094
- package/dist/esm/quickbase.js +0 -8333
- package/dist/esm/quickbase.js.map +0 -1
- package/dist/esm/quickbase.min.js +0 -2
- package/dist/esm/quickbase.min.js.map +0 -1
- package/dist/umd/quickbase.umd.js +0 -8909
- package/dist/umd/quickbase.umd.js.map +0 -1
- package/dist/umd/quickbase.umd.min.js +0 -2
- package/dist/umd/quickbase.umd.min.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,330 +1,454 @@
|
|
|
1
|
-
#
|
|
1
|
+
# QuickBase JS SDK v2
|
|
2
2
|
|
|
3
|
-
A
|
|
3
|
+
A TypeScript/JavaScript client for the QuickBase JSON RESTful API.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Features
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
- **Typed API Methods** - Full TypeScript support with auto-generated types from OpenAPI spec
|
|
8
|
+
- **Multiple Auth Methods** - User token, temporary token, and SSO authentication
|
|
9
|
+
- **Fluent Pagination** - Chain `.all()`, `.paginate()`, or `.noPaginate()` on paginated endpoints
|
|
10
|
+
- **Date Conversion** - Automatic conversion of ISO date strings to JavaScript Date objects
|
|
11
|
+
- **Rate Limit Handling** - Automatic retry with exponential backoff on 429 errors
|
|
12
|
+
- **Proactive Throttling** - Optional client-side request throttling
|
|
13
|
+
- **Tree-Shakeable** - Static method generation for optimal bundle size
|
|
8
14
|
|
|
9
|
-
|
|
15
|
+
## API Reference
|
|
10
16
|
|
|
11
|
-
|
|
17
|
+
**[View all 59 API methods →](./interfaces/QuickbaseAPI.html)**
|
|
12
18
|
|
|
13
|
-
|
|
19
|
+
The SDK provides typed methods for all QuickBase API endpoints including Apps, Tables, Fields, Records, Reports, Users, and more. Each method includes JSDoc documentation with links to the official QuickBase API docs.
|
|
14
20
|
|
|
15
21
|
## Installation
|
|
16
22
|
|
|
17
|
-
|
|
23
|
+
### npm / Node.js
|
|
18
24
|
|
|
19
25
|
```bash
|
|
20
|
-
npm install
|
|
26
|
+
npm install quickbase-js
|
|
21
27
|
```
|
|
22
28
|
|
|
23
|
-
|
|
29
|
+
### Browser / CDN (QuickBase Code Pages)
|
|
24
30
|
|
|
25
|
-
|
|
31
|
+
```html
|
|
32
|
+
<script src="https://cdn.jsdelivr.net/npm/quickbase-js@2/dist/quickbase.min.js"></script>
|
|
33
|
+
<script>
|
|
34
|
+
const client = QuickBase.createClient({
|
|
35
|
+
realm: 'mycompany',
|
|
36
|
+
auth: { type: 'temp-token' },
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
client.getApp({ appId: 'bpqe82s1' }).then(app => {
|
|
40
|
+
console.log(app.name);
|
|
41
|
+
});
|
|
42
|
+
</script>
|
|
43
|
+
```
|
|
26
44
|
|
|
27
|
-
|
|
45
|
+
Or with ES modules:
|
|
28
46
|
|
|
29
47
|
```html
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
<head>
|
|
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>
|
|
36
|
-
</head>
|
|
37
|
-
<body>
|
|
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,
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
qb.getApp({ appId })
|
|
48
|
-
.then((app) => console.log(app.name))
|
|
49
|
-
.catch((err) => console.log(err.message));
|
|
50
|
-
</script>
|
|
51
|
-
</body>
|
|
52
|
-
</html>
|
|
53
|
-
```
|
|
48
|
+
<script type="module">
|
|
49
|
+
import { createClient } from 'https://cdn.jsdelivr.net/npm/quickbase-js@2/dist/quickbase.esm.js';
|
|
54
50
|
|
|
55
|
-
|
|
51
|
+
const client = createClient({
|
|
52
|
+
realm: 'mycompany',
|
|
53
|
+
auth: { type: 'temp-token' },
|
|
54
|
+
});
|
|
56
55
|
|
|
57
|
-
|
|
56
|
+
const app = await client.getApp({ appId: 'bpqe82s1' });
|
|
57
|
+
console.log(app.name);
|
|
58
|
+
</script>
|
|
59
|
+
```
|
|
58
60
|
|
|
59
|
-
|
|
60
|
-
import { quickbase } from "quickbase-js"; // Adjust the import path as needed
|
|
61
|
+
## Quick Start
|
|
61
62
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
const QB_USER_TOKEN = ""; // Your QuickBase user token (e.g., 'b12345_abcde...')
|
|
65
|
-
const QB_APP_ID = ""; // Your app ID (e.g., 'bxyz789')
|
|
63
|
+
```typescript
|
|
64
|
+
import { createClient } from 'quickbase-js';
|
|
66
65
|
|
|
67
|
-
const
|
|
68
|
-
realm:
|
|
69
|
-
|
|
66
|
+
const client = createClient({
|
|
67
|
+
realm: 'mycompany',
|
|
68
|
+
auth: {
|
|
69
|
+
type: 'user-token',
|
|
70
|
+
userToken: 'your-user-token',
|
|
71
|
+
},
|
|
70
72
|
});
|
|
71
73
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
};
|
|
74
|
+
// Use typed API methods
|
|
75
|
+
const app = await client.getApp({ appId: 'bpqe82s1' });
|
|
76
|
+
console.log(app.name);
|
|
82
77
|
|
|
83
|
-
|
|
78
|
+
// Query records
|
|
79
|
+
const records = await client.runQuery({
|
|
80
|
+
from: 'bpqe82s1',
|
|
81
|
+
select: [3, 6, 7],
|
|
82
|
+
where: "{6.EX.'Active'}",
|
|
83
|
+
});
|
|
84
|
+
console.log(records.data);
|
|
84
85
|
```
|
|
85
86
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
```javascript
|
|
89
|
-
import { quickbase } from "quickbase-js"; // Adjust the import path as needed
|
|
87
|
+
## Authentication
|
|
90
88
|
|
|
91
|
-
|
|
92
|
-
const QB_REALM = ""; // Your QuickBase realm (e.g., 'mycompany')
|
|
93
|
-
const QB_APP_ID = ""; // Your app ID (e.g., 'bxyz789')
|
|
89
|
+
### User Token (Recommended for Server-Side)
|
|
94
90
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
91
|
+
```typescript
|
|
92
|
+
const client = createClient({
|
|
93
|
+
realm: 'mycompany',
|
|
94
|
+
auth: {
|
|
95
|
+
type: 'user-token',
|
|
96
|
+
userToken: 'your-user-token',
|
|
97
|
+
},
|
|
98
98
|
});
|
|
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();
|
|
112
99
|
```
|
|
113
100
|
|
|
114
|
-
###
|
|
101
|
+
### Temporary Token (Recommended for Browser/Code Pages)
|
|
115
102
|
|
|
116
|
-
|
|
117
|
-
import { quickbase } from "quickbase-js"; // Adjust the import path as needed
|
|
103
|
+
Temporary tokens are automatically fetched and cached per database. They refresh on 401 errors.
|
|
118
104
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
const
|
|
122
|
-
|
|
105
|
+
```typescript
|
|
106
|
+
// In QuickBase Code Pages - no user token needed (uses browser session)
|
|
107
|
+
const client = createClient({
|
|
108
|
+
realm: 'mycompany',
|
|
109
|
+
auth: {
|
|
110
|
+
type: 'temp-token',
|
|
111
|
+
},
|
|
112
|
+
});
|
|
123
113
|
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
114
|
+
// Outside Code Pages - user token required to fetch temp tokens
|
|
115
|
+
const client = createClient({
|
|
116
|
+
realm: 'mycompany',
|
|
117
|
+
auth: {
|
|
118
|
+
type: 'temp-token',
|
|
119
|
+
userToken: 'your-user-token', // Required outside Code Pages
|
|
120
|
+
appToken: 'optional-app-token', // If app requires it
|
|
121
|
+
},
|
|
128
122
|
});
|
|
123
|
+
```
|
|
129
124
|
|
|
130
|
-
|
|
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
|
-
};
|
|
125
|
+
### SSO Token
|
|
140
126
|
|
|
141
|
-
|
|
127
|
+
```typescript
|
|
128
|
+
const client = createClient({
|
|
129
|
+
realm: 'mycompany',
|
|
130
|
+
auth: {
|
|
131
|
+
type: 'sso',
|
|
132
|
+
samlToken: 'your-saml-token',
|
|
133
|
+
},
|
|
134
|
+
});
|
|
142
135
|
```
|
|
143
136
|
|
|
144
|
-
##
|
|
137
|
+
## Pagination
|
|
145
138
|
|
|
146
|
-
|
|
139
|
+
Paginated endpoints (`runQuery`, `runReport`, `getUsers`, etc.) return a `PaginatedRequest` that supports fluent pagination methods.
|
|
147
140
|
|
|
148
|
-
###
|
|
141
|
+
### Default Behavior (Single Page)
|
|
149
142
|
|
|
150
|
-
|
|
143
|
+
```typescript
|
|
144
|
+
// Returns first page only
|
|
145
|
+
const page = await client.runQuery({ from: 'tableId' });
|
|
146
|
+
console.log(page.data.length); // e.g., 100 records
|
|
147
|
+
console.log(page.metadata.totalRecords); // e.g., 5000 total
|
|
148
|
+
```
|
|
151
149
|
|
|
152
|
-
|
|
150
|
+
### Fetch All Pages
|
|
153
151
|
|
|
154
|
-
|
|
152
|
+
```typescript
|
|
153
|
+
// Automatically fetches all pages and combines results
|
|
154
|
+
const all = await client.runQuery({ from: 'tableId' }).all();
|
|
155
|
+
console.log(all.data.length); // 5000 records
|
|
156
|
+
```
|
|
155
157
|
|
|
156
|
-
|
|
158
|
+
### Fetch with Record Limit
|
|
157
159
|
|
|
158
|
-
|
|
160
|
+
```typescript
|
|
161
|
+
// Fetch up to 500 records (may span multiple pages)
|
|
162
|
+
const limited = await client.runQuery({ from: 'tableId' }).paginate({ limit: 500 });
|
|
163
|
+
console.log(limited.data.length); // 500 records
|
|
164
|
+
```
|
|
159
165
|
|
|
160
|
-
###
|
|
166
|
+
### Explicit Single Page
|
|
161
167
|
|
|
162
|
-
|
|
168
|
+
```typescript
|
|
169
|
+
// Explicitly fetch single page (useful when autoPaginate is enabled globally)
|
|
170
|
+
const single = await client.runQuery({ from: 'tableId' }).noPaginate();
|
|
171
|
+
```
|
|
163
172
|
|
|
164
|
-
|
|
173
|
+
### Global Auto-Pagination
|
|
165
174
|
|
|
166
|
-
|
|
175
|
+
```typescript
|
|
176
|
+
const client = createClient({
|
|
177
|
+
realm: 'mycompany',
|
|
178
|
+
auth: { type: 'user-token', userToken: 'token' },
|
|
179
|
+
autoPaginate: true, // Default await now fetches all pages
|
|
180
|
+
});
|
|
167
181
|
|
|
168
|
-
|
|
182
|
+
// Now direct await fetches all pages
|
|
183
|
+
const all = await client.runQuery({ from: 'tableId' });
|
|
169
184
|
|
|
170
|
-
|
|
185
|
+
// Use .noPaginate() to get single page
|
|
186
|
+
const page = await client.runQuery({ from: 'tableId' }).noPaginate();
|
|
187
|
+
```
|
|
171
188
|
|
|
172
|
-
|
|
189
|
+
## Date Conversion
|
|
173
190
|
|
|
174
|
-
|
|
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).
|
|
191
|
+
By default, ISO 8601 date strings in API responses are automatically converted to JavaScript `Date` objects:
|
|
178
192
|
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
- `{ type: 'burst-aware', burst: 100, windowSeconds: 10 }`: **~10s for 100 requests**, (100 instant, refreshing every 10s for next burst).
|
|
193
|
+
```typescript
|
|
194
|
+
const app = await client.getApp({ appId: 'bpqe82s1' });
|
|
182
195
|
|
|
183
|
-
|
|
196
|
+
// Date fields are now Date objects
|
|
197
|
+
console.log(app.created instanceof Date); // true
|
|
198
|
+
console.log(app.created.toISOString()); // "2024-01-15T10:30:00.000Z"
|
|
184
199
|
|
|
185
|
-
|
|
200
|
+
// Works with nested objects and arrays
|
|
201
|
+
const records = await client.runQuery({ from: 'tableId' });
|
|
202
|
+
records.data.forEach(record => {
|
|
203
|
+
// Date field values are converted
|
|
204
|
+
console.log(record['7'].value instanceof Date); // true for date/timestamp fields
|
|
205
|
+
});
|
|
206
|
+
```
|
|
186
207
|
|
|
187
|
-
|
|
208
|
+
To disable date conversion and keep dates as strings:
|
|
188
209
|
|
|
189
|
-
|
|
210
|
+
```typescript
|
|
211
|
+
const client = createClient({
|
|
212
|
+
realm: 'mycompany',
|
|
213
|
+
auth: { type: 'user-token', userToken: 'token' },
|
|
214
|
+
convertDates: false, // Keep dates as ISO strings
|
|
215
|
+
});
|
|
216
|
+
```
|
|
190
217
|
|
|
191
|
-
|
|
218
|
+
## Configuration Options
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const client = createClient({
|
|
222
|
+
// Required
|
|
223
|
+
realm: 'mycompany',
|
|
224
|
+
auth: { /* see authentication section */ },
|
|
225
|
+
|
|
226
|
+
// Optional
|
|
227
|
+
debug: false, // Enable debug logging
|
|
228
|
+
timeout: 30000, // Request timeout in ms
|
|
229
|
+
baseUrl: 'https://api.quickbase.com/v1', // API base URL
|
|
230
|
+
autoPaginate: false, // Auto-paginate on direct await
|
|
231
|
+
convertDates: true, // Convert ISO date strings to Date objects
|
|
232
|
+
|
|
233
|
+
// Rate limiting
|
|
234
|
+
rateLimit: {
|
|
235
|
+
// Optional client-side throttling
|
|
236
|
+
// QuickBase allows 100 requests per 10 seconds per user token
|
|
237
|
+
proactiveThrottle: {
|
|
238
|
+
enabled: false,
|
|
239
|
+
requestsPer10Seconds: 100,
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
// Retry configuration for 429 and 5xx errors
|
|
243
|
+
retry: {
|
|
244
|
+
maxAttempts: 3,
|
|
245
|
+
initialDelayMs: 1000,
|
|
246
|
+
maxDelayMs: 30000,
|
|
247
|
+
multiplier: 2,
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
// Callback when rate limited
|
|
251
|
+
onRateLimit: (info) => {
|
|
252
|
+
console.log(`Rate limited! Retry after ${info.retryAfter}s`);
|
|
253
|
+
console.log(`Request: ${info.requestUrl}`);
|
|
254
|
+
console.log(`Ray ID: ${info.qbApiRay}`);
|
|
255
|
+
},
|
|
256
|
+
},
|
|
257
|
+
});
|
|
258
|
+
```
|
|
192
259
|
|
|
193
|
-
|
|
260
|
+
## API Methods
|
|
194
261
|
|
|
195
|
-
|
|
262
|
+
All QuickBase API endpoints are available as typed methods:
|
|
196
263
|
|
|
197
|
-
|
|
264
|
+
```typescript
|
|
265
|
+
// Apps
|
|
266
|
+
const app = await client.getApp({ appId: 'bpqe82s1' });
|
|
267
|
+
const newApp = await client.createApp({ name: 'My App', description: 'Test' });
|
|
268
|
+
await client.updateApp({ appId: 'bpqe82s1' }, { name: 'Updated Name' });
|
|
269
|
+
await client.deleteApp({ appId: 'bpqe82s1' }, { name: 'My App' });
|
|
198
270
|
|
|
199
|
-
|
|
271
|
+
// Tables
|
|
272
|
+
const tables = await client.getAppTables({ appId: 'bpqe82s1' });
|
|
273
|
+
const table = await client.getTable({ appId: 'bpqe82s1', tableId: 'byyy82s1' });
|
|
200
274
|
|
|
201
|
-
|
|
275
|
+
// Fields
|
|
276
|
+
const fields = await client.getFields({ tableId: 'byyy82s1' });
|
|
202
277
|
|
|
203
|
-
|
|
278
|
+
// Records
|
|
279
|
+
const records = await client.runQuery({
|
|
280
|
+
from: 'byyy82s1',
|
|
281
|
+
select: [3, 6, 7],
|
|
282
|
+
where: "{6.GT.100}",
|
|
283
|
+
sortBy: [{ fieldId: 3, order: 'ASC' }],
|
|
284
|
+
options: { top: 100, skip: 0 },
|
|
285
|
+
});
|
|
204
286
|
|
|
205
|
-
|
|
287
|
+
// Insert/Update records
|
|
288
|
+
const result = await client.upsert({
|
|
289
|
+
to: 'byyy82s1',
|
|
290
|
+
data: [
|
|
291
|
+
{ '6': { value: 'New Record' }, '7': { value: 42 } },
|
|
292
|
+
],
|
|
293
|
+
});
|
|
206
294
|
|
|
207
|
-
|
|
295
|
+
// Delete records
|
|
296
|
+
await client.deleteRecords({
|
|
297
|
+
from: 'byyy82s1',
|
|
298
|
+
where: "{3.EX.123}",
|
|
299
|
+
});
|
|
208
300
|
|
|
209
|
-
|
|
210
|
-
|
|
301
|
+
// Reports
|
|
302
|
+
const report = await client.runReport(
|
|
303
|
+
{ reportId: 'abc123', tableId: 'byyy82s1' },
|
|
304
|
+
{ skip: 0, top: 100 }
|
|
305
|
+
);
|
|
306
|
+
|
|
307
|
+
// Users
|
|
308
|
+
const users = await client.getUsers(
|
|
309
|
+
{ accountId: '123456' },
|
|
310
|
+
{ appIds: ['bpqe82s1'] }
|
|
311
|
+
);
|
|
312
|
+
```
|
|
211
313
|
|
|
212
|
-
|
|
314
|
+
### Raw Request
|
|
213
315
|
|
|
214
|
-
|
|
316
|
+
For endpoints not covered by typed methods, use the generic `request` method:
|
|
215
317
|
|
|
216
|
-
|
|
318
|
+
```typescript
|
|
319
|
+
const result = await client.request<MyResponseType>({
|
|
320
|
+
method: 'POST',
|
|
321
|
+
path: '/some/endpoint',
|
|
322
|
+
body: { key: 'value' },
|
|
323
|
+
query: { param: 'value' },
|
|
324
|
+
});
|
|
325
|
+
```
|
|
217
326
|
|
|
218
|
-
|
|
327
|
+
## Error Handling
|
|
328
|
+
|
|
329
|
+
```typescript
|
|
330
|
+
import {
|
|
331
|
+
QuickbaseError,
|
|
332
|
+
RateLimitError,
|
|
333
|
+
AuthenticationError,
|
|
334
|
+
AuthorizationError,
|
|
335
|
+
NotFoundError,
|
|
336
|
+
ValidationError,
|
|
337
|
+
ServerError,
|
|
338
|
+
} from 'quickbase-js';
|
|
339
|
+
|
|
340
|
+
try {
|
|
341
|
+
await client.getApp({ appId: 'invalid' });
|
|
342
|
+
} catch (error) {
|
|
343
|
+
if (error instanceof RateLimitError) {
|
|
344
|
+
console.log(`Rate limited. Retry after ${error.retryAfter} seconds`);
|
|
345
|
+
console.log(`Ray ID: ${error.rayId}`);
|
|
346
|
+
} else if (error instanceof AuthenticationError) {
|
|
347
|
+
console.log('Invalid or expired token');
|
|
348
|
+
} else if (error instanceof AuthorizationError) {
|
|
349
|
+
console.log('Permission denied');
|
|
350
|
+
} else if (error instanceof NotFoundError) {
|
|
351
|
+
console.log('Resource not found');
|
|
352
|
+
} else if (error instanceof ValidationError) {
|
|
353
|
+
console.log('Bad request:', error.message);
|
|
354
|
+
} else if (error instanceof ServerError) {
|
|
355
|
+
console.log('Server error:', error.statusCode);
|
|
356
|
+
} else if (error instanceof QuickbaseError) {
|
|
357
|
+
console.log(`API error ${error.statusCode}: ${error.message}`);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
```
|
|
219
361
|
|
|
220
|
-
|
|
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**:
|
|
362
|
+
## Migration from v1
|
|
225
363
|
|
|
226
|
-
|
|
227
|
-
import { quickbase } from "quickbase-js"; // Adjust the import path as needed
|
|
364
|
+
### Authentication
|
|
228
365
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
const
|
|
366
|
+
```typescript
|
|
367
|
+
// v1 - user token
|
|
368
|
+
const qb = quickbase({ realm: 'company', userToken: 'token' });
|
|
232
369
|
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
370
|
+
// v2 - user token (explicit type)
|
|
371
|
+
const client = createClient({
|
|
372
|
+
realm: 'company',
|
|
373
|
+
auth: { type: 'user-token', userToken: 'token' },
|
|
237
374
|
});
|
|
238
375
|
|
|
239
|
-
|
|
240
|
-
|
|
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
|
-
};
|
|
376
|
+
// v1 - temp tokens in Code Pages
|
|
377
|
+
const qb = quickbase({ realm: 'company', useTempTokens: true });
|
|
255
378
|
|
|
256
|
-
|
|
379
|
+
// v2 - temp tokens in Code Pages
|
|
380
|
+
const client = createClient({
|
|
381
|
+
realm: 'company',
|
|
382
|
+
auth: { type: 'temp-token' },
|
|
383
|
+
});
|
|
257
384
|
```
|
|
258
385
|
|
|
259
|
-
|
|
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**:
|
|
386
|
+
### Pagination
|
|
267
387
|
|
|
268
|
-
```
|
|
269
|
-
|
|
388
|
+
```typescript
|
|
389
|
+
// v1 - callback-based
|
|
390
|
+
await qb.withPaginationDisabled(async () => qb.runQuery({ body: { from: tableId } }));
|
|
391
|
+
await qb.withPaginationLimit(100, async () => qb.runQuery({ body: { from: tableId } }));
|
|
270
392
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
393
|
+
// v2 - fluent API
|
|
394
|
+
await client.runQuery({ from: tableId }).noPaginate();
|
|
395
|
+
await client.runQuery({ from: tableId }).paginate({ limit: 100 });
|
|
396
|
+
```
|
|
274
397
|
|
|
275
|
-
|
|
276
|
-
realm: QB_REALM,
|
|
277
|
-
userToken: QB_USER_TOKEN,
|
|
278
|
-
autoPaginate: true, // Pagination enabled by default
|
|
279
|
-
});
|
|
398
|
+
### Request Body
|
|
280
399
|
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
-
};
|
|
400
|
+
```typescript
|
|
401
|
+
// v1 - body wrapper
|
|
402
|
+
await qb.runQuery({ body: { from: tableId, select: [3, 6] } });
|
|
297
403
|
|
|
298
|
-
|
|
404
|
+
// v2 - direct parameters
|
|
405
|
+
await client.runQuery({ from: tableId, select: [3, 6] });
|
|
299
406
|
```
|
|
300
407
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
### Development workflow
|
|
408
|
+
## Development
|
|
304
409
|
|
|
305
410
|
```bash
|
|
306
|
-
|
|
411
|
+
# Install dependencies
|
|
412
|
+
npm install
|
|
413
|
+
|
|
414
|
+
# Run tests
|
|
415
|
+
npm test
|
|
416
|
+
|
|
417
|
+
# Build
|
|
307
418
|
npm run build
|
|
308
|
-
npm run test:all
|
|
309
|
-
```
|
|
310
419
|
|
|
311
|
-
|
|
420
|
+
# Type check
|
|
421
|
+
npm run typecheck
|
|
312
422
|
|
|
313
|
-
|
|
423
|
+
# Generate types from OpenAPI spec
|
|
424
|
+
npm run spec:generate
|
|
425
|
+
```
|
|
314
426
|
|
|
315
|
-
|
|
316
|
-
- A Quickbase account. [Free tier available](https://www.quickbase.com/builder-program).
|
|
427
|
+
### Spec Tools
|
|
317
428
|
|
|
318
|
-
|
|
429
|
+
```bash
|
|
430
|
+
# Full spec processing pipeline
|
|
431
|
+
npm run spec:build
|
|
432
|
+
|
|
433
|
+
# Individual steps
|
|
434
|
+
npm run spec:convert # Swagger 2.0 → OpenAPI 3.0
|
|
435
|
+
npm run spec:patch # Apply fixes from overrides
|
|
436
|
+
npm run spec:validate # Validate spec
|
|
437
|
+
npm run spec:split # Split by tag (for editing)
|
|
438
|
+
npm run spec:generate # Generate TypeScript types
|
|
439
|
+
```
|
|
319
440
|
|
|
320
|
-
###
|
|
441
|
+
### Documentation
|
|
321
442
|
|
|
322
|
-
|
|
443
|
+
Generate API documentation from source code:
|
|
323
444
|
|
|
324
|
-
|
|
445
|
+
```bash
|
|
446
|
+
npm run docs # Generate docs to ./docs
|
|
447
|
+
npm run docs:watch # Watch mode for development
|
|
448
|
+
```
|
|
325
449
|
|
|
326
|
-
|
|
450
|
+
The documentation is generated using [TypeDoc](https://typedoc.org/) and extracts JSDoc comments from the source code. Open `docs/index.html` to view locally.
|
|
327
451
|
|
|
328
|
-
|
|
452
|
+
## License
|
|
329
453
|
|
|
330
|
-
|
|
454
|
+
MIT
|