@vkenliu/adit-cloud 0.2.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/LICENSE +21 -0
- package/dist/auth/credentials.d.ts +62 -0
- package/dist/auth/credentials.d.ts.map +1 -0
- package/dist/auth/credentials.js +151 -0
- package/dist/auth/credentials.js.map +1 -0
- package/dist/auth/device-auth.d.ts +40 -0
- package/dist/auth/device-auth.d.ts.map +1 -0
- package/dist/auth/device-auth.js +84 -0
- package/dist/auth/device-auth.js.map +1 -0
- package/dist/config.d.ts +48 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +80 -0
- package/dist/config.js.map +1 -0
- package/dist/http/client.d.ts +28 -0
- package/dist/http/client.d.ts.map +1 -0
- package/dist/http/client.js +229 -0
- package/dist/http/client.js.map +1 -0
- package/dist/http/errors.d.ts +19 -0
- package/dist/http/errors.d.ts.map +1 -0
- package/dist/http/errors.js +31 -0
- package/dist/http/errors.js.map +1 -0
- package/dist/index.d.ts +20 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +25 -0
- package/dist/index.js.map +1 -0
- package/dist/project-link/auto-link.d.ts +30 -0
- package/dist/project-link/auto-link.d.ts.map +1 -0
- package/dist/project-link/auto-link.js +91 -0
- package/dist/project-link/auto-link.js.map +1 -0
- package/dist/project-link/bulk-task.d.ts +15 -0
- package/dist/project-link/bulk-task.d.ts.map +1 -0
- package/dist/project-link/bulk-task.js +107 -0
- package/dist/project-link/bulk-task.js.map +1 -0
- package/dist/project-link/cache.d.ts +22 -0
- package/dist/project-link/cache.d.ts.map +1 -0
- package/dist/project-link/cache.js +82 -0
- package/dist/project-link/cache.js.map +1 -0
- package/dist/project-link/doc-discovery.d.ts +35 -0
- package/dist/project-link/doc-discovery.d.ts.map +1 -0
- package/dist/project-link/doc-discovery.js +260 -0
- package/dist/project-link/doc-discovery.js.map +1 -0
- package/dist/project-link/git-collector.d.ts +88 -0
- package/dist/project-link/git-collector.d.ts.map +1 -0
- package/dist/project-link/git-collector.js +250 -0
- package/dist/project-link/git-collector.js.map +1 -0
- package/dist/project-link/index.d.ts +15 -0
- package/dist/project-link/index.d.ts.map +1 -0
- package/dist/project-link/index.js +20 -0
- package/dist/project-link/index.js.map +1 -0
- package/dist/project-link/intent-command.d.ts +23 -0
- package/dist/project-link/intent-command.d.ts.map +1 -0
- package/dist/project-link/intent-command.js +104 -0
- package/dist/project-link/intent-command.js.map +1 -0
- package/dist/project-link/link-command.d.ts +26 -0
- package/dist/project-link/link-command.d.ts.map +1 -0
- package/dist/project-link/link-command.js +350 -0
- package/dist/project-link/link-command.js.map +1 -0
- package/dist/project-link/qualify.d.ts +25 -0
- package/dist/project-link/qualify.d.ts.map +1 -0
- package/dist/project-link/qualify.js +45 -0
- package/dist/project-link/qualify.js.map +1 -0
- package/dist/project-link/types.d.ts +254 -0
- package/dist/project-link/types.d.ts.map +1 -0
- package/dist/project-link/types.js +8 -0
- package/dist/project-link/types.js.map +1 -0
- package/dist/sync/auto-sync.d.ts +42 -0
- package/dist/sync/auto-sync.d.ts.map +1 -0
- package/dist/sync/auto-sync.js +136 -0
- package/dist/sync/auto-sync.js.map +1 -0
- package/dist/sync/conflicts.d.ts +27 -0
- package/dist/sync/conflicts.d.ts.map +1 -0
- package/dist/sync/conflicts.js +28 -0
- package/dist/sync/conflicts.js.map +1 -0
- package/dist/sync/engine.d.ts +76 -0
- package/dist/sync/engine.d.ts.map +1 -0
- package/dist/sync/engine.js +152 -0
- package/dist/sync/engine.js.map +1 -0
- package/dist/sync/serializer.d.ts +123 -0
- package/dist/sync/serializer.d.ts.map +1 -0
- package/dist/sync/serializer.js +280 -0
- package/dist/sync/serializer.js.map +1 -0
- package/dist/transcript/auto-upload.d.ts +25 -0
- package/dist/transcript/auto-upload.d.ts.map +1 -0
- package/dist/transcript/auto-upload.js +75 -0
- package/dist/transcript/auto-upload.js.map +1 -0
- package/dist/transcript/index.d.ts +4 -0
- package/dist/transcript/index.d.ts.map +1 -0
- package/dist/transcript/index.js +4 -0
- package/dist/transcript/index.js.map +1 -0
- package/dist/transcript/manager.d.ts +63 -0
- package/dist/transcript/manager.d.ts.map +1 -0
- package/dist/transcript/manager.js +143 -0
- package/dist/transcript/manager.js.map +1 -0
- package/dist/transcript/uploader.d.ts +135 -0
- package/dist/transcript/uploader.d.ts.map +1 -0
- package/dist/transcript/uploader.js +235 -0
- package/dist/transcript/uploader.js.map +1 -0
- package/package.json +29 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 vkenliu
|
|
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.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud credential storage.
|
|
3
|
+
*
|
|
4
|
+
* Persists JWT tokens and server-assigned client ID to
|
|
5
|
+
* ~/.adit/cloud-credentials.json with restricted file permissions.
|
|
6
|
+
*/
|
|
7
|
+
export interface CloudCredentials {
|
|
8
|
+
/** Authentication type: "device" (default) or "token" (static JWT) */
|
|
9
|
+
authType?: "device" | "token";
|
|
10
|
+
/** JWT access token (1-hour expiry for device, static for token) */
|
|
11
|
+
accessToken: string;
|
|
12
|
+
/** Opaque refresh token (90-day expiry); empty string for token auth */
|
|
13
|
+
refreshToken: string;
|
|
14
|
+
/** Server-assigned client UUID */
|
|
15
|
+
clientId: string;
|
|
16
|
+
/** Access token expiration (ISO 8601); empty string for token auth (never expires) */
|
|
17
|
+
expiresAt: string;
|
|
18
|
+
/** Server URL these credentials belong to */
|
|
19
|
+
serverUrl: string;
|
|
20
|
+
/** Consecutive sync error count (circuit breaker) */
|
|
21
|
+
syncErrorCount?: number;
|
|
22
|
+
/** True when circuit breaker has tripped (sync disabled) */
|
|
23
|
+
syncDisabled?: boolean;
|
|
24
|
+
/** ISO 8601 timestamp of the first error in the current failure window */
|
|
25
|
+
firstSyncErrorAt?: string;
|
|
26
|
+
}
|
|
27
|
+
/** Load stored credentials, or null if not logged in */
|
|
28
|
+
export declare function loadCredentials(): CloudCredentials | null;
|
|
29
|
+
/** Save credentials to disk with restricted permissions (0600) */
|
|
30
|
+
export declare function saveCredentials(creds: CloudCredentials): void;
|
|
31
|
+
/** Remove stored credentials (logout) */
|
|
32
|
+
export declare function clearCredentials(): void;
|
|
33
|
+
/** Check if the access token has expired (with 60s safety margin) */
|
|
34
|
+
export declare function isTokenExpired(creds: CloudCredentials): boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Create in-memory credentials from the ADIT_AUTH_TOKEN env var.
|
|
37
|
+
* Returns null if the env var is not set.
|
|
38
|
+
*/
|
|
39
|
+
export declare function credentialsFromEnvToken(serverUrl: string, clientId: string): CloudCredentials | null;
|
|
40
|
+
/**
|
|
41
|
+
* Increment the sync error counter in stored credentials.
|
|
42
|
+
*
|
|
43
|
+
* The circuit breaker uses a time-windowed approach: errors are only
|
|
44
|
+
* counted within a rolling window (default 1 hour). If the first error
|
|
45
|
+
* in the current window is older than the window, the counter resets
|
|
46
|
+
* before incrementing. This ensures that transient outages don't
|
|
47
|
+
* permanently disable auto-sync.
|
|
48
|
+
*
|
|
49
|
+
* Returns true if sync is now disabled (threshold reached within window).
|
|
50
|
+
*/
|
|
51
|
+
export declare function incrementSyncErrors(threshold?: number): boolean;
|
|
52
|
+
/** Reset sync error counter and re-enable sync. */
|
|
53
|
+
export declare function clearSyncErrors(): void;
|
|
54
|
+
/**
|
|
55
|
+
* Check if sync has been disabled by the circuit breaker.
|
|
56
|
+
*
|
|
57
|
+
* If the breaker is tripped but the error window has expired (>1 hour
|
|
58
|
+
* since the first error), automatically resets the breaker and returns
|
|
59
|
+
* false — giving auto-sync another chance.
|
|
60
|
+
*/
|
|
61
|
+
export declare function isSyncDisabled(): boolean;
|
|
62
|
+
//# sourceMappingURL=credentials.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.d.ts","sourceRoot":"","sources":["../../src/auth/credentials.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAaH,MAAM,WAAW,gBAAgB;IAC/B,sEAAsE;IACtE,QAAQ,CAAC,EAAE,QAAQ,GAAG,OAAO,CAAC;IAC9B,oEAAoE;IACpE,WAAW,EAAE,MAAM,CAAC;IACpB,wEAAwE;IACxE,YAAY,EAAE,MAAM,CAAC;IACrB,kCAAkC;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,sFAAsF;IACtF,SAAS,EAAE,MAAM,CAAC;IAClB,6CAA6C;IAC7C,SAAS,EAAE,MAAM,CAAC;IAClB,qDAAqD;IACrD,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,4DAA4D;IAC5D,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,0EAA0E;IAC1E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAQD,wDAAwD;AACxD,wBAAgB,eAAe,IAAI,gBAAgB,GAAG,IAAI,CAgBzD;AAED,kEAAkE;AAClE,wBAAgB,eAAe,CAAC,KAAK,EAAE,gBAAgB,GAAG,IAAI,CAS7D;AAED,yCAAyC;AACzC,wBAAgB,gBAAgB,IAAI,IAAI,CAKvC;AAED,qEAAqE;AACrE,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAM/D;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,gBAAgB,GAAG,IAAI,CAWzB;AAKD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,SAAI,GAAG,OAAO,CAyB1D;AAED,mDAAmD;AACnD,wBAAgB,eAAe,IAAI,IAAI,CAUtC;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,IAAI,OAAO,CAexC"}
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud credential storage.
|
|
3
|
+
*
|
|
4
|
+
* Persists JWT tokens and server-assigned client ID to
|
|
5
|
+
* ~/.adit/cloud-credentials.json with restricted file permissions.
|
|
6
|
+
*/
|
|
7
|
+
import { join } from "node:path";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync, chmodSync, } from "node:fs";
|
|
10
|
+
const CREDENTIALS_FILE = "cloud-credentials.json";
|
|
11
|
+
function credentialsPath() {
|
|
12
|
+
return join(homedir(), ".adit", CREDENTIALS_FILE);
|
|
13
|
+
}
|
|
14
|
+
/** Load stored credentials, or null if not logged in */
|
|
15
|
+
export function loadCredentials() {
|
|
16
|
+
const path = credentialsPath();
|
|
17
|
+
if (!existsSync(path))
|
|
18
|
+
return null;
|
|
19
|
+
try {
|
|
20
|
+
const raw = readFileSync(path, "utf-8");
|
|
21
|
+
const parsed = JSON.parse(raw);
|
|
22
|
+
if (!parsed.accessToken)
|
|
23
|
+
return null;
|
|
24
|
+
// Token auth only requires accessToken; device auth requires all fields
|
|
25
|
+
if (parsed.authType !== "token" && (!parsed.refreshToken || !parsed.clientId)) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
return parsed;
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/** Save credentials to disk with restricted permissions (0600) */
|
|
35
|
+
export function saveCredentials(creds) {
|
|
36
|
+
const path = credentialsPath();
|
|
37
|
+
mkdirSync(join(homedir(), ".adit"), { recursive: true });
|
|
38
|
+
writeFileSync(path, JSON.stringify(creds, null, 2), "utf-8");
|
|
39
|
+
try {
|
|
40
|
+
chmodSync(path, 0o600);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
// chmod may fail on some platforms (Windows) — not critical
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/** Remove stored credentials (logout) */
|
|
47
|
+
export function clearCredentials() {
|
|
48
|
+
const path = credentialsPath();
|
|
49
|
+
if (existsSync(path)) {
|
|
50
|
+
unlinkSync(path);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/** Check if the access token has expired (with 60s safety margin) */
|
|
54
|
+
export function isTokenExpired(creds) {
|
|
55
|
+
// Static tokens never expire
|
|
56
|
+
if (creds.authType === "token")
|
|
57
|
+
return false;
|
|
58
|
+
const expiresAt = new Date(creds.expiresAt).getTime();
|
|
59
|
+
const safetyMarginMs = 60_000; // Refresh 60s before actual expiry
|
|
60
|
+
return Date.now() >= expiresAt - safetyMarginMs;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Create in-memory credentials from the ADIT_AUTH_TOKEN env var.
|
|
64
|
+
* Returns null if the env var is not set.
|
|
65
|
+
*/
|
|
66
|
+
export function credentialsFromEnvToken(serverUrl, clientId) {
|
|
67
|
+
const token = process.env.ADIT_AUTH_TOKEN;
|
|
68
|
+
if (!token)
|
|
69
|
+
return null;
|
|
70
|
+
return {
|
|
71
|
+
authType: "token",
|
|
72
|
+
accessToken: token,
|
|
73
|
+
refreshToken: "",
|
|
74
|
+
clientId,
|
|
75
|
+
expiresAt: "",
|
|
76
|
+
serverUrl,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
/** Default circuit breaker window in milliseconds (1 hour) */
|
|
80
|
+
const CIRCUIT_BREAKER_WINDOW_MS = 60 * 60 * 1000;
|
|
81
|
+
/**
|
|
82
|
+
* Increment the sync error counter in stored credentials.
|
|
83
|
+
*
|
|
84
|
+
* The circuit breaker uses a time-windowed approach: errors are only
|
|
85
|
+
* counted within a rolling window (default 1 hour). If the first error
|
|
86
|
+
* in the current window is older than the window, the counter resets
|
|
87
|
+
* before incrementing. This ensures that transient outages don't
|
|
88
|
+
* permanently disable auto-sync.
|
|
89
|
+
*
|
|
90
|
+
* Returns true if sync is now disabled (threshold reached within window).
|
|
91
|
+
*/
|
|
92
|
+
export function incrementSyncErrors(threshold = 5) {
|
|
93
|
+
const creds = loadCredentials();
|
|
94
|
+
if (!creds)
|
|
95
|
+
return false;
|
|
96
|
+
const now = new Date().toISOString();
|
|
97
|
+
let count = creds.syncErrorCount ?? 0;
|
|
98
|
+
let firstErrorAt = creds.firstSyncErrorAt ?? now;
|
|
99
|
+
// If the first error is outside the window, reset the counter
|
|
100
|
+
const elapsed = Date.now() - new Date(firstErrorAt).getTime();
|
|
101
|
+
if (elapsed > CIRCUIT_BREAKER_WINDOW_MS) {
|
|
102
|
+
count = 0;
|
|
103
|
+
firstErrorAt = now;
|
|
104
|
+
}
|
|
105
|
+
count += 1;
|
|
106
|
+
const disabled = count >= threshold;
|
|
107
|
+
saveCredentials({
|
|
108
|
+
...creds,
|
|
109
|
+
syncErrorCount: count,
|
|
110
|
+
syncDisabled: disabled,
|
|
111
|
+
firstSyncErrorAt: firstErrorAt,
|
|
112
|
+
});
|
|
113
|
+
return disabled;
|
|
114
|
+
}
|
|
115
|
+
/** Reset sync error counter and re-enable sync. */
|
|
116
|
+
export function clearSyncErrors() {
|
|
117
|
+
const creds = loadCredentials();
|
|
118
|
+
if (!creds)
|
|
119
|
+
return;
|
|
120
|
+
if (!creds.syncErrorCount && !creds.syncDisabled)
|
|
121
|
+
return;
|
|
122
|
+
saveCredentials({
|
|
123
|
+
...creds,
|
|
124
|
+
syncErrorCount: 0,
|
|
125
|
+
syncDisabled: false,
|
|
126
|
+
firstSyncErrorAt: undefined,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Check if sync has been disabled by the circuit breaker.
|
|
131
|
+
*
|
|
132
|
+
* If the breaker is tripped but the error window has expired (>1 hour
|
|
133
|
+
* since the first error), automatically resets the breaker and returns
|
|
134
|
+
* false — giving auto-sync another chance.
|
|
135
|
+
*/
|
|
136
|
+
export function isSyncDisabled() {
|
|
137
|
+
const creds = loadCredentials();
|
|
138
|
+
if (creds?.syncDisabled !== true)
|
|
139
|
+
return false;
|
|
140
|
+
// Auto-reset if the error window has expired
|
|
141
|
+
const firstErrorAt = creds.firstSyncErrorAt;
|
|
142
|
+
if (firstErrorAt) {
|
|
143
|
+
const elapsed = Date.now() - new Date(firstErrorAt).getTime();
|
|
144
|
+
if (elapsed > CIRCUIT_BREAKER_WINDOW_MS) {
|
|
145
|
+
clearSyncErrors();
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return true;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credentials.js","sourceRoot":"","sources":["../../src/auth/credentials.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device authorization flow.
|
|
3
|
+
*
|
|
4
|
+
* Implements the device code flow (similar to GitHub CLI / VS Code):
|
|
5
|
+
* 1. Client requests a device code + user code
|
|
6
|
+
* 2. User opens a browser, enters the user code, and approves
|
|
7
|
+
* 3. Client polls until approved, then receives tokens
|
|
8
|
+
*/
|
|
9
|
+
export interface DeviceCodeResponse {
|
|
10
|
+
deviceCode: string;
|
|
11
|
+
userCode: string;
|
|
12
|
+
verificationUrl: string;
|
|
13
|
+
expiresAt: string;
|
|
14
|
+
}
|
|
15
|
+
export interface TokenResponse {
|
|
16
|
+
accessToken: string;
|
|
17
|
+
refreshToken: string;
|
|
18
|
+
clientId: string;
|
|
19
|
+
expiresAt: string;
|
|
20
|
+
}
|
|
21
|
+
export interface DeviceAuthOptions {
|
|
22
|
+
/** Machine identifier (hardware fingerprint) */
|
|
23
|
+
machineId: string;
|
|
24
|
+
/** Platform (e.g., "darwin-arm64") */
|
|
25
|
+
platform: string;
|
|
26
|
+
/** ADIT version */
|
|
27
|
+
aditVersion: string;
|
|
28
|
+
/** Display name for the device (e.g., "MacBook Pro Work") */
|
|
29
|
+
displayName?: string;
|
|
30
|
+
}
|
|
31
|
+
/** Step 1: Request a device code from the server */
|
|
32
|
+
export declare function requestDeviceCode(serverUrl: string, options: DeviceAuthOptions): Promise<DeviceCodeResponse>;
|
|
33
|
+
/**
|
|
34
|
+
* Step 2: Poll for token approval.
|
|
35
|
+
*
|
|
36
|
+
* Polls the server every `intervalMs` until the user approves
|
|
37
|
+
* the device or the request expires/times out.
|
|
38
|
+
*/
|
|
39
|
+
export declare function pollForToken(serverUrl: string, deviceCode: string, intervalMs?: number, timeoutMs?: number): Promise<TokenResponse>;
|
|
40
|
+
//# sourceMappingURL=device-auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-auth.d.ts","sourceRoot":"","sources":["../../src/auth/device-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,kBAAkB;IACjC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,oDAAoD;AACpD,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,iBAAiB,GACzB,OAAO,CAAC,kBAAkB,CAAC,CAgC7B;AAED;;;;;GAKG;AACH,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,UAAU,SAAO,EACjB,SAAS,SAAU,GAClB,OAAO,CAAC,aAAa,CAAC,CAwDxB"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Device authorization flow.
|
|
3
|
+
*
|
|
4
|
+
* Implements the device code flow (similar to GitHub CLI / VS Code):
|
|
5
|
+
* 1. Client requests a device code + user code
|
|
6
|
+
* 2. User opens a browser, enters the user code, and approves
|
|
7
|
+
* 3. Client polls until approved, then receives tokens
|
|
8
|
+
*/
|
|
9
|
+
import { CloudApiError, CloudNetworkError } from "../http/errors.js";
|
|
10
|
+
/** Step 1: Request a device code from the server */
|
|
11
|
+
export async function requestDeviceCode(serverUrl, options) {
|
|
12
|
+
const url = `${serverUrl.replace(/\/$/, "")}/api/auth/device`;
|
|
13
|
+
try {
|
|
14
|
+
const response = await fetch(url, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: { "Content-Type": "application/json" },
|
|
17
|
+
body: JSON.stringify({
|
|
18
|
+
machineId: options.machineId,
|
|
19
|
+
platform: options.platform,
|
|
20
|
+
aditVersion: options.aditVersion,
|
|
21
|
+
displayName: options.displayName,
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
const body = await response.text();
|
|
26
|
+
throw new CloudApiError(`Failed to request device code: ${response.status}`, response.status, body);
|
|
27
|
+
}
|
|
28
|
+
return (await response.json());
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof CloudApiError)
|
|
32
|
+
throw error;
|
|
33
|
+
throw new CloudNetworkError(`Failed to connect to ${serverUrl}: ${error instanceof Error ? error.message : String(error)}`, error instanceof Error ? error : undefined);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Step 2: Poll for token approval.
|
|
38
|
+
*
|
|
39
|
+
* Polls the server every `intervalMs` until the user approves
|
|
40
|
+
* the device or the request expires/times out.
|
|
41
|
+
*/
|
|
42
|
+
export async function pollForToken(serverUrl, deviceCode, intervalMs = 5000, timeoutMs = 300_000) {
|
|
43
|
+
const url = `${serverUrl.replace(/\/$/, "")}/api/auth/device/token`;
|
|
44
|
+
const deadline = Date.now() + timeoutMs;
|
|
45
|
+
while (Date.now() < deadline) {
|
|
46
|
+
try {
|
|
47
|
+
const response = await fetch(url, {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: { "Content-Type": "application/json" },
|
|
50
|
+
body: JSON.stringify({ deviceCode }),
|
|
51
|
+
});
|
|
52
|
+
if (response.ok) {
|
|
53
|
+
return (await response.json());
|
|
54
|
+
}
|
|
55
|
+
// 428 = authorization_pending (standard device flow response)
|
|
56
|
+
if (response.status === 428) {
|
|
57
|
+
await sleep(intervalMs);
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
// 410 = expired
|
|
61
|
+
if (response.status === 410) {
|
|
62
|
+
throw new CloudApiError("Device authorization request expired. Please try again.", 410);
|
|
63
|
+
}
|
|
64
|
+
// 409 = denied
|
|
65
|
+
if (response.status === 409) {
|
|
66
|
+
throw new CloudApiError("Device authorization was denied by the user.", 409);
|
|
67
|
+
}
|
|
68
|
+
// Other errors
|
|
69
|
+
const body = await response.text();
|
|
70
|
+
throw new CloudApiError(`Unexpected response during device polling: ${response.status}`, response.status, body);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (error instanceof CloudApiError)
|
|
74
|
+
throw error;
|
|
75
|
+
// Network errors during polling — wait and retry
|
|
76
|
+
await sleep(intervalMs);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
throw new CloudApiError("Device authorization timed out. Please try again.", 408);
|
|
80
|
+
}
|
|
81
|
+
function sleep(ms) {
|
|
82
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=device-auth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-auth.js","sourceRoot":"","sources":["../../src/auth/device-auth.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA2BrE,oDAAoD;AACpD,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAAiB,EACjB,OAA0B;IAE1B,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,kBAAkB,CAAC;IAE9D,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAChC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;gBACnB,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;gBAC1B,WAAW,EAAE,OAAO,CAAC,WAAW;gBAChC,WAAW,EAAE,OAAO,CAAC,WAAW;aACjC,CAAC;SACH,CAAC,CAAC;QAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;YACjB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,aAAa,CACrB,kCAAkC,QAAQ,CAAC,MAAM,EAAE,EACnD,QAAQ,CAAC,MAAM,EACf,IAAI,CACL,CAAC;QACJ,CAAC;QAED,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;IACvD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,aAAa;YAAE,MAAM,KAAK,CAAC;QAChD,MAAM,IAAI,iBAAiB,CACzB,wBAAwB,SAAS,KAAK,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EAC9F,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAC3C,CAAC;IACJ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,SAAiB,EACjB,UAAkB,EAClB,UAAU,GAAG,IAAI,EACjB,SAAS,GAAG,OAAO;IAEnB,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,wBAAwB,CAAC;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC;IAExC,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;gBAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,UAAU,EAAE,CAAC;aACrC,CAAC,CAAC;YAEH,IAAI,QAAQ,CAAC,EAAE,EAAE,CAAC;gBAChB,OAAO,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAkB,CAAC;YAClD,CAAC;YAED,8DAA8D;YAC9D,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;gBACxB,SAAS;YACX,CAAC;YAED,gBAAgB;YAChB,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,IAAI,aAAa,CACrB,yDAAyD,EACzD,GAAG,CACJ,CAAC;YACJ,CAAC;YAED,eAAe;YACf,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBAC5B,MAAM,IAAI,aAAa,CACrB,8CAA8C,EAC9C,GAAG,CACJ,CAAC;YACJ,CAAC;YAED,eAAe;YACf,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,IAAI,aAAa,CACrB,8CAA8C,QAAQ,CAAC,MAAM,EAAE,EAC/D,QAAQ,CAAC,MAAM,EACf,IAAI,CACL,CAAC;QACJ,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,KAAK,YAAY,aAAa;gBAAE,MAAM,KAAK,CAAC;YAChD,iDAAiD;YACjD,MAAM,KAAK,CAAC,UAAU,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IAED,MAAM,IAAI,aAAa,CACrB,mDAAmD,EACnD,GAAG,CACJ,CAAC;AACJ,CAAC;AAED,SAAS,KAAK,CAAC,EAAU;IACvB,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC;AAC3D,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud sync configuration.
|
|
3
|
+
*
|
|
4
|
+
* Loaded from environment variables with sensible defaults.
|
|
5
|
+
* Cloud sync is entirely optional — when serverUrl is null,
|
|
6
|
+
* all cloud features are disabled.
|
|
7
|
+
*/
|
|
8
|
+
export interface CloudConfig {
|
|
9
|
+
/** Cloud server URL (e.g., "https://adit-cloud.varve.ai") */
|
|
10
|
+
serverUrl: string | null;
|
|
11
|
+
/** Whether cloud sync is enabled */
|
|
12
|
+
enabled: boolean;
|
|
13
|
+
/** Auto-sync after hook events (fire-and-forget) */
|
|
14
|
+
autoSync: boolean;
|
|
15
|
+
/** Max records per sync batch (server limit: 500) */
|
|
16
|
+
batchSize: number;
|
|
17
|
+
/** Minimum unsynced events before auto-sync triggers (default: 20) */
|
|
18
|
+
syncThreshold: number;
|
|
19
|
+
/** Hours since last successful sync before auto-sync triggers regardless of count (default: 2) */
|
|
20
|
+
syncTimeoutHours: number;
|
|
21
|
+
/** Transcript upload configuration */
|
|
22
|
+
transcriptUpload: TranscriptUploadConfig;
|
|
23
|
+
/** Project-link auto-sync configuration */
|
|
24
|
+
projectLink: ProjectLinkConfig;
|
|
25
|
+
}
|
|
26
|
+
export interface ProjectLinkConfig {
|
|
27
|
+
/** Whether project-link auto-sync is enabled on session-start (default: true) */
|
|
28
|
+
autoSync: boolean;
|
|
29
|
+
/** Hours before cached project-link data is considered stale (default: 2) */
|
|
30
|
+
staleHours: number;
|
|
31
|
+
}
|
|
32
|
+
export interface TranscriptUploadConfig {
|
|
33
|
+
/** Whether transcript upload is enabled (default: true) */
|
|
34
|
+
enabled: boolean;
|
|
35
|
+
/** Interval in seconds between upload checks (default: 30) */
|
|
36
|
+
pollIntervalSec: number;
|
|
37
|
+
/** Max concurrent uploads (default: 2) */
|
|
38
|
+
maxConcurrent: number;
|
|
39
|
+
/** Max consecutive failures per file before giving up (default: 3) */
|
|
40
|
+
maxRetries: number;
|
|
41
|
+
/** Minimum bytes of new data before uploading an increment (default: 1024) */
|
|
42
|
+
minIncrementBytes: number;
|
|
43
|
+
}
|
|
44
|
+
/** Default cloud server URL */
|
|
45
|
+
export declare const DEFAULT_SERVER_URL = "https://adit-cloud.varve.ai";
|
|
46
|
+
/** Load cloud configuration from environment variables */
|
|
47
|
+
export declare function loadCloudConfig(): CloudConfig;
|
|
48
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,WAAW;IAC1B,6DAA6D;IAC7D,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,oCAAoC;IACpC,OAAO,EAAE,OAAO,CAAC;IACjB,oDAAoD;IACpD,QAAQ,EAAE,OAAO,CAAC;IAClB,qDAAqD;IACrD,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,aAAa,EAAE,MAAM,CAAC;IACtB,kGAAkG;IAClG,gBAAgB,EAAE,MAAM,CAAC;IACzB,sCAAsC;IACtC,gBAAgB,EAAE,sBAAsB,CAAC;IACzC,2CAA2C;IAC3C,WAAW,EAAE,iBAAiB,CAAC;CAChC;AAED,MAAM,WAAW,iBAAiB;IAChC,iFAAiF;IACjF,QAAQ,EAAE,OAAO,CAAC;IAClB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,2DAA2D;IAC3D,OAAO,EAAE,OAAO,CAAC;IACjB,8DAA8D;IAC9D,eAAe,EAAE,MAAM,CAAC;IACxB,0CAA0C;IAC1C,aAAa,EAAE,MAAM,CAAC;IACtB,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,8EAA8E;IAC9E,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,+BAA+B;AAC/B,eAAO,MAAM,kBAAkB,gCAAgC,CAAC;AAEhE,0DAA0D;AAC1D,wBAAgB,eAAe,IAAI,WAAW,CA6B7C"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cloud sync configuration.
|
|
3
|
+
*
|
|
4
|
+
* Loaded from environment variables with sensible defaults.
|
|
5
|
+
* Cloud sync is entirely optional — when serverUrl is null,
|
|
6
|
+
* all cloud features are disabled.
|
|
7
|
+
*/
|
|
8
|
+
/** Default cloud server URL */
|
|
9
|
+
export const DEFAULT_SERVER_URL = "https://adit-cloud.varve.ai";
|
|
10
|
+
/** Load cloud configuration from environment variables */
|
|
11
|
+
export function loadCloudConfig() {
|
|
12
|
+
const serverUrl = process.env.ADIT_CLOUD_URL ?? null;
|
|
13
|
+
// Cloud is enabled unless explicitly disabled via env var.
|
|
14
|
+
// When ADIT_CLOUD_ENABLED is not set, enabled is true — actual
|
|
15
|
+
// activation depends on credentials existing (checked by auto-sync).
|
|
16
|
+
const enabled = process.env.ADIT_CLOUD_ENABLED !== "false";
|
|
17
|
+
// Auto-sync is enabled by default when credentials exist.
|
|
18
|
+
// Only disabled when explicitly set to "false".
|
|
19
|
+
const autoSync = process.env.ADIT_CLOUD_AUTO_SYNC !== "false";
|
|
20
|
+
return {
|
|
21
|
+
serverUrl,
|
|
22
|
+
enabled,
|
|
23
|
+
autoSync,
|
|
24
|
+
batchSize: Math.min(parseInt(process.env.ADIT_CLOUD_BATCH_SIZE ?? "500", 10) || 500, 500),
|
|
25
|
+
syncThreshold: parseSyncThreshold(process.env.ADIT_CLOUD_SYNC_THRESHOLD),
|
|
26
|
+
syncTimeoutHours: parseSyncTimeoutHours(process.env.ADIT_CLOUD_SYNC_TIMEOUT_HOURS),
|
|
27
|
+
transcriptUpload: loadTranscriptUploadConfig(),
|
|
28
|
+
projectLink: loadProjectLinkConfig(),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function loadTranscriptUploadConfig() {
|
|
32
|
+
return {
|
|
33
|
+
enabled: process.env.ADIT_TRANSCRIPT_UPLOAD !== "false",
|
|
34
|
+
pollIntervalSec: parsePositiveInt(process.env.ADIT_TRANSCRIPT_POLL_INTERVAL, 30),
|
|
35
|
+
maxConcurrent: parsePositiveInt(process.env.ADIT_TRANSCRIPT_MAX_CONCURRENT, 2),
|
|
36
|
+
maxRetries: parsePositiveInt(process.env.ADIT_TRANSCRIPT_MAX_RETRIES, 3),
|
|
37
|
+
minIncrementBytes: parsePositiveInt(process.env.ADIT_TRANSCRIPT_MIN_INCREMENT, 1024),
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
function loadProjectLinkConfig() {
|
|
41
|
+
return {
|
|
42
|
+
autoSync: process.env.ADIT_PROJECT_LINK_AUTO_SYNC !== "false",
|
|
43
|
+
staleHours: parsePositiveFloat(process.env.ADIT_PROJECT_LINK_STALE_HOURS, 2),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function parsePositiveFloat(raw, defaultVal) {
|
|
47
|
+
if (raw === undefined)
|
|
48
|
+
return defaultVal;
|
|
49
|
+
const parsed = parseFloat(raw);
|
|
50
|
+
if (Number.isNaN(parsed) || parsed <= 0)
|
|
51
|
+
return defaultVal;
|
|
52
|
+
return parsed;
|
|
53
|
+
}
|
|
54
|
+
function parseSyncTimeoutHours(raw) {
|
|
55
|
+
const DEFAULT = 2;
|
|
56
|
+
if (raw === undefined)
|
|
57
|
+
return DEFAULT;
|
|
58
|
+
const parsed = parseFloat(raw);
|
|
59
|
+
if (Number.isNaN(parsed) || parsed <= 0)
|
|
60
|
+
return DEFAULT;
|
|
61
|
+
return parsed;
|
|
62
|
+
}
|
|
63
|
+
function parseSyncThreshold(raw) {
|
|
64
|
+
const DEFAULT = 20;
|
|
65
|
+
if (raw === undefined)
|
|
66
|
+
return DEFAULT;
|
|
67
|
+
const parsed = parseInt(raw, 10);
|
|
68
|
+
if (Number.isNaN(parsed))
|
|
69
|
+
return DEFAULT;
|
|
70
|
+
return Math.max(parsed, 1);
|
|
71
|
+
}
|
|
72
|
+
function parsePositiveInt(raw, defaultVal) {
|
|
73
|
+
if (raw === undefined)
|
|
74
|
+
return defaultVal;
|
|
75
|
+
const parsed = parseInt(raw, 10);
|
|
76
|
+
if (Number.isNaN(parsed) || parsed < 1)
|
|
77
|
+
return defaultVal;
|
|
78
|
+
return parsed;
|
|
79
|
+
}
|
|
80
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* HTTP client for adit-cloud API.
|
|
3
|
+
*
|
|
4
|
+
* Handles Bearer auth, automatic token refresh, and exponential
|
|
5
|
+
* backoff retry on network errors and 429 rate limits.
|
|
6
|
+
*/
|
|
7
|
+
import type { CloudCredentials } from "../auth/credentials.js";
|
|
8
|
+
export declare class CloudClient {
|
|
9
|
+
private credentials;
|
|
10
|
+
private readonly serverUrl;
|
|
11
|
+
constructor(serverUrl: string, credentials: CloudCredentials);
|
|
12
|
+
/** GET request with auth */
|
|
13
|
+
get<T>(path: string): Promise<T>;
|
|
14
|
+
/** HEAD request with auth — returns headers only */
|
|
15
|
+
head(path: string): Promise<Record<string, string>>;
|
|
16
|
+
/** POST request with auth and JSON body */
|
|
17
|
+
post<T>(path: string, body: unknown): Promise<T>;
|
|
18
|
+
/** PATCH request with auth */
|
|
19
|
+
patch<T>(path: string, body: unknown): Promise<T>;
|
|
20
|
+
/** DELETE request with auth */
|
|
21
|
+
delete(path: string): Promise<void>;
|
|
22
|
+
/** Get the current credentials (may have been refreshed) */
|
|
23
|
+
getCredentials(): CloudCredentials;
|
|
24
|
+
private request;
|
|
25
|
+
/** Refresh the access token using the refresh token */
|
|
26
|
+
private refreshToken;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/http/client.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAQ/D,qBAAa,WAAW;IACtB,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,gBAAgB;IAK5D,4BAA4B;IACtB,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC;IAItC,oDAAoD;IAC9C,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAoDzD,2CAA2C;IACrC,IAAI,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAItD,8BAA8B;IACxB,KAAK,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,OAAO,CAAC,CAAC,CAAC;IAIvD,+BAA+B;IACzB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIzC,4DAA4D;IAC5D,cAAc,IAAI,gBAAgB;YAIpB,OAAO;IAoJrB,uDAAuD;YACzC,YAAY;CA8C3B"}
|