quickbase-js 2.3.0 → 2.4.1
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 +145 -1107
- package/dist/auth/ticket.d.ts.map +1 -1
- package/dist/auth/ticket.js +4 -3
- package/dist/auth/ticket.js.map +1 -1
- package/dist/client/request.d.ts +4 -0
- package/dist/client/request.d.ts.map +1 -1
- package/dist/client/request.js +15 -3
- package/dist/client/request.js.map +1 -1
- package/dist/generated/client.d.ts +2 -0
- package/dist/generated/client.d.ts.map +1 -1
- package/dist/generated/client.js +134 -113
- package/dist/generated/client.js.map +1 -1
- package/dist/generated/types.d.ts +2700 -2256
- package/dist/generated/types.d.ts.map +1 -1
- package/dist/generated/types.js +0 -2
- package/dist/generated/types.js.map +1 -1
- package/dist/quickbase.esm.js +3 -3
- package/dist/quickbase.esm.js.map +3 -3
- package/dist/quickbase.min.js +3 -3
- package/dist/quickbase.min.js.map +3 -3
- package/package.json +16 -13
- package/src/auth/index.ts +55 -0
- package/src/auth/sso-token.ts +143 -0
- package/src/auth/temp-token.ts +160 -0
- package/src/auth/ticket.ts +329 -0
- package/src/auth/token-cache.ts +97 -0
- package/src/auth/types.ts +50 -0
- package/src/auth/user-token.ts +38 -0
- package/src/cli/schema.ts +512 -0
- package/src/client/index.ts +36 -0
- package/src/client/pagination.ts +337 -0
- package/src/client/request.ts +544 -0
- package/src/client/retry.ts +169 -0
- package/src/client/throttle.ts +105 -0
- package/src/core/config.ts +160 -0
- package/src/core/dates.ts +63 -0
- package/src/core/errors.ts +349 -0
- package/src/core/index.ts +50 -0
- package/src/core/logger.ts +113 -0
- package/src/core/schema.ts +213 -0
- package/src/core/transform.ts +295 -0
- package/src/core/types.ts +337 -0
- package/src/generated/client.ts +1785 -0
- package/src/generated/operations.json +672 -0
- package/src/generated/types.ts +4884 -0
- package/src/index.ts +259 -0
- package/src/xml/codepages.ts +119 -0
- package/src/xml/dbvars.ts +75 -0
- package/src/xml/errors.ts +133 -0
- package/src/xml/fields.ts +121 -0
- package/src/xml/groups.ts +560 -0
- package/src/xml/html.ts +152 -0
- package/src/xml/index.ts +1196 -0
- package/src/xml/metadata.ts +111 -0
- package/src/xml/records.ts +301 -0
- package/src/xml/request.ts +238 -0
- package/src/xml/roles.ts +321 -0
- package/src/xml/schema.ts +436 -0
- package/src/xml/transform.ts +381 -0
- package/src/xml/types.ts +602 -0
- package/src/xml/users.ts +221 -0
- package/src/xml/webhooks.ts +260 -0
package/package.json
CHANGED
|
@@ -1,24 +1,25 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "quickbase-js",
|
|
3
|
-
"version": "2.
|
|
4
|
-
"description": "TypeScript
|
|
3
|
+
"version": "2.4.1",
|
|
4
|
+
"description": "TypeScript client for the QuickBase JSON and XML APIs: every endpoint, pagination, retries, code-page temp tokens",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
8
|
-
"browser": "dist/quickbase.min.js",
|
|
9
8
|
"types": "dist/index.d.ts",
|
|
10
9
|
"exports": {
|
|
11
10
|
".": {
|
|
12
|
-
"import": "./dist/index.js",
|
|
13
11
|
"types": "./dist/index.d.ts",
|
|
14
|
-
"
|
|
15
|
-
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
},
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
16
|
},
|
|
17
17
|
"bin": {
|
|
18
18
|
"quickbase-js": "./bin/quickbase-js.js"
|
|
19
19
|
},
|
|
20
20
|
"files": [
|
|
21
21
|
"dist",
|
|
22
|
+
"src",
|
|
22
23
|
"bin",
|
|
23
24
|
"README.md",
|
|
24
25
|
"LICENSE"
|
|
@@ -35,14 +36,13 @@
|
|
|
35
36
|
"test:watch": "vitest",
|
|
36
37
|
"test:coverage": "vitest run --coverage",
|
|
37
38
|
"lint": "eslint src tests",
|
|
38
|
-
"typecheck": "tsc --noEmit",
|
|
39
|
-
"spec:
|
|
39
|
+
"typecheck": "tsc --noEmit && tsc -p tsconfig.examples.json",
|
|
40
|
+
"spec:normalize": "tsx spec/tools/cli.ts normalize",
|
|
40
41
|
"spec:patch": "tsx spec/tools/cli.ts patch",
|
|
41
42
|
"spec:validate": "tsx spec/tools/cli.ts validate",
|
|
42
|
-
"spec:split": "tsx spec/tools/cli.ts split",
|
|
43
43
|
"spec:generate": "tsx scripts/spec/generate.ts",
|
|
44
|
-
"spec:build": "npm run spec:
|
|
45
|
-
"docs": "typedoc",
|
|
44
|
+
"spec:build": "npm run spec:normalize && npm run spec:patch && npm run spec:validate && npm run spec:generate",
|
|
45
|
+
"docs": "typedoc && node scripts/build-llms.js",
|
|
46
46
|
"docs:watch": "typedoc --watch",
|
|
47
47
|
"prepublishOnly": "npm run clean && npm run build && npm run test"
|
|
48
48
|
},
|
|
@@ -58,7 +58,7 @@
|
|
|
58
58
|
"license": "MIT",
|
|
59
59
|
"repository": {
|
|
60
60
|
"type": "git",
|
|
61
|
-
"url": "https://github.com/DrewBradfordXYZ/quickbase-js.git"
|
|
61
|
+
"url": "git+https://github.com/DrewBradfordXYZ/quickbase-js.git"
|
|
62
62
|
},
|
|
63
63
|
"bugs": {
|
|
64
64
|
"url": "https://github.com/DrewBradfordXYZ/quickbase-js/issues"
|
|
@@ -76,5 +76,8 @@
|
|
|
76
76
|
"typescript": "^5.4.0",
|
|
77
77
|
"vitest": "^1.4.0",
|
|
78
78
|
"yaml": "^2.4.0"
|
|
79
|
-
}
|
|
79
|
+
},
|
|
80
|
+
"unpkg": "dist/quickbase.min.js",
|
|
81
|
+
"jsdelivr": "dist/quickbase.min.js",
|
|
82
|
+
"sideEffects": false
|
|
80
83
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication module exports
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export type { AuthStrategy, AuthContext, CachedToken } from './types.js';
|
|
6
|
+
export { UserTokenStrategy } from './user-token.js';
|
|
7
|
+
export { TempTokenStrategy } from './temp-token.js';
|
|
8
|
+
export { SsoTokenStrategy } from './sso-token.js';
|
|
9
|
+
export { TicketStrategy } from './ticket.js'; // XML-API-TICKET: Remove if XML API discontinued
|
|
10
|
+
export { TokenCache } from './token-cache.js';
|
|
11
|
+
|
|
12
|
+
import type { AuthConfig } from '../core/types.js';
|
|
13
|
+
import type { AuthStrategy, AuthContext } from './types.js';
|
|
14
|
+
import { UserTokenStrategy } from './user-token.js';
|
|
15
|
+
import { TempTokenStrategy } from './temp-token.js';
|
|
16
|
+
import { SsoTokenStrategy } from './sso-token.js';
|
|
17
|
+
import { TicketStrategy } from './ticket.js'; // XML-API-TICKET: Remove if XML API discontinued
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Factory function to create the appropriate auth strategy
|
|
21
|
+
*/
|
|
22
|
+
export function createAuthStrategy(
|
|
23
|
+
authConfig: AuthConfig,
|
|
24
|
+
context: AuthContext
|
|
25
|
+
): AuthStrategy {
|
|
26
|
+
switch (authConfig.type) {
|
|
27
|
+
case 'user-token':
|
|
28
|
+
return new UserTokenStrategy(authConfig.userToken, context);
|
|
29
|
+
|
|
30
|
+
case 'temp-token':
|
|
31
|
+
return new TempTokenStrategy(authConfig.userToken, context, {
|
|
32
|
+
appToken: authConfig.appToken,
|
|
33
|
+
tokenLifespanMs: authConfig.tokenLifespanMs,
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
case 'sso':
|
|
37
|
+
return new SsoTokenStrategy(authConfig.samlToken, context);
|
|
38
|
+
|
|
39
|
+
// XML-API-TICKET: Remove this case if XML API is discontinued
|
|
40
|
+
case 'ticket':
|
|
41
|
+
return new TicketStrategy(
|
|
42
|
+
authConfig.username,
|
|
43
|
+
authConfig.password,
|
|
44
|
+
{
|
|
45
|
+
hours: authConfig.hours,
|
|
46
|
+
onExpired: authConfig.onExpired,
|
|
47
|
+
persist: authConfig.persist,
|
|
48
|
+
},
|
|
49
|
+
context
|
|
50
|
+
);
|
|
51
|
+
|
|
52
|
+
default:
|
|
53
|
+
throw new Error(`Unknown auth type: ${(authConfig as { type: string }).type}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SSO Token Authentication Strategy
|
|
3
|
+
*
|
|
4
|
+
* Exchanges a SAML token for a QuickBase temporary token via OAuth token exchange.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import type { AuthStrategy, AuthContext } from './types.js';
|
|
8
|
+
import type { Logger } from '../core/logger.js';
|
|
9
|
+
import { TokenCache } from './token-cache.js';
|
|
10
|
+
import { DEFAULT_CONFIG } from '../core/types.js';
|
|
11
|
+
import { AuthenticationError } from '../core/errors.js';
|
|
12
|
+
|
|
13
|
+
export class SsoTokenStrategy implements AuthStrategy {
|
|
14
|
+
private readonly samlToken: string;
|
|
15
|
+
private readonly realm: string;
|
|
16
|
+
private readonly baseUrl: string;
|
|
17
|
+
private readonly fetchApi: typeof fetch;
|
|
18
|
+
private readonly logger: Logger;
|
|
19
|
+
private readonly cache: TokenCache;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Track pending SSO token exchange to deduplicate concurrent requests
|
|
23
|
+
*/
|
|
24
|
+
private pendingExchange: Promise<string> | null = null;
|
|
25
|
+
|
|
26
|
+
constructor(
|
|
27
|
+
samlToken: string,
|
|
28
|
+
context: AuthContext,
|
|
29
|
+
options?: { tokenLifespanMs?: number }
|
|
30
|
+
) {
|
|
31
|
+
this.samlToken = samlToken;
|
|
32
|
+
this.realm = context.realm;
|
|
33
|
+
this.baseUrl = context.baseUrl;
|
|
34
|
+
this.fetchApi = context.fetchApi;
|
|
35
|
+
this.logger = context.logger;
|
|
36
|
+
// SSO tokens are global, not per-dbid, so we use a single cache key
|
|
37
|
+
this.cache = new TokenCache(
|
|
38
|
+
options?.tokenLifespanMs ?? DEFAULT_CONFIG.tempTokenLifespanMs
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
private get cacheKey(): string {
|
|
43
|
+
return '__sso__';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
async getToken(_dbid?: string): Promise<string> {
|
|
47
|
+
// Check cache first
|
|
48
|
+
const cachedToken = this.cache.get(this.cacheKey);
|
|
49
|
+
if (cachedToken) {
|
|
50
|
+
this.logger.token('cache-hit');
|
|
51
|
+
return cachedToken;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
this.logger.token('cache-miss');
|
|
55
|
+
|
|
56
|
+
// Check if there's already an exchange in progress
|
|
57
|
+
if (this.pendingExchange) {
|
|
58
|
+
this.logger.debug('Waiting for existing SSO token exchange');
|
|
59
|
+
return this.pendingExchange;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Exchange SAML token for QuickBase token
|
|
63
|
+
const exchangePromise = this.exchangeToken();
|
|
64
|
+
this.pendingExchange = exchangePromise;
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
return await exchangePromise;
|
|
68
|
+
} finally {
|
|
69
|
+
this.pendingExchange = null;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private async exchangeToken(): Promise<string> {
|
|
74
|
+
this.logger.token('fetch');
|
|
75
|
+
|
|
76
|
+
const url = `${this.baseUrl}/auth/oauth/token`;
|
|
77
|
+
|
|
78
|
+
const body = new URLSearchParams({
|
|
79
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:token-exchange',
|
|
80
|
+
requested_token_type: 'urn:quickbase:params:oauth:token-type:temp_token',
|
|
81
|
+
subject_token: this.samlToken,
|
|
82
|
+
subject_token_type: 'urn:ietf:params:oauth:token-type:saml2',
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
const response = await this.fetchApi(url, {
|
|
86
|
+
method: 'POST',
|
|
87
|
+
headers: {
|
|
88
|
+
'QB-Realm-Hostname': `${this.realm}.quickbase.com`,
|
|
89
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
90
|
+
},
|
|
91
|
+
body: body.toString(),
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
if (!response.ok) {
|
|
95
|
+
const errorText = await response.text();
|
|
96
|
+
throw new AuthenticationError(
|
|
97
|
+
`SSO token exchange failed: ${response.status} ${errorText}`,
|
|
98
|
+
{ rayId: response.headers.get('qb-api-ray') || undefined }
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const data = await response.json() as {
|
|
103
|
+
access_token?: string;
|
|
104
|
+
issued_token_type?: string;
|
|
105
|
+
token_type?: string;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
const token = data.access_token;
|
|
109
|
+
if (!token) {
|
|
110
|
+
throw new AuthenticationError('No access_token in SSO exchange response');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// Cache the token
|
|
114
|
+
this.cache.set(this.cacheKey, token);
|
|
115
|
+
this.logger.debug('Cached new SSO token');
|
|
116
|
+
|
|
117
|
+
return token;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
getAuthorizationHeader(token: string): string {
|
|
121
|
+
return `QB-TEMP-TOKEN ${token}`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async handleAuthError(_dbid?: string): Promise<boolean> {
|
|
125
|
+
// Invalidate the cached token
|
|
126
|
+
this.invalidate();
|
|
127
|
+
|
|
128
|
+
// Try to exchange for a new token
|
|
129
|
+
try {
|
|
130
|
+
this.logger.token('refresh');
|
|
131
|
+
await this.getToken();
|
|
132
|
+
return true;
|
|
133
|
+
} catch (error) {
|
|
134
|
+
this.logger.error('Failed to refresh SSO token', error);
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
invalidate(_dbid?: string): void {
|
|
140
|
+
this.logger.token('expire');
|
|
141
|
+
this.cache.clear();
|
|
142
|
+
}
|
|
143
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Temporary Token Authentication Strategy
|
|
3
|
+
*
|
|
4
|
+
* Fetches database-specific temporary tokens from the QuickBase API.
|
|
5
|
+
* Tokens are cached and automatically refreshed when expired.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import type { AuthStrategy, AuthContext } from './types.js';
|
|
9
|
+
import type { Logger } from '../core/logger.js';
|
|
10
|
+
import { TokenCache } from './token-cache.js';
|
|
11
|
+
import { DEFAULT_CONFIG } from '../core/types.js';
|
|
12
|
+
import { AuthenticationError } from '../core/errors.js';
|
|
13
|
+
|
|
14
|
+
export class TempTokenStrategy implements AuthStrategy {
|
|
15
|
+
private readonly userToken?: string;
|
|
16
|
+
private readonly appToken?: string;
|
|
17
|
+
private readonly realm: string;
|
|
18
|
+
private readonly baseUrl: string;
|
|
19
|
+
private readonly fetchApi: typeof fetch;
|
|
20
|
+
private readonly logger: Logger;
|
|
21
|
+
private readonly cache: TokenCache;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Track pending token fetches to deduplicate concurrent requests
|
|
25
|
+
* This prevents multiple simultaneous API calls for the same dbid
|
|
26
|
+
*/
|
|
27
|
+
private readonly pendingFetches = new Map<string, Promise<string>>();
|
|
28
|
+
|
|
29
|
+
constructor(
|
|
30
|
+
userToken: string | undefined,
|
|
31
|
+
context: AuthContext,
|
|
32
|
+
options?: { appToken?: string; tokenLifespanMs?: number }
|
|
33
|
+
) {
|
|
34
|
+
this.userToken = userToken;
|
|
35
|
+
this.appToken = options?.appToken;
|
|
36
|
+
this.realm = context.realm;
|
|
37
|
+
this.baseUrl = context.baseUrl;
|
|
38
|
+
this.fetchApi = context.fetchApi;
|
|
39
|
+
this.logger = context.logger;
|
|
40
|
+
this.cache = new TokenCache(
|
|
41
|
+
options?.tokenLifespanMs ?? DEFAULT_CONFIG.tempTokenLifespanMs
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
async getToken(dbid?: string): Promise<string> {
|
|
46
|
+
if (!dbid) {
|
|
47
|
+
throw new Error('Database ID (dbid) is required for temporary token authentication');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Check cache first
|
|
51
|
+
const cachedToken = this.cache.get(dbid);
|
|
52
|
+
if (cachedToken) {
|
|
53
|
+
this.logger.token('cache-hit', dbid);
|
|
54
|
+
return cachedToken;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
this.logger.token('cache-miss', dbid);
|
|
58
|
+
|
|
59
|
+
// Check if there's already a fetch in progress for this dbid
|
|
60
|
+
const pendingFetch = this.pendingFetches.get(dbid);
|
|
61
|
+
if (pendingFetch) {
|
|
62
|
+
this.logger.debug(`Waiting for existing token fetch for dbid: ${dbid}`);
|
|
63
|
+
return pendingFetch;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Fetch new token
|
|
67
|
+
const fetchPromise = this.fetchToken(dbid);
|
|
68
|
+
this.pendingFetches.set(dbid, fetchPromise);
|
|
69
|
+
|
|
70
|
+
try {
|
|
71
|
+
const token = await fetchPromise;
|
|
72
|
+
return token;
|
|
73
|
+
} finally {
|
|
74
|
+
this.pendingFetches.delete(dbid);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
private async fetchToken(dbid: string): Promise<string> {
|
|
79
|
+
this.logger.token('fetch', dbid);
|
|
80
|
+
|
|
81
|
+
const url = `${this.baseUrl}/auth/temporary/${dbid}`;
|
|
82
|
+
const headers: Record<string, string> = {
|
|
83
|
+
'QB-Realm-Hostname': `${this.realm}.quickbase.com`,
|
|
84
|
+
'Content-Type': 'application/json',
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Only include Authorization header if we have a userToken
|
|
88
|
+
// For Code Pages, browser session cookies handle auth instead
|
|
89
|
+
if (this.userToken) {
|
|
90
|
+
headers['Authorization'] = `QB-USER-TOKEN ${this.userToken}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (this.appToken) {
|
|
94
|
+
headers['QB-App-Token'] = this.appToken;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const response = await this.fetchApi(url, {
|
|
98
|
+
method: 'GET',
|
|
99
|
+
headers,
|
|
100
|
+
credentials: 'include', // Include cookies for Code Page auth
|
|
101
|
+
} as RequestInit);
|
|
102
|
+
|
|
103
|
+
if (!response.ok) {
|
|
104
|
+
const errorText = await response.text();
|
|
105
|
+
throw new AuthenticationError(
|
|
106
|
+
`Failed to fetch temporary token for ${dbid}: ${response.status} ${errorText}`,
|
|
107
|
+
{ rayId: response.headers.get('qb-api-ray') || undefined }
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
const data = await response.json() as { temporaryAuthorization?: string };
|
|
112
|
+
const token = data.temporaryAuthorization;
|
|
113
|
+
|
|
114
|
+
if (!token) {
|
|
115
|
+
throw new AuthenticationError(
|
|
116
|
+
`No temporary token in response for ${dbid}`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// Cache the token
|
|
121
|
+
this.cache.set(dbid, token);
|
|
122
|
+
this.logger.debug(`Cached new token for dbid: ${dbid}`);
|
|
123
|
+
|
|
124
|
+
return token;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
getAuthorizationHeader(token: string): string {
|
|
128
|
+
return `QB-TEMP-TOKEN ${token}`;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
async handleAuthError(dbid?: string): Promise<boolean> {
|
|
132
|
+
if (!dbid) {
|
|
133
|
+
this.logger.debug('Auth error without dbid - cannot refresh temp token');
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Invalidate the cached token
|
|
138
|
+
this.invalidate(dbid);
|
|
139
|
+
|
|
140
|
+
// Try to fetch a new token
|
|
141
|
+
try {
|
|
142
|
+
this.logger.token('refresh', dbid);
|
|
143
|
+
await this.getToken(dbid);
|
|
144
|
+
return true;
|
|
145
|
+
} catch (error) {
|
|
146
|
+
this.logger.error(`Failed to refresh temp token for ${dbid}`, error);
|
|
147
|
+
return false;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
invalidate(dbid?: string): void {
|
|
152
|
+
if (dbid) {
|
|
153
|
+
this.logger.token('expire', dbid);
|
|
154
|
+
this.cache.delete(dbid);
|
|
155
|
+
} else {
|
|
156
|
+
// Invalidate all tokens
|
|
157
|
+
this.cache.clear();
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|