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.
- package/CHANGELOG.md +7 -0
- package/LICENSE +21 -0
- package/README.md +102 -0
- package/build.js +66 -0
- package/dist/quickbaseClient.d.ts +3888 -0
- package/dist/quickbaseClient.js +5812 -0
- package/dist/quickbaseClient.js.map +1 -0
- package/examples/react.js +22 -0
- package/examples/vanillajs.html +23 -0
- package/logGen.yaml +1820 -0
- package/package.json +72 -0
- package/playwright.config.ts +37 -0
- package/rollup.config.js +70 -0
- package/src/code-generation/fix-spec-definitions.ts +136 -0
- package/src/code-generation/fix-spec-main.ts +176 -0
- package/src/code-generation/fix-spec-paths.ts +163 -0
- package/src/code-generation/generate-unified-interface.ts +152 -0
- package/src/code-generation/output/quickbase-fixed.json +8435 -0
- package/src/code-generation/regenerate-client.ts +110 -0
- package/src/generated-unified/QuickbaseClient.ts +59 -0
- package/src/index.ts +1 -0
- package/src/log-gen.ts +122 -0
- package/src/quickbaseClient.ts +320 -0
- package/src/specs/QuickBase_RESTful_API_2025-03-04T06_22_39.725Z.json +46878 -0
- package/src/tokenCache.ts +51 -0
- package/src/utils.ts +5 -0
- package/test-artifacts/.last-run.json +4 -0
- package/test-artifacts/test-results.json +1801 -0
- package/test-results.json +2050 -0
- package/tests/playwright/qb/auth/cacheSwitching.test.ts +189 -0
- package/tests/playwright/qb/auth/fetchTempToken401.test.ts +217 -0
- package/tests/playwright/qb/auth/getAppWithUserToken.test.ts +151 -0
- package/tests/playwright/qb/auth/getTempToken.test.ts +180 -0
- package/tests/playwright/qb/auth/tokenPrefetch.test.ts +192 -0
- package/tests/playwright/qb/auth/tokenRenewal.test.ts +110 -0
- package/tests/setup.ts +19 -0
- package/tests/vitest/qb/apps/getApp.test.ts +46 -0
- package/tests/vitest/qb/fields/getFields.test.ts +234 -0
- package/tests/vitest/qb/index.ts +4 -0
- package/tests/vitest/qb/tables/getAppTables.test.ts +67 -0
- package/tests/vitest/unit/apps/getApp.test.ts +81 -0
- package/tests/vitest/unit/auth/fetchTempToken401.test.ts +59 -0
- package/tests/vitest/unit/auth/getTempToken.test.ts +83 -0
- package/tests/vitest/unit/auth/retryOn401.test.ts +72 -0
- package/tests/vitest/unit/auth/two401s.test.ts +77 -0
- package/tests/vitest/unit/fields/getFields.test.ts +115 -0
- package/tests/vitest/unit/index.ts +4 -0
- package/tests/vitest/unit/tables/getAppTables.test.ts +72 -0
- package/text.txt +104 -0
- package/tsconfig.json +28 -0
- package/versionrc.json +9 -0
- 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();
|