quickbase-js 1.1.0 → 2.0.0-alpha.2
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/README.md +351 -227
- package/dist/auth/index.d.ts +15 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +29 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/sso-token.d.ts +28 -0
- package/dist/auth/sso-token.d.ts.map +1 -0
- package/dist/auth/sso-token.js +108 -0
- package/dist/auth/sso-token.js.map +1 -0
- package/dist/auth/temp-token.d.ts +31 -0
- package/dist/auth/temp-token.d.ts.map +1 -0
- package/dist/auth/temp-token.js +121 -0
- package/dist/auth/temp-token.js.map +1 -0
- package/dist/auth/token-cache.d.ts +44 -0
- package/dist/auth/token-cache.d.ts.map +1 -0
- package/dist/auth/token-cache.js +84 -0
- package/dist/auth/token-cache.js.map +1 -0
- package/dist/auth/types.d.ts +44 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +5 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/auth/user-token.d.ts +17 -0
- package/dist/auth/user-token.d.ts.map +1 -0
- package/dist/auth/user-token.js +30 -0
- package/dist/auth/user-token.js.map +1 -0
- package/dist/client/index.d.ts +12 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +8 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/pagination.d.ts +131 -0
- package/dist/client/pagination.d.ts.map +1 -0
- package/dist/client/pagination.js +226 -0
- package/dist/client/pagination.js.map +1 -0
- package/dist/client/request.d.ts +40 -0
- package/dist/client/request.d.ts.map +1 -0
- package/dist/client/request.js +194 -0
- package/dist/client/request.js.map +1 -0
- package/dist/client/retry.d.ts +41 -0
- package/dist/client/retry.d.ts.map +1 -0
- package/dist/client/retry.js +122 -0
- package/dist/client/retry.js.map +1 -0
- package/dist/client/throttle.d.ts +46 -0
- package/dist/client/throttle.d.ts.map +1 -0
- package/dist/client/throttle.js +85 -0
- package/dist/client/throttle.js.map +1 -0
- package/dist/core/config.d.ts +13 -0
- package/dist/core/config.d.ts.map +1 -0
- package/dist/core/config.js +120 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/dates.d.ts +18 -0
- package/dist/core/dates.d.ts.map +1 -0
- package/dist/core/dates.js +58 -0
- package/dist/core/dates.js.map +1 -0
- package/dist/core/errors.d.ts +134 -0
- package/dist/core/errors.d.ts.map +1 -0
- package/dist/core/errors.js +185 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/index.d.ts +10 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +9 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +41 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +96 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/types.d.ts +154 -0
- package/dist/core/types.d.ts.map +1 -0
- package/dist/core/types.js +23 -0
- package/dist/core/types.js.map +1 -0
- package/dist/generated/client.d.ts +18 -0
- package/dist/generated/client.d.ts.map +1 -0
- package/dist/generated/client.js +1390 -0
- package/dist/generated/client.js.map +1 -0
- package/dist/generated/types.d.ts +3827 -0
- package/dist/generated/types.d.ts.map +1 -0
- package/dist/generated/types.js +8 -0
- package/dist/generated/types.js.map +1 -0
- package/dist/index.d.ts +89 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -0
- package/dist/quickbase.esm.js +7 -0
- package/dist/quickbase.esm.js.map +7 -0
- package/dist/quickbase.min.js +7 -0
- package/dist/quickbase.min.js.map +7 -0
- package/package.json +57 -86
- package/dist/esm/quickbase.d.ts +0 -8094
- package/dist/esm/quickbase.js +0 -8330
- package/dist/esm/quickbase.js.map +0 -1
- package/dist/esm/quickbase.min.js +0 -2
- package/dist/esm/quickbase.min.js.map +0 -1
- package/dist/umd/quickbase.umd.js +0 -8906
- package/dist/umd/quickbase.umd.js.map +0 -1
- package/dist/umd/quickbase.umd.min.js +0 -2
- package/dist/umd/quickbase.umd.min.js.map +0 -1
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Retry logic with exponential backoff
|
|
3
|
+
*
|
|
4
|
+
* Handles:
|
|
5
|
+
* - HTTP 429 (Rate Limited) - uses Retry-After header
|
|
6
|
+
* - HTTP 5xx (Server Errors) - exponential backoff
|
|
7
|
+
* - Timeout errors - exponential backoff
|
|
8
|
+
*/
|
|
9
|
+
import { RateLimitError, ServerError, TimeoutError, isRetryableError, } from '../core/errors.js';
|
|
10
|
+
/**
|
|
11
|
+
* Calculate delay for exponential backoff
|
|
12
|
+
*/
|
|
13
|
+
export function calculateBackoffDelay(attempt, options) {
|
|
14
|
+
// Exponential backoff: initialDelay * multiplier^(attempt-1)
|
|
15
|
+
const delay = options.initialDelayMs * Math.pow(options.multiplier, attempt - 1);
|
|
16
|
+
// Add jitter (±10%) to prevent thundering herd
|
|
17
|
+
const jitter = delay * 0.1 * (Math.random() * 2 - 1);
|
|
18
|
+
return Math.min(delay + jitter, options.maxDelayMs);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get delay from Retry-After header or fall back to backoff calculation
|
|
22
|
+
*/
|
|
23
|
+
export function getRetryDelay(response, attempt, options) {
|
|
24
|
+
if (response) {
|
|
25
|
+
const retryAfter = response.headers.get('Retry-After');
|
|
26
|
+
if (retryAfter) {
|
|
27
|
+
// Retry-After can be seconds or a date string
|
|
28
|
+
const seconds = parseInt(retryAfter, 10);
|
|
29
|
+
if (!isNaN(seconds)) {
|
|
30
|
+
return seconds * 1000;
|
|
31
|
+
}
|
|
32
|
+
// Try parsing as a date
|
|
33
|
+
const date = Date.parse(retryAfter);
|
|
34
|
+
if (!isNaN(date)) {
|
|
35
|
+
return Math.max(0, date - Date.now());
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return calculateBackoffDelay(attempt, options);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Extract rate limit info from response headers
|
|
43
|
+
*/
|
|
44
|
+
export function extractRateLimitInfo(response, requestUrl, attempt) {
|
|
45
|
+
const retryAfter = response.headers.get('Retry-After');
|
|
46
|
+
return {
|
|
47
|
+
timestamp: new Date(),
|
|
48
|
+
requestUrl,
|
|
49
|
+
httpStatus: response.status,
|
|
50
|
+
retryAfter: retryAfter ? parseInt(retryAfter, 10) : undefined,
|
|
51
|
+
cfRay: response.headers.get('cf-ray') || undefined,
|
|
52
|
+
tid: response.headers.get('tid') || undefined,
|
|
53
|
+
qbApiRay: response.headers.get('qb-api-ray') || undefined,
|
|
54
|
+
attempt,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Sleep for a given duration
|
|
59
|
+
*/
|
|
60
|
+
export function sleep(ms) {
|
|
61
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Determine if a response status is retryable
|
|
65
|
+
*/
|
|
66
|
+
export function isRetryableStatus(status) {
|
|
67
|
+
return status === 429 || (status >= 500 && status < 600);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Execute a request with retry logic
|
|
71
|
+
*/
|
|
72
|
+
export async function executeWithRetry(fn, context, config, logger) {
|
|
73
|
+
const options = config.retry;
|
|
74
|
+
let lastError = null;
|
|
75
|
+
for (let attempt = 1; attempt <= options.maxAttempts; attempt++) {
|
|
76
|
+
context.attempt = attempt;
|
|
77
|
+
try {
|
|
78
|
+
return await fn(context);
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
lastError = error;
|
|
82
|
+
// Check if error is retryable
|
|
83
|
+
if (!isRetryableError(error)) {
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
86
|
+
// Don't retry if we've exhausted attempts
|
|
87
|
+
if (attempt >= options.maxAttempts) {
|
|
88
|
+
throw error;
|
|
89
|
+
}
|
|
90
|
+
// Calculate retry delay
|
|
91
|
+
let delayMs;
|
|
92
|
+
let reason;
|
|
93
|
+
if (error instanceof RateLimitError) {
|
|
94
|
+
delayMs = error.retryAfter
|
|
95
|
+
? error.retryAfter * 1000
|
|
96
|
+
: calculateBackoffDelay(attempt, options);
|
|
97
|
+
reason = `Rate limited (429)`;
|
|
98
|
+
// Notify callback
|
|
99
|
+
if (config.onRateLimit) {
|
|
100
|
+
config.onRateLimit(error.rateLimitInfo);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
else if (error instanceof ServerError) {
|
|
104
|
+
delayMs = calculateBackoffDelay(attempt, options);
|
|
105
|
+
reason = `Server error (${error.statusCode})`;
|
|
106
|
+
}
|
|
107
|
+
else if (error instanceof TimeoutError) {
|
|
108
|
+
delayMs = calculateBackoffDelay(attempt, options);
|
|
109
|
+
reason = `Timeout`;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
delayMs = calculateBackoffDelay(attempt, options);
|
|
113
|
+
reason = `Unknown retryable error`;
|
|
114
|
+
}
|
|
115
|
+
logger.retry(attempt, options.maxAttempts, delayMs, reason);
|
|
116
|
+
await sleep(delayMs);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// This should never be reached, but TypeScript needs it
|
|
120
|
+
throw lastError || new Error('Retry loop exited unexpectedly');
|
|
121
|
+
}
|
|
122
|
+
//# sourceMappingURL=retry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"retry.js","sourceRoot":"","sources":["../../src/client/retry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side throttling (optional)
|
|
3
|
+
*
|
|
4
|
+
* Implements a sliding window rate limiter that matches QuickBase's
|
|
5
|
+
* "100 requests per 10 seconds per user token" limit.
|
|
6
|
+
*
|
|
7
|
+
* This is OPTIONAL - QuickBase handles rate limiting server-side.
|
|
8
|
+
* Enable this if you want to avoid hitting 429s proactively.
|
|
9
|
+
*/
|
|
10
|
+
export declare class SlidingWindowThrottle {
|
|
11
|
+
private readonly requestsPer10Seconds;
|
|
12
|
+
private readonly timestamps;
|
|
13
|
+
constructor(requestsPer10Seconds?: number);
|
|
14
|
+
/**
|
|
15
|
+
* Wait until a request slot is available
|
|
16
|
+
*/
|
|
17
|
+
acquire(): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Get the number of requests made in the current window
|
|
20
|
+
*/
|
|
21
|
+
getWindowCount(): number;
|
|
22
|
+
/**
|
|
23
|
+
* Get remaining requests available in the current window
|
|
24
|
+
*/
|
|
25
|
+
getRemaining(): number;
|
|
26
|
+
/**
|
|
27
|
+
* Reset the throttle state
|
|
28
|
+
*/
|
|
29
|
+
reset(): void;
|
|
30
|
+
private sleep;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* No-op throttle for when proactive throttling is disabled
|
|
34
|
+
*/
|
|
35
|
+
export declare class NoOpThrottle {
|
|
36
|
+
acquire(): Promise<void>;
|
|
37
|
+
getWindowCount(): number;
|
|
38
|
+
getRemaining(): number;
|
|
39
|
+
reset(): void;
|
|
40
|
+
}
|
|
41
|
+
export type Throttle = SlidingWindowThrottle | NoOpThrottle;
|
|
42
|
+
export declare function createThrottle(config: {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
requestsPer10Seconds: number;
|
|
45
|
+
}): Throttle;
|
|
46
|
+
//# sourceMappingURL=throttle.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.d.ts","sourceRoot":"","sources":["../../src/client/throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,qBAAa,qBAAqB;IAChC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAS;IAC9C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAgB;gBAE/B,oBAAoB,GAAE,MAAY;IAI9C;;OAEG;IACG,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB9B;;OAEG;IACH,cAAc,IAAI,MAAM;IAKxB;;OAEG;IACH,YAAY,IAAI,MAAM;IAItB;;OAEG;IACH,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,KAAK;CAGd;AAED;;GAEG;AACH,qBAAa,YAAY;IACjB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,cAAc,IAAI,MAAM;IAIxB,YAAY,IAAI,MAAM;IAItB,KAAK,IAAI,IAAI;CAGd;AAED,MAAM,MAAM,QAAQ,GAAG,qBAAqB,GAAG,YAAY,CAAC;AAE5D,wBAAgB,cAAc,CAAC,MAAM,EAAE;IACrC,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB,EAAE,MAAM,CAAC;CAC9B,GAAG,QAAQ,CAKX"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Client-side throttling (optional)
|
|
3
|
+
*
|
|
4
|
+
* Implements a sliding window rate limiter that matches QuickBase's
|
|
5
|
+
* "100 requests per 10 seconds per user token" limit.
|
|
6
|
+
*
|
|
7
|
+
* This is OPTIONAL - QuickBase handles rate limiting server-side.
|
|
8
|
+
* Enable this if you want to avoid hitting 429s proactively.
|
|
9
|
+
*/
|
|
10
|
+
export class SlidingWindowThrottle {
|
|
11
|
+
requestsPer10Seconds;
|
|
12
|
+
timestamps = [];
|
|
13
|
+
constructor(requestsPer10Seconds = 100) {
|
|
14
|
+
this.requestsPer10Seconds = requestsPer10Seconds;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Wait until a request slot is available
|
|
18
|
+
*/
|
|
19
|
+
async acquire() {
|
|
20
|
+
const now = Date.now();
|
|
21
|
+
const windowStart = now - 10000; // 10 second window
|
|
22
|
+
// Remove timestamps outside the window
|
|
23
|
+
while (this.timestamps.length > 0 && this.timestamps[0] < windowStart) {
|
|
24
|
+
this.timestamps.shift();
|
|
25
|
+
}
|
|
26
|
+
// If we're at the limit, wait until the oldest request exits the window
|
|
27
|
+
if (this.timestamps.length >= this.requestsPer10Seconds) {
|
|
28
|
+
const oldestTimestamp = this.timestamps[0];
|
|
29
|
+
const waitTime = oldestTimestamp + 10000 - now;
|
|
30
|
+
if (waitTime > 0) {
|
|
31
|
+
await this.sleep(waitTime);
|
|
32
|
+
// Recurse to recheck after waiting
|
|
33
|
+
return this.acquire();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// Record this request
|
|
37
|
+
this.timestamps.push(Date.now());
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Get the number of requests made in the current window
|
|
41
|
+
*/
|
|
42
|
+
getWindowCount() {
|
|
43
|
+
const windowStart = Date.now() - 10000;
|
|
44
|
+
return this.timestamps.filter((t) => t >= windowStart).length;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Get remaining requests available in the current window
|
|
48
|
+
*/
|
|
49
|
+
getRemaining() {
|
|
50
|
+
return Math.max(0, this.requestsPer10Seconds - this.getWindowCount());
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Reset the throttle state
|
|
54
|
+
*/
|
|
55
|
+
reset() {
|
|
56
|
+
this.timestamps.length = 0;
|
|
57
|
+
}
|
|
58
|
+
sleep(ms) {
|
|
59
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* No-op throttle for when proactive throttling is disabled
|
|
64
|
+
*/
|
|
65
|
+
export class NoOpThrottle {
|
|
66
|
+
async acquire() {
|
|
67
|
+
// No-op
|
|
68
|
+
}
|
|
69
|
+
getWindowCount() {
|
|
70
|
+
return 0;
|
|
71
|
+
}
|
|
72
|
+
getRemaining() {
|
|
73
|
+
return Infinity;
|
|
74
|
+
}
|
|
75
|
+
reset() {
|
|
76
|
+
// No-op
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
export function createThrottle(config) {
|
|
80
|
+
if (config.enabled) {
|
|
81
|
+
return new SlidingWindowThrottle(config.requestsPer10Seconds);
|
|
82
|
+
}
|
|
83
|
+
return new NoOpThrottle();
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=throttle.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"throttle.js","sourceRoot":"","sources":["../../src/client/throttle.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,OAAO,qBAAqB;IACf,oBAAoB,CAAS;IAC7B,UAAU,GAAa,EAAE,CAAC;IAE3C,YAAY,uBAA+B,GAAG;QAC5C,IAAI,CAAC,oBAAoB,GAAG,oBAAoB,CAAC;IACnD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,GAAG,GAAG,KAAK,CAAC,CAAC,mBAAmB;QAEpD,uCAAuC;QACvC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,CAAC,CAAE,GAAG,WAAW,EAAE,CAAC;YACvE,IAAI,CAAC,UAAU,CAAC,KAAK,EAAE,CAAC;QAC1B,CAAC;QAED,wEAAwE;QACxE,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,IAAI,IAAI,CAAC,oBAAoB,EAAE,CAAC;YACxD,MAAM,eAAe,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAE,CAAC;YAC5C,MAAM,QAAQ,GAAG,eAAe,GAAG,KAAK,GAAG,GAAG,CAAC;YAE/C,IAAI,QAAQ,GAAG,CAAC,EAAE,CAAC;gBACjB,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;gBAC3B,mCAAmC;gBACnC,OAAO,IAAI,CAAC,OAAO,EAAE,CAAC;YACxB,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;OAEG;IACH,cAAc;QACZ,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACvC,OAAO,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,WAAW,CAAC,CAAC,MAAM,CAAC;IAChE,CAAC;IAED;;OAEG;IACH,YAAY;QACV,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,oBAAoB,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC;IACxE,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7B,CAAC;IAEO,KAAK,CAAC,EAAU;QACtB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;IAC3D,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,YAAY;IACvB,KAAK,CAAC,OAAO;QACX,QAAQ;IACV,CAAC;IAED,cAAc;QACZ,OAAO,CAAC,CAAC;IACX,CAAC;IAED,YAAY;QACV,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,KAAK;QACH,QAAQ;IACV,CAAC;CACF;AAID,MAAM,UAAU,cAAc,CAAC,MAG9B;IACC,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,OAAO,IAAI,qBAAqB,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC;IAChE,CAAC;IACD,OAAO,IAAI,YAAY,EAAE,CAAC;AAC5B,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolution and validation
|
|
3
|
+
*/
|
|
4
|
+
import type { QuickbaseConfig, ResolvedConfig } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve user configuration with defaults
|
|
7
|
+
*/
|
|
8
|
+
export declare function resolveConfig(config: QuickbaseConfig): ResolvedConfig;
|
|
9
|
+
/**
|
|
10
|
+
* Build the realm hostname from the realm name
|
|
11
|
+
*/
|
|
12
|
+
export declare function getRealmHostname(realm: string): string;
|
|
13
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAe,MAAM,YAAY,CAAC;AAG/E;;GAEG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,eAAe,GAAG,cAAc,CA8BrE;AAoGD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAEtD"}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration resolution and validation
|
|
3
|
+
*/
|
|
4
|
+
import { DEFAULT_CONFIG } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Resolve user configuration with defaults
|
|
7
|
+
*/
|
|
8
|
+
export function resolveConfig(config) {
|
|
9
|
+
validateConfig(config);
|
|
10
|
+
const retry = {
|
|
11
|
+
maxAttempts: config.rateLimit?.retry?.maxAttempts ?? DEFAULT_CONFIG.retry.maxAttempts,
|
|
12
|
+
initialDelayMs: config.rateLimit?.retry?.initialDelayMs ?? DEFAULT_CONFIG.retry.initialDelayMs,
|
|
13
|
+
maxDelayMs: config.rateLimit?.retry?.maxDelayMs ?? DEFAULT_CONFIG.retry.maxDelayMs,
|
|
14
|
+
multiplier: config.rateLimit?.retry?.multiplier ?? DEFAULT_CONFIG.retry.multiplier,
|
|
15
|
+
};
|
|
16
|
+
const proactiveThrottle = {
|
|
17
|
+
enabled: config.rateLimit?.proactiveThrottle?.enabled ?? DEFAULT_CONFIG.proactiveThrottle.enabled,
|
|
18
|
+
requestsPer10Seconds: config.rateLimit?.proactiveThrottle?.requestsPer10Seconds ??
|
|
19
|
+
DEFAULT_CONFIG.proactiveThrottle.requestsPer10Seconds,
|
|
20
|
+
};
|
|
21
|
+
return {
|
|
22
|
+
realm: config.realm,
|
|
23
|
+
baseUrl: config.baseUrl ?? DEFAULT_CONFIG.baseUrl,
|
|
24
|
+
timeout: config.timeout ?? DEFAULT_CONFIG.timeout,
|
|
25
|
+
debug: config.debug ?? DEFAULT_CONFIG.debug,
|
|
26
|
+
fetchApi: config.fetchApi ?? globalThis.fetch,
|
|
27
|
+
auth: config.auth,
|
|
28
|
+
retry,
|
|
29
|
+
proactiveThrottle,
|
|
30
|
+
onRateLimit: config.rateLimit?.onRateLimit,
|
|
31
|
+
autoPaginate: config.autoPaginate ?? DEFAULT_CONFIG.autoPaginate,
|
|
32
|
+
convertDates: config.convertDates ?? DEFAULT_CONFIG.convertDates,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Validate configuration and throw if invalid
|
|
37
|
+
*/
|
|
38
|
+
function validateConfig(config) {
|
|
39
|
+
if (!config.realm) {
|
|
40
|
+
throw new Error('QuickBase realm is required');
|
|
41
|
+
}
|
|
42
|
+
if (typeof config.realm !== 'string') {
|
|
43
|
+
throw new Error('QuickBase realm must be a string');
|
|
44
|
+
}
|
|
45
|
+
// Remove .quickbase.com suffix if provided
|
|
46
|
+
if (config.realm.includes('.')) {
|
|
47
|
+
throw new Error('Realm should be just the subdomain (e.g., "mycompany" not "mycompany.quickbase.com")');
|
|
48
|
+
}
|
|
49
|
+
if (!config.auth) {
|
|
50
|
+
throw new Error('Authentication configuration is required');
|
|
51
|
+
}
|
|
52
|
+
validateAuthConfig(config.auth);
|
|
53
|
+
if (config.timeout !== undefined) {
|
|
54
|
+
if (typeof config.timeout !== 'number' || config.timeout <= 0) {
|
|
55
|
+
throw new Error('Timeout must be a positive number');
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
if (config.rateLimit?.retry) {
|
|
59
|
+
validateRetryConfig(config.rateLimit.retry);
|
|
60
|
+
}
|
|
61
|
+
if (config.rateLimit?.proactiveThrottle) {
|
|
62
|
+
validateThrottleConfig(config.rateLimit.proactiveThrottle);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function validateAuthConfig(auth) {
|
|
66
|
+
switch (auth.type) {
|
|
67
|
+
case 'user-token':
|
|
68
|
+
if (!auth.userToken) {
|
|
69
|
+
throw new Error('User token is required for user-token auth');
|
|
70
|
+
}
|
|
71
|
+
break;
|
|
72
|
+
case 'temp-token':
|
|
73
|
+
// userToken is optional for temp-token auth
|
|
74
|
+
// When running in Code Pages, the browser session is used
|
|
75
|
+
break;
|
|
76
|
+
case 'sso':
|
|
77
|
+
if (!auth.samlToken) {
|
|
78
|
+
throw new Error('SAML token is required for SSO auth');
|
|
79
|
+
}
|
|
80
|
+
break;
|
|
81
|
+
default:
|
|
82
|
+
throw new Error(`Unknown auth type: ${auth.type}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function validateRetryConfig(retry) {
|
|
86
|
+
if (retry.maxAttempts !== undefined) {
|
|
87
|
+
if (typeof retry.maxAttempts !== 'number' || retry.maxAttempts < 0) {
|
|
88
|
+
throw new Error('maxAttempts must be a non-negative number');
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (retry.initialDelayMs !== undefined) {
|
|
92
|
+
if (typeof retry.initialDelayMs !== 'number' || retry.initialDelayMs < 0) {
|
|
93
|
+
throw new Error('initialDelayMs must be a non-negative number');
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (retry.maxDelayMs !== undefined) {
|
|
97
|
+
if (typeof retry.maxDelayMs !== 'number' || retry.maxDelayMs < 0) {
|
|
98
|
+
throw new Error('maxDelayMs must be a non-negative number');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
if (retry.multiplier !== undefined) {
|
|
102
|
+
if (typeof retry.multiplier !== 'number' || retry.multiplier < 1) {
|
|
103
|
+
throw new Error('multiplier must be a number >= 1');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
function validateThrottleConfig(throttle) {
|
|
108
|
+
if (throttle.requestsPer10Seconds !== undefined) {
|
|
109
|
+
if (typeof throttle.requestsPer10Seconds !== 'number' || throttle.requestsPer10Seconds <= 0) {
|
|
110
|
+
throw new Error('requestsPer10Seconds must be a positive number');
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Build the realm hostname from the realm name
|
|
116
|
+
*/
|
|
117
|
+
export function getRealmHostname(realm) {
|
|
118
|
+
return `${realm}.quickbase.com`;
|
|
119
|
+
}
|
|
120
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date transformation utilities
|
|
3
|
+
*
|
|
4
|
+
* Converts ISO 8601 date strings in API responses to JavaScript Date objects.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Check if a string looks like an ISO 8601 date
|
|
8
|
+
*/
|
|
9
|
+
export declare function isIsoDateString(value: string): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Recursively transform ISO date strings to Date objects in an object
|
|
12
|
+
*
|
|
13
|
+
* @param obj - The object to transform
|
|
14
|
+
* @param enabled - Whether to perform conversion (pass false to skip)
|
|
15
|
+
* @returns A new object with date strings converted to Date objects
|
|
16
|
+
*/
|
|
17
|
+
export declare function transformDates<T>(obj: T, enabled: boolean): T;
|
|
18
|
+
//# sourceMappingURL=dates.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dates.d.ts","sourceRoot":"","sources":["../../src/core/dates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH;;GAEG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAEtD;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,OAAO,EAAE,OAAO,GAAG,CAAC,CAoC7D"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Date transformation utilities
|
|
3
|
+
*
|
|
4
|
+
* Converts ISO 8601 date strings in API responses to JavaScript Date objects.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* ISO 8601 date pattern
|
|
8
|
+
* Matches: 2024-01-15, 2024-01-15T10:30:00, 2024-01-15T10:30:00.000Z, etc.
|
|
9
|
+
*/
|
|
10
|
+
const ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2}(\.\d{1,3})?(Z|[+-]\d{2}:?\d{2})?)?$/;
|
|
11
|
+
/**
|
|
12
|
+
* Check if a string looks like an ISO 8601 date
|
|
13
|
+
*/
|
|
14
|
+
export function isIsoDateString(value) {
|
|
15
|
+
return ISO_DATE_PATTERN.test(value);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Recursively transform ISO date strings to Date objects in an object
|
|
19
|
+
*
|
|
20
|
+
* @param obj - The object to transform
|
|
21
|
+
* @param enabled - Whether to perform conversion (pass false to skip)
|
|
22
|
+
* @returns A new object with date strings converted to Date objects
|
|
23
|
+
*/
|
|
24
|
+
export function transformDates(obj, enabled) {
|
|
25
|
+
if (!enabled || obj === null || obj === undefined) {
|
|
26
|
+
return obj;
|
|
27
|
+
}
|
|
28
|
+
if (typeof obj !== 'object') {
|
|
29
|
+
return obj;
|
|
30
|
+
}
|
|
31
|
+
if (Array.isArray(obj)) {
|
|
32
|
+
return obj.map((item) => transformDates(item, enabled));
|
|
33
|
+
}
|
|
34
|
+
if (obj instanceof Date) {
|
|
35
|
+
return obj;
|
|
36
|
+
}
|
|
37
|
+
const result = {};
|
|
38
|
+
for (const [key, value] of Object.entries(obj)) {
|
|
39
|
+
if (typeof value === 'string' && isIsoDateString(value)) {
|
|
40
|
+
// Convert ISO date string to Date object
|
|
41
|
+
result[key] = new Date(value);
|
|
42
|
+
}
|
|
43
|
+
else if (value instanceof Date) {
|
|
44
|
+
// Keep existing Date objects as-is
|
|
45
|
+
result[key] = value;
|
|
46
|
+
}
|
|
47
|
+
else if (typeof value === 'object' && value !== null) {
|
|
48
|
+
// Recursively transform nested objects
|
|
49
|
+
result[key] = transformDates(value, enabled);
|
|
50
|
+
}
|
|
51
|
+
else {
|
|
52
|
+
// Keep other values as-is
|
|
53
|
+
result[key] = value;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return result;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=dates.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dates.js","sourceRoot":"","sources":["../../src/core/dates.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;GAGG;AACH,MAAM,gBAAgB,GAAG,2EAA2E,CAAC;AAErG;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,KAAa;IAC3C,OAAO,gBAAgB,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AACtC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,cAAc,CAAI,GAAM,EAAE,OAAgB;IACxD,IAAI,CAAC,OAAO,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS,EAAE,CAAC;QAClD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,OAAO,CAAC,CAAM,CAAC;IAC/D,CAAC;IAED,IAAI,GAAG,YAAY,IAAI,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC;IACb,CAAC;IAED,MAAM,MAAM,GAA4B,EAAE,CAAC;IAE3C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,eAAe,CAAC,KAAK,CAAC,EAAE,CAAC;YACxD,yCAAyC;YACzC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;aAAM,IAAI,KAAK,YAAY,IAAI,EAAE,CAAC;YACjC,mCAAmC;YACnC,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;aAAM,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;YACvD,uCAAuC;YACvC,MAAM,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;QAC/C,CAAC;aAAM,CAAC;YACN,0BAA0B;YAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAW,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom error types for the QuickBase SDK
|
|
3
|
+
*/
|
|
4
|
+
import type { RateLimitInfo } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Base error class for all QuickBase SDK errors
|
|
7
|
+
*/
|
|
8
|
+
export declare class QuickbaseError extends Error {
|
|
9
|
+
readonly statusCode: number;
|
|
10
|
+
readonly description?: string;
|
|
11
|
+
readonly rayId?: string;
|
|
12
|
+
constructor(message: string, statusCode: number, options?: {
|
|
13
|
+
description?: string;
|
|
14
|
+
rayId?: string;
|
|
15
|
+
cause?: Error;
|
|
16
|
+
});
|
|
17
|
+
toJSON(): {
|
|
18
|
+
name: string;
|
|
19
|
+
message: string;
|
|
20
|
+
statusCode: number;
|
|
21
|
+
description: string | undefined;
|
|
22
|
+
rayId: string | undefined;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Error thrown when rate limited (HTTP 429)
|
|
27
|
+
*/
|
|
28
|
+
export declare class RateLimitError extends QuickbaseError {
|
|
29
|
+
readonly retryAfter?: number;
|
|
30
|
+
readonly rateLimitInfo: RateLimitInfo;
|
|
31
|
+
constructor(rateLimitInfo: RateLimitInfo, message?: string);
|
|
32
|
+
toJSON(): {
|
|
33
|
+
retryAfter: number | undefined;
|
|
34
|
+
rateLimitInfo: RateLimitInfo;
|
|
35
|
+
name: string;
|
|
36
|
+
message: string;
|
|
37
|
+
statusCode: number;
|
|
38
|
+
description: string | undefined;
|
|
39
|
+
rayId: string | undefined;
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Error thrown when authentication fails (HTTP 401)
|
|
44
|
+
*/
|
|
45
|
+
export declare class AuthenticationError extends QuickbaseError {
|
|
46
|
+
constructor(message: string, options?: {
|
|
47
|
+
rayId?: string;
|
|
48
|
+
cause?: Error;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Error thrown when authorization fails (HTTP 403)
|
|
53
|
+
*/
|
|
54
|
+
export declare class AuthorizationError extends QuickbaseError {
|
|
55
|
+
constructor(message: string, options?: {
|
|
56
|
+
rayId?: string;
|
|
57
|
+
cause?: Error;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Error thrown when a resource is not found (HTTP 404)
|
|
62
|
+
*/
|
|
63
|
+
export declare class NotFoundError extends QuickbaseError {
|
|
64
|
+
constructor(message: string, options?: {
|
|
65
|
+
rayId?: string;
|
|
66
|
+
cause?: Error;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Error thrown for bad requests (HTTP 400)
|
|
71
|
+
*/
|
|
72
|
+
export declare class ValidationError extends QuickbaseError {
|
|
73
|
+
readonly errors?: Array<{
|
|
74
|
+
field?: string;
|
|
75
|
+
message: string;
|
|
76
|
+
}>;
|
|
77
|
+
constructor(message: string, options?: {
|
|
78
|
+
description?: string;
|
|
79
|
+
rayId?: string;
|
|
80
|
+
errors?: Array<{
|
|
81
|
+
field?: string;
|
|
82
|
+
message: string;
|
|
83
|
+
}>;
|
|
84
|
+
cause?: Error;
|
|
85
|
+
});
|
|
86
|
+
toJSON(): {
|
|
87
|
+
errors: {
|
|
88
|
+
field?: string;
|
|
89
|
+
message: string;
|
|
90
|
+
}[] | undefined;
|
|
91
|
+
name: string;
|
|
92
|
+
message: string;
|
|
93
|
+
statusCode: number;
|
|
94
|
+
description: string | undefined;
|
|
95
|
+
rayId: string | undefined;
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Error thrown when request times out
|
|
100
|
+
*/
|
|
101
|
+
export declare class TimeoutError extends QuickbaseError {
|
|
102
|
+
readonly timeoutMs: number;
|
|
103
|
+
constructor(timeoutMs: number, options?: {
|
|
104
|
+
rayId?: string;
|
|
105
|
+
cause?: Error;
|
|
106
|
+
});
|
|
107
|
+
toJSON(): {
|
|
108
|
+
timeoutMs: number;
|
|
109
|
+
name: string;
|
|
110
|
+
message: string;
|
|
111
|
+
statusCode: number;
|
|
112
|
+
description: string | undefined;
|
|
113
|
+
rayId: string | undefined;
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Error thrown for server errors (HTTP 5xx)
|
|
118
|
+
*/
|
|
119
|
+
export declare class ServerError extends QuickbaseError {
|
|
120
|
+
constructor(statusCode: number, message: string, options?: {
|
|
121
|
+
description?: string;
|
|
122
|
+
rayId?: string;
|
|
123
|
+
cause?: Error;
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* Parse an error response from the QuickBase API
|
|
128
|
+
*/
|
|
129
|
+
export declare function parseErrorResponse(response: Response, requestUrl: string): Promise<QuickbaseError>;
|
|
130
|
+
/**
|
|
131
|
+
* Check if an error is retryable
|
|
132
|
+
*/
|
|
133
|
+
export declare function isRetryableError(error: unknown): boolean;
|
|
134
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/core/errors.ts"],"names":[],"mappings":"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"}
|