quickbase-js 2.1.0 → 2.2.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 (112) hide show
  1. package/README.md +674 -90
  2. package/bin/quickbase-js.js +54 -0
  3. package/dist/auth/index.d.ts.map +1 -1
  4. package/dist/auth/index.js +5 -1
  5. package/dist/auth/index.js.map +1 -1
  6. package/dist/auth/ticket.d.ts +13 -0
  7. package/dist/auth/ticket.d.ts.map +1 -1
  8. package/dist/auth/ticket.js +103 -3
  9. package/dist/auth/ticket.js.map +1 -1
  10. package/dist/cli/schema.d.ts +23 -0
  11. package/dist/cli/schema.d.ts.map +1 -0
  12. package/dist/cli/schema.js +425 -0
  13. package/dist/cli/schema.js.map +1 -0
  14. package/dist/client/request.d.ts +2 -1
  15. package/dist/client/request.d.ts.map +1 -1
  16. package/dist/client/request.js +165 -18
  17. package/dist/client/request.js.map +1 -1
  18. package/dist/core/config.d.ts.map +1 -1
  19. package/dist/core/config.js +3 -0
  20. package/dist/core/config.js.map +1 -1
  21. package/dist/core/errors.d.ts +17 -0
  22. package/dist/core/errors.d.ts.map +1 -1
  23. package/dist/core/errors.js +32 -0
  24. package/dist/core/errors.js.map +1 -1
  25. package/dist/core/index.d.ts +2 -2
  26. package/dist/core/index.d.ts.map +1 -1
  27. package/dist/core/index.js +1 -1
  28. package/dist/core/index.js.map +1 -1
  29. package/dist/core/schema.d.ts +37 -0
  30. package/dist/core/schema.d.ts.map +1 -0
  31. package/dist/core/schema.js +168 -0
  32. package/dist/core/schema.js.map +1 -0
  33. package/dist/core/transform.d.ts +36 -0
  34. package/dist/core/transform.d.ts.map +1 -0
  35. package/dist/core/transform.js +205 -0
  36. package/dist/core/transform.js.map +1 -0
  37. package/dist/core/types.d.ts +87 -0
  38. package/dist/core/types.d.ts.map +1 -1
  39. package/dist/core/types.js.map +1 -1
  40. package/dist/index.d.ts +11 -2
  41. package/dist/index.d.ts.map +1 -1
  42. package/dist/index.js +7 -1
  43. package/dist/index.js.map +1 -1
  44. package/dist/quickbase.esm.js +3 -3
  45. package/dist/quickbase.esm.js.map +4 -4
  46. package/dist/quickbase.min.js +3 -3
  47. package/dist/quickbase.min.js.map +4 -4
  48. package/dist/xml/codepages.d.ts +60 -0
  49. package/dist/xml/codepages.d.ts.map +1 -0
  50. package/dist/xml/codepages.js +88 -0
  51. package/dist/xml/codepages.js.map +1 -0
  52. package/dist/xml/dbvars.d.ts +39 -0
  53. package/dist/xml/dbvars.d.ts.map +1 -0
  54. package/dist/xml/dbvars.js +54 -0
  55. package/dist/xml/dbvars.js.map +1 -0
  56. package/dist/xml/errors.d.ts +64 -0
  57. package/dist/xml/errors.d.ts.map +1 -0
  58. package/dist/xml/errors.js +102 -0
  59. package/dist/xml/errors.js.map +1 -0
  60. package/dist/xml/fields.d.ts +45 -0
  61. package/dist/xml/fields.d.ts.map +1 -0
  62. package/dist/xml/fields.js +86 -0
  63. package/dist/xml/fields.js.map +1 -0
  64. package/dist/xml/groups.d.ts +196 -0
  65. package/dist/xml/groups.d.ts.map +1 -0
  66. package/dist/xml/groups.js +424 -0
  67. package/dist/xml/groups.js.map +1 -0
  68. package/dist/xml/html.d.ts +61 -0
  69. package/dist/xml/html.d.ts.map +1 -0
  70. package/dist/xml/html.js +110 -0
  71. package/dist/xml/html.js.map +1 -0
  72. package/dist/xml/index.d.ts +453 -0
  73. package/dist/xml/index.d.ts.map +1 -0
  74. package/dist/xml/index.js +741 -0
  75. package/dist/xml/index.js.map +1 -0
  76. package/dist/xml/metadata.d.ts +49 -0
  77. package/dist/xml/metadata.d.ts.map +1 -0
  78. package/dist/xml/metadata.js +84 -0
  79. package/dist/xml/metadata.js.map +1 -0
  80. package/dist/xml/records.d.ts +106 -0
  81. package/dist/xml/records.d.ts.map +1 -0
  82. package/dist/xml/records.js +220 -0
  83. package/dist/xml/records.js.map +1 -0
  84. package/dist/xml/request.d.ts +115 -0
  85. package/dist/xml/request.d.ts.map +1 -0
  86. package/dist/xml/request.js +167 -0
  87. package/dist/xml/request.js.map +1 -0
  88. package/dist/xml/roles.d.ts +117 -0
  89. package/dist/xml/roles.d.ts.map +1 -0
  90. package/dist/xml/roles.js +241 -0
  91. package/dist/xml/roles.js.map +1 -0
  92. package/dist/xml/schema.d.ts +94 -0
  93. package/dist/xml/schema.d.ts.map +1 -0
  94. package/dist/xml/schema.js +354 -0
  95. package/dist/xml/schema.js.map +1 -0
  96. package/dist/xml/transform.d.ts +154 -0
  97. package/dist/xml/transform.d.ts.map +1 -0
  98. package/dist/xml/transform.js +182 -0
  99. package/dist/xml/transform.js.map +1 -0
  100. package/dist/xml/types.d.ts +531 -0
  101. package/dist/xml/types.d.ts.map +1 -0
  102. package/dist/xml/types.js +22 -0
  103. package/dist/xml/types.js.map +1 -0
  104. package/dist/xml/users.d.ts +92 -0
  105. package/dist/xml/users.d.ts.map +1 -0
  106. package/dist/xml/users.js +166 -0
  107. package/dist/xml/users.js.map +1 -0
  108. package/dist/xml/webhooks.d.ts +98 -0
  109. package/dist/xml/webhooks.d.ts.map +1 -0
  110. package/dist/xml/webhooks.js +202 -0
  111. package/dist/xml/webhooks.js.map +1 -0
  112. package/package.json +6 -2
@@ -0,0 +1,741 @@
1
+ /**
2
+ * XML API Client Module
3
+ *
4
+ * Provides access to legacy QuickBase XML API endpoints that have no
5
+ * JSON API equivalent (roles, groups, DBVars, code pages, etc.).
6
+ *
7
+ * XML-API: Remove this file when QuickBase discontinues the XML API.
8
+ * To find all XML API code, search for: XML-API
9
+ *
10
+ * @example
11
+ * ```typescript
12
+ * import { createClient } from 'quickbase-js';
13
+ * import { createXmlClient } from 'quickbase-js/xml';
14
+ *
15
+ * const qb = createClient({
16
+ * realm: 'myrealm',
17
+ * auth: { type: 'user-token', userToken: '...' },
18
+ * });
19
+ *
20
+ * const xml = createXmlClient(qb);
21
+ *
22
+ * // Get all roles in an app
23
+ * const roles = await xml.getRoleInfo('bqxyz123');
24
+ * ```
25
+ */
26
+ // Re-export types
27
+ export * from './types.js';
28
+ export { XmlError, XmlErrorCode, isUnauthorized, isNotFound, isInvalidTicket, isInvalidInput } from './errors.js';
29
+ // Import ReadOnlyError for consistent error handling
30
+ import { ReadOnlyError } from '../core/errors.js';
31
+ import { resolveTableAlias, resolveFieldAlias } from '../core/schema.js';
32
+ // Import response transformation functions and types
33
+ import { transformGetRecordInfoResult, transformGetSchemaResult, transformFieldAddChoicesResult, transformFieldRemoveChoicesResult, transformGrantedDBsResult, transformGrantedDBsForGroupResult, transformGetAppDTMInfoResult, transformFindDBByNameResult, } from './transform.js';
34
+ // Import endpoint implementations
35
+ import { getRoleInfo as getRoleInfoImpl, userRoles as userRolesImpl, getUserRole as getUserRoleImpl, addUserToRole as addUserToRoleImpl, removeUserFromRole as removeUserFromRoleImpl, changeUserRole as changeUserRoleImpl, } from './roles.js';
36
+ import { createGroup as createGroupImpl, deleteGroup as deleteGroupImpl, copyGroup as copyGroupImpl, changeGroupInfo as changeGroupInfoImpl, getUsersInGroup as getUsersInGroupImpl, addUserToGroup as addUserToGroupImpl, removeUserFromGroup as removeUserFromGroupImpl, getGroupRole as getGroupRoleImpl, addGroupToRole as addGroupToRoleImpl, removeGroupFromRole as removeGroupFromRoleImpl, grantedGroups as grantedGroupsImpl, grantedDBsForGroup as grantedDBsForGroupImpl, addSubgroup as addSubgroupImpl, removeSubgroup as removeSubgroupImpl, } from './groups.js';
37
+ import { getUserInfo as getUserInfoImpl, provisionUser as provisionUserImpl, sendInvitation as sendInvitationImpl, changeManager as changeManagerImpl, changeRecordOwner as changeRecordOwnerImpl, } from './users.js';
38
+ import { grantedDBs as grantedDBsImpl, findDBByName as findDBByNameImpl, getDBInfo as getDBInfoImpl, getNumRecords as getNumRecordsImpl, getSchema as getSchemaImpl, } from './schema.js';
39
+ import { getDBVar as getDBVarImpl, setDBVar as setDBVarImpl, } from './dbvars.js';
40
+ import { getDBPage as getDBPageImpl, addReplaceDBPage as addReplaceDBPageImpl, } from './codepages.js';
41
+ import { doQueryCount as doQueryCountImpl, getRecordInfo as getRecordInfoImpl, getRecordInfoByKey as getRecordInfoByKeyImpl, importFromCSV as importFromCSVImpl, runImport as runImportImpl, copyMasterDetail as copyMasterDetailImpl, } from './records.js';
42
+ import { webhooksCreate as webhooksCreateImpl, webhooksEdit as webhooksEditImpl, webhooksDelete as webhooksDeleteImpl, webhooksActivate as webhooksActivateImpl, webhooksDeactivate as webhooksDeactivateImpl, webhooksCopy as webhooksCopyImpl, } from './webhooks.js';
43
+ import { fieldAddChoices as fieldAddChoicesImpl, fieldRemoveChoices as fieldRemoveChoicesImpl, setKeyField as setKeyFieldImpl, } from './fields.js';
44
+ import { genAddRecordForm as genAddRecordFormImpl, genResultsTable as genResultsTableImpl, getRecordAsHTML as getRecordAsHTMLImpl, } from './html.js';
45
+ import { getAppDTMInfo as getAppDTMInfoImpl, getAncestorInfo as getAncestorInfoImpl, signOut as signOutImpl, } from './metadata.js';
46
+ /**
47
+ * Set of XML API actions that modify data.
48
+ * Used to enforce read-only mode.
49
+ */
50
+ const xmlWriteActions = new Set([
51
+ // User/Role management
52
+ 'API_AddUserToRole',
53
+ 'API_RemoveUserFromRole',
54
+ 'API_ChangeUserRole',
55
+ 'API_ProvisionUser',
56
+ 'API_SendInvitation',
57
+ 'API_ChangeManager',
58
+ 'API_ChangeRecordOwner',
59
+ // Group management
60
+ 'API_CreateGroup',
61
+ 'API_DeleteGroup',
62
+ 'API_AddUserToGroup',
63
+ 'API_RemoveUserFromGroup',
64
+ 'API_AddGroupToRole',
65
+ 'API_RemoveGroupFromRole',
66
+ 'API_CopyGroup',
67
+ 'API_ChangeGroupInfo',
68
+ 'API_AddSubgroup',
69
+ 'API_RemoveSubgroup',
70
+ // Variables
71
+ 'API_SetDBVar',
72
+ // Code pages
73
+ 'API_AddReplaceDBPage',
74
+ // Fields
75
+ 'API_FieldAddChoices',
76
+ 'API_FieldRemoveChoices',
77
+ 'API_SetKeyField',
78
+ // Webhooks
79
+ 'API_Webhooks_Create',
80
+ 'API_Webhooks_Edit',
81
+ 'API_Webhooks_Delete',
82
+ 'API_Webhooks_Activate',
83
+ 'API_Webhooks_Deactivate',
84
+ 'API_Webhooks_Copy',
85
+ // Records/Import
86
+ 'API_ImportFromCSV',
87
+ 'API_RunImport',
88
+ 'API_CopyMasterDetail',
89
+ 'API_PurgeRecords',
90
+ 'API_AddRecord',
91
+ 'API_EditRecord',
92
+ 'API_DeleteRecord',
93
+ // Auth (clears session state)
94
+ 'API_SignOut',
95
+ ]);
96
+ /**
97
+ * Check if an XML API action modifies data.
98
+ */
99
+ export function isXmlWriteAction(action) {
100
+ return xmlWriteActions.has(action);
101
+ }
102
+ /**
103
+ * XML API Client
104
+ *
105
+ * Provides methods for calling legacy QuickBase XML API endpoints.
106
+ * Create using the `createXmlClient()` function.
107
+ */
108
+ export class XmlClient {
109
+ caller;
110
+ readOnly;
111
+ schema;
112
+ constructor(caller, options) {
113
+ this.caller = caller;
114
+ this.readOnly = options?.readOnly ?? false;
115
+ this.schema = options?.schema;
116
+ }
117
+ /**
118
+ * Resolve a table alias to its ID using the configured schema.
119
+ * If no schema is configured or the input is already a table ID, returns unchanged.
120
+ */
121
+ resolveTable(tableRef) {
122
+ return resolveTableAlias(this.schema, tableRef);
123
+ }
124
+ /**
125
+ * Resolve a field alias to its ID using the configured schema.
126
+ * If no schema is configured or the input is already a field ID, returns unchanged.
127
+ */
128
+ resolveField(tableId, fieldRef) {
129
+ return resolveFieldAlias(this.schema, tableId, fieldRef);
130
+ }
131
+ /**
132
+ * Check if an action is allowed (not blocked by read-only mode).
133
+ * Throws ReadOnlyError if the action is blocked.
134
+ */
135
+ checkWriteAllowed(action) {
136
+ if (this.readOnly && isXmlWriteAction(action)) {
137
+ throw new ReadOnlyError('POST', `/db/${this.caller.realm()}`, action);
138
+ }
139
+ }
140
+ /**
141
+ * Execute a raw XML API request.
142
+ * Enforces read-only mode if enabled.
143
+ * This is exposed for direct XML API calls not covered by typed methods.
144
+ */
145
+ async executeXml(dbid, action, body) {
146
+ this.checkWriteAllowed(action);
147
+ return this.caller.doXml(dbid, action, body);
148
+ }
149
+ /**
150
+ * Get the realm name
151
+ */
152
+ realm() {
153
+ return this.caller.realm();
154
+ }
155
+ // ============================================================================
156
+ // Role Management
157
+ // ============================================================================
158
+ /**
159
+ * Get all roles defined in an application.
160
+ * @see https://help.quickbase.com/docs/api-getroleinfo
161
+ */
162
+ async getRoleInfo(appId) {
163
+ return getRoleInfoImpl(this.caller, this.resolveTable(appId));
164
+ }
165
+ /**
166
+ * Get all users in an application and their role assignments.
167
+ * @see https://help.quickbase.com/docs/api-userroles
168
+ */
169
+ async userRoles(appId) {
170
+ return userRolesImpl(this.caller, this.resolveTable(appId));
171
+ }
172
+ /**
173
+ * Get roles for a specific user.
174
+ * @see https://help.quickbase.com/docs/api-getuserrole
175
+ */
176
+ async getUserRole(appId, userId, includeGroups) {
177
+ return getUserRoleImpl(this.caller, this.resolveTable(appId), userId, includeGroups);
178
+ }
179
+ /**
180
+ * Assign a user to a role.
181
+ * @see https://help.quickbase.com/docs/api-addusertorole
182
+ */
183
+ async addUserToRole(appId, userId, roleId) {
184
+ this.checkWriteAllowed('API_AddUserToRole');
185
+ return addUserToRoleImpl(this.caller, this.resolveTable(appId), userId, roleId);
186
+ }
187
+ /**
188
+ * Remove a user from a role.
189
+ * @see https://help.quickbase.com/docs/api-removeuserfromrole
190
+ */
191
+ async removeUserFromRole(appId, userId, roleId) {
192
+ this.checkWriteAllowed('API_RemoveUserFromRole');
193
+ return removeUserFromRoleImpl(this.caller, this.resolveTable(appId), userId, roleId);
194
+ }
195
+ /**
196
+ * Change a user's role.
197
+ * @see https://help.quickbase.com/docs/api-changeuserrole
198
+ */
199
+ async changeUserRole(appId, userId, currentRoleId, newRoleId) {
200
+ this.checkWriteAllowed('API_ChangeUserRole');
201
+ return changeUserRoleImpl(this.caller, this.resolveTable(appId), userId, currentRoleId, newRoleId);
202
+ }
203
+ // ============================================================================
204
+ // Group Management
205
+ // ============================================================================
206
+ /**
207
+ * Create a new group.
208
+ * @see https://help.quickbase.com/docs/api-creategroup
209
+ */
210
+ async createGroup(name, description, accountId) {
211
+ this.checkWriteAllowed('API_CreateGroup');
212
+ return createGroupImpl(this.caller, name, description, accountId);
213
+ }
214
+ /**
215
+ * Delete a group.
216
+ * @see https://help.quickbase.com/docs/api-deletegroup
217
+ */
218
+ async deleteGroup(groupId) {
219
+ this.checkWriteAllowed('API_DeleteGroup');
220
+ return deleteGroupImpl(this.caller, groupId);
221
+ }
222
+ /**
223
+ * Copy a group.
224
+ * @see https://help.quickbase.com/docs/api-copygroup
225
+ */
226
+ async copyGroup(groupId, name, description, accountId) {
227
+ this.checkWriteAllowed('API_CopyGroup');
228
+ return copyGroupImpl(this.caller, groupId, name, description, accountId);
229
+ }
230
+ /**
231
+ * Change group information.
232
+ * @see https://help.quickbase.com/docs/api-changegroupinfo
233
+ */
234
+ async changeGroupInfo(groupId, name, description, accountId) {
235
+ this.checkWriteAllowed('API_ChangeGroupInfo');
236
+ return changeGroupInfoImpl(this.caller, groupId, name, description, accountId);
237
+ }
238
+ /**
239
+ * Get users and managers in a group.
240
+ * @see https://help.quickbase.com/docs/api-getusersingroup
241
+ */
242
+ async getUsersInGroup(groupId, includeManagers) {
243
+ return getUsersInGroupImpl(this.caller, groupId, includeManagers);
244
+ }
245
+ /**
246
+ * Add a user to a group.
247
+ * @see https://help.quickbase.com/docs/api-addusertogroup
248
+ */
249
+ async addUserToGroup(groupId, userId, allowAdminAccess) {
250
+ this.checkWriteAllowed('API_AddUserToGroup');
251
+ return addUserToGroupImpl(this.caller, groupId, userId, allowAdminAccess);
252
+ }
253
+ /**
254
+ * Remove a user from a group.
255
+ * @see https://help.quickbase.com/docs/api-removeuserfromgroup
256
+ */
257
+ async removeUserFromGroup(groupId, userId) {
258
+ this.checkWriteAllowed('API_RemoveUserFromGroup');
259
+ return removeUserFromGroupImpl(this.caller, groupId, userId);
260
+ }
261
+ /**
262
+ * Get roles assigned to a group in an app.
263
+ * @see https://help.quickbase.com/docs/api-getgrouprole
264
+ */
265
+ async getGroupRole(appId, groupId) {
266
+ return getGroupRoleImpl(this.caller, this.resolveTable(appId), groupId);
267
+ }
268
+ /**
269
+ * Assign a group to a role.
270
+ * @see https://help.quickbase.com/docs/api-addgrouptorole
271
+ */
272
+ async addGroupToRole(appId, groupId, roleId) {
273
+ this.checkWriteAllowed('API_AddGroupToRole');
274
+ return addGroupToRoleImpl(this.caller, this.resolveTable(appId), groupId, roleId);
275
+ }
276
+ /**
277
+ * Remove a group from a role.
278
+ * @see https://help.quickbase.com/docs/api-removegroupfromrole
279
+ */
280
+ async removeGroupFromRole(appId, groupId, roleId, allRoles) {
281
+ this.checkWriteAllowed('API_RemoveGroupFromRole');
282
+ return removeGroupFromRoleImpl(this.caller, this.resolveTable(appId), groupId, roleId, allRoles);
283
+ }
284
+ /**
285
+ * Get groups a user belongs to.
286
+ * @see https://help.quickbase.com/docs/api-grantedgroups
287
+ */
288
+ async grantedGroups(userId, adminOnly) {
289
+ return grantedGroupsImpl(this.caller, userId, adminOnly);
290
+ }
291
+ /**
292
+ * Get apps a group can access.
293
+ * @see https://help.quickbase.com/docs/api-granteddbsforgroup
294
+ */
295
+ async grantedDBsForGroup(groupId) {
296
+ const result = await grantedDBsForGroupImpl(this.caller, groupId);
297
+ return transformGrantedDBsForGroupResult(result, this.schema);
298
+ }
299
+ /**
300
+ * Add a subgroup to a group.
301
+ * @see https://help.quickbase.com/docs/api-addsubgroup
302
+ */
303
+ async addSubgroup(groupId, subgroupId) {
304
+ this.checkWriteAllowed('API_AddSubgroup');
305
+ return addSubgroupImpl(this.caller, groupId, subgroupId);
306
+ }
307
+ /**
308
+ * Remove a subgroup from a group.
309
+ * @see https://help.quickbase.com/docs/api-removesubgroup
310
+ */
311
+ async removeSubgroup(groupId, subgroupId) {
312
+ this.checkWriteAllowed('API_RemoveSubgroup');
313
+ return removeSubgroupImpl(this.caller, groupId, subgroupId);
314
+ }
315
+ // ============================================================================
316
+ // User Management
317
+ // ============================================================================
318
+ /**
319
+ * Get user information by email.
320
+ * @see https://help.quickbase.com/docs/api-getuserinfo
321
+ */
322
+ async getUserInfo(email) {
323
+ return getUserInfoImpl(this.caller, email);
324
+ }
325
+ /**
326
+ * Create a new unregistered user.
327
+ * @see https://help.quickbase.com/docs/api-provisionuser
328
+ */
329
+ async provisionUser(appId, email, firstName, lastName, roleId) {
330
+ this.checkWriteAllowed('API_ProvisionUser');
331
+ return provisionUserImpl(this.caller, this.resolveTable(appId), email, firstName, lastName, roleId);
332
+ }
333
+ /**
334
+ * Send invitation email to a user.
335
+ * @see https://help.quickbase.com/docs/api-sendinvitation
336
+ */
337
+ async sendInvitation(appId, userId, userText) {
338
+ this.checkWriteAllowed('API_SendInvitation');
339
+ return sendInvitationImpl(this.caller, this.resolveTable(appId), userId, userText);
340
+ }
341
+ /**
342
+ * Change the application manager.
343
+ * @see https://help.quickbase.com/docs/api-changemanager
344
+ */
345
+ async changeManager(appId, newManagerEmail) {
346
+ this.checkWriteAllowed('API_ChangeManager');
347
+ return changeManagerImpl(this.caller, this.resolveTable(appId), newManagerEmail);
348
+ }
349
+ /**
350
+ * Change the owner of a record.
351
+ * @see https://help.quickbase.com/docs/api-changerecordowner
352
+ */
353
+ async changeRecordOwner(tableId, recordId, newOwner) {
354
+ this.checkWriteAllowed('API_ChangeRecordOwner');
355
+ return changeRecordOwnerImpl(this.caller, this.resolveTable(tableId), recordId, newOwner);
356
+ }
357
+ // ============================================================================
358
+ // App Discovery
359
+ // ============================================================================
360
+ /**
361
+ * List all apps/tables the user can access.
362
+ * @see https://help.quickbase.com/docs/api-granteddbs
363
+ */
364
+ async grantedDBs(options) {
365
+ const result = await grantedDBsImpl(this.caller, options);
366
+ return transformGrantedDBsResult(result, this.schema);
367
+ }
368
+ /**
369
+ * Find an app by name.
370
+ * @see https://help.quickbase.com/docs/api-finddbbyname
371
+ */
372
+ async findDBByName(name, parentsOnly) {
373
+ const result = await findDBByNameImpl(this.caller, name, parentsOnly);
374
+ return transformFindDBByNameResult(result, this.schema);
375
+ }
376
+ /**
377
+ * Get app/table metadata.
378
+ * @see https://help.quickbase.com/docs/api-getdbinfo
379
+ */
380
+ async getDBInfo(dbid) {
381
+ return getDBInfoImpl(this.caller, this.resolveTable(dbid));
382
+ }
383
+ /**
384
+ * Get total record count for a table.
385
+ * @see https://help.quickbase.com/docs/api-getnumrecords
386
+ */
387
+ async getNumRecords(tableId) {
388
+ return getNumRecordsImpl(this.caller, this.resolveTable(tableId));
389
+ }
390
+ // ============================================================================
391
+ // Schema Information
392
+ // ============================================================================
393
+ /**
394
+ * Get comprehensive app/table metadata.
395
+ * @see https://help.quickbase.com/docs/api-getschema
396
+ */
397
+ async getSchema(dbid) {
398
+ const resolvedDbid = this.resolveTable(dbid);
399
+ const result = await getSchemaImpl(this.caller, resolvedDbid);
400
+ return transformGetSchemaResult(result, this.schema, resolvedDbid);
401
+ }
402
+ // ============================================================================
403
+ // Application Variables (DBVars)
404
+ // ============================================================================
405
+ /**
406
+ * Get an application variable value.
407
+ * @see https://help.quickbase.com/docs/api-getdbvar
408
+ */
409
+ async getDBVar(appId, varName) {
410
+ return getDBVarImpl(this.caller, this.resolveTable(appId), varName);
411
+ }
412
+ /**
413
+ * Set an application variable value.
414
+ * @see https://help.quickbase.com/docs/api-setdbvar
415
+ */
416
+ async setDBVar(appId, varName, value) {
417
+ this.checkWriteAllowed('API_SetDBVar');
418
+ return setDBVarImpl(this.caller, this.resolveTable(appId), varName, value);
419
+ }
420
+ // ============================================================================
421
+ // Code Pages
422
+ // ============================================================================
423
+ /**
424
+ * Get stored code page content.
425
+ * @see https://help.quickbase.com/docs/api-getdbpage
426
+ */
427
+ async getDBPage(appId, pageIdOrName) {
428
+ return getDBPageImpl(this.caller, this.resolveTable(appId), pageIdOrName);
429
+ }
430
+ /**
431
+ * Create or update a code page.
432
+ * @see https://help.quickbase.com/docs/api-addreplacedbpage
433
+ */
434
+ async addReplaceDBPage(appId, pageName, pageId, pageType, pageBody) {
435
+ this.checkWriteAllowed('API_AddReplaceDBPage');
436
+ return addReplaceDBPageImpl(this.caller, this.resolveTable(appId), pageName, pageId, pageType, pageBody);
437
+ }
438
+ // ============================================================================
439
+ // Field Management
440
+ // ============================================================================
441
+ /**
442
+ * Add choices to a multiple-choice field.
443
+ * @see https://help.quickbase.com/docs/api-fieldaddchoices
444
+ */
445
+ async fieldAddChoices(tableId, fieldId, choices) {
446
+ this.checkWriteAllowed('API_FieldAddChoices');
447
+ const resolvedTableId = this.resolveTable(tableId);
448
+ const resolvedFieldId = this.resolveField(resolvedTableId, fieldId);
449
+ const result = await fieldAddChoicesImpl(this.caller, resolvedTableId, resolvedFieldId, choices);
450
+ return transformFieldAddChoicesResult(result, this.schema, resolvedTableId);
451
+ }
452
+ /**
453
+ * Remove choices from a multiple-choice field.
454
+ * @see https://help.quickbase.com/docs/api-fieldremovechoices
455
+ */
456
+ async fieldRemoveChoices(tableId, fieldId, choices) {
457
+ this.checkWriteAllowed('API_FieldRemoveChoices');
458
+ const resolvedTableId = this.resolveTable(tableId);
459
+ const resolvedFieldId = this.resolveField(resolvedTableId, fieldId);
460
+ const result = await fieldRemoveChoicesImpl(this.caller, resolvedTableId, resolvedFieldId, choices);
461
+ return transformFieldRemoveChoicesResult(result, this.schema, resolvedTableId);
462
+ }
463
+ /**
464
+ * Set the key field for a table.
465
+ * @see https://help.quickbase.com/docs/api-setkeyfield
466
+ */
467
+ async setKeyField(tableId, fieldId) {
468
+ this.checkWriteAllowed('API_SetKeyField');
469
+ const resolvedTableId = this.resolveTable(tableId);
470
+ const resolvedFieldId = this.resolveField(resolvedTableId, fieldId);
471
+ return setKeyFieldImpl(this.caller, resolvedTableId, resolvedFieldId);
472
+ }
473
+ // ============================================================================
474
+ // Record Information
475
+ // ============================================================================
476
+ /**
477
+ * Get count of matching records without fetching data.
478
+ * @see https://help.quickbase.com/docs/api-doquerycount
479
+ */
480
+ async doQueryCount(tableId, query) {
481
+ return doQueryCountImpl(this.caller, this.resolveTable(tableId), query);
482
+ }
483
+ /**
484
+ * Get a record with field metadata.
485
+ * @see https://help.quickbase.com/docs/api-getrecordinfo
486
+ */
487
+ async getRecordInfo(tableId, recordId) {
488
+ const resolvedTableId = this.resolveTable(tableId);
489
+ const result = await getRecordInfoImpl(this.caller, resolvedTableId, recordId);
490
+ return transformGetRecordInfoResult(result, this.schema, resolvedTableId);
491
+ }
492
+ /**
493
+ * Get a record by key field value.
494
+ * @see https://help.quickbase.com/docs/api-getrecordinfo
495
+ */
496
+ async getRecordInfoByKey(tableId, keyValue) {
497
+ const resolvedTableId = this.resolveTable(tableId);
498
+ const result = await getRecordInfoByKeyImpl(this.caller, resolvedTableId, keyValue);
499
+ return transformGetRecordInfoResult(result, this.schema, resolvedTableId);
500
+ }
501
+ /**
502
+ * Bulk import/update records from CSV data.
503
+ * @see https://help.quickbase.com/docs/api-importfromcsv
504
+ */
505
+ async importFromCSV(tableId, options) {
506
+ this.checkWriteAllowed('API_ImportFromCSV');
507
+ const resolvedTableId = this.resolveTable(tableId);
508
+ // Resolve field aliases in clist and mergeFieldId
509
+ const resolvedOptions = {
510
+ ...options,
511
+ clist: options.clist?.map(f => this.resolveField(resolvedTableId, f)),
512
+ mergeFieldId: options.mergeFieldId !== undefined
513
+ ? this.resolveField(resolvedTableId, options.mergeFieldId)
514
+ : undefined,
515
+ };
516
+ return importFromCSVImpl(this.caller, resolvedTableId, resolvedOptions);
517
+ }
518
+ /**
519
+ * Execute a saved import definition.
520
+ * @see https://help.quickbase.com/docs/api-runimport
521
+ */
522
+ async runImport(tableId, importId) {
523
+ this.checkWriteAllowed('API_RunImport');
524
+ return runImportImpl(this.caller, this.resolveTable(tableId), importId);
525
+ }
526
+ /**
527
+ * Copy a master record with its detail records.
528
+ * @see https://help.quickbase.com/docs/api-copymasterdetail
529
+ */
530
+ async copyMasterDetail(tableId, options) {
531
+ this.checkWriteAllowed('API_CopyMasterDetail');
532
+ const resolvedTableId = this.resolveTable(tableId);
533
+ // Resolve field aliases in copyfid and relfids
534
+ const resolvedOptions = {
535
+ ...options,
536
+ copyfid: options.copyfid !== undefined
537
+ ? this.resolveField(resolvedTableId, options.copyfid)
538
+ : undefined,
539
+ relfids: options.relfids?.map(f => this.resolveField(resolvedTableId, f)),
540
+ };
541
+ return copyMasterDetailImpl(this.caller, resolvedTableId, resolvedOptions);
542
+ }
543
+ // ============================================================================
544
+ // App Metadata
545
+ // ============================================================================
546
+ /**
547
+ * Get modification timestamps (fast, no auth required).
548
+ * @see https://help.quickbase.com/docs/api-getappdtminfo
549
+ */
550
+ async getAppDTMInfo(appId) {
551
+ const result = await getAppDTMInfoImpl(this.caller, this.resolveTable(appId));
552
+ return transformGetAppDTMInfoResult(result, this.schema);
553
+ }
554
+ /**
555
+ * Get app copy/template lineage info.
556
+ * @see https://help.quickbase.com/docs/api-getancestorinfo
557
+ */
558
+ async getAncestorInfo(appId) {
559
+ return getAncestorInfoImpl(this.caller, this.resolveTable(appId));
560
+ }
561
+ // ============================================================================
562
+ // Webhooks
563
+ // ============================================================================
564
+ /**
565
+ * Create a webhook.
566
+ * @see https://help.quickbase.com/docs/api-webhooks-create
567
+ */
568
+ async webhooksCreate(tableId, options) {
569
+ this.checkWriteAllowed('API_Webhooks_Create');
570
+ return webhooksCreateImpl(this.caller, this.resolveTable(tableId), options);
571
+ }
572
+ /**
573
+ * Edit a webhook.
574
+ * @see https://help.quickbase.com/docs/api-webhooks-edit
575
+ */
576
+ async webhooksEdit(tableId, actionId, options) {
577
+ this.checkWriteAllowed('API_Webhooks_Edit');
578
+ return webhooksEditImpl(this.caller, this.resolveTable(tableId), actionId, options);
579
+ }
580
+ /**
581
+ * Delete webhooks.
582
+ * @see https://help.quickbase.com/docs/api-webhooks-delete
583
+ */
584
+ async webhooksDelete(tableId, actionIds) {
585
+ this.checkWriteAllowed('API_Webhooks_Delete');
586
+ return webhooksDeleteImpl(this.caller, this.resolveTable(tableId), actionIds);
587
+ }
588
+ /**
589
+ * Activate webhooks.
590
+ * @see https://help.quickbase.com/docs/api-webhooks-activate
591
+ */
592
+ async webhooksActivate(tableId, actionIds) {
593
+ this.checkWriteAllowed('API_Webhooks_Activate');
594
+ return webhooksActivateImpl(this.caller, this.resolveTable(tableId), actionIds);
595
+ }
596
+ /**
597
+ * Deactivate webhooks.
598
+ * @see https://help.quickbase.com/docs/api-webhooks-deactivate
599
+ */
600
+ async webhooksDeactivate(tableId, actionIds) {
601
+ this.checkWriteAllowed('API_Webhooks_Deactivate');
602
+ return webhooksDeactivateImpl(this.caller, this.resolveTable(tableId), actionIds);
603
+ }
604
+ /**
605
+ * Copy a webhook.
606
+ * @see https://help.quickbase.com/docs/api-webhooks-copy
607
+ */
608
+ async webhooksCopy(tableId, actionId) {
609
+ this.checkWriteAllowed('API_Webhooks_Copy');
610
+ return webhooksCopyImpl(this.caller, this.resolveTable(tableId), actionId);
611
+ }
612
+ // ============================================================================
613
+ // HTML Generation
614
+ // ============================================================================
615
+ /**
616
+ * Generate HTML form for adding a record.
617
+ * @see https://help.quickbase.com/docs/api-genaddrecordform
618
+ */
619
+ async genAddRecordForm(tableId, fields) {
620
+ const resolvedTableId = this.resolveTable(tableId);
621
+ const resolvedFields = fields?.map(f => ({
622
+ id: this.resolveField(resolvedTableId, f.id),
623
+ value: f.value,
624
+ }));
625
+ return genAddRecordFormImpl(this.caller, resolvedTableId, resolvedFields);
626
+ }
627
+ /**
628
+ * Generate HTML/JS/CSV table of query results.
629
+ * @see https://help.quickbase.com/docs/api-genresultstable
630
+ */
631
+ async genResultsTable(tableId, options) {
632
+ const resolvedTableId = this.resolveTable(tableId);
633
+ const resolvedOptions = options ? {
634
+ ...options,
635
+ clist: options.clist?.map(f => this.resolveField(resolvedTableId, f)),
636
+ slist: options.slist?.map(f => this.resolveField(resolvedTableId, f)),
637
+ } : undefined;
638
+ return genResultsTableImpl(this.caller, resolvedTableId, resolvedOptions);
639
+ }
640
+ /**
641
+ * Get a record rendered as HTML.
642
+ * @see https://help.quickbase.com/docs/api-getrecordashtml
643
+ */
644
+ async getRecordAsHTML(tableId, options) {
645
+ const resolvedTableId = this.resolveTable(tableId);
646
+ const resolvedOptions = {
647
+ ...options,
648
+ dfid: options.dfid !== undefined
649
+ ? this.resolveField(resolvedTableId, options.dfid)
650
+ : undefined,
651
+ };
652
+ return getRecordAsHTMLImpl(this.caller, resolvedTableId, resolvedOptions);
653
+ }
654
+ // ============================================================================
655
+ // Authentication
656
+ // ============================================================================
657
+ /**
658
+ * Clear ticket cookie (browser-focused).
659
+ * @see https://help.quickbase.com/docs/api-signout
660
+ */
661
+ async signOut() {
662
+ return signOutImpl(this.caller);
663
+ }
664
+ }
665
+ /**
666
+ * Create an XML API client from a QuickBase client.
667
+ *
668
+ * @param client - The main QuickBase client
669
+ * @param options - Options for the XML client
670
+ * @returns XmlClient instance
671
+ *
672
+ * @example
673
+ * ```typescript
674
+ * const qb = createClient({ realm: 'myrealm', auth: {...} });
675
+ * const xml = createXmlClient(qb);
676
+ *
677
+ * const roles = await xml.getRoleInfo('bqxyz123');
678
+ * ```
679
+ */
680
+ export function createXmlClient(client, options) {
681
+ const config = client.getConfig();
682
+ // Get auth strategy if available
683
+ const getAuth = client.getAuthStrategy;
684
+ if (!getAuth) {
685
+ throw new Error('XML client requires access to auth strategy. ' +
686
+ 'Make sure you are using a compatible version of the QuickBase client.');
687
+ }
688
+ const auth = getAuth();
689
+ // Create an XmlCaller adapter that makes XML requests
690
+ const caller = {
691
+ realm: () => config.realm,
692
+ doXml: async (dbid, action, body) => {
693
+ const url = `https://${config.realm}.quickbase.com/db/${encodeURIComponent(dbid)}`;
694
+ // Get auth token for this dbid
695
+ const token = await auth.getToken(dbid);
696
+ const authHeader = auth.getAuthorizationHeader(token);
697
+ // Create abort controller for timeout
698
+ const controller = new AbortController();
699
+ const timeoutId = setTimeout(() => controller.abort(), config.timeout);
700
+ try {
701
+ const response = await config.fetchApi(url, {
702
+ method: 'POST',
703
+ headers: {
704
+ 'Content-Type': 'application/xml',
705
+ 'QUICKBASE-ACTION': action,
706
+ 'Authorization': authHeader,
707
+ },
708
+ body,
709
+ signal: controller.signal,
710
+ credentials: 'omit',
711
+ });
712
+ const text = await response.text();
713
+ // Check for HTTP-level errors (429, 5xx)
714
+ if (response.status === 429) {
715
+ const retryAfter = response.headers.get('Retry-After');
716
+ throw new Error(`Rate limited (429). Retry after: ${retryAfter ?? 'unknown'} seconds`);
717
+ }
718
+ if (response.status >= 500) {
719
+ throw new Error(`Server error: ${response.status} ${response.statusText}`);
720
+ }
721
+ return text;
722
+ }
723
+ catch (error) {
724
+ if (error instanceof Error && error.name === 'AbortError') {
725
+ throw new Error(`Request timeout after ${config.timeout}ms`);
726
+ }
727
+ throw error;
728
+ }
729
+ finally {
730
+ clearTimeout(timeoutId);
731
+ }
732
+ },
733
+ };
734
+ // Inherit readOnly and schema from main client if not explicitly set in options
735
+ const resolvedOptions = {
736
+ readOnly: options?.readOnly ?? config.readOnly ?? false,
737
+ schema: options?.schema ?? config.schema,
738
+ };
739
+ return new XmlClient(caller, resolvedOptions);
740
+ }
741
+ //# sourceMappingURL=index.js.map