quickbase-js 0.1.0-beta.10 → 0.1.0-beta.12
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 +16 -0
- package/README.md +56 -24
- package/dist/esm/quickbase.d.ts +1 -0
- package/dist/esm/quickbase.js +125 -87
- package/dist/esm/quickbase.js.map +1 -1
- package/dist/esm/quickbase.min.js +1 -1
- package/dist/esm/quickbase.min.js.map +1 -1
- package/dist/umd/quickbase.umd.js +125 -87
- package/dist/umd/quickbase.umd.js.map +1 -1
- package/dist/umd/quickbase.umd.min.js +1 -1
- package/dist/umd/quickbase.umd.min.js.map +1 -1
- package/examples/quicbase-jsCDN.html +2 -2
- package/package.json +1 -1
- package/src/ThrottleBucket.ts +52 -16
- package/src/authorizationStrategy.ts +62 -35
- package/src/generated-unified/QuickbaseClient.ts +1 -1
- package/src/invokeMethod.ts +33 -66
- package/src/quickbaseClient.ts +12 -7
- package/src/rateLimiter.ts +8 -3
- package/src/tokenCache.ts +4 -0
- package/tests/playwright/qb/auth/getAppWithTempTokenConcurrency.test.ts +208 -0
- package/tests/vitest/qb/ThrottleBucket.test.ts +77 -0
- package/tests/vitest/qb/auth/ssoTokenConcurrency.test.ts +68 -0
- package/tests/vitest/qb/auth/userTokenConcurrency.test.ts +63 -0
- package/tests/vitest/qb/fields/getFieldsUsage.test.ts +2 -2
- package/tests/vitest/unit/ThrottleBucket.test.ts +16 -10
- package/tests/vitest/unit/apps/getAppConcurrency.test.ts +151 -0
- package/tests/vitest/unit/auth/fetchTempToken401.test.ts +20 -2
- package/tests/vitest/unit/auth/userTokenConcurrency.test.ts +62 -0
- package/tests/vitest/unit/index.ts +1 -1
- package/tests/vitest/unit/quickbaseClientHttpMethods.test.ts +3 -3
- package/tools/log-gen.ts +1 -1
- package/tools/log-gen.yaml +130 -78
- package/api-examples.md +0 -49
- package/markdown-examples.md +0 -85
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// tests/vitest/unit/auth/userTokenConcurrency.test.ts
|
|
2
|
+
import { describe, it, expect, vi } from "vitest";
|
|
3
|
+
import { quickbase } from "../../../../src/quickbaseClient";
|
|
4
|
+
import { QB_APP_ID, QB_REALM, QB_USER_TOKEN, mockFetch } from "@tests/setup.ts";
|
|
5
|
+
|
|
6
|
+
describe("QuickbaseClient Unit - UserTokenStrategy Concurrency", () => {
|
|
7
|
+
it("handles concurrent getApp requests with static user token", async () => {
|
|
8
|
+
mockFetch.mockClear();
|
|
9
|
+
const client = quickbase({
|
|
10
|
+
realm: QB_REALM,
|
|
11
|
+
userToken: QB_USER_TOKEN,
|
|
12
|
+
debug: true,
|
|
13
|
+
fetchApi: mockFetch,
|
|
14
|
+
});
|
|
15
|
+
|
|
16
|
+
mockFetch.mockResolvedValue({
|
|
17
|
+
ok: true,
|
|
18
|
+
status: 200,
|
|
19
|
+
json: () =>
|
|
20
|
+
Promise.resolve({
|
|
21
|
+
id: QB_APP_ID,
|
|
22
|
+
name: "test-app",
|
|
23
|
+
created: "2025-02-13T18:22:33Z",
|
|
24
|
+
updated: "2025-03-22T04:00:18Z",
|
|
25
|
+
}),
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const concurrentRequests = [
|
|
29
|
+
client.getApp({ appId: QB_APP_ID }),
|
|
30
|
+
client.getApp({ appId: QB_APP_ID }),
|
|
31
|
+
client.getApp({ appId: QB_APP_ID }),
|
|
32
|
+
];
|
|
33
|
+
|
|
34
|
+
const results = await Promise.all(concurrentRequests);
|
|
35
|
+
|
|
36
|
+
expect(results).toHaveLength(3);
|
|
37
|
+
results.forEach((result) =>
|
|
38
|
+
expect(result).toEqual({
|
|
39
|
+
id: QB_APP_ID,
|
|
40
|
+
name: "test-app",
|
|
41
|
+
created: expect.any(Date),
|
|
42
|
+
updated: expect.any(Date),
|
|
43
|
+
})
|
|
44
|
+
);
|
|
45
|
+
|
|
46
|
+
const appCalls = mockFetch.mock.calls.filter((call) =>
|
|
47
|
+
call[0].includes(`/apps/${QB_APP_ID}`)
|
|
48
|
+
);
|
|
49
|
+
expect(appCalls).toHaveLength(3);
|
|
50
|
+
appCalls.forEach((call) =>
|
|
51
|
+
expect(call[1].headers).toMatchObject({
|
|
52
|
+
Authorization: `QB-USER-TOKEN ${QB_USER_TOKEN}`,
|
|
53
|
+
})
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
// No token fetches occur with UserTokenStrategy
|
|
57
|
+
const tokenFetchCalls = mockFetch.mock.calls.filter((call) =>
|
|
58
|
+
call[0].includes("/auth")
|
|
59
|
+
);
|
|
60
|
+
expect(tokenFetchCalls).toHaveLength(0);
|
|
61
|
+
});
|
|
62
|
+
});
|
|
@@ -9,7 +9,7 @@ export * from "./apps/getApp.test.ts";
|
|
|
9
9
|
export * from "./auth/fetchTempToken401.test.ts";
|
|
10
10
|
export * from "./auth/getTempToken.test.ts";
|
|
11
11
|
export * from "./auth/retryOn401.test.ts";
|
|
12
|
-
export * from "./auth/
|
|
12
|
+
export * from "./auth/retryTempTokenMaxRetries.test.ts";
|
|
13
13
|
|
|
14
14
|
// Fields
|
|
15
15
|
export * from "./fields/getFields.test.ts";
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
// tests/vitest/unit/quickbaseClient.test.ts
|
|
2
2
|
|
|
3
3
|
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
4
|
-
import { quickbase } from "../../../src/quickbaseClient";
|
|
4
|
+
import { quickbase } from "../../../src/quickbaseClient.ts";
|
|
5
5
|
import { mockFetch, QB_APP_ID, QB_REALM } from "../../setup.ts";
|
|
6
6
|
import {
|
|
7
7
|
UpdateAppRequest,
|
|
8
8
|
UpdateApp200Response,
|
|
9
|
-
} from "../../../src/generated/models";
|
|
10
|
-
import { ChangesetSolution200Response } from "../../../src/generated/models";
|
|
9
|
+
} from "../../../src/generated/models/index.ts";
|
|
10
|
+
import { ChangesetSolution200Response } from "../../../src/generated/models/index.ts";
|
|
11
11
|
|
|
12
12
|
describe("QuickbaseClient Unit - HTTP Method Extraction", () => {
|
|
13
13
|
let clientTemp: ReturnType<typeof quickbase>;
|
package/tools/log-gen.ts
CHANGED
|
@@ -53,7 +53,7 @@ const includeFiles: string[] = [
|
|
|
53
53
|
"src/generated-unified/QuickbaseClient.ts",
|
|
54
54
|
"src/authorizationStrategy.ts",
|
|
55
55
|
"src/rateLimiter.ts",
|
|
56
|
-
|
|
56
|
+
"src/RateLimitError.ts",
|
|
57
57
|
"src/ThrottleBucket.ts",
|
|
58
58
|
"src/tokenCache.ts",
|
|
59
59
|
"src/utils.ts",
|
package/tools/log-gen.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
project: >-
|
|
2
2
|
quickbase-js
|
|
3
3
|
date: >-
|
|
4
|
-
3/
|
|
4
|
+
3/23/2025
|
|
5
5
|
root: >-
|
|
6
6
|
/home/drew/Projects/quickbase-js
|
|
7
7
|
goals:
|
|
@@ -727,10 +727,6 @@ tree:
|
|
|
727
727
|
README.md
|
|
728
728
|
type: >-
|
|
729
729
|
file
|
|
730
|
-
- name: >-
|
|
731
|
-
api-examples.md
|
|
732
|
-
type: >-
|
|
733
|
-
file
|
|
734
730
|
- name: >-
|
|
735
731
|
build-common.js
|
|
736
732
|
type: >-
|
|
@@ -1056,10 +1052,6 @@ tree:
|
|
|
1056
1052
|
index.md
|
|
1057
1053
|
type: >-
|
|
1058
1054
|
file
|
|
1059
|
-
- name: >-
|
|
1060
|
-
markdown-examples.md
|
|
1061
|
-
type: >-
|
|
1062
|
-
file
|
|
1063
1055
|
- name: >-
|
|
1064
1056
|
open-api
|
|
1065
1057
|
type: >-
|
|
@@ -1194,6 +1186,26 @@ tree:
|
|
|
1194
1186
|
RateLimitError.ts
|
|
1195
1187
|
type: >-
|
|
1196
1188
|
file
|
|
1189
|
+
contents: >
|
|
1190
|
+
//
|
|
1191
|
+
src/RateLimitError.ts
|
|
1192
|
+
|
|
1193
|
+
export
|
|
1194
|
+
class
|
|
1195
|
+
RateLimitError
|
|
1196
|
+
extends
|
|
1197
|
+
Error
|
|
1198
|
+
{
|
|
1199
|
+
public readonly status: number;
|
|
1200
|
+
public readonly retryAfter?: number;
|
|
1201
|
+
|
|
1202
|
+
constructor(message: string, status: number, retryAfter?: number) {
|
|
1203
|
+
super(message);
|
|
1204
|
+
this.name = "RateLimitError";
|
|
1205
|
+
this.status = status;
|
|
1206
|
+
this.retryAfter = retryAfter; // Seconds from Retry-After header, if present
|
|
1207
|
+
}
|
|
1208
|
+
}
|
|
1197
1209
|
- name: >-
|
|
1198
1210
|
ThrottleBucket.ts
|
|
1199
1211
|
type: >-
|
|
@@ -1253,7 +1265,6 @@ tree:
|
|
|
1253
1265
|
//
|
|
1254
1266
|
src/authorizationStrategy.ts
|
|
1255
1267
|
|
|
1256
|
-
|
|
1257
1268
|
import
|
|
1258
1269
|
{
|
|
1259
1270
|
TokenCache
|
|
@@ -1279,18 +1290,14 @@ tree:
|
|
|
1279
1290
|
}
|
|
1280
1291
|
|
|
1281
1292
|
|
|
1282
|
-
//
|
|
1283
|
-
src/authorizationStrategy.ts
|
|
1284
|
-
(partial
|
|
1285
|
-
update)
|
|
1286
|
-
|
|
1287
|
-
|
|
1288
1293
|
export
|
|
1289
1294
|
class
|
|
1290
1295
|
TempTokenStrategy
|
|
1291
1296
|
implements
|
|
1292
1297
|
AuthorizationStrategy
|
|
1293
1298
|
{
|
|
1299
|
+
private pendingFetches: Map<string, Promise<string>> = new Map();
|
|
1300
|
+
|
|
1294
1301
|
constructor(
|
|
1295
1302
|
private tokenCache: TokenCache,
|
|
1296
1303
|
private initialTempToken: string | undefined,
|
|
@@ -1334,7 +1341,15 @@ tree:
|
|
|
1334
1341
|
async getToken(dbid: string): Promise<string | undefined> {
|
|
1335
1342
|
let token = this.tokenCache.get(dbid) || this.initialTempToken;
|
|
1336
1343
|
if (!token && dbid) {
|
|
1337
|
-
|
|
1344
|
+
if (this.pendingFetches.has(dbid)) {
|
|
1345
|
+
console.log(`[getToken] Waiting for existing fetch for dbid: ${dbid}`);
|
|
1346
|
+
return this.pendingFetches.get(dbid);
|
|
1347
|
+
}
|
|
1348
|
+
const fetchPromise = this.fetchTempToken(dbid).finally(() =>
|
|
1349
|
+
this.pendingFetches.delete(dbid)
|
|
1350
|
+
);
|
|
1351
|
+
this.pendingFetches.set(dbid, fetchPromise);
|
|
1352
|
+
token = await fetchPromise;
|
|
1338
1353
|
}
|
|
1339
1354
|
return token;
|
|
1340
1355
|
}
|
|
@@ -1369,9 +1384,12 @@ tree:
|
|
|
1369
1384
|
return null;
|
|
1370
1385
|
}
|
|
1371
1386
|
if (debug) console.log(`Refreshing temp token for dbid: ${dbid}`);
|
|
1372
|
-
const newToken = await this.
|
|
1373
|
-
|
|
1374
|
-
|
|
1387
|
+
const newToken = await this.getToken(dbid);
|
|
1388
|
+
if (newToken) {
|
|
1389
|
+
this.tokenCache.set(dbid, newToken);
|
|
1390
|
+
return newToken;
|
|
1391
|
+
}
|
|
1392
|
+
return null;
|
|
1375
1393
|
}
|
|
1376
1394
|
}
|
|
1377
1395
|
|
|
@@ -1382,7 +1400,10 @@ tree:
|
|
|
1382
1400
|
implements
|
|
1383
1401
|
AuthorizationStrategy
|
|
1384
1402
|
{
|
|
1385
|
-
constructor(
|
|
1403
|
+
constructor(
|
|
1404
|
+
private userToken: string,
|
|
1405
|
+
private baseUrl: string = "https://api.quickbase.com/v1" // Added for consistency, unused
|
|
1406
|
+
) {}
|
|
1386
1407
|
|
|
1387
1408
|
async getToken(_dbid: string): Promise<string> {
|
|
1388
1409
|
return this.userToken;
|
|
@@ -1419,23 +1440,32 @@ tree:
|
|
|
1419
1440
|
AuthorizationStrategy
|
|
1420
1441
|
{
|
|
1421
1442
|
private currentToken: string | undefined;
|
|
1443
|
+
private pendingFetches: Map<string, Promise<string>> = new Map();
|
|
1422
1444
|
|
|
1423
1445
|
constructor(
|
|
1424
1446
|
private samlToken: string,
|
|
1425
1447
|
private realm: string,
|
|
1426
1448
|
private fetchApi: typeof fetch,
|
|
1427
|
-
private debug: boolean = false
|
|
1449
|
+
private debug: boolean = false,
|
|
1450
|
+
private baseUrl: string = "https://api.quickbase.com/v1" // Added and used
|
|
1428
1451
|
) {}
|
|
1429
1452
|
|
|
1430
1453
|
async getToken(_dbid: string): Promise<string | undefined> {
|
|
1431
1454
|
if (!this.currentToken) {
|
|
1432
|
-
|
|
1455
|
+
if (this.pendingFetches.has("sso")) {
|
|
1456
|
+
if (this.debug)
|
|
1457
|
+
console.log("[getToken] Waiting for existing SSO fetch");
|
|
1458
|
+
return this.pendingFetches.get("sso");
|
|
1459
|
+
}
|
|
1460
|
+
const fetchPromise = this.fetchSsoToken({
|
|
1433
1461
|
grant_type: "urn:ietf:params:oauth:grant-type:token-exchange",
|
|
1434
1462
|
requested_token_type:
|
|
1435
1463
|
"urn:quickbase:params:oauth:token-type:temp_token",
|
|
1436
1464
|
subject_token: this.samlToken,
|
|
1437
1465
|
subject_token_type: "urn:ietf:params:oauth:token-type:saml2",
|
|
1438
|
-
});
|
|
1466
|
+
}).finally(() => this.pendingFetches.delete("sso"));
|
|
1467
|
+
this.pendingFetches.set("sso", fetchPromise);
|
|
1468
|
+
this.currentToken = await fetchPromise;
|
|
1439
1469
|
}
|
|
1440
1470
|
return this.currentToken;
|
|
1441
1471
|
}
|
|
@@ -1478,18 +1508,15 @@ tree:
|
|
|
1478
1508
|
subject_token_type: "urn:ietf:params:oauth:token-type:saml2",
|
|
1479
1509
|
};
|
|
1480
1510
|
|
|
1481
|
-
const response = await this.fetchApi(
|
|
1482
|
-
|
|
1483
|
-
{
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
1490
|
-
credentials: "omit",
|
|
1491
|
-
}
|
|
1492
|
-
);
|
|
1511
|
+
const response = await this.fetchApi(`${this.baseUrl}/auth/oauth/token`, {
|
|
1512
|
+
method: "POST",
|
|
1513
|
+
headers: {
|
|
1514
|
+
"QB-Realm-Hostname": `${this.realm}.quickbase.com`,
|
|
1515
|
+
"Content-Type": "application/json",
|
|
1516
|
+
},
|
|
1517
|
+
body: JSON.stringify(payload),
|
|
1518
|
+
credentials: "omit",
|
|
1519
|
+
});
|
|
1493
1520
|
|
|
1494
1521
|
if (!response.ok) {
|
|
1495
1522
|
const errorBody = await response.json().catch(() => ({}));
|
|
@@ -1519,18 +1546,15 @@ tree:
|
|
|
1519
1546
|
subject_token: string;
|
|
1520
1547
|
subject_token_type: string;
|
|
1521
1548
|
}): Promise<string> {
|
|
1522
|
-
const response = await this.fetchApi(
|
|
1523
|
-
|
|
1524
|
-
{
|
|
1525
|
-
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
credentials: "omit",
|
|
1532
|
-
}
|
|
1533
|
-
);
|
|
1549
|
+
const response = await this.fetchApi(`${this.baseUrl}/auth/oauth/token`, {
|
|
1550
|
+
method: "POST",
|
|
1551
|
+
headers: {
|
|
1552
|
+
"QB-Realm-Hostname": `${this.realm}.quickbase.com`,
|
|
1553
|
+
"Content-Type": "application/json",
|
|
1554
|
+
},
|
|
1555
|
+
body: JSON.stringify(params),
|
|
1556
|
+
credentials: "omit",
|
|
1557
|
+
});
|
|
1534
1558
|
|
|
1535
1559
|
if (!response.ok) {
|
|
1536
1560
|
const errorBody = await response.json().catch(() => ({}));
|
|
@@ -2327,7 +2351,7 @@ tree:
|
|
|
2327
2351
|
//
|
|
2328
2352
|
Generated
|
|
2329
2353
|
on
|
|
2330
|
-
2025-03-
|
|
2354
|
+
2025-03-23T16:58:27.294Z
|
|
2331
2355
|
|
|
2332
2356
|
import
|
|
2333
2357
|
{
|
|
@@ -3638,6 +3662,10 @@ tree:
|
|
|
3638
3662
|
}
|
|
3639
3663
|
|
|
3640
3664
|
|
|
3665
|
+
//
|
|
3666
|
+
src/invokeMethod.ts
|
|
3667
|
+
(fixed)
|
|
3668
|
+
|
|
3641
3669
|
export
|
|
3642
3670
|
async
|
|
3643
3671
|
function
|
|
@@ -3657,7 +3685,9 @@ tree:
|
|
|
3657
3685
|
rateLimiter: RateLimiter,
|
|
3658
3686
|
transformDates: (obj: any, convertStringsToDates: boolean) => any,
|
|
3659
3687
|
debug: boolean | undefined,
|
|
3660
|
-
convertDates: boolean
|
|
3688
|
+
convertDates: boolean,
|
|
3689
|
+
attempt: number = 0,
|
|
3690
|
+
maxAttempts: number = rateLimiter.maxRetries + 1
|
|
3661
3691
|
):
|
|
3662
3692
|
Promise<ReturnType<QuickbaseClient[K]>>
|
|
3663
3693
|
{
|
|
@@ -3781,9 +3811,6 @@ tree:
|
|
|
3781
3811
|
return { message, status };
|
|
3782
3812
|
}
|
|
3783
3813
|
|
|
3784
|
-
let attempt = 0;
|
|
3785
|
-
const maxAttempts = rateLimiter.maxRetries + 1;
|
|
3786
|
-
|
|
3787
3814
|
while (attempt < maxAttempts) {
|
|
3788
3815
|
console.log("[invokeMethod] Attempt:", attempt + 1, "of", maxAttempts);
|
|
3789
3816
|
try {
|
|
@@ -3810,17 +3837,7 @@ tree:
|
|
|
3810
3837
|
({ message, status } = await parseErrorResponse(response));
|
|
3811
3838
|
} else {
|
|
3812
3839
|
if (debug) console.log(`[${methodName}] Unexpected error:`, error);
|
|
3813
|
-
|
|
3814
|
-
if (error instanceof Error && "response" in error) {
|
|
3815
|
-
response = (error as any).response;
|
|
3816
|
-
if (response instanceof Response) {
|
|
3817
|
-
({ message, status } = await parseErrorResponse(response));
|
|
3818
|
-
} else {
|
|
3819
|
-
throw error; // Rethrow if no response
|
|
3820
|
-
}
|
|
3821
|
-
} else {
|
|
3822
|
-
throw error; // Rethrow truly unexpected errors
|
|
3823
|
-
}
|
|
3840
|
+
throw error; // Rethrow truly unexpected errors
|
|
3824
3841
|
}
|
|
3825
3842
|
|
|
3826
3843
|
if (debug)
|
|
@@ -3846,14 +3863,23 @@ tree:
|
|
|
3846
3863
|
continue;
|
|
3847
3864
|
}
|
|
3848
3865
|
|
|
3849
|
-
|
|
3850
|
-
|
|
3851
|
-
|
|
3852
|
-
|
|
3853
|
-
|
|
3854
|
-
|
|
3855
|
-
|
|
3856
|
-
|
|
3866
|
+
// Handle the error and decide whether to retry
|
|
3867
|
+
let newToken: string | null = null;
|
|
3868
|
+
try {
|
|
3869
|
+
newToken = await authStrategy.handleError(
|
|
3870
|
+
status,
|
|
3871
|
+
params,
|
|
3872
|
+
attempt,
|
|
3873
|
+
maxAttempts,
|
|
3874
|
+
debug,
|
|
3875
|
+
methodName
|
|
3876
|
+
);
|
|
3877
|
+
} catch (authError) {
|
|
3878
|
+
if (debug)
|
|
3879
|
+
console.log(`[${methodName}] Auth strategy error:`, authError);
|
|
3880
|
+
throw authError; // Propagate the fetchTempToken error and exit
|
|
3881
|
+
}
|
|
3882
|
+
|
|
3857
3883
|
if (newToken) {
|
|
3858
3884
|
token = newToken;
|
|
3859
3885
|
authStrategy.applyHeaders(baseHeaders, token);
|
|
@@ -3879,7 +3905,6 @@ tree:
|
|
|
3879
3905
|
//
|
|
3880
3906
|
src/quickbaseClient.ts
|
|
3881
3907
|
|
|
3882
|
-
|
|
3883
3908
|
import
|
|
3884
3909
|
{
|
|
3885
3910
|
QuickbaseClient
|
|
@@ -3920,9 +3945,6 @@ tree:
|
|
|
3920
3945
|
}
|
|
3921
3946
|
from
|
|
3922
3947
|
"./utils";
|
|
3923
|
-
//
|
|
3924
|
-
Updated
|
|
3925
|
-
import
|
|
3926
3948
|
|
|
3927
3949
|
import
|
|
3928
3950
|
{
|
|
@@ -4042,7 +4064,13 @@ tree:
|
|
|
4042
4064
|
}
|
|
4043
4065
|
|
|
4044
4066
|
const authStrategy: AuthorizationStrategy = useSso
|
|
4045
|
-
? new SsoTokenStrategy(
|
|
4067
|
+
? new SsoTokenStrategy(
|
|
4068
|
+
samlToken || "",
|
|
4069
|
+
realm,
|
|
4070
|
+
effectiveFetch,
|
|
4071
|
+
debug,
|
|
4072
|
+
baseUrl
|
|
4073
|
+
)
|
|
4046
4074
|
: useTempTokens
|
|
4047
4075
|
? new TempTokenStrategy(
|
|
4048
4076
|
tokenCache,
|
|
@@ -4051,7 +4079,7 @@ tree:
|
|
|
4051
4079
|
realm,
|
|
4052
4080
|
baseUrl
|
|
4053
4081
|
)
|
|
4054
|
-
: new UserTokenStrategy(userToken || "");
|
|
4082
|
+
: new UserTokenStrategy(userToken || "", baseUrl);
|
|
4055
4083
|
|
|
4056
4084
|
const baseHeaders: HTTPHeaders = {
|
|
4057
4085
|
"QB-Realm-Hostname": `${realm}.quickbase.com`,
|
|
@@ -4338,6 +4366,10 @@ tree:
|
|
|
4338
4366
|
.last-run.json
|
|
4339
4367
|
type: >-
|
|
4340
4368
|
file
|
|
4369
|
+
- name: >-
|
|
4370
|
+
test-results.json
|
|
4371
|
+
type: >-
|
|
4372
|
+
file
|
|
4341
4373
|
- name: >-
|
|
4342
4374
|
tests
|
|
4343
4375
|
type: >-
|
|
@@ -4370,6 +4402,10 @@ tree:
|
|
|
4370
4402
|
getAppWithTempToken.test.ts
|
|
4371
4403
|
type: >-
|
|
4372
4404
|
file
|
|
4405
|
+
- name: >-
|
|
4406
|
+
getAppWithTempTokenConcurrency.test.ts
|
|
4407
|
+
type: >-
|
|
4408
|
+
file
|
|
4373
4409
|
- name: >-
|
|
4374
4410
|
getAppWithUserToken.test.ts
|
|
4375
4411
|
type: >-
|
|
@@ -4442,10 +4478,18 @@ tree:
|
|
|
4442
4478
|
retryUserToken401.test.ts
|
|
4443
4479
|
type: >-
|
|
4444
4480
|
file
|
|
4481
|
+
- name: >-
|
|
4482
|
+
ssoTokenConcurrency.test.ts
|
|
4483
|
+
type: >-
|
|
4484
|
+
file
|
|
4445
4485
|
- name: >-
|
|
4446
4486
|
ssoTokenIntegrationWithServer.test.ts
|
|
4447
4487
|
type: >-
|
|
4448
4488
|
file
|
|
4489
|
+
- name: >-
|
|
4490
|
+
userTokenConcurrency.test.ts
|
|
4491
|
+
type: >-
|
|
4492
|
+
file
|
|
4449
4493
|
- name: >-
|
|
4450
4494
|
fields
|
|
4451
4495
|
type: >-
|
|
@@ -4580,6 +4624,10 @@ tree:
|
|
|
4580
4624
|
getApp.test.ts
|
|
4581
4625
|
type: >-
|
|
4582
4626
|
file
|
|
4627
|
+
- name: >-
|
|
4628
|
+
getAppConcurrency.test.ts
|
|
4629
|
+
type: >-
|
|
4630
|
+
file
|
|
4583
4631
|
- name: >-
|
|
4584
4632
|
getAppEvents.test.ts
|
|
4585
4633
|
type: >-
|
|
@@ -4617,6 +4665,10 @@ tree:
|
|
|
4617
4665
|
ssoTokenRefresh.test.ts
|
|
4618
4666
|
type: >-
|
|
4619
4667
|
file
|
|
4668
|
+
- name: >-
|
|
4669
|
+
userTokenConcurrency.test.ts
|
|
4670
|
+
type: >-
|
|
4671
|
+
file
|
|
4620
4672
|
- name: >-
|
|
4621
4673
|
fields
|
|
4622
4674
|
type: >-
|
package/api-examples.md
DELETED
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
outline: deep
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Runtime API Examples
|
|
6
|
-
|
|
7
|
-
This page demonstrates usage of some of the runtime APIs provided by VitePress.
|
|
8
|
-
|
|
9
|
-
The main `useData()` API can be used to access site, theme, and page data for the current page. It works in both `.md` and `.vue` files:
|
|
10
|
-
|
|
11
|
-
```md
|
|
12
|
-
<script setup>
|
|
13
|
-
import { useData } from 'vitepress'
|
|
14
|
-
|
|
15
|
-
const { theme, page, frontmatter } = useData()
|
|
16
|
-
</script>
|
|
17
|
-
|
|
18
|
-
## Results
|
|
19
|
-
|
|
20
|
-
### Theme Data
|
|
21
|
-
<pre>{{ theme }}</pre>
|
|
22
|
-
|
|
23
|
-
### Page Data
|
|
24
|
-
<pre>{{ page }}</pre>
|
|
25
|
-
|
|
26
|
-
### Page Frontmatter
|
|
27
|
-
<pre>{{ frontmatter }}</pre>
|
|
28
|
-
```
|
|
29
|
-
|
|
30
|
-
<script setup>
|
|
31
|
-
import { useData } from 'vitepress'
|
|
32
|
-
|
|
33
|
-
const { site, theme, page, frontmatter } = useData()
|
|
34
|
-
</script>
|
|
35
|
-
|
|
36
|
-
## Results
|
|
37
|
-
|
|
38
|
-
### Theme Data
|
|
39
|
-
<pre>{{ theme }}</pre>
|
|
40
|
-
|
|
41
|
-
### Page Data
|
|
42
|
-
<pre>{{ page }}</pre>
|
|
43
|
-
|
|
44
|
-
### Page Frontmatter
|
|
45
|
-
<pre>{{ frontmatter }}</pre>
|
|
46
|
-
|
|
47
|
-
## More
|
|
48
|
-
|
|
49
|
-
Check out the documentation for the [full list of runtime APIs](https://vitepress.dev/reference/runtime-api#usedata).
|
package/markdown-examples.md
DELETED
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
# Markdown Extension Examples
|
|
2
|
-
|
|
3
|
-
This page demonstrates some of the built-in markdown extensions provided by VitePress.
|
|
4
|
-
|
|
5
|
-
## Syntax Highlighting
|
|
6
|
-
|
|
7
|
-
VitePress provides Syntax Highlighting powered by [Shiki](https://github.com/shikijs/shiki), with additional features like line-highlighting:
|
|
8
|
-
|
|
9
|
-
**Input**
|
|
10
|
-
|
|
11
|
-
````md
|
|
12
|
-
```js{4}
|
|
13
|
-
export default {
|
|
14
|
-
data () {
|
|
15
|
-
return {
|
|
16
|
-
msg: 'Highlighted!'
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
```
|
|
21
|
-
````
|
|
22
|
-
|
|
23
|
-
**Output**
|
|
24
|
-
|
|
25
|
-
```js{4}
|
|
26
|
-
export default {
|
|
27
|
-
data () {
|
|
28
|
-
return {
|
|
29
|
-
msg: 'Highlighted!'
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Custom Containers
|
|
36
|
-
|
|
37
|
-
**Input**
|
|
38
|
-
|
|
39
|
-
```md
|
|
40
|
-
::: info
|
|
41
|
-
This is an info box.
|
|
42
|
-
:::
|
|
43
|
-
|
|
44
|
-
::: tip
|
|
45
|
-
This is a tip.
|
|
46
|
-
:::
|
|
47
|
-
|
|
48
|
-
::: warning
|
|
49
|
-
This is a warning.
|
|
50
|
-
:::
|
|
51
|
-
|
|
52
|
-
::: danger
|
|
53
|
-
This is a dangerous warning.
|
|
54
|
-
:::
|
|
55
|
-
|
|
56
|
-
::: details
|
|
57
|
-
This is a details block.
|
|
58
|
-
:::
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
**Output**
|
|
62
|
-
|
|
63
|
-
::: info
|
|
64
|
-
This is an info box.
|
|
65
|
-
:::
|
|
66
|
-
|
|
67
|
-
::: tip
|
|
68
|
-
This is a tip.
|
|
69
|
-
:::
|
|
70
|
-
|
|
71
|
-
::: warning
|
|
72
|
-
This is a warning.
|
|
73
|
-
:::
|
|
74
|
-
|
|
75
|
-
::: danger
|
|
76
|
-
This is a dangerous warning.
|
|
77
|
-
:::
|
|
78
|
-
|
|
79
|
-
::: details
|
|
80
|
-
This is a details block.
|
|
81
|
-
:::
|
|
82
|
-
|
|
83
|
-
## More
|
|
84
|
-
|
|
85
|
-
Check out the documentation for the [full list of markdown extensions](https://vitepress.dev/guide/markdown).
|