quickbase-js 2.3.0 → 2.4.1

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 (62) hide show
  1. package/README.md +145 -1107
  2. package/dist/auth/ticket.d.ts.map +1 -1
  3. package/dist/auth/ticket.js +4 -3
  4. package/dist/auth/ticket.js.map +1 -1
  5. package/dist/client/request.d.ts +4 -0
  6. package/dist/client/request.d.ts.map +1 -1
  7. package/dist/client/request.js +15 -3
  8. package/dist/client/request.js.map +1 -1
  9. package/dist/generated/client.d.ts +2 -0
  10. package/dist/generated/client.d.ts.map +1 -1
  11. package/dist/generated/client.js +134 -113
  12. package/dist/generated/client.js.map +1 -1
  13. package/dist/generated/types.d.ts +2700 -2256
  14. package/dist/generated/types.d.ts.map +1 -1
  15. package/dist/generated/types.js +0 -2
  16. package/dist/generated/types.js.map +1 -1
  17. package/dist/quickbase.esm.js +3 -3
  18. package/dist/quickbase.esm.js.map +3 -3
  19. package/dist/quickbase.min.js +3 -3
  20. package/dist/quickbase.min.js.map +3 -3
  21. package/package.json +16 -13
  22. package/src/auth/index.ts +55 -0
  23. package/src/auth/sso-token.ts +143 -0
  24. package/src/auth/temp-token.ts +160 -0
  25. package/src/auth/ticket.ts +329 -0
  26. package/src/auth/token-cache.ts +97 -0
  27. package/src/auth/types.ts +50 -0
  28. package/src/auth/user-token.ts +38 -0
  29. package/src/cli/schema.ts +512 -0
  30. package/src/client/index.ts +36 -0
  31. package/src/client/pagination.ts +337 -0
  32. package/src/client/request.ts +544 -0
  33. package/src/client/retry.ts +169 -0
  34. package/src/client/throttle.ts +105 -0
  35. package/src/core/config.ts +160 -0
  36. package/src/core/dates.ts +63 -0
  37. package/src/core/errors.ts +349 -0
  38. package/src/core/index.ts +50 -0
  39. package/src/core/logger.ts +113 -0
  40. package/src/core/schema.ts +213 -0
  41. package/src/core/transform.ts +295 -0
  42. package/src/core/types.ts +337 -0
  43. package/src/generated/client.ts +1785 -0
  44. package/src/generated/operations.json +672 -0
  45. package/src/generated/types.ts +4884 -0
  46. package/src/index.ts +259 -0
  47. package/src/xml/codepages.ts +119 -0
  48. package/src/xml/dbvars.ts +75 -0
  49. package/src/xml/errors.ts +133 -0
  50. package/src/xml/fields.ts +121 -0
  51. package/src/xml/groups.ts +560 -0
  52. package/src/xml/html.ts +152 -0
  53. package/src/xml/index.ts +1196 -0
  54. package/src/xml/metadata.ts +111 -0
  55. package/src/xml/records.ts +301 -0
  56. package/src/xml/request.ts +238 -0
  57. package/src/xml/roles.ts +321 -0
  58. package/src/xml/schema.ts +436 -0
  59. package/src/xml/transform.ts +381 -0
  60. package/src/xml/types.ts +602 -0
  61. package/src/xml/users.ts +221 -0
  62. package/src/xml/webhooks.ts +260 -0
@@ -0,0 +1,221 @@
1
+ /**
2
+ * XML API User Management
3
+ *
4
+ * Endpoints for managing users and user-related operations.
5
+ *
6
+ * XML-API: Remove this file when QuickBase discontinues the XML API.
7
+ * To find all XML API code, search for: XML-API
8
+ */
9
+
10
+ import type {
11
+ XmlCaller,
12
+ UserInfo,
13
+ ProvisionUserResult,
14
+ } from './types.js';
15
+ import { checkError } from './errors.js';
16
+ import {
17
+ buildRequest,
18
+ escapeXml,
19
+ parseBaseResponse,
20
+ getTagContent,
21
+ parseXmlBool,
22
+ } from './request.js';
23
+
24
+ /**
25
+ * Get user information by email.
26
+ *
27
+ * Returns user ID, name, and other details for a registered QuickBase user.
28
+ * If no email is provided, returns info for the current user.
29
+ *
30
+ * @see https://help.quickbase.com/docs/api-getuserinfo
31
+ *
32
+ * @example
33
+ * ```typescript
34
+ * // Get info for specific user
35
+ * const user = await getUserInfo(caller, 'user@example.com');
36
+ * console.log(`User ID: ${user.id}, Name: ${user.firstName} ${user.lastName}`);
37
+ *
38
+ * // Get info for current user
39
+ * const me = await getUserInfo(caller);
40
+ * ```
41
+ */
42
+ export async function getUserInfo(
43
+ caller: XmlCaller,
44
+ email?: string
45
+ ): Promise<UserInfo> {
46
+ let inner = '';
47
+ if (email) {
48
+ inner = `<email>${escapeXml(email)}</email>`;
49
+ }
50
+ const body = buildRequest(inner);
51
+ const xml = await caller.doXml('main', 'API_GetUserInfo', body);
52
+
53
+ const base = parseBaseResponse(xml);
54
+ checkError(base);
55
+
56
+ // Parse user element
57
+ const userMatch = xml.match(/<user[^>]*id="([^"]*)"[^>]*>([\s\S]*?)<\/user>/);
58
+ if (!userMatch || !userMatch[1]) {
59
+ throw new Error('Invalid API_GetUserInfo response: no user element');
60
+ }
61
+
62
+ const userXml = userMatch[0];
63
+ const id = userMatch[1];
64
+ const firstName = getTagContent(userXml, 'firstName');
65
+ const lastName = getTagContent(userXml, 'lastName');
66
+ const login = getTagContent(userXml, 'login') || undefined;
67
+ const userEmail = getTagContent(userXml, 'email') || undefined;
68
+ const screenName = getTagContent(userXml, 'screenName') || undefined;
69
+ const isVerifiedStr = getTagContent(userXml, 'isVerified');
70
+ const isVerified = isVerifiedStr ? parseXmlBool(isVerifiedStr) : undefined;
71
+ const externalAuthStr = getTagContent(userXml, 'externalAuth');
72
+ const externalAuth = externalAuthStr ? parseXmlBool(externalAuthStr) : undefined;
73
+
74
+ return {
75
+ id,
76
+ firstName,
77
+ lastName,
78
+ login,
79
+ email: userEmail,
80
+ screenName,
81
+ isVerified,
82
+ externalAuth,
83
+ };
84
+ }
85
+
86
+ /**
87
+ * Create a new unregistered user and add them to an application.
88
+ *
89
+ * This is for users who are NOT yet registered with QuickBase.
90
+ * For existing users, use getUserInfo + addUserToRole + sendInvitation.
91
+ *
92
+ * After provisioning, call sendInvitation to email the user.
93
+ *
94
+ * @see https://help.quickbase.com/docs/api-provisionuser
95
+ *
96
+ * @example
97
+ * ```typescript
98
+ * const result = await provisionUser(caller, 'bqxyz123', 'new@example.com', 'John', 'Doe', 11);
99
+ * console.log(`Created user: ${result.userId}`);
100
+ *
101
+ * // Now send invitation
102
+ * await sendInvitation(caller, 'bqxyz123', result.userId, 'Welcome to our app!');
103
+ * ```
104
+ */
105
+ export async function provisionUser(
106
+ caller: XmlCaller,
107
+ appId: string,
108
+ email: string,
109
+ firstName: string,
110
+ lastName: string,
111
+ roleId?: number
112
+ ): Promise<ProvisionUserResult> {
113
+ let inner =
114
+ `<email>${escapeXml(email)}</email>` +
115
+ `<fname>${escapeXml(firstName)}</fname>` +
116
+ `<lname>${escapeXml(lastName)}</lname>`;
117
+
118
+ if (roleId !== undefined) {
119
+ inner += `<roleid>${roleId}</roleid>`;
120
+ }
121
+
122
+ const body = buildRequest(inner);
123
+ const xml = await caller.doXml(appId, 'API_ProvisionUser', body);
124
+
125
+ const base = parseBaseResponse(xml);
126
+ checkError(base);
127
+
128
+ const userId = getTagContent(xml, 'userid');
129
+ if (!userId) {
130
+ throw new Error('Invalid API_ProvisionUser response: no userid element');
131
+ }
132
+
133
+ return { userId };
134
+ }
135
+
136
+ /**
137
+ * Send an invitation email to a user.
138
+ *
139
+ * Use after adding a user to a role (via addUserToRole or provisionUser).
140
+ *
141
+ * @see https://help.quickbase.com/docs/api-sendinvitation
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * await sendInvitation(caller, 'bqxyz123', '112149.bhsv', 'Welcome to our team app!');
146
+ * ```
147
+ */
148
+ export async function sendInvitation(
149
+ caller: XmlCaller,
150
+ appId: string,
151
+ userId: string,
152
+ userText?: string
153
+ ): Promise<void> {
154
+ let inner = `<userid>${escapeXml(userId)}</userid>`;
155
+ if (userText) {
156
+ inner += `<usertext>${escapeXml(userText)}</usertext>`;
157
+ }
158
+
159
+ const body = buildRequest(inner);
160
+ const xml = await caller.doXml(appId, 'API_SendInvitation', body);
161
+
162
+ const base = parseBaseResponse(xml);
163
+ checkError(base);
164
+ }
165
+
166
+ /**
167
+ * Change the application manager.
168
+ *
169
+ * Requires account admin or realm admin permissions.
170
+ *
171
+ * @see https://help.quickbase.com/docs/api-changemanager
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * await changeManager(caller, 'bqxyz123', 'newmanager@example.com');
176
+ * ```
177
+ */
178
+ export async function changeManager(
179
+ caller: XmlCaller,
180
+ appId: string,
181
+ newManagerEmail: string
182
+ ): Promise<void> {
183
+ const inner = `<newmgr>${escapeXml(newManagerEmail)}</newmgr>`;
184
+ const body = buildRequest(inner);
185
+ const xml = await caller.doXml(appId, 'API_ChangeManager', body);
186
+
187
+ const base = parseBaseResponse(xml);
188
+ checkError(base);
189
+ }
190
+
191
+ /**
192
+ * Change the owner of a record.
193
+ *
194
+ * Transfers ownership from the current record owner to another user.
195
+ * Requires Full Administration rights on the application.
196
+ *
197
+ * @see https://help.quickbase.com/docs/api-changerecordowner
198
+ *
199
+ * @param newOwner - The new owner's QuickBase username or email address
200
+ *
201
+ * @example
202
+ * ```typescript
203
+ * // By record ID
204
+ * await changeRecordOwner(caller, 'bqtable123', 42, 'newowner@example.com');
205
+ * ```
206
+ */
207
+ export async function changeRecordOwner(
208
+ caller: XmlCaller,
209
+ tableId: string,
210
+ recordId: number,
211
+ newOwner: string
212
+ ): Promise<void> {
213
+ const inner =
214
+ `<rid>${recordId}</rid>` +
215
+ `<newowner>${escapeXml(newOwner)}</newowner>`;
216
+ const body = buildRequest(inner);
217
+ const xml = await caller.doXml(tableId, 'API_ChangeRecordOwner', body);
218
+
219
+ const base = parseBaseResponse(xml);
220
+ checkError(base);
221
+ }
@@ -0,0 +1,260 @@
1
+ /**
2
+ * XML API Webhooks
3
+ *
4
+ * Endpoints for managing webhooks.
5
+ *
6
+ * XML-API: Remove this file when QuickBase discontinues the XML API.
7
+ * To find all XML API code, search for: XML-API
8
+ */
9
+
10
+ import type {
11
+ XmlCaller,
12
+ WebhooksCreateOptions,
13
+ WebhooksEditOptions,
14
+ } from './types.js';
15
+ import { checkError } from './errors.js';
16
+ import {
17
+ buildRequest,
18
+ escapeXml,
19
+ parseBaseResponse,
20
+ getTagContent,
21
+ parseXmlNumber,
22
+ } from './request.js';
23
+
24
+ /**
25
+ * Build webhook XML from create options
26
+ */
27
+ function buildWebhookCreateXml(options: WebhooksCreateOptions): string {
28
+ let inner = `<label>${escapeXml(options.label)}</label>`;
29
+ inner += `<WebhookURL>${escapeXml(options.webhookUrl)}</WebhookURL>`;
30
+
31
+ if (options.description) {
32
+ inner += `<Description>${escapeXml(options.description)}</Description>`;
33
+ }
34
+ if (options.query) {
35
+ inner += `<Query>${escapeXml(options.query)}</Query>`;
36
+ }
37
+ if (options.workflowWhen) {
38
+ inner += `<WorkflowWhen>${escapeXml(options.workflowWhen)}</WorkflowWhen>`;
39
+ }
40
+ if (options.headers && options.headers.length > 0) {
41
+ inner += `<WebhookHeaderCount>${options.headers.length}</WebhookHeaderCount>`;
42
+ options.headers.forEach((h, i) => {
43
+ inner += `<WebhookHeaderKey${i + 1}>${escapeXml(h.key)}</WebhookHeaderKey${i + 1}>`;
44
+ inner += `<WebhookHeaderValue${i + 1}>${escapeXml(h.value)}</WebhookHeaderValue${i + 1}>`;
45
+ });
46
+ }
47
+ if (options.message) {
48
+ inner += `<WebhookMessage>${escapeXml(options.message)}</WebhookMessage>`;
49
+ }
50
+ if (options.messageFormat) {
51
+ inner += `<WebhookMessageFormat>${options.messageFormat}</WebhookMessageFormat>`;
52
+ }
53
+ if (options.httpVerb) {
54
+ inner += `<WebhookHTTPVerb>${options.httpVerb}</WebhookHTTPVerb>`;
55
+ }
56
+ if (options.triggerFields && options.triggerFields.length > 0) {
57
+ inner += '<tfidsWhich>TRUE</tfidsWhich>';
58
+ for (const fid of options.triggerFields) {
59
+ inner += `<tfids>${fid}</tfids>`;
60
+ }
61
+ }
62
+
63
+ return inner;
64
+ }
65
+
66
+ /**
67
+ * Build webhook XML from edit options
68
+ */
69
+ function buildWebhookEditXml(actionId: string, options: WebhooksEditOptions): string {
70
+ let inner = `<actionId>${escapeXml(actionId)}</actionId>`;
71
+ inner += buildWebhookCreateXml(options);
72
+
73
+ // Handle clearing trigger fields
74
+ if (options.clearTriggerFields) {
75
+ // Remove any tfidsWhich/tfids we just added and replace with clear
76
+ inner = inner.replace(/<tfidsWhich>TRUE<\/tfidsWhich>/, '');
77
+ inner = inner.replace(/<tfids>\d+<\/tfids>/g, '');
78
+ inner += '<tfidsWhich>tfidsAny</tfidsWhich>';
79
+ }
80
+
81
+ return inner;
82
+ }
83
+
84
+ /**
85
+ * Create a webhook.
86
+ *
87
+ * @see https://help.quickbase.com/docs/api-webhooks-create
88
+ *
89
+ * @example
90
+ * ```typescript
91
+ * await webhooksCreate(caller, 'bqtable123', {
92
+ * label: 'Notify on new records',
93
+ * webhookUrl: 'https://example.com/webhook',
94
+ * workflowWhen: 'a',
95
+ * messageFormat: 'JSON',
96
+ * headers: [{ key: 'Content-Type', value: 'application/json' }],
97
+ * });
98
+ * ```
99
+ */
100
+ export async function webhooksCreate(
101
+ caller: XmlCaller,
102
+ tableId: string,
103
+ options: WebhooksCreateOptions
104
+ ): Promise<void> {
105
+ const inner = buildWebhookCreateXml(options);
106
+ const body = buildRequest(inner);
107
+ const xml = await caller.doXml(tableId, 'API_Webhooks_Create', body);
108
+
109
+ const base = parseBaseResponse(xml);
110
+ checkError(base);
111
+ }
112
+
113
+ /**
114
+ * Edit a webhook.
115
+ *
116
+ * @see https://help.quickbase.com/docs/api-webhooks-edit
117
+ *
118
+ * @example
119
+ * ```typescript
120
+ * await webhooksEdit(caller, 'bqtable123', '15', {
121
+ * label: 'Updated webhook name',
122
+ * webhookUrl: 'https://example.com/new-endpoint',
123
+ * messageFormat: 'JSON',
124
+ * });
125
+ * ```
126
+ */
127
+ export async function webhooksEdit(
128
+ caller: XmlCaller,
129
+ tableId: string,
130
+ actionId: string,
131
+ options: WebhooksEditOptions
132
+ ): Promise<void> {
133
+ const inner = buildWebhookEditXml(actionId, options);
134
+ const body = buildRequest(inner);
135
+ const xml = await caller.doXml(tableId, 'API_Webhooks_Edit', body);
136
+
137
+ const base = parseBaseResponse(xml);
138
+ checkError(base);
139
+ }
140
+
141
+ /**
142
+ * Delete webhooks.
143
+ *
144
+ * @see https://help.quickbase.com/docs/api-webhooks-delete
145
+ *
146
+ * @example
147
+ * ```typescript
148
+ * const result = await webhooksDelete(caller, 'bqtable123', ['15', '16']);
149
+ * console.log(`Deleted ${result.numChanged} webhooks`);
150
+ * ```
151
+ */
152
+ export async function webhooksDelete(
153
+ caller: XmlCaller,
154
+ tableId: string,
155
+ actionIds: string[]
156
+ ): Promise<{ numChanged: number }> {
157
+ if (actionIds.length === 0) {
158
+ throw new Error('actionIds array cannot be empty');
159
+ }
160
+ const inner = `<actionIDList>${actionIds.join(',')}</actionIDList>`;
161
+ const body = buildRequest(inner);
162
+ const xml = await caller.doXml(tableId, 'API_Webhooks_Delete', body);
163
+
164
+ const base = parseBaseResponse(xml);
165
+ checkError(base);
166
+
167
+ return {
168
+ numChanged: parseXmlNumber(getTagContent(xml, 'numChanged')),
169
+ };
170
+ }
171
+
172
+ /**
173
+ * Activate webhooks.
174
+ *
175
+ * @see https://help.quickbase.com/docs/api-webhooks-activate
176
+ *
177
+ * @example
178
+ * ```typescript
179
+ * const result = await webhooksActivate(caller, 'bqtable123', ['15']);
180
+ * console.log(`Activated ${result.numChanged} webhooks`);
181
+ * ```
182
+ */
183
+ export async function webhooksActivate(
184
+ caller: XmlCaller,
185
+ tableId: string,
186
+ actionIds: string[]
187
+ ): Promise<{ numChanged: number }> {
188
+ if (actionIds.length === 0) {
189
+ throw new Error('actionIds array cannot be empty');
190
+ }
191
+ const inner = `<actionIDList>${actionIds.join(',')}</actionIDList>`;
192
+ const body = buildRequest(inner);
193
+ const xml = await caller.doXml(tableId, 'API_Webhooks_Activate', body);
194
+
195
+ const base = parseBaseResponse(xml);
196
+ checkError(base);
197
+
198
+ return {
199
+ numChanged: parseXmlNumber(getTagContent(xml, 'numChanged')),
200
+ };
201
+ }
202
+
203
+ /**
204
+ * Deactivate webhooks.
205
+ *
206
+ * @see https://help.quickbase.com/docs/api-webhooks-deactivate
207
+ *
208
+ * @example
209
+ * ```typescript
210
+ * const result = await webhooksDeactivate(caller, 'bqtable123', ['15']);
211
+ * console.log(`Deactivated ${result.numChanged} webhooks`);
212
+ * ```
213
+ */
214
+ export async function webhooksDeactivate(
215
+ caller: XmlCaller,
216
+ tableId: string,
217
+ actionIds: string[]
218
+ ): Promise<{ numChanged: number }> {
219
+ if (actionIds.length === 0) {
220
+ throw new Error('actionIds array cannot be empty');
221
+ }
222
+ const inner = `<actionIDList>${actionIds.join(',')}</actionIDList>`;
223
+ const body = buildRequest(inner);
224
+ const xml = await caller.doXml(tableId, 'API_Webhooks_Deactivate', body);
225
+
226
+ const base = parseBaseResponse(xml);
227
+ checkError(base);
228
+
229
+ return {
230
+ numChanged: parseXmlNumber(getTagContent(xml, 'numChanged')),
231
+ };
232
+ }
233
+
234
+ /**
235
+ * Copy a webhook.
236
+ *
237
+ * @see https://help.quickbase.com/docs/api-webhooks-copy
238
+ *
239
+ * @example
240
+ * ```typescript
241
+ * const result = await webhooksCopy(caller, 'bqtable123', '15');
242
+ * console.log(`Created webhook copy with ID: ${result.actionId}`);
243
+ * ```
244
+ */
245
+ export async function webhooksCopy(
246
+ caller: XmlCaller,
247
+ tableId: string,
248
+ actionId: string
249
+ ): Promise<{ actionId: string }> {
250
+ const inner = `<actionId>${escapeXml(actionId)}</actionId>`;
251
+ const body = buildRequest(inner);
252
+ const xml = await caller.doXml(tableId, 'API_Webhooks_Copy', body);
253
+
254
+ const base = parseBaseResponse(xml);
255
+ checkError(base);
256
+
257
+ return {
258
+ actionId: getTagContent(xml, 'actionId'),
259
+ };
260
+ }