quickbase-js 1.1.0-beta.6 → 1.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 (111) hide show
  1. package/README.md +253 -135
  2. package/dist/esm/quickbase.d.ts +5614 -2861
  3. package/dist/esm/quickbase.js +3207 -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 +3536 -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/log-gen.yaml DELETED
@@ -1,1372 +0,0 @@
1
- project: quickbase-js
2
- date: 3/13/2025
3
- root: /home/drew/Projects/quickbase-js
4
- goals:
5
- - A library for interacting with the QuickBase RESTful API.
6
- - Use OpenAPI to generate types and methods using a proxy. Validate with tests.
7
- - Provide robust and intuitive temporary token support for browser environments.
8
- - User Tokens support both Node.js and browser environments.
9
- - 'Use case: JS frameworks like React, Vue, and Angular hosted in QuickBase code pages.'
10
- - Enable a flexible or native fetch in the browser.
11
- - Enable a flexible fetch framework in Node.js.
12
- - '#'
13
- - No manual updating methods when the QuickBase API changes.
14
- - The proxy magic dynamically maps generated methods and types.
15
- - '#'
16
- - TokenCache is defined per quickbaseClient call, so each instance has its own isolated TokenCache.
17
- - Each quickbase client instance has an isolated and individual token cache.
18
- pipelineOverview:
19
- - 'fix-spec-main.ts: Input: Reads the latest QuickBase_RESTful*.json file from the specs/ folder and applies fixes to the parameters and paths.'
20
- - filters out the QB-Realm-Hostname, Authorization, and User-Agent parameters.
21
- - Converts parameter names to camelCase.
22
- - Fixes array schemas and applies custom paths.
23
- - Merges paths from fix-spec-paths.ts and definitions from fix-spec-definitions.ts.
24
- - 'Output: writes quickbase-fixed.json to src/code-generation/output/.'
25
- - 'Key Behavior: The merge (spec.paths = { ...spec.paths, ...paths }) preserves all origional endpoints, only overriding those defined in fix-spec-paths.ts.'
26
- - '#'
27
- - 'regenerate-client.ts: Uses quickbase-fixed.json to generate raw TypeScript-fetch files (src/generated/). including models and APIs.'
28
- - '#'
29
- - 'generate-unified-interface.ts: Uses quickbase-fixed.json to generate a unified QuickbaseClient.ts interface in src/generated-unified/.'
30
- - QuickbaseClient.ts includes all endpoints from src/code-generation/output/quickbase-fixed, and types from src/generated.
31
- - '#'
32
- - /specs/QuickBase_RESTful_API_*.json is over 46k lines of JSON, so it's not included in the snapshot, its too large to give to an AI.
33
- - which creates difficulties in understanding the structure of the API.
34
- - It makes it difficult to model the src/code-generation/fix-spec-*.ts files in the snapshot.
35
- - '#'
36
- - vitest unit and integration tests. Integration tests use the real QuickBase API with user token auth.
37
- - playwright is used to test the real QuickBase API in a browser enviornment with temporary token auth.
38
- - temp tokens can only be generated in a browser enviornment and can not be fetched with a user token.
39
- - '#'
40
- - getTempTokenDBID() method is wrapped to enhance temporary token generation reuse interacting with a token cache.
41
- - '#'
42
- - 'npm run fix-spec: Generates quickbase-fixed.json from the latest QuickBase_RESTful*.json file.'
43
- - npm run regenerate:openapi Generates raw TypeScript-fetch files in src/generated/.
44
- - 'npm run generate:unified: Generates a unified QuickbaseClient.ts interface in src/generated-unified/.'
45
- tree:
46
- name: .
47
- type: directory
48
- children:
49
- - name: .env
50
- type: file
51
- - name: .gitignore
52
- type: file
53
- - name: CHANGELOG.md
54
- type: file
55
- - name: LICENSE
56
- type: file
57
- - name: README.md
58
- type: file
59
- - name: build.js
60
- type: file
61
- contents: |-
62
- import { execSync } from 'child_process';
63
- import { rollup } from 'rollup';
64
- import terser from '@rollup/plugin-terser';
65
- import nodeResolve from '@rollup/plugin-node-resolve';
66
- import commonjs from '@rollup/plugin-commonjs';
67
- import dts from 'rollup-plugin-dts';
68
- import { rimrafSync } from 'rimraf';
69
- import { copyFileSync, readdirSync, readFileSync, writeFileSync, mkdirSync, statSync } from 'fs';
70
- import { join } from 'path';
71
-
72
- // Clean the dist folder
73
- rimrafSync('dist');
74
- rimrafSync('dist/temp-src');
75
-
76
- // Step 1: Copy runtime-relevant files from src/ to dist/temp-src and remove .ts extensions
77
- const srcDir = join(process.cwd(), 'src');
78
- const tempSrcDir = join(process.cwd(), 'dist/temp-src');
79
- const runtimeDirs = ['generated', 'generated-unified'];
80
- const runtimeFiles = ['index.ts', 'quickbaseClient.ts', 'tokenCache.ts'];
81
-
82
- function copyAndRewriteTsExtensions(src, dest) {
83
- console.log(`Copying from ${src} to ${dest}`);
84
- mkdirSync(dest, { recursive: true });
85
- const files = readdirSync(src, { withFileTypes: true });
86
- for (const file of files) {
87
- const srcPath = join(src, file.name);
88
- const destPath = join(dest, file.name);
89
- if (file.isDirectory()) {
90
- if (runtimeDirs.includes(file.name) || runtimeDirs.some(dir => src.includes(dir))) {
91
- copyAndRewriteTsExtensions(srcPath, destPath);
92
- } else {
93
- console.log(`Skipping non-runtime directory ${srcPath}`);
94
- }
95
- } else if (file.name.endsWith('.ts')) {
96
- if (runtimeFiles.includes(file.name) || src.includes('generated') || src.includes('generated-unified')) {
97
- console.log(`Processing ${srcPath} -> ${destPath}`);
98
- let content = readFileSync(srcPath, 'utf8');
99
- content = content.replace(/(from\s+["']\.[\w\/-]+)\.ts(["'])/g, '$1$2');
100
- content = content.replace(/(export\s+\*\s+from\s+["']\.[\w\/-]+)\.ts(["'])/g, '$1$2');
101
- writeFileSync(destPath, content, 'utf8');
102
- } else {
103
- console.log(`Skipping non-runtime file ${srcPath}`);
104
- }
105
- } else {
106
- console.log(`Skipping non-.ts file ${srcPath}`);
107
- }
108
- }
109
- }
110
- copyAndRewriteTsExtensions(srcDir, tempSrcDir);
111
-
112
- // Step 2: Compile TypeScript to JavaScript with tsc
113
- console.log('Running tsc...');
114
- const tsFiles = readdirSync(tempSrcDir, { recursive: true })
115
- .filter(file => file.endsWith('.ts'))
116
- .map(file => join(tempSrcDir, file));
117
- const tscCommand = `npx tsc ${tsFiles.join(' ')} --outDir ${join(process.cwd(), 'dist/temp')} --module ESNext --target ESNext --sourceMap --moduleResolution bundler --baseUrl ${process.cwd()}`;
118
- console.log(`Command: ${tscCommand}`);
119
- execSync(tscCommand, { stdio: 'inherit' });
120
-
121
- // Step 3: Rollup configuration
122
- const isProd = process.env.NODE_ENV === 'production';
123
- const external = [
124
- 'node:http', 'node:https', 'node:zlib', 'node:stream', 'node:buffer',
125
- 'node:util', 'node:url', 'node:net', 'node:fs', 'node:path', 'node-fetch',
126
- ];
127
- const globals = { 'node-fetch': 'fetch' };
128
-
129
- // Function to create Rollup bundle
130
- async function createBundle(input, plugins, format, outputOptions) {
131
- const bundle = await rollup({
132
- input,
133
- external,
134
- plugins,
135
- });
136
- await bundle.write(outputOptions);
137
- await bundle.close();
138
- }
139
-
140
- // ESM Builds
141
- console.log('Building ESM bundles...');
142
- // Unminified ESM build (always generated)
143
- await createBundle(
144
- 'dist/temp/quickbaseClient.js',
145
- [
146
- nodeResolve({ preferBuiltins: true }),
147
- commonjs(),
148
- ],
149
- 'esm',
150
- {
151
- dir: 'dist/esm',
152
- format: 'esm',
153
- sourcemap: true,
154
- entryFileNames: 'quickbase.js',
155
- }
156
- );
157
-
158
- // Minified ESM build (only in production)
159
- if (isProd) {
160
- await createBundle(
161
- 'dist/temp/quickbaseClient.js',
162
- [
163
- nodeResolve({ preferBuiltins: true }),
164
- commonjs(),
165
- terser(),
166
- ],
167
- 'esm',
168
- {
169
- dir: 'dist/esm',
170
- format: 'esm',
171
- sourcemap: true,
172
- entryFileNames: 'quickbase.min.js',
173
- }
174
- );
175
- }
176
-
177
- // UMD Builds
178
- console.log('Building UMD bundles...');
179
- // Unminified UMD build (always generated)
180
- await createBundle(
181
- 'dist/temp/quickbaseClient.js',
182
- [
183
- nodeResolve({ preferBuiltins: true, browser: true }),
184
- commonjs(),
185
- ],
186
- 'umd',
187
- {
188
- file: join(process.cwd(), 'dist/umd', 'quickbase.umd.js'),
189
- format: 'umd',
190
- name: 'QuickbaseJS',
191
- sourcemap: true,
192
- globals,
193
- }
194
- );
195
-
196
- // Minified UMD build (only in production)
197
- if (isProd) {
198
- await createBundle(
199
- 'dist/temp/quickbaseClient.js',
200
- [
201
- nodeResolve({ preferBuiltins: true, browser: true }),
202
- commonjs(),
203
- terser(),
204
- ],
205
- 'umd',
206
- {
207
- file: join(process.cwd(), 'dist/umd', 'quickbase.umd.min.js'),
208
- format: 'umd',
209
- name: 'QuickbaseJS',
210
- sourcemap: true,
211
- globals,
212
- }
213
- );
214
- }
215
-
216
- // Declarations
217
- console.log('Generating declarations...');
218
- const dtsBundle = await rollup({
219
- input: 'src/quickbaseClient.ts',
220
- plugins: [dts({ tsconfig: './tsconfig.json', respectExternal: true })],
221
- });
222
- await dtsBundle.write({ file: 'dist/esm/quickbase.d.ts', format: 'esm' });
223
- await dtsBundle.write({ file: 'dist/umd/quickbase.umd.d.ts', format: 'umd' });
224
- await dtsBundle.close();
225
-
226
- // Clean up
227
- rimrafSync('dist/temp');
228
- rimrafSync('dist/temp-src');
229
-
230
- // List generated files and their sizes
231
- console.log('\nGenerated files:');
232
- function listFilesWithSizes(dir, prefix = '') {
233
- const files = readdirSync(dir, { withFileTypes: true });
234
- for (const file of files) {
235
- const filePath = join(dir, file.name);
236
- if (file.isDirectory()) {
237
- listFilesWithSizes(filePath, `${prefix}${file.name}/`);
238
- } else {
239
- const stats = statSync(filePath);
240
- const sizeKB = (stats.size / 1024).toFixed(2);
241
- console.log(`${prefix}${file.name} - ${sizeKB} KB`);
242
- }
243
- }
244
- }
245
- listFilesWithSizes(join(process.cwd(), 'dist'));
246
-
247
- console.log('\nBuild completed successfully');
248
- - name: dist
249
- type: directory
250
- children:
251
- - name: esm
252
- type: directory
253
- children:
254
- - name: quickbase.d.ts
255
- type: file
256
- - name: quickbase.js
257
- type: file
258
- - name: quickbase.js.map
259
- type: file
260
- - name: quickbase.min.js
261
- type: file
262
- - name: quickbase.min.js.map
263
- type: file
264
- - name: umd
265
- type: directory
266
- children:
267
- - name: quickbase.umd.d.ts
268
- type: file
269
- - name: quickbase.umd.js
270
- type: file
271
- - name: quickbase.umd.js.map
272
- type: file
273
- - name: quickbase.umd.min.js
274
- type: file
275
- - name: quickbase.umd.min.js.map
276
- type: file
277
- - name: examples
278
- type: directory
279
- children:
280
- - name: react.js
281
- type: file
282
- - name: vanillajs.html
283
- type: file
284
- - name: vanillatest.html
285
- type: file
286
- - name: log-gen.yaml
287
- type: file
288
- - name: open-api
289
- type: directory
290
- children:
291
- - name: definitions
292
- type: directory
293
- children:
294
- - name: apps.ts
295
- type: file
296
- - name: auth.ts
297
- type: file
298
- - name: fields.ts
299
- type: file
300
- - name: index.ts
301
- type: file
302
- - name: records.ts
303
- type: file
304
- - name: relationships.ts
305
- type: file
306
- - name: reports.ts
307
- type: file
308
- - name: tables.ts
309
- type: file
310
- - name: fix-spec-main.ts
311
- type: file
312
- - name: generate-unified-interface.ts
313
- type: file
314
- - name: output
315
- type: directory
316
- children:
317
- - name: quickbase-fixed.json
318
- type: file
319
- - name: paths
320
- type: directory
321
- children:
322
- - name: apps.ts
323
- type: file
324
- - name: auth.ts
325
- type: file
326
- - name: fields.ts
327
- type: file
328
- - name: index.ts
329
- type: file
330
- - name: records.ts
331
- type: file
332
- - name: relationships.ts
333
- type: file
334
- - name: reports.ts
335
- type: file
336
- - name: tables.ts
337
- type: file
338
- - name: regenerate-client.ts
339
- type: file
340
- - name: openapitools.json
341
- type: file
342
- - name: package-lock.json
343
- type: file
344
- - name: package.json
345
- type: file
346
- contents: |
347
- {
348
- "name": "quickbase-js",
349
- "version": "1.1.0-beta.5",
350
- "description": "QuickBase JavaScript client for frameworks and vanilla JS",
351
- "type": "module",
352
- "main": "dist/esm/quickbase.js",
353
- "module": "dist/esm/quickbase.js",
354
- "types": "dist/esm/quickbase.d.ts",
355
- "publishConfig": {
356
- "access": "public"
357
- },
358
- "exports": {
359
- ".": {
360
- "import": {
361
- "minified": "./dist/esm/quickbase.min.js",
362
- "default": "./dist/esm/quickbase.js"
363
- },
364
- "require": {
365
- "minified": "./dist/umd/quickbase.umd.min.js",
366
- "default": "./dist/umd/quickbase.umd.js"
367
- },
368
- "types": "./dist/esm/quickbase.d.ts",
369
- "umd:types": "./dist/umd/quickbase.umd.d.ts"
370
- }
371
- },
372
- "scripts": {
373
- "release": "standard-version",
374
- "release:beta": "standard-version --prerelease beta",
375
- "release:alpha": "standard-version --prerelease alpha",
376
- "release:push": "npm run release:beta && git push --follow-tags origin main",
377
- "release:publish": "npm run release:push && npm publish --tag beta",
378
- "release:stable": "standard-version && git push --follow-tags origin main && npm publish",
379
- "fix-spec": "node --loader ts-node/esm open-api/fix-spec-main.ts",
380
- "regenerate:openapi": "rimraf src/generated && node --loader ts-node/esm open-api/regenerate-client.ts",
381
- "regenerate:unified": "node --loader ts-node/esm open-api/generate-unified-interface.ts",
382
- "regenerate:all": "npm run fix-spec && npm run regenerate:openapi && npm run regenerate:unified",
383
- "log-gen": "node --loader ts-node/esm tools/log-gen.ts",
384
- "build": "rimraf dist && node --loader ts-node/esm build.js",
385
- "build:prod": "rimraf dist && NODE_ENV=production node --loader ts-node/esm build.js",
386
- "test:all": "vitest run tests/vitest/**/**/*.test.ts --reporter=basic && playwright test tests/playwright/qb --config playwright.config.ts --reporter=dot --quiet",
387
- "test:pw:qb:all": "playwright test tests/playwright/qb --config playwright.config.ts",
388
- "test:vitest:all": "vitest run tests/vitest/**/**/*.test.ts",
389
- "test:vitest:qb": "vitest run tests/vitest/qb/**/*.test.ts",
390
- "test:vitest:unit": "vitest run tests/vitest/unit/**/*.test.ts",
391
- "test:vitest:qb:apps": "vitest run tests/vitest/qb/apps/**/*.test.ts",
392
- "test:vitest:qb:auth": "vitest run tests/vitest/qb/auth/**/*.test.ts",
393
- "test:vitest:qb:fields": "vitest run tests/vitest/qb/fields/**/*.test.ts",
394
- "test:vitest:qb:records": "vitest run tests/vitest/qb/records/**/*.test.ts",
395
- "test:vitest:qb:tables": "vitest run tests/vitest/qb/tables/**/*.test.ts",
396
- "test:vitest:unit:apps": "vitest run tests/vitest/unit/apps/**/*.test.ts",
397
- "test:vitest:unit:auth": "vitest run tests/vitest/unit/auth/**/*.test.ts",
398
- "test:vitest:unit:fields": "vitest run tests/vitest/unit/fields/**/*.test.ts",
399
- "test:vitest:unit:records": "vitest run tests/vitest/unit/records/**/*.test.ts",
400
- "test:vitest:unit:tables": "vitest run tests/vitest/unit/tables/**/*.test.ts",
401
- "test:pw:qb:auth": "playwright test tests/playwright/qb/auth"
402
- },
403
- "dependencies": {
404
- "typescript": "^5.8.2"
405
- },
406
- "devDependencies": {
407
- "@openapitools/openapi-generator-cli": "^2.17.0",
408
- "@playwright/test": "^1.51.0",
409
- "@rollup/plugin-commonjs": "^28.0.3",
410
- "@rollup/plugin-node-resolve": "^16.0.0",
411
- "@rollup/plugin-terser": "^0.4.4",
412
- "@rollup/plugin-typescript": "^12.1.2",
413
- "@types/js-yaml": "^4.0.9",
414
- "@types/node": "^22.13.10",
415
- "dotenv": "^16.4.7",
416
- "glob": "^11.0.1",
417
- "js-yaml": "^4.1.0",
418
- "jsdom": "^26.0.0",
419
- "node-fetch": "^3.3.2",
420
- "openapi-types": "^12.1.3",
421
- "rimraf": "^5.0.10",
422
- "rollup": "^4.35.0",
423
- "rollup-plugin-dts": "^6.1.1",
424
- "standard-version": "^9.5.0",
425
- "ts-morph": "^25.0.1",
426
- "ts-node": "^10.9.2",
427
- "tslib": "^2.8.1",
428
- "undici-types": "^7.5.0",
429
- "vitest": "^3.0.8"
430
- }
431
- }
432
- - name: playwright-results.txt
433
- type: directory
434
- children:
435
- - name: .last-run.json
436
- type: file
437
- - name: playwright.config.ts
438
- type: file
439
- - name: rollup.config.mjs
440
- type: file
441
- - name: src
442
- type: directory
443
- children:
444
- - name: generated
445
- type: directory
446
- children:
447
- - name: .openapi-generator
448
- type: directory
449
- children:
450
- - name: FILES
451
- type: file
452
- - name: VERSION
453
- type: file
454
- - name: .openapi-generator-ignore
455
- type: file
456
- - name: apis
457
- type: directory
458
- children:
459
- - name: AppsApi.ts
460
- type: file
461
- - name: AuditApi.ts
462
- type: file
463
- - name: AuthApi.ts
464
- type: file
465
- - name: DocumentTemplatesApi.ts
466
- type: file
467
- - name: FieldsApi.ts
468
- type: file
469
- - name: FilesApi.ts
470
- type: file
471
- - name: FormulasApi.ts
472
- type: file
473
- - name: PlatformAnalyticsApi.ts
474
- type: file
475
- - name: RecordsApi.ts
476
- type: file
477
- - name: RelationshipsApi.ts
478
- type: file
479
- - name: ReportsApi.ts
480
- type: file
481
- - name: SolutionsApi.ts
482
- type: file
483
- - name: TablesApi.ts
484
- type: file
485
- - name: UserTokenApi.ts
486
- type: file
487
- - name: UsersApi.ts
488
- type: file
489
- - name: index.ts
490
- type: file
491
- - name: index.ts
492
- type: file
493
- - name: models
494
- type: directory
495
- children:
496
- - name: AddMembersToGroup200Response.ts
497
- type: file
498
- - name: AddSubgroupsToGroup200Response.ts
499
- type: file
500
- - name: App.ts
501
- type: file
502
- - name: AppMemoryInfo.ts
503
- type: file
504
- - name: AppSecurityProperties.ts
505
- type: file
506
- - name: Audit200Response.ts
507
- type: file
508
- - name: Audit202Response.ts
509
- type: file
510
- - name: AuditRequest.ts
511
- type: file
512
- - name: CloneUserToken200Response.ts
513
- type: file
514
- - name: CloneUserTokenRequest.ts
515
- type: file
516
- - name: CopyApp200Response.ts
517
- type: file
518
- - name: CopyAppRequest.ts
519
- type: file
520
- - name: CopyAppRequestProperties.ts
521
- type: file
522
- - name: CreateApp200Response.ts
523
- type: file
524
- - name: CreateAppRequest.ts
525
- type: file
526
- - name: CreateAppRequestVariablesInner.ts
527
- type: file
528
- - name: CreateField200Response.ts
529
- type: file
530
- - name: CreateFieldRequest.ts
531
- type: file
532
- - name: CreateRelationship200Response.ts
533
- type: file
534
- - name: CreateRelationshipRequest.ts
535
- type: file
536
- - name: CreateTableRequest.ts
537
- type: file
538
- - name: DeactivateUserToken200Response.ts
539
- type: file
540
- - name: DeleteApp200Response.ts
541
- type: file
542
- - name: DeleteAppRequest.ts
543
- type: file
544
- - name: DeleteFields200Response.ts
545
- type: file
546
- - name: DeleteFieldsRequest.ts
547
- type: file
548
- - name: DeleteFile200Response.ts
549
- type: file
550
- - name: DeleteRecords200Response.ts
551
- type: file
552
- - name: DeleteRecordsRequest.ts
553
- type: file
554
- - name: DeleteRelationship200Response.ts
555
- type: file
556
- - name: DeleteTableResponse.ts
557
- type: file
558
- - name: DenyUsers200Response.ts
559
- type: file
560
- - name: ExchangeSsoToken200Response.ts
561
- type: file
562
- - name: ExchangeSsoTokenRequest.ts
563
- type: file
564
- - name: Field.ts
565
- type: file
566
- - name: FieldPermissionsInner.ts
567
- type: file
568
- - name: FieldProperties.ts
569
- type: file
570
- - name: FieldUsage.ts
571
- type: file
572
- - name: FieldUsageField.ts
573
- type: file
574
- - name: FieldUsageUsage.ts
575
- type: file
576
- - name: GenerateDocument200Response.ts
577
- type: file
578
- - name: GetRelationships200Response.ts
579
- type: file
580
- - name: GetRelationships200ResponseMetadata.ts
581
- type: file
582
- - name: GetReport200Response.ts
583
- type: file
584
- - name: GetTempTokenDBID200Response.ts
585
- type: file
586
- - name: GetUsers200Response.ts
587
- type: file
588
- - name: GetUsersRequest.ts
589
- type: file
590
- - name: PlatformAnalyticEventSummaries200Response.ts
591
- type: file
592
- - name: PlatformAnalyticEventSummaries200ResponseMetadata.ts
593
- type: file
594
- - name: PlatformAnalyticEventSummaries200ResponseResultsInner.ts
595
- type: file
596
- - name: PlatformAnalyticEventSummaries200ResponseResultsInnerEventTypesInner.ts
597
- type: file
598
- - name: PlatformAnalyticEventSummaries200ResponseResultsInnerTotals.ts
599
- type: file
600
- - name: PlatformAnalyticEventSummaries200ResponseTotals.ts
601
- type: file
602
- - name: PlatformAnalyticEventSummaries200ResponseWhereInner.ts
603
- type: file
604
- - name: PlatformAnalyticEventSummariesRequest.ts
605
- type: file
606
- - name: PlatformAnalyticEventSummariesRequestWhereInner.ts
607
- type: file
608
- - name: PlatformAnalyticReads200Response.ts
609
- type: file
610
- - name: Record.ts
611
- type: file
612
- - name: RecordValue.ts
613
- type: file
614
- - name: Relationship.ts
615
- type: file
616
- - name: RelationshipField.ts
617
- type: file
618
- - name: RemoveMembersFromGroup200Response.ts
619
- type: file
620
- - name: RemoveSubgroupsFromGroup200Response.ts
621
- type: file
622
- - name: ReportRunResponse.ts
623
- type: file
624
- - name: RunFormula200Response.ts
625
- type: file
626
- - name: RunFormulaRequest.ts
627
- type: file
628
- - name: RunQueryRequest.ts
629
- type: file
630
- - name: RunQueryRequestGroupByInner.ts
631
- type: file
632
- - name: RunQueryRequestOptions.ts
633
- type: file
634
- - name: RunQueryRequestSortByInner.ts
635
- type: file
636
- - name: RunQueryResponse.ts
637
- type: file
638
- - name: RunQueryResponseFieldsInner.ts
639
- type: file
640
- - name: RunQueryResponseMetadata.ts
641
- type: file
642
- - name: Table.ts
643
- type: file
644
- - name: TransferUserToken200Response.ts
645
- type: file
646
- - name: TransferUserTokenRequest.ts
647
- type: file
648
- - name: UndenyUsers200Response.ts
649
- type: file
650
- - name: UpdateRelationshipRequest.ts
651
- type: file
652
- - name: UpdateTableRequest.ts
653
- type: file
654
- - name: Upsert200Response.ts
655
- type: file
656
- - name: Upsert200ResponseDataInnerValue.ts
657
- type: file
658
- - name: Upsert200ResponseMetadata.ts
659
- type: file
660
- - name: Upsert207Response.ts
661
- type: file
662
- - name: Upsert207ResponseMetadata.ts
663
- type: file
664
- - name: UpsertRequest.ts
665
- type: file
666
- - name: UsageCount.ts
667
- type: file
668
- - name: index.ts
669
- type: file
670
- - name: runtime.ts
671
- type: file
672
- - name: generated-unified
673
- type: directory
674
- children:
675
- - name: QuickbaseClient.ts
676
- type: file
677
- contents: |
678
- // Generated on 2025-03-12T19:20:50.952Z
679
- import { App, CopyApp200Response, CopyAppRequest, CreateApp200Response, CreateAppRequest, CreateField200Response, CreateFieldRequest, DeleteApp200Response, DeleteAppRequest, DeleteFields200Response, DeleteFieldsRequest, DeleteRecords200Response, DeleteRecordsRequest, DeleteTableResponse, Field, FieldUsage, GetRelationships200Response, GetTempTokenDBID200Response, ReportRunResponse, RunQueryRequest, RunQueryResponse, Table, UpdateTableRequest, Upsert200Response, Upsert207Response, UpsertRequest } from "../generated/models";
680
-
681
- export interface QuickbaseClient {
682
- createApp: (params: { body: CreateAppRequest }) => Promise<CreateApp200Response>;
683
- getApp: (params: { appId: string }) => Promise<App>;
684
- deleteApp: (params: { appId: string; body: DeleteAppRequest }) => Promise<DeleteApp200Response>;
685
- getAppEvents: (params: { appId: string }) => Promise<any[]>;
686
- copyApp: (params: { appId: string; body: CopyAppRequest }) => Promise<CopyApp200Response>;
687
- getAppTables: (params: { appId: string }) => Promise<Table[]>;
688
- createTable: (params: { appId: string; body: any }) => Promise<Table>;
689
- getTable: (params: { tableId: string; appId: string }) => Promise<Table>;
690
- updateTable: (params: { tableId: string; appId: string; body: UpdateTableRequest }) => Promise<Table>;
691
- deleteTable: (params: { tableId: string; appId: string }) => Promise<DeleteTableResponse>;
692
- getRelationships: (params: { tableId: string; skip?: number }) => Promise<GetRelationships200Response>;
693
- createRelationship: (params: { tableId: string; generated?: any }) => Promise<{ [key: string]: any }>;
694
- updateRelationship: (params: { tableId: string; relationshipId: any; generated?: any }) => Promise<{ [key: string]: any }>;
695
- deleteRelationship: (params: { tableId: string; relationshipId: any }) => Promise<{ [key: string]: any }>;
696
- getTableReports: (params: { tableId: string }) => Promise<any[]>;
697
- getReport: (params: { tableId: string; reportId: string }) => Promise<{ [key: string]: any }>;
698
- runReport: (params: { reportId: string; generated: any }) => Promise<ReportRunResponse[]>;
699
- getFields: (params: { tableId: string; includeFieldPerms?: boolean }) => Promise<Field[]>;
700
- createField: (params: { tableId: string; body: CreateFieldRequest }) => Promise<CreateField200Response>;
701
- deleteFields: (params: { tableId: string; body: DeleteFieldsRequest }) => Promise<DeleteFields200Response>;
702
- getField: (params: { fieldId: number; tableId: string; includeFieldPerms?: boolean }) => Promise<Field>;
703
- getFieldsUsage: (params: { tableId: string; skip?: number; top?: number }) => Promise<FieldUsage[]>;
704
- getFieldUsage: (params: { fieldId: number; tableId: string }) => Promise<FieldUsage[]>;
705
- runFormula: (params: { generated?: any }) => Promise<{ [key: string]: any }>;
706
- upsert: (params: { body: UpsertRequest }) => Promise<Upsert200Response | Upsert207Response>;
707
- deleteRecords: (params: { body: DeleteRecordsRequest }) => Promise<DeleteRecords200Response>;
708
- runQuery: (params: { body: RunQueryRequest }) => Promise<RunQueryResponse>;
709
- getTempTokenDBID: (params: { dbid: string }) => Promise<GetTempTokenDBID200Response>;
710
- exchangeSsoToken: (params: { generated?: any }) => Promise<{ [key: string]: any }>;
711
- cloneUserToken: (params: { generated?: any }) => Promise<{ [key: string]: any }>;
712
- transferUserToken: (params: { generated?: any }) => Promise<{ [key: string]: any }>;
713
- deactivateUserToken: (params: { }) => Promise<{ [key: string]: any }>;
714
- deleteUserToken: (params: { }) => Promise<{ [key: string]: any }>;
715
- downloadFile: (params: { tableId: string; recordId: number; fieldId: number; versionNumber: number }) => Promise<any>;
716
- deleteFile: (params: { tableId: string; recordId: number; fieldId: number; versionNumber: number }) => Promise<{ [key: string]: any }>;
717
- getUsers: (params: { accountId?: any; generated?: { [key: string]: any } }) => Promise<{ [key: string]: any }>;
718
- denyUsers: (params: { accountId?: any; generated?: string[] }) => Promise<{ [key: string]: any }>;
719
- denyUsersAndGroups: (params: { accountId?: any; shouldDeleteFromGroups: boolean; generated?: string[] }) => Promise<{ [key: string]: any }>;
720
- undenyUsers: (params: { accountId?: any; generated?: string[] }) => Promise<{ [key: string]: any }>;
721
- addMembersToGroup: (params: { gid: any; generated?: string[] }) => Promise<{ [key: string]: any }>;
722
- removeMembersFromGroup: (params: { gid: any; generated?: string[] }) => Promise<{ [key: string]: any }>;
723
- addManagersToGroup: (params: { gid: any; generated?: string[] }) => Promise<{ [key: string]: any }>;
724
- removeManagersFromGroup: (params: { gid: any; generated?: string[] }) => Promise<{ [key: string]: any }>;
725
- addSubgroupsToGroup: (params: { gid: any; generated?: string[] }) => Promise<{ [key: string]: any }>;
726
- removeSubgroupsFromGroup: (params: { gid: any; generated?: string[] }) => Promise<{ [key: string]: any }>;
727
- audit: (params: { generated?: any }) => Promise<{ [key: string]: any }>;
728
- platformAnalyticReads: (params: { day?: string }) => Promise<{ [key: string]: any }>;
729
- platformAnalyticEventSummaries: (params: { accountId?: any; generated?: any }) => Promise<any>;
730
- exportSolution: (params: { solutionId: string; qBLVersion?: string }) => Promise<any>;
731
- updateSolution: (params: { solutionId: string; generated?: any; xQBLErrorsAsSuccess?: boolean }) => Promise<any>;
732
- createSolution: (params: { generated?: any; xQBLErrorsAsSuccess?: boolean }) => Promise<any>;
733
- exportSolutionToRecord: (params: { solutionId: string; tableId: string; fieldId: number; xQBLErrorsAsSuccess?: boolean; qBLVersion?: string }) => Promise<any>;
734
- createSolutionFromRecord: (params: { tableId: string; fieldId: number; recordId: number; xQBLErrorsAsSuccess?: boolean }) => Promise<any>;
735
- updateSolutionToRecord: (params: { solutionId: string; tableId: string; fieldId: number; recordId: number; xQBLErrorsAsSuccess?: boolean }) => Promise<any>;
736
- changesetSolution: (params: { solutionId: string; generated?: any; xQBLErrorsAsSuccess?: boolean }) => Promise<any>;
737
- changesetSolutionFromRecord: (params: { solutionId: string; tableId: string; fieldId: number; recordId: number; xQBLErrorsAsSuccess?: boolean }) => Promise<any>;
738
- generateDocument: (params: { templateId: any; tableId: string; recordId?: any; filename: string; accept?: string; format?: string; margin?: string; unit?: string; pageSize?: string; orientation?: string; realm?: string }) => Promise<{ [key: string]: any }>;
739
- }
740
- - name: index.ts
741
- type: file
742
- - name: quickbaseClient.ts
743
- type: file
744
- contents: |
745
- // src/quickbaseClient.ts
746
- import { QuickbaseClient as IQuickbaseClient } from "./generated-unified/QuickbaseClient.ts";
747
- import {
748
- Configuration,
749
- HTTPHeaders,
750
- ResponseError,
751
- } from "./generated/runtime.ts";
752
- import * as apis from "./generated/apis/index.ts";
753
- import { TokenCache } from "./tokenCache.ts";
754
-
755
- // Re-export all model types from generated/models
756
- export * from "./generated/models";
757
-
758
- const simplifyName = (name: string): string =>
759
- name
760
- .replace(/ById$/, "")
761
- .replace(/Api$/, "")
762
- .replace(/^(\w)/, (_, c) => c.toLowerCase());
763
-
764
- export interface QuickbaseClient extends IQuickbaseClient {}
765
-
766
- export interface QuickbaseConfig {
767
- realm: string;
768
- userToken?: string;
769
- tempToken?: string;
770
- useTempTokens?: boolean;
771
- debug?: boolean;
772
- fetchApi?: typeof fetch;
773
- }
774
-
775
- export interface TempTokenParams {
776
- appId?: string;
777
- tableId?: string;
778
- dbid?: string;
779
- }
780
-
781
- type ApiMethod<K extends keyof QuickbaseClient> = (
782
- requestParameters: Parameters<QuickbaseClient[K]>[0],
783
- initOverrides?: RequestInit
784
- ) => Promise<ReturnType<QuickbaseClient[K]>>;
785
-
786
- interface MethodInfo<K extends keyof QuickbaseClient> {
787
- api: any;
788
- method: ApiMethod<K>;
789
- paramMap: string[];
790
- }
791
-
792
- type MethodMap = { [K in keyof QuickbaseClient]: MethodInfo<K> };
793
-
794
- const getParamNames = (fn: (...args: any[]) => any): string[] =>
795
- fn
796
- .toString()
797
- .slice(fn.toString().indexOf("(") + 1, fn.toString().indexOf(")"))
798
- .split(",")
799
- .map((p) => p.trim().split("=")[0].trim())
800
- .filter((p) => p && !p.match(/^\{/) && p !== "options");
801
-
802
- const extractDbid = (
803
- params: Partial<TempTokenParams>,
804
- errorMessage: string
805
- ): string => {
806
- const dbid = params.dbid || params.tableId || params.appId;
807
- if (!dbid) {
808
- throw new Error(errorMessage);
809
- }
810
- return dbid;
811
- };
812
-
813
- export function quickbase(config: QuickbaseConfig): QuickbaseClient {
814
- const {
815
- realm,
816
- userToken,
817
- tempToken: initialTempToken,
818
- useTempTokens,
819
- fetchApi,
820
- debug,
821
- } = config;
822
- const baseUrl = `https://api.quickbase.com/v1`;
823
-
824
- const tokenCache = new TokenCache();
825
-
826
- const baseHeaders: HTTPHeaders = {
827
- "QB-Realm-Hostname": `${realm}.quickbase.com`,
828
- "Content-Type": "application/json",
829
- };
830
-
831
- if (initialTempToken) {
832
- baseHeaders["Authorization"] = `QB-TEMP-TOKEN ${initialTempToken}`;
833
- } else if (userToken && !useTempTokens) {
834
- baseHeaders["Authorization"] = `QB-USER-TOKEN ${userToken}`;
835
- }
836
-
837
- const defaultFetch: typeof fetch | undefined =
838
- typeof globalThis.window !== "undefined"
839
- ? globalThis.window.fetch.bind(globalThis.window)
840
- : undefined;
841
- const configuration = new Configuration({
842
- basePath: baseUrl,
843
- headers: { ...baseHeaders },
844
- fetchApi: fetchApi || defaultFetch,
845
- credentials: useTempTokens ? "include" : "omit",
846
- });
847
-
848
- if (!configuration.fetchApi && typeof globalThis.window === "undefined") {
849
- throw new Error(
850
- "fetchApi must be provided in non-browser environments (e.g., Node.js)"
851
- );
852
- }
853
-
854
- const apiInstances = Object.fromEntries(
855
- Object.entries(apis)
856
- .filter(([name]) => name.endsWith("Api"))
857
- .map(([name, ApiClass]) => [
858
- name.replace("Api", "").toLowerCase(),
859
- new ApiClass(configuration),
860
- ])
861
- );
862
-
863
- const methodMap = buildMethodMap();
864
-
865
- function buildMethodMap(): MethodMap {
866
- const methodMap: Partial<MethodMap> = {};
867
- const isValidMethod = (name: string) =>
868
- !name.startsWith("_") &&
869
- name !== "constructor" &&
870
- !["Middleware", "Pre", "Post", "Raw"].some((s) => name.includes(s));
871
-
872
- for (const [apiName, api] of Object.entries(apiInstances)) {
873
- Object.getOwnPropertyNames(Object.getPrototypeOf(api))
874
- .filter(
875
- (name) =>
876
- isValidMethod(name) &&
877
- typeof api[name as keyof typeof api] === "function"
878
- )
879
- .forEach((rawMethodName) => {
880
- const simplifiedName = simplifyName(
881
- rawMethodName
882
- ) as keyof QuickbaseClient;
883
- const method = api[rawMethodName as keyof typeof api];
884
- const boundMethod = method.bind(api as any) as unknown;
885
- if (typeof boundMethod === "function" && boundMethod.length <= 2) {
886
- methodMap[simplifiedName] = {
887
- api,
888
- method: boundMethod as ApiMethod<typeof simplifiedName>,
889
- paramMap: getParamNames(method),
890
- };
891
- }
892
- });
893
- }
894
- return methodMap as MethodMap;
895
- }
896
-
897
- const fetchTempToken = async (dbid: string): Promise<string> => {
898
- const effectiveFetch = fetchApi || defaultFetch;
899
- if (!effectiveFetch) {
900
- throw new Error(
901
- "No fetch implementation available for fetching temp token"
902
- );
903
- }
904
-
905
- const response = await effectiveFetch(
906
- `https://api.quickbase.com/v1/auth/temporary/${dbid}`,
907
- {
908
- method: "GET",
909
- headers: { ...baseHeaders },
910
- credentials: "include",
911
- }
912
- );
913
-
914
- if (!response.ok) {
915
- const errorBody: { message?: string } = await response.json();
916
- throw new Error(
917
- `API Error: ${errorBody.message || "Unknown error"} (Status: ${
918
- response.status
919
- })`
920
- );
921
- }
922
-
923
- const tokenResult = await response.json();
924
- const token = tokenResult.temporaryAuthorization;
925
- if (!token) {
926
- throw new Error("No temporary token returned from API");
927
- }
928
- tokenCache.set(dbid, token);
929
- if (debug) {
930
- console.log(
931
- `Fetched and cached new token for dbid: ${dbid}`,
932
- token,
933
- `Expires at: ${new Date(
934
- Date.now() + (4 * 60 + 50) * 1000
935
- ).toISOString()}`
936
- );
937
- }
938
- return token;
939
- };
940
-
941
- async function invokeMethod<K extends keyof QuickbaseClient>(
942
- methodName: K,
943
- params: Parameters<QuickbaseClient[K]>[0] & Partial<TempTokenParams>,
944
- retryCount: number = 0
945
- ): Promise<ReturnType<QuickbaseClient[K]>> {
946
- const methodInfo = methodMap[methodName];
947
- if (!methodInfo) {
948
- throw new Error(`Method ${methodName} not found`);
949
- }
950
-
951
- const requestParameters =
952
- methodInfo.paramMap.length === 1 &&
953
- methodInfo.paramMap[0] === "requestParameters"
954
- ? { requestParameters: params }
955
- : params;
956
- let requestOptions: RequestInit = {};
957
-
958
- const selectedToken =
959
- initialTempToken || (userToken && !useTempTokens ? userToken : undefined);
960
-
961
- if (methodName === "getTempTokenDBID" && useTempTokens) {
962
- const dbid = extractDbid(params, "No dbid provided for getTempTokenDBID");
963
- const cachedToken = tokenCache.get(dbid);
964
- if (cachedToken) {
965
- return { temporaryAuthorization: cachedToken } as ReturnType<
966
- QuickbaseClient[K]
967
- >;
968
- }
969
- }
970
-
971
- let authorizationToken = selectedToken;
972
- if (useTempTokens && !authorizationToken) {
973
- const dbid = extractDbid(
974
- params,
975
- `No dbid found in params for ${methodName} to fetch temp token`
976
- );
977
- const cachedToken = tokenCache.get(dbid);
978
- authorizationToken = cachedToken || (await fetchTempToken(dbid));
979
- if (methodName === "getTempTokenDBID") {
980
- return { temporaryAuthorization: authorizationToken } as ReturnType<
981
- QuickbaseClient[K]
982
- >;
983
- }
984
- requestOptions.headers = {
985
- ...baseHeaders,
986
- Authorization: `QB-TEMP-TOKEN ${authorizationToken}`,
987
- };
988
- } else if (authorizationToken) {
989
- requestOptions.headers = {
990
- ...baseHeaders,
991
- Authorization: `QB-USER-TOKEN ${authorizationToken}`,
992
- };
993
- }
994
-
995
- try {
996
- return await methodInfo.method(requestParameters, requestOptions);
997
- } catch (error) {
998
- if (
999
- error instanceof ResponseError &&
1000
- error.response.status === 401 &&
1001
- retryCount < 1 &&
1002
- useTempTokens
1003
- ) {
1004
- if (debug) {
1005
- console.log(
1006
- `Authorization error for ${methodName}, refreshing token:`,
1007
- error.message
1008
- );
1009
- }
1010
- const dbid = extractDbid(
1011
- params,
1012
- `No dbid to refresh token after authorization error`
1013
- );
1014
- authorizationToken = await fetchTempToken(dbid);
1015
- requestOptions.headers = {
1016
- ...baseHeaders,
1017
- Authorization: `QB-TEMP-TOKEN ${authorizationToken}`,
1018
- };
1019
- if (debug) {
1020
- console.log(`Retrying ${methodName} with new token`);
1021
- }
1022
- return invokeMethod(methodName, params, retryCount + 1);
1023
- }
1024
- if (error instanceof ResponseError) {
1025
- let errorMessage = error.message;
1026
- try {
1027
- const errorBody: { message?: string } = await error.response.json();
1028
- if (debug) {
1029
- console.log(`Error response body for ${methodName}:`, errorBody);
1030
- }
1031
- errorMessage = errorBody.message || errorMessage;
1032
- } catch (e) {
1033
- // Silent fail on parse error
1034
- }
1035
- throw new Error(
1036
- `API Error: ${errorMessage} (Status: ${error.response.status})`
1037
- );
1038
- }
1039
- throw error;
1040
- }
1041
- }
1042
-
1043
- const proxy = new Proxy<QuickbaseClient>({} as QuickbaseClient, {
1044
- get: (_, prop: string): ((params: any) => Promise<any>) | undefined => {
1045
- if (prop in methodMap) {
1046
- const methodName = prop as keyof QuickbaseClient;
1047
- return (params: Parameters<QuickbaseClient[typeof methodName]>[0]) =>
1048
- invokeMethod(methodName, params);
1049
- }
1050
- return undefined;
1051
- },
1052
- });
1053
-
1054
- return proxy;
1055
- }
1056
- - name: tokenCache.ts
1057
- type: file
1058
- contents: |
1059
- interface CachedToken {
1060
- token: string;
1061
- expiresAt: number; // Timestamp in milliseconds
1062
- }
1063
-
1064
- export class TokenCache {
1065
- private cache: Map<string, CachedToken>;
1066
- private readonly lifespan: number; // Token lifespan in milliseconds
1067
-
1068
- constructor(lifespan: number = 4 * 60 * 1000 + 50 * 1000) {
1069
- // Default 4:50
1070
- this.cache = new Map<string, CachedToken>();
1071
- this.lifespan = lifespan;
1072
- }
1073
-
1074
- get(dbid: string): string | undefined {
1075
- const entry = this.cache.get(dbid);
1076
- const now = Date.now();
1077
- if (entry && entry.expiresAt > now) {
1078
- return entry.token;
1079
- }
1080
- return undefined; // Expired or not found
1081
- }
1082
-
1083
- // New method to get full entry
1084
- getEntry(dbid: string): CachedToken | undefined {
1085
- const entry = this.cache.get(dbid);
1086
- const now = Date.now();
1087
- if (entry && entry.expiresAt > now) {
1088
- return entry;
1089
- }
1090
- return undefined; // Expired or not found
1091
- }
1092
-
1093
- set(dbid: string, token: string): void {
1094
- const now = Date.now();
1095
- this.cache.set(dbid, {
1096
- token,
1097
- expiresAt: now + this.lifespan,
1098
- });
1099
- }
1100
-
1101
- dump(): [string, CachedToken][] {
1102
- return Array.from(this.cache.entries());
1103
- }
1104
-
1105
- // New method to clear the cache
1106
- clear(): void {
1107
- this.cache.clear();
1108
- }
1109
- }
1110
- - name: test-artifacts
1111
- type: directory
1112
- children:
1113
- - name: .last-run.json
1114
- type: file
1115
- - name: test-esm.js
1116
- type: file
1117
- - name: test-results.json
1118
- type: file
1119
- - name: test-umd.js
1120
- type: file
1121
- - name: test.ts
1122
- type: file
1123
- - name: tests
1124
- type: directory
1125
- children:
1126
- - name: playwright
1127
- type: directory
1128
- children:
1129
- - name: qb
1130
- type: directory
1131
- children:
1132
- - name: auth
1133
- type: directory
1134
- children:
1135
- - name: cacheSwitching.test.ts
1136
- type: file
1137
- - name: fetchTempToken401.test.ts
1138
- type: file
1139
- - name: getAppWithUserToken.test.ts
1140
- type: file
1141
- - name: getTempToken.test.ts
1142
- type: file
1143
- - name: tokenPrefetch.test.ts
1144
- type: file
1145
- - name: tokenRenewal.test.ts
1146
- type: file
1147
- - name: umd.test.ts
1148
- type: file
1149
- - name: setup.ts
1150
- type: file
1151
- - name: vitest
1152
- type: directory
1153
- children:
1154
- - name: qb
1155
- type: directory
1156
- children:
1157
- - name: apps
1158
- type: directory
1159
- children:
1160
- - name: copyApp.test.ts
1161
- type: file
1162
- - name: createApp.test.ts
1163
- type: file
1164
- - name: deleteApp.test.ts
1165
- type: file
1166
- - name: getApp.test.ts
1167
- type: file
1168
- - name: fields
1169
- type: directory
1170
- children:
1171
- - name: createField.test.ts
1172
- type: file
1173
- - name: deleteFields.test.ts
1174
- type: file
1175
- - name: getField.test.ts
1176
- type: file
1177
- - name: getFieldUsage.test.ts
1178
- type: file
1179
- - name: getFields.test.ts
1180
- type: file
1181
- - name: getFieldsUsage.test.ts
1182
- type: file
1183
- - name: index.ts
1184
- type: file
1185
- - name: records
1186
- type: directory
1187
- children:
1188
- - name: deleteRecords.test.ts
1189
- type: file
1190
- - name: runQuery.test.ts
1191
- type: file
1192
- - name: upsert.test.ts
1193
- type: file
1194
- - name: tables
1195
- type: directory
1196
- children:
1197
- - name: createTable.test.ts
1198
- type: file
1199
- - name: deleteTable.test.ts
1200
- type: file
1201
- - name: getAppTables.test.ts
1202
- type: file
1203
- - name: getRelationships.test.ts
1204
- type: file
1205
- - name: getTable.test.ts
1206
- type: file
1207
- - name: updateTable.test.ts
1208
- type: file
1209
- - name: unit
1210
- type: directory
1211
- children:
1212
- - name: apps
1213
- type: directory
1214
- children:
1215
- - name: copyApp.test.ts
1216
- type: file
1217
- - name: createApp.test.ts
1218
- type: file
1219
- - name: deleteApp.test.ts
1220
- type: file
1221
- - name: getApp.test.ts
1222
- type: file
1223
- - name: auth
1224
- type: directory
1225
- children:
1226
- - name: fetchTempToken401.test.ts
1227
- type: file
1228
- - name: getTempToken.test.ts
1229
- type: file
1230
- - name: retryOn401.test.ts
1231
- type: file
1232
- - name: two401s.test.ts
1233
- type: file
1234
- - name: fields
1235
- type: directory
1236
- children:
1237
- - name: createField.test.ts
1238
- type: file
1239
- - name: deleteFields.test.ts
1240
- type: file
1241
- - name: getField.test.ts
1242
- type: file
1243
- - name: getFieldUsage.test.ts
1244
- type: file
1245
- - name: getFields.test.ts
1246
- type: file
1247
- - name: getFieldsUsage.test.ts
1248
- type: file
1249
- - name: index.ts
1250
- type: file
1251
- - name: records
1252
- type: directory
1253
- children:
1254
- - name: deleteRecords.test.ts
1255
- type: file
1256
- - name: runQuery.test.ts
1257
- type: file
1258
- - name: upsert.test.ts
1259
- type: file
1260
- - name: tables
1261
- type: directory
1262
- children:
1263
- - name: createTable.test.ts
1264
- type: file
1265
- - name: deleteTable.test.ts
1266
- type: file
1267
- - name: getAppTables.test.ts
1268
- type: file
1269
- - name: getRelationships.test.ts
1270
- type: file
1271
- - name: getTable.test.ts
1272
- type: file
1273
- - name: updateTable.test.ts
1274
- type: file
1275
- - name: umd.test.ts
1276
- type: file
1277
- - name: text.txt
1278
- type: file
1279
- - name: tools
1280
- type: directory
1281
- children:
1282
- - name: log-gen.ts
1283
- type: file
1284
- - name: openapi-jars
1285
- type: directory
1286
- children:
1287
- - name: openapi-generator-cli-7.12.0.jar
1288
- type: file
1289
- - name: tsconfig.build.json
1290
- type: file
1291
- contents: |-
1292
- {
1293
- "extends": "./tsconfig.json",
1294
- "compilerOptions": {
1295
- "outDir": "dist/temp",
1296
- "noEmit": false,
1297
- "allowImportingTsExtensions": false,
1298
- "declaration": false,
1299
- "sourceMap": true
1300
- },
1301
- "include": ["dist/temp-src/**/*"],
1302
- "exclude": [
1303
- "node_modules",
1304
- "dist",
1305
- "tests/**/*",
1306
- "src/**/*" // Exclude original src/ to avoid confusion
1307
- ]
1308
- }
1309
- - name: tsconfig.json
1310
- type: file
1311
- contents: |-
1312
- {
1313
- "compilerOptions": {
1314
- "target": "ESNext",
1315
- "module": "ESNext",
1316
- "moduleResolution": "bundler",
1317
- "strict": true,
1318
- "lib": ["ES2015", "ESNext", "DOM"],
1319
- "types": ["node", "playwright/test", "undici-types"],
1320
- "esModuleInterop": true,
1321
- "resolveJsonModule": true,
1322
- "allowImportingTsExtensions": true,
1323
- "noEmit": true,
1324
- "outDir": "dist",
1325
- "rootDir": ".",
1326
- "declaration": true,
1327
- "sourceMap": true,
1328
- "baseUrl": ".",
1329
- "paths": {
1330
- "@/*": ["src/*"],
1331
- "@tests/*": ["tests/*"]
1332
- }
1333
- },
1334
- "include": ["src/**/*", "tests/**/*", "open-api/**/*", "tools/**/*"],
1335
- "exclude": ["node_modules", "dist", "specs"],
1336
- "ts-node": {
1337
- "esm": true,
1338
- "transpileOnly": true
1339
- }
1340
- }
1341
- - name: versionrc.json
1342
- type: file
1343
- - name: vitest.config.ts
1344
- type: file
1345
- contents: |
1346
- // vitest.config.ts
1347
- import { defineConfig } from "vitest/config";
1348
- import path from "path";
1349
- import dotenv from "dotenv"; // Add this import
1350
-
1351
- // Load .env variables before tests run
1352
- dotenv.config({ path: path.resolve(__dirname, ".env") });
1353
-
1354
- export default defineConfig({
1355
- test: {
1356
- environment: "jsdom",
1357
- include: ["tests/vitest/**/**/*.test.ts"],
1358
- setupFiles: ["tests/setup.ts"], // Relative path from root
1359
- pool: "forks",
1360
- poolOptions: {
1361
- forks: {
1362
- singleFork: true, // Run tests sequentially
1363
- },
1364
- },
1365
- },
1366
- resolve: {
1367
- alias: {
1368
- "@": path.resolve(__dirname, "./src"), // For src/ imports
1369
- "@tests": path.resolve(__dirname, "./tests"), // For tests/ imports
1370
- },
1371
- },
1372
- });