@ace-sdk/core 2.3.2 → 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.
Files changed (41) hide show
  1. package/dist/auth/device-auth.d.ts +39 -0
  2. package/dist/auth/device-auth.d.ts.map +1 -0
  3. package/dist/auth/device-auth.js +219 -0
  4. package/dist/auth/device-auth.js.map +1 -0
  5. package/dist/auth/index.d.ts +7 -0
  6. package/dist/auth/index.d.ts.map +1 -0
  7. package/dist/auth/index.js +9 -0
  8. package/dist/auth/index.js.map +1 -0
  9. package/dist/auth/utils.d.ts +49 -0
  10. package/dist/auth/utils.d.ts.map +1 -0
  11. package/dist/auth/utils.js +156 -0
  12. package/dist/auth/utils.js.map +1 -0
  13. package/dist/client/ace-client.d.ts +4 -0
  14. package/dist/client/ace-client.d.ts.map +1 -1
  15. package/dist/client/ace-client.js +36 -5
  16. package/dist/client/ace-client.js.map +1 -1
  17. package/dist/client/http.d.ts +103 -0
  18. package/dist/client/http.d.ts.map +1 -0
  19. package/dist/client/http.js +290 -0
  20. package/dist/client/http.js.map +1 -0
  21. package/dist/config/auth.d.ts +48 -0
  22. package/dist/config/auth.d.ts.map +1 -0
  23. package/dist/config/auth.js +255 -0
  24. package/dist/config/auth.js.map +1 -0
  25. package/dist/config/loader.d.ts.map +1 -1
  26. package/dist/config/loader.js +9 -2
  27. package/dist/config/loader.js.map +1 -1
  28. package/dist/config/migration.js +1 -1
  29. package/dist/config/migration.js.map +1 -1
  30. package/dist/index.d.ts +7 -0
  31. package/dist/index.d.ts.map +1 -1
  32. package/dist/index.js +19 -0
  33. package/dist/index.js.map +1 -1
  34. package/dist/types/auth.d.ts +128 -0
  35. package/dist/types/auth.d.ts.map +1 -0
  36. package/dist/types/auth.js +31 -0
  37. package/dist/types/auth.js.map +1 -0
  38. package/dist/types/config.d.ts +4 -0
  39. package/dist/types/config.d.ts.map +1 -1
  40. package/dist/types/config.js.map +1 -1
  41. package/package.json +2 -1
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Device Code Authentication Flow (RFC 8628)
3
+ *
4
+ * Implements the OAuth 2.0 Device Authorization Grant for CLI/terminal clients.
5
+ *
6
+ * Flow:
7
+ * 1. Client requests device code: POST /api/v1/auth/device
8
+ * 2. User visits URL and enters code
9
+ * 3. Client polls for token: POST /api/v1/auth/device/token
10
+ * 4. On success, save credentials to config
11
+ *
12
+ * @package @ace-sdk/core
13
+ */
14
+ import type { DeviceCodeResponse, TokenResponse, DeviceAuthError, LoginOptions, CurrentUser } from '../types/auth.js';
15
+ import type { ILogger } from '../logger/index.js';
16
+ /**
17
+ * Request device code from server
18
+ * POST /api/v1/auth/device
19
+ */
20
+ export declare function requestDeviceCode(clientType: string, logger?: ILogger, deviceId?: string): Promise<DeviceCodeResponse>;
21
+ /**
22
+ * Poll for token after user authorizes
23
+ * POST /api/v1/auth/device/token
24
+ */
25
+ export declare function pollForToken(deviceCode: string, _logger?: ILogger): Promise<TokenResponse | DeviceAuthError>;
26
+ /**
27
+ * Complete device code login flow
28
+ *
29
+ * 1. Request device code
30
+ * 2. Open browser / show code to user
31
+ * 3. Poll for token
32
+ * 4. Save credentials
33
+ */
34
+ export declare function login(options: LoginOptions, logger?: ILogger): Promise<CurrentUser>;
35
+ /**
36
+ * Logout - clear credentials
37
+ */
38
+ export declare function logout(logger?: ILogger): void;
39
+ //# 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;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,kBAAkB,EAClB,aAAa,EACb,eAAe,EACf,YAAY,EACZ,WAAW,EACZ,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAsBlD;;;GAGG;AACH,wBAAsB,iBAAiB,CACrC,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,OAAO,EAChB,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,kBAAkB,CAAC,CAwB7B;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE,OAAO,GAChB,OAAO,CAAC,aAAa,GAAG,eAAe,CAAC,CAuB1C;AAgBD;;;;;;;GAOG;AACH,wBAAsB,KAAK,CAAC,OAAO,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,CA+IzF;AAED;;GAEG;AACH,wBAAgB,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,IAAI,CAG7C"}
@@ -0,0 +1,219 @@
1
+ /**
2
+ * Device Code Authentication Flow (RFC 8628)
3
+ *
4
+ * Implements the OAuth 2.0 Device Authorization Grant for CLI/terminal clients.
5
+ *
6
+ * Flow:
7
+ * 1. Client requests device code: POST /api/v1/auth/device
8
+ * 2. User visits URL and enters code
9
+ * 3. Client polls for token: POST /api/v1/auth/device/token
10
+ * 4. On success, save credentials to config
11
+ *
12
+ * @package @ace-sdk/core
13
+ */
14
+ import { saveAuthCredentials, clearAuth, getOrCreateDeviceId } from '../config/auth.js';
15
+ import { getEffectiveToken } from './utils.js';
16
+ import { loadConfig } from '../config/loader.js';
17
+ /**
18
+ * Default server URL
19
+ */
20
+ const DEFAULT_SERVER_URL = 'https://ace-api.code-engine.app';
21
+ /**
22
+ * Get server URL from config or default
23
+ */
24
+ function getServerUrl() {
25
+ try {
26
+ const config = loadConfig();
27
+ return config.serverUrl || DEFAULT_SERVER_URL;
28
+ }
29
+ catch {
30
+ return DEFAULT_SERVER_URL;
31
+ }
32
+ }
33
+ /**
34
+ * Request device code from server
35
+ * POST /api/v1/auth/device
36
+ */
37
+ export async function requestDeviceCode(clientType, logger, deviceId) {
38
+ const serverUrl = getServerUrl();
39
+ const url = `${serverUrl}/api/v1/auth/device`;
40
+ logger?.debug(`Requesting device code from ${url}`);
41
+ const response = await fetch(url, {
42
+ method: 'POST',
43
+ headers: {
44
+ 'Content-Type': 'application/json'
45
+ },
46
+ body: JSON.stringify({
47
+ client_type: clientType,
48
+ // v4.5.0: Include device_id for device tracking
49
+ ...(deviceId && { device_id: deviceId })
50
+ })
51
+ });
52
+ if (!response.ok) {
53
+ const error = await response.text();
54
+ throw new Error(`Failed to request device code: ${error}`);
55
+ }
56
+ return response.json();
57
+ }
58
+ /**
59
+ * Poll for token after user authorizes
60
+ * POST /api/v1/auth/device/token
61
+ */
62
+ export async function pollForToken(deviceCode, _logger) {
63
+ const serverUrl = getServerUrl();
64
+ const url = `${serverUrl}/api/v1/auth/device/token`;
65
+ const response = await fetch(url, {
66
+ method: 'POST',
67
+ headers: {
68
+ 'Content-Type': 'application/json'
69
+ },
70
+ body: JSON.stringify({ device_code: deviceCode })
71
+ });
72
+ const rawData = await response.json();
73
+ // Server wraps error responses in 'detail' object
74
+ const data = (rawData.detail || rawData);
75
+ // Check for error response
76
+ if (data.error) {
77
+ return data;
78
+ }
79
+ return data;
80
+ }
81
+ /**
82
+ * Check if response is an error
83
+ */
84
+ function isDeviceAuthError(response) {
85
+ return 'error' in response;
86
+ }
87
+ /**
88
+ * Sleep for specified milliseconds
89
+ */
90
+ function sleep(ms) {
91
+ return new Promise(resolve => setTimeout(resolve, ms));
92
+ }
93
+ /**
94
+ * Complete device code login flow
95
+ *
96
+ * 1. Request device code
97
+ * 2. Open browser / show code to user
98
+ * 3. Poll for token
99
+ * 4. Save credentials
100
+ */
101
+ export async function login(options, logger) {
102
+ const { clientType, onUserCode, onSuccess, onProgress, timeout = 300000, // 5 minutes
103
+ signal, noBrowser = false } = options;
104
+ // Check if already logged in
105
+ const existingToken = getEffectiveToken(logger);
106
+ if (existingToken) {
107
+ logger?.warn('Already logged in. Use logout first to switch accounts.');
108
+ }
109
+ // v4.5.0: Get or create device ID (persists across logins)
110
+ const deviceId = getOrCreateDeviceId(logger);
111
+ onProgress?.('Requesting device code...');
112
+ // Step 1: Request device code (include device_id)
113
+ const deviceCode = await requestDeviceCode(clientType, logger, deviceId);
114
+ logger?.debug(`Device code: ${deviceCode.device_code}`);
115
+ logger?.debug(`User code: ${deviceCode.user_code}`);
116
+ logger?.debug(`Verification URL: ${deviceCode.verification_uri}`);
117
+ // Step 2: Show code to user
118
+ onUserCode?.(deviceCode.user_code, deviceCode.verification_uri_complete || deviceCode.verification_uri);
119
+ // Step 3: Open browser (unless noBrowser or SSH mode)
120
+ if (!noBrowser && deviceCode.verification_uri_complete) {
121
+ onProgress?.('Opening browser...');
122
+ try {
123
+ // Dynamic import for open package
124
+ const open = (await import('open')).default;
125
+ await open(deviceCode.verification_uri_complete);
126
+ }
127
+ catch (err) {
128
+ logger?.debug('Could not open browser:', err instanceof Error ? err.message : String(err));
129
+ onProgress?.('Could not open browser automatically');
130
+ }
131
+ }
132
+ // Step 4: Poll for token
133
+ onProgress?.('Waiting for authorization...');
134
+ let interval = deviceCode.interval * 1000; // Convert to ms
135
+ const startTime = Date.now();
136
+ const deviceCodeExpiresAt = startTime + (deviceCode.expires_in * 1000);
137
+ while (true) {
138
+ // Check abort signal
139
+ if (signal?.aborted) {
140
+ throw new Error('Login cancelled');
141
+ }
142
+ // Check timeout
143
+ if (Date.now() > startTime + timeout) {
144
+ throw new Error('Login timed out');
145
+ }
146
+ // Check expiry
147
+ if (Date.now() > deviceCodeExpiresAt) {
148
+ throw new Error('Device code expired. Please try again.');
149
+ }
150
+ // Wait before polling
151
+ await sleep(interval);
152
+ // Poll for token
153
+ const response = await pollForToken(deviceCode.device_code, logger);
154
+ if (isDeviceAuthError(response)) {
155
+ switch (response.error) {
156
+ case 'authorization_pending':
157
+ // User hasn't authorized yet, keep polling
158
+ logger?.debug('Authorization pending...');
159
+ continue;
160
+ case 'slow_down':
161
+ // Slow down polling (+5 seconds per RFC 8628)
162
+ interval += 5000;
163
+ logger?.debug(`Slowing down polling to ${interval / 1000}s`);
164
+ continue;
165
+ case 'expired_token':
166
+ throw new Error('Device code expired. Please try again.');
167
+ case 'access_denied':
168
+ throw new Error('Authorization denied by user.');
169
+ default:
170
+ throw new Error(response.error_description || `Auth error: ${response.error}`);
171
+ }
172
+ }
173
+ // Success! Save credentials
174
+ onProgress?.('Saving credentials...');
175
+ const tokenResponse = response;
176
+ // Handle both nested and flat response formats
177
+ // Nested: { user: { user_id, email }, organizations }
178
+ // Flat: { user_id, email, organizations }
179
+ const userData = tokenResponse.user || tokenResponse;
180
+ const orgs = tokenResponse.organizations || [];
181
+ // v4.5.0: Calculate expiration timestamps from seconds
182
+ const now = new Date();
183
+ const tokenExpiresAt = tokenResponse.expires_in
184
+ ? new Date(now.getTime() + tokenResponse.expires_in * 1000).toISOString()
185
+ : tokenResponse.token_expires_at;
186
+ const tokenRefreshExpiresAt = tokenResponse.refresh_expires_in
187
+ ? new Date(now.getTime() + tokenResponse.refresh_expires_in * 1000).toISOString()
188
+ : tokenResponse.refresh_expires_at;
189
+ saveAuthCredentials({
190
+ token: tokenResponse.access_token,
191
+ user_id: userData.user_id,
192
+ email: userData.email,
193
+ organizations: orgs,
194
+ authenticated_at: new Date().toISOString(),
195
+ // v4.5.0: Token expiration and refresh
196
+ refresh_token: tokenResponse.refresh_token,
197
+ expires_at: tokenExpiresAt,
198
+ refresh_expires_at: tokenRefreshExpiresAt
199
+ }, logger);
200
+ const currentUser = {
201
+ user_id: userData.user_id,
202
+ email: userData.email,
203
+ name: userData.name,
204
+ image_url: userData.image_url,
205
+ organizations: orgs,
206
+ authenticated_at: new Date().toISOString()
207
+ };
208
+ onSuccess?.(currentUser);
209
+ return currentUser;
210
+ }
211
+ }
212
+ /**
213
+ * Logout - clear credentials
214
+ */
215
+ export function logout(logger) {
216
+ clearAuth(logger);
217
+ logger?.info('Logged out successfully');
218
+ }
219
+ //# sourceMappingURL=device-auth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"device-auth.js","sourceRoot":"","sources":["../../src/auth/device-auth.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Auth Module Index
3
+ * @package @ace-sdk/core
4
+ */
5
+ export { requestDeviceCode, pollForToken, login, logout } from './device-auth.js';
6
+ export { getEffectiveToken, getEffectiveOrgId, isAuthenticated, isUserAuthenticated, getCurrentUser, getTokenType, maskToken } from './utils.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,KAAK,EACL,MAAM,EACP,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,SAAS,EACV,MAAM,YAAY,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Auth Module Index
3
+ * @package @ace-sdk/core
4
+ */
5
+ // Device code authentication
6
+ export { requestDeviceCode, pollForToken, login, logout } from './device-auth.js';
7
+ // Auth utilities
8
+ export { getEffectiveToken, getEffectiveOrgId, isAuthenticated, isUserAuthenticated, getCurrentUser, getTokenType, maskToken } from './utils.js';
9
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,6BAA6B;AAC7B,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,KAAK,EACL,MAAM,EACP,MAAM,kBAAkB,CAAC;AAE1B,iBAAiB;AACjB,OAAO,EACL,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,cAAc,EACd,YAAY,EACZ,SAAS,EACV,MAAM,YAAY,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Authentication Utilities
3
+ *
4
+ * Helper functions for checking auth state and getting effective credentials.
5
+ *
6
+ * @package @ace-sdk/core
7
+ */
8
+ import type { CurrentUser, TokenType } from '../types/auth.js';
9
+ import type { ILogger } from '../logger/index.js';
10
+ /**
11
+ * Get effective API token (user token takes priority over legacy org token)
12
+ *
13
+ * Priority:
14
+ * 1. Environment: ACE_API_TOKEN
15
+ * 2. Config: auth.token (user token)
16
+ * 3. Config: apiToken (legacy org token)
17
+ */
18
+ export declare function getEffectiveToken(logger?: ILogger): string | null;
19
+ /**
20
+ * Get effective organization ID
21
+ *
22
+ * Priority:
23
+ * 1. Environment: ACE_ORG_ID
24
+ * 2. Config: default_org_id
25
+ * 3. First org in auth.organizations
26
+ * 4. Extract from legacy org token
27
+ */
28
+ export declare function getEffectiveOrgId(logger?: ILogger): string | null;
29
+ /**
30
+ * Check if user is authenticated
31
+ */
32
+ export declare function isAuthenticated(logger?: ILogger): boolean;
33
+ /**
34
+ * Check if using user token (vs legacy org token)
35
+ */
36
+ export declare function isUserAuthenticated(logger?: ILogger): boolean;
37
+ /**
38
+ * Get current user info from config
39
+ */
40
+ export declare function getCurrentUser(logger?: ILogger): CurrentUser | null;
41
+ /**
42
+ * Get token type of current effective token
43
+ */
44
+ export declare function getTokenType(logger?: ILogger): TokenType;
45
+ /**
46
+ * Mask token for display (show first 15 chars + ...)
47
+ */
48
+ export declare function maskToken(token: string): string;
49
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/auth/utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,WAAW,EAAY,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEzE,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAGlD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAiCjE;AAED;;;;;;;;GAQG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CA0CjE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAGzD;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAI7D;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,WAAW,GAAG,IAAI,CA2BnE;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAGxD;AAED;;GAEG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI/C"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Authentication Utilities
3
+ *
4
+ * Helper functions for checking auth state and getting effective credentials.
5
+ *
6
+ * @package @ace-sdk/core
7
+ */
8
+ import { existsSync, readFileSync } from 'fs';
9
+ import { detectTokenType } from '../types/auth.js';
10
+ import { getXdgConfigPath } from '../config/xdg.js';
11
+ /**
12
+ * Get effective API token (user token takes priority over legacy org token)
13
+ *
14
+ * Priority:
15
+ * 1. Environment: ACE_API_TOKEN
16
+ * 2. Config: auth.token (user token)
17
+ * 3. Config: apiToken (legacy org token)
18
+ */
19
+ export function getEffectiveToken(logger) {
20
+ // Priority 1: Environment variable
21
+ if (process.env.ACE_API_TOKEN) {
22
+ logger?.debug('Using token from ACE_API_TOKEN');
23
+ return process.env.ACE_API_TOKEN;
24
+ }
25
+ // Load config
26
+ const configPath = getXdgConfigPath();
27
+ if (!existsSync(configPath)) {
28
+ return null;
29
+ }
30
+ try {
31
+ const config = JSON.parse(readFileSync(configPath, 'utf8'));
32
+ // Priority 2: User token (new auth block)
33
+ if (config.auth?.token) {
34
+ logger?.debug('Using user token from auth.token');
35
+ return config.auth.token;
36
+ }
37
+ // Priority 3: Legacy org token
38
+ if (config.apiToken) {
39
+ logger?.debug('Using legacy token from apiToken');
40
+ return config.apiToken;
41
+ }
42
+ return null;
43
+ }
44
+ catch {
45
+ logger?.warn('Failed to read token from config');
46
+ return null;
47
+ }
48
+ }
49
+ /**
50
+ * Get effective organization ID
51
+ *
52
+ * Priority:
53
+ * 1. Environment: ACE_ORG_ID
54
+ * 2. Config: default_org_id
55
+ * 3. First org in auth.organizations
56
+ * 4. Extract from legacy org token
57
+ */
58
+ export function getEffectiveOrgId(logger) {
59
+ // Priority 1: Environment variable
60
+ if (process.env.ACE_ORG_ID) {
61
+ logger?.debug('Using org from ACE_ORG_ID');
62
+ return process.env.ACE_ORG_ID;
63
+ }
64
+ // Load config
65
+ const configPath = getXdgConfigPath();
66
+ if (!existsSync(configPath)) {
67
+ return null;
68
+ }
69
+ try {
70
+ const config = JSON.parse(readFileSync(configPath, 'utf8'));
71
+ // Priority 2: Explicit default_org_id
72
+ if (config.default_org_id) {
73
+ logger?.debug('Using default org from config');
74
+ return config.default_org_id;
75
+ }
76
+ // Priority 3: First org from user auth
77
+ if (config.auth?.organizations?.length > 0) {
78
+ const firstOrg = config.auth.organizations[0].org_id;
79
+ logger?.debug(`Using first org: ${firstOrg}`);
80
+ return firstOrg;
81
+ }
82
+ // Priority 4: Extract from legacy token
83
+ if (config.apiToken && detectTokenType(config.apiToken) === 'org') {
84
+ // Legacy token format: ace_{orgId8chars}{random}
85
+ const orgId = config.apiToken.substring(4, 12);
86
+ logger?.debug(`Extracted org from legacy token: ${orgId}`);
87
+ return orgId;
88
+ }
89
+ return null;
90
+ }
91
+ catch {
92
+ logger?.warn('Failed to read org from config');
93
+ return null;
94
+ }
95
+ }
96
+ /**
97
+ * Check if user is authenticated
98
+ */
99
+ export function isAuthenticated(logger) {
100
+ const token = getEffectiveToken(logger);
101
+ return !!token;
102
+ }
103
+ /**
104
+ * Check if using user token (vs legacy org token)
105
+ */
106
+ export function isUserAuthenticated(logger) {
107
+ const token = getEffectiveToken(logger);
108
+ if (!token)
109
+ return false;
110
+ return detectTokenType(token) === 'user';
111
+ }
112
+ /**
113
+ * Get current user info from config
114
+ */
115
+ export function getCurrentUser(logger) {
116
+ const configPath = getXdgConfigPath();
117
+ if (!existsSync(configPath)) {
118
+ return null;
119
+ }
120
+ try {
121
+ const config = JSON.parse(readFileSync(configPath, 'utf8'));
122
+ if (!config.auth) {
123
+ return null;
124
+ }
125
+ const auth = config.auth;
126
+ return {
127
+ user_id: auth.user_id,
128
+ email: auth.email,
129
+ organizations: auth.organizations || [],
130
+ default_org_id: config.default_org_id,
131
+ authenticated_at: auth.authenticated_at
132
+ };
133
+ }
134
+ catch {
135
+ logger?.warn('Failed to read current user from config');
136
+ return null;
137
+ }
138
+ }
139
+ /**
140
+ * Get token type of current effective token
141
+ */
142
+ export function getTokenType(logger) {
143
+ const token = getEffectiveToken(logger);
144
+ return token ? detectTokenType(token) : 'unknown';
145
+ }
146
+ /**
147
+ * Mask token for display (show first 15 chars + ...)
148
+ */
149
+ export function maskToken(token) {
150
+ if (!token)
151
+ return '(none)';
152
+ if (token.length <= 15)
153
+ return token;
154
+ return `${token.substring(0, 15)}...`;
155
+ }
156
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/auth/utils.ts"],"names":[],"mappings":"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"}
@@ -18,12 +18,16 @@ import { ILogger } from '../logger/index.js';
18
18
  export interface AceClientOptions {
19
19
  /** Logger for output (optional - defaults to silent) */
20
20
  logger?: ILogger;
21
+ /** Enable auto-refresh of expired tokens (v4.5.0, default: true for user tokens) */
22
+ autoRefresh?: boolean;
21
23
  }
22
24
  export declare class AceClient {
23
25
  private config;
24
26
  private localCache;
25
27
  private memoryCache?;
26
28
  private logger;
29
+ private autoRefresh;
30
+ private currentToken;
27
31
  private configCache;
28
32
  private CONFIG_CACHE_TTL;
29
33
  constructor(config: AceConfig | AceContext, options?: AceClientOptions);
@@ -1 +1 @@
1
- {"version":3,"file":"ace-client.d.ts","sourceRoot":"","sources":["../../src/client/ace-client.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ace-client.d.ts","sourceRoot":"","sources":["../../src/client/ace-client.ts"],"names":[],"mappings":"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"}
@@ -9,11 +9,15 @@
9
9
  * @package @ace-sdk/core
10
10
  */
11
11
  import { LocalCacheService } from '../cache/local-cache.js';
12
+ import { ensureValidToken } from './http.js';
13
+ import { isUserToken } from '../types/auth.js';
12
14
  export class AceClient {
13
15
  config;
14
16
  localCache;
15
17
  memoryCache; // RAM cache
16
18
  logger;
19
+ autoRefresh;
20
+ currentToken; // Tracks potentially refreshed token
17
21
  // Config cache (v3.6.0+) - 1-hour TTL (configurable)
18
22
  configCache = { data: null, timestamp: 0 };
19
23
  CONFIG_CACHE_TTL = 60 * 60 * 1000; // 60 minutes (1 hour)
@@ -26,6 +30,9 @@ export class AceClient {
26
30
  const projectId = config.projectId;
27
31
  const orgId = 'orgId' in config ? config.orgId : this.extractOrgId(apiToken);
28
32
  const cacheTtlMinutes = config.cacheTtlMinutes;
33
+ // v4.5.0: Auto-refresh enabled by default for user tokens
34
+ this.currentToken = apiToken;
35
+ this.autoRefresh = options?.autoRefresh !== false && isUserToken(apiToken);
29
36
  // Initialize local SQLite cache (optional - graceful fallback for Node 25+)
30
37
  try {
31
38
  const cacheConfig = {
@@ -77,14 +84,38 @@ export class AceClient {
77
84
  this.logger.trace(`Request body: ${truncated}`);
78
85
  }
79
86
  }
87
+ // v4.5.0: Auto-refresh token if enabled and using user token
88
+ let token = this.currentToken;
89
+ if (this.autoRefresh) {
90
+ try {
91
+ const result = await ensureValidToken(this.config.serverUrl, this.logger);
92
+ token = result.token;
93
+ if (result.wasRefreshed) {
94
+ this.currentToken = token;
95
+ this.logger?.debug('Token refreshed automatically');
96
+ }
97
+ }
98
+ catch (error) {
99
+ // If token refresh fails, try with current token anyway
100
+ // (might work if server hasn't invalidated it yet)
101
+ this.logger?.debug('Token refresh failed, using current token');
102
+ }
103
+ }
80
104
  const startTime = Date.now();
105
+ // Build headers with X-ACE-Org for user tokens
106
+ const headers = {
107
+ 'Content-Type': 'application/json',
108
+ 'Authorization': `Bearer ${token}`,
109
+ 'X-ACE-Project': this.config.projectId
110
+ };
111
+ // Add X-ACE-Org header for user tokens (selects which org per-request)
112
+ const orgId = 'orgId' in this.config ? this.config.orgId : this.extractOrgId(this.config.apiToken);
113
+ if (orgId && orgId !== 'default') {
114
+ headers['X-ACE-Org'] = orgId;
115
+ }
81
116
  const response = await fetch(url, {
82
117
  method,
83
- headers: {
84
- 'Content-Type': 'application/json',
85
- 'Authorization': `Bearer ${this.config.apiToken}`,
86
- 'X-ACE-Project': this.config.projectId
87
- },
118
+ headers,
88
119
  body: body ? JSON.stringify(body) : undefined
89
120
  });
90
121
  const duration = Date.now() - startTime;