quickbase-js 1.0.1-beta.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 (52) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/LICENSE +21 -0
  3. package/README.md +102 -0
  4. package/build.js +66 -0
  5. package/dist/quickbaseClient.d.ts +3888 -0
  6. package/dist/quickbaseClient.js +5812 -0
  7. package/dist/quickbaseClient.js.map +1 -0
  8. package/examples/react.js +22 -0
  9. package/examples/vanillajs.html +23 -0
  10. package/logGen.yaml +1820 -0
  11. package/package.json +72 -0
  12. package/playwright.config.ts +37 -0
  13. package/rollup.config.js +70 -0
  14. package/src/code-generation/fix-spec-definitions.ts +136 -0
  15. package/src/code-generation/fix-spec-main.ts +176 -0
  16. package/src/code-generation/fix-spec-paths.ts +163 -0
  17. package/src/code-generation/generate-unified-interface.ts +152 -0
  18. package/src/code-generation/output/quickbase-fixed.json +8435 -0
  19. package/src/code-generation/regenerate-client.ts +110 -0
  20. package/src/generated-unified/QuickbaseClient.ts +59 -0
  21. package/src/index.ts +1 -0
  22. package/src/log-gen.ts +122 -0
  23. package/src/quickbaseClient.ts +320 -0
  24. package/src/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +46878 -0
  25. package/src/tokenCache.ts +51 -0
  26. package/src/utils.ts +5 -0
  27. package/test-artifacts/.last-run.json +4 -0
  28. package/test-artifacts/test-results.json +1801 -0
  29. package/test-results.json +2050 -0
  30. package/tests/playwright/qb/auth/cacheSwitching.test.ts +189 -0
  31. package/tests/playwright/qb/auth/fetchTempToken401.test.ts +217 -0
  32. package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +151 -0
  33. package/tests/playwright/qb/auth/getTempToken.test.ts +180 -0
  34. package/tests/playwright/qb/auth/tokenPrefetch.test.ts +192 -0
  35. package/tests/playwright/qb/auth/tokenRenewal.test.ts +110 -0
  36. package/tests/setup.ts +19 -0
  37. package/tests/vitest/qb/apps/getApp.test.ts +46 -0
  38. package/tests/vitest/qb/fields/getFields.test.ts +234 -0
  39. package/tests/vitest/qb/index.ts +4 -0
  40. package/tests/vitest/qb/tables/getAppTables.test.ts +67 -0
  41. package/tests/vitest/unit/apps/getApp.test.ts +81 -0
  42. package/tests/vitest/unit/auth/fetchTempToken401.test.ts +59 -0
  43. package/tests/vitest/unit/auth/getTempToken.test.ts +83 -0
  44. package/tests/vitest/unit/auth/retryOn401.test.ts +72 -0
  45. package/tests/vitest/unit/auth/two401s.test.ts +77 -0
  46. package/tests/vitest/unit/fields/getFields.test.ts +115 -0
  47. package/tests/vitest/unit/index.ts +4 -0
  48. package/tests/vitest/unit/tables/getAppTables.test.ts +72 -0
  49. package/text.txt +104 -0
  50. package/tsconfig.json +28 -0
  51. package/versionrc.json +9 -0
  52. package/vitest.config.ts +21 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,7 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
+
5
+ ### 1.0.1-beta.0 (2025-03-10)
6
+
7
+ Testing done in a consuming library for getApp() and getFields()
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Drew Bradford
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,102 @@
1
+ # quickbase-js
2
+
3
+ # Development workflow
4
+
5
+ ```bash
6
+ npm run fix-spec
7
+ npm run regenerate
8
+ npm run generate-unified
9
+ npm run build
10
+ npm run test
11
+ npm run test:pw:qb:all
12
+ ```
13
+
14
+ ## In QuickBase Code Pages (Browser Environment)
15
+
16
+ ### useTempTokens: true:
17
+
18
+ Token Fetch: Auto-fetches temporary tokens using the provided fetchApi (or window.fetch by default) with cookies (withCredentials: true in the internal tokenClient).
19
+
20
+ Subsequent Calls (e.g., getApp): Uses the same fetchApi (or window.fetch) with the QB-TEMP-TOKEN {TOKEN} header. No additional config needed beyond realm and useTempTokens.
21
+
22
+ How It Works: Leverages the browser’s session cookies for the initial token fetch, then uses the token for all API calls. In a real code page, window.fetch handles both steps seamlessly.
23
+
24
+ Test Output: The test uses page.evaluate for token fetch and node-fetch for getApp to bypass Playwright’s browser fetch issue, but in a code page, it’s all window.fetch.
25
+
26
+ ### userToken:
27
+
28
+ All Calls: Uses the provided fetchApi (or window.fetch by default) with the QB-USER-TOKEN {TOKEN} header. No session cookies needed (credentials: "omit").
29
+
30
+ How It Works: The user token authenticates directly, independent of the browser session, making it straightforward and reliable.
31
+
32
+ Test Output: Confirms this with page.evaluate sending QB-USER-TOKEN.
33
+
34
+ ## In Node.js (Non-Browser Environment)
35
+
36
+ ### userToken:
37
+
38
+ All Calls: Works with a provided fetchApi (e.g., fetchApi: node-fetch). Sets QB-USER-TOKEN {TOKEN} header.
39
+
40
+ How It Works: Fully functional as long as fetchApi is supplied (e.g., node-fetch), since user tokens don’t require a browser session.
41
+
42
+ Requirement: Must provide fetchApi explicitly (no default in Node.js).
43
+
44
+ ### useTempTokens: true:
45
+
46
+ Behavior: Fails with a clear error unless a browser-like fetchApi is provided:
47
+
48
+ "Temporary tokens require a browser environment or a custom fetchApi with browser-like session support"
49
+
50
+ How It Works: Temp tokens need a browser session with cookies, which Node.js can’t provide natively. A custom fetchApi (e.g., via Puppeteer) could work but is impractical for typical Node.js use.
51
+
52
+ Practicality: Effectively unusable in Node.js without external browser support, aligning with QuickBase’s temp token requirement.
53
+
54
+ ## getTempTokenDBID
55
+
56
+ Temporary Token Handling with getTempTokenDBID
57
+ The QuickBase API provides the getTempTokenDBID method to fetch temporary tokens (QB-TEMP-TOKEN) for browser-based authentication, typically using session credentials (e.g., cookies). These tokens are short-lived (~5 minutes) and intended for secure, client-side API calls. In the generated OpenAPI client, getTempTokenDBID makes a straightforward GET request to /v1/auth/temporary/{dbid} and returns { temporaryAuthorization: string }. However, this raw implementation lacks caching and doesn’t optimize repeated calls, which can lead to unnecessary API requests.
58
+ In quickbaseClient.ts, we enhance getTempTokenDBID when useTempTokens: true is enabled, wrapping it with intelligent token management:
59
+ Caching: We introduce a TokenCache to store temporary tokens by dbid. Before fetching a new token, the client checks the cache. If a valid token exists, it’s returned immediately, avoiding redundant API calls.
60
+
61
+ Custom Fetch Logic: Instead of relying solely on the generated method, we use a custom fetchTempToken function to fetch tokens. This ensures consistency with browser-based session authentication (credentials: "include") and allows us to cache the result.
62
+
63
+ Early Returns: For getTempTokenDBID, we bypass the generated method’s execution by returning the cached or freshly fetched token directly. This prevents unnecessary calls to the underlying API when the token is already available or just retrieved.
64
+
65
+ Why This Matters
66
+ Efficiency: Caching reduces API requests, crucial for performance in browser environments where temp tokens are fetched frequently but don’t change within their lifespan.
67
+
68
+ Seamless Integration: The wrapper supports both QB-USER-TOKEN (server-side) and QB-TEMP-TOKEN (client-side) workflows, controlled by the useTempTokens config. This makes the client versatile for different use cases.
69
+
70
+ Testability: The enhancement fixes issues in unit tests (e.g., getTempToken.test.ts) by ensuring predictable behavior—fetching once and reusing cached tokens—avoiding unexpected errors from redundant calls.
71
+
72
+ How It Works
73
+ When you call client.getTempTokenDBID({ dbid: "someDbid" }) with useTempTokens: true:
74
+ Cache Check: Looks for an existing token in tokenCache for the given dbid.
75
+
76
+ Fetch if Needed: If no cached token exists, fetchTempToken requests a new one from /v1/auth/temporary/{dbid} and caches it.
77
+
78
+ Return Early: Returns { temporaryAuthorization: token } immediately, skipping the generated method’s execution.
79
+
80
+ For other methods (e.g., getFields), the fetched temp token is applied to the Authorization header, ensuring authenticated API calls without re-fetching.
81
+
82
+ ## 401 Unauthorized Error Behavior
83
+
84
+ The quickbase-js library manages 401 Unauthorized errors from the QuickBase API when using temporary tokens (useTempTokens: true). Normally, it keeps tokens fresh via a time-managed cache intending to never have a 401 Unauthorized error, but there is added safety measures incase a 401 happens to occur.
85
+
86
+ If a 401 happens, the library tries once more with a fresh temporary token.
87
+
88
+ It gets the new token using fetchTempToken and retries the call.
89
+
90
+ If the retry fails with another 401, it stops and throws an error like API Error: Unauthorized (Status: 401).
91
+
92
+ Fetching a New Token:
93
+ If fetchTempToken itself gets a 401 (e.g., no valid login session), it doesn’t retry.
94
+
95
+ It throws an error right away: API Error: Unauthorized (Status: 401).
96
+
97
+ Why It’s Like This
98
+ One Retry: Retries once to fix expired tokens, but stops to avoid endless tries.
99
+
100
+ Fast Fail: No retry on fetchTempToken 401s means you know quickly if login is broken.
101
+
102
+ No Loops: Built to never get stuck retrying forever.
package/build.js ADDED
@@ -0,0 +1,66 @@
1
+ #!/usr/bin/env node
2
+ const { readFile, writeFile } = require("fs/promises");
3
+ const { execSync } = require("child_process");
4
+ const esbuild = require("esbuild");
5
+ const pkg = require("./package.json");
6
+
7
+ async function build() {
8
+ try {
9
+ // Compile TypeScript
10
+ console.log("Compiling TypeScript...");
11
+ execSync("npx tsc -b", { stdio: "inherit" });
12
+
13
+ // Format with Prettier
14
+ console.log("Formatting files with Prettier...");
15
+ execSync("npx prettier --write src/**/*.ts dist/**/*.js", {
16
+ stdio: "inherit",
17
+ });
18
+
19
+ // Bundle for Browser
20
+ console.log("Bundling for Browser...");
21
+ await esbuild.build({
22
+ entryPoints: ["dist/QuickBaseClient.js"],
23
+ bundle: true,
24
+ minify: true,
25
+ sourcemap: true,
26
+ target: ["es2015"],
27
+ outfile: "dist/quickbase-client.browser.min.js",
28
+ });
29
+
30
+ // Load Sources
31
+ console.log("Loading Sources...");
32
+ const browserSource = await readFile(
33
+ "dist/quickbase-client.browser.min.js",
34
+ "utf8"
35
+ );
36
+ const cjsSource = await readFile("dist/QuickBaseClient.js", "utf8");
37
+ const license = await readFile("LICENSE", "utf8");
38
+
39
+ // Build Header
40
+ console.log("Adding Metadata...");
41
+ const header = [
42
+ "/*! ",
43
+ ` * ${pkg.name} v${pkg.version}`,
44
+ ` * ${pkg.description || "A QuickBase API Client"}`,
45
+ ` * License: ${pkg.license}`,
46
+ ` * ${license}`,
47
+ " */",
48
+ ].join("\n");
49
+
50
+ // Write Output Files
51
+ await Promise.all([
52
+ writeFile(
53
+ "dist/quickbase-client.browser.min.js",
54
+ header + "\n" + browserSource
55
+ ),
56
+ writeFile("dist/QuickBaseClient.js", header + "\n" + cjsSource),
57
+ ]);
58
+
59
+ console.log("Build completed successfully.");
60
+ } catch (error) {
61
+ console.error("Build failed:", error);
62
+ process.exit(1);
63
+ }
64
+ }
65
+
66
+ build();