@wayai/cli 0.2.46 → 0.2.48
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/dist/commands/login.d.ts +4 -1
- package/dist/commands/login.js +49 -29
- package/dist/commands/login.js.map +1 -1
- package/dist/lib/auth.d.ts +23 -38
- package/dist/lib/auth.js +107 -76
- package/dist/lib/auth.js.map +1 -1
- package/dist/lib/config.d.ts +13 -2
- package/dist/lib/config.js +4 -7
- package/dist/lib/config.js.map +1 -1
- package/package.json +1 -1
package/dist/commands/login.d.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* wayai login —
|
|
2
|
+
* wayai login — OAuth 2.1 + PKCE browser flow (default) or --token fallback
|
|
3
|
+
*
|
|
4
|
+
* Browser login: Opens AuthKit authorize → PKCE flow → JWT + refresh token
|
|
5
|
+
* Token login: User pastes a way_ scoped token directly
|
|
3
6
|
*/
|
|
4
7
|
export declare function parseApiUrl(args: string[]): string;
|
|
5
8
|
export declare function loginCommand(args: string[]): Promise<void>;
|
package/dist/commands/login.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* wayai login —
|
|
2
|
+
* wayai login — OAuth 2.1 + PKCE browser flow (default) or --token fallback
|
|
3
|
+
*
|
|
4
|
+
* Browser login: Opens AuthKit authorize → PKCE flow → JWT + refresh token
|
|
5
|
+
* Token login: User pastes a way_ scoped token directly
|
|
3
6
|
*/
|
|
4
7
|
import * as readline from 'node:readline';
|
|
5
|
-
import { generateState,
|
|
8
|
+
import { generateState, generateCodeVerifier, generateCodeChallenge, startCallbackServer, exchangeCodeForTokens, validateToken, getAuthKitDomain, getAuthKitClientId, OAUTH_CALLBACK_PORT, } from '../lib/auth.js';
|
|
6
9
|
import { writeConfig } from '../lib/config.js';
|
|
7
10
|
function prompt(question, defaultValue) {
|
|
8
11
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
@@ -34,38 +37,56 @@ export async function loginCommand(args) {
|
|
|
34
37
|
}
|
|
35
38
|
async function loginWithBrowser(apiUrl) {
|
|
36
39
|
console.log('\nConnecting to WayAI...');
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
+
const authkitDomain = getAuthKitDomain();
|
|
41
|
+
const clientId = getAuthKitClientId();
|
|
42
|
+
// Generate PKCE parameters
|
|
43
|
+
const codeVerifier = generateCodeVerifier();
|
|
44
|
+
const codeChallenge = await generateCodeChallenge(codeVerifier);
|
|
40
45
|
const state = generateState();
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
// Try to open browser
|
|
53
|
-
const openedBrowser = await tryOpenBrowser(loginUrl);
|
|
54
|
-
if (!openedBrowser) {
|
|
55
|
-
console.log(`\nOpen this URL in your browser to log in:\n\n ${loginUrl}\n`);
|
|
56
|
-
}
|
|
57
|
-
else {
|
|
58
|
-
console.log('Opening browser for login...');
|
|
59
|
-
}
|
|
46
|
+
// Fixed port so the redirect URI matches what's registered in WorkOS
|
|
47
|
+
const port = OAUTH_CALLBACK_PORT;
|
|
48
|
+
const redirectUri = `http://127.0.0.1:${port}/callback`;
|
|
49
|
+
// Build AuthKit authorization URL with PKCE
|
|
50
|
+
const authorizeUrl = new URL(`${authkitDomain}/oauth2/authorize`);
|
|
51
|
+
authorizeUrl.searchParams.set('client_id', clientId);
|
|
52
|
+
authorizeUrl.searchParams.set('redirect_uri', redirectUri);
|
|
53
|
+
authorizeUrl.searchParams.set('response_type', 'code');
|
|
54
|
+
authorizeUrl.searchParams.set('code_challenge', codeChallenge);
|
|
55
|
+
authorizeUrl.searchParams.set('code_challenge_method', 'S256');
|
|
56
|
+
authorizeUrl.searchParams.set('state', state);
|
|
60
57
|
try {
|
|
58
|
+
// Start callback server before opening browser
|
|
59
|
+
const callbackPromise = startCallbackServer(port, state);
|
|
60
|
+
// Try to open browser
|
|
61
|
+
const openedBrowser = await tryOpenBrowser(authorizeUrl.toString());
|
|
62
|
+
if (!openedBrowser) {
|
|
63
|
+
console.log(`\nOpen this URL in your browser to log in:\n\n ${authorizeUrl.toString()}\n`);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
console.log('Opening browser for login...');
|
|
67
|
+
}
|
|
61
68
|
const { code } = await callbackPromise;
|
|
62
69
|
console.log('Exchanging authorization code...');
|
|
63
|
-
const
|
|
70
|
+
const tokens = await exchangeCodeForTokens(authkitDomain, clientId, code, codeVerifier, redirectUri);
|
|
71
|
+
// Exchange the short-lived JWT for a long-lived way_ token
|
|
72
|
+
console.log('Generating API token...');
|
|
73
|
+
const tokenRes = await fetch(`${apiUrl}/auth/connect/token`, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
headers: { Authorization: `Bearer ${tokens.access_token}` },
|
|
76
|
+
});
|
|
77
|
+
if (!tokenRes.ok) {
|
|
78
|
+
const body = await tokenRes.text();
|
|
79
|
+
throw new Error(`Token generation failed (${tokenRes.status}): ${body}`);
|
|
80
|
+
}
|
|
81
|
+
const { token } = await tokenRes.json();
|
|
82
|
+
if (!token || typeof token !== 'string') {
|
|
83
|
+
throw new Error('Invalid response from token endpoint');
|
|
84
|
+
}
|
|
64
85
|
writeConfig({
|
|
65
86
|
api_url: apiUrl,
|
|
66
|
-
token
|
|
87
|
+
token,
|
|
67
88
|
});
|
|
68
|
-
console.log(
|
|
89
|
+
console.log('\nLogin successful!');
|
|
69
90
|
console.log('Configuration saved to ~/.wayai/config.json');
|
|
70
91
|
}
|
|
71
92
|
catch (err) {
|
|
@@ -74,7 +95,7 @@ async function loginWithBrowser(apiUrl) {
|
|
|
74
95
|
}
|
|
75
96
|
}
|
|
76
97
|
async function loginWithToken(apiUrl) {
|
|
77
|
-
const token = await prompt('
|
|
98
|
+
const token = await prompt('API Token (way_...)');
|
|
78
99
|
if (!token) {
|
|
79
100
|
console.error('Token is required.');
|
|
80
101
|
process.exit(1);
|
|
@@ -98,7 +119,6 @@ async function loginWithToken(apiUrl) {
|
|
|
98
119
|
console.log('\nLogin successful! Configuration saved to ~/.wayai/config.json');
|
|
99
120
|
}
|
|
100
121
|
async function tryOpenBrowser(url) {
|
|
101
|
-
// Skip in headless environments
|
|
102
122
|
if (process.env.SSH_CONNECTION || process.env.SSH_TTY) {
|
|
103
123
|
return false;
|
|
104
124
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/auth.d.ts
CHANGED
|
@@ -1,56 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Authentication —
|
|
2
|
+
* Authentication — OAuth 2.1 + PKCE browser login + way_ token fallback
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1. Browser login (default):
|
|
6
|
-
* 2. Token login (--token): User pastes a way_ token directly
|
|
4
|
+
* Two login paths:
|
|
5
|
+
* 1. Browser login (default): OAuth 2.1 with PKCE → JWT + refresh token
|
|
6
|
+
* 2. Token login (--token): User pastes a way_ scoped token directly
|
|
7
|
+
*
|
|
8
|
+
* The CLI exchanges codes directly with AuthKit's token endpoint.
|
|
7
9
|
*/
|
|
8
10
|
import type { CliConfig } from './config.js';
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*/
|
|
11
|
+
export declare function generateCodeVerifier(): string;
|
|
12
|
+
export declare function generateCodeChallenge(verifier: string): Promise<string>;
|
|
12
13
|
export declare function generateState(): string;
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
orgId: string;
|
|
23
|
-
userId: string;
|
|
24
|
-
email: string;
|
|
14
|
+
export declare function exchangeCodeForTokens(authkitDomain: string, clientId: string, code: string, codeVerifier: string, redirectUri: string): Promise<{
|
|
15
|
+
access_token: string;
|
|
16
|
+
refresh_token: string;
|
|
17
|
+
expires_in: number;
|
|
18
|
+
}>;
|
|
19
|
+
export declare function refreshAccessToken(authkitDomain: string, clientId: string, refreshToken: string): Promise<{
|
|
20
|
+
access_token: string;
|
|
21
|
+
refresh_token?: string;
|
|
22
|
+
expires_in: number;
|
|
25
23
|
}>;
|
|
26
|
-
/**
|
|
27
|
-
* Validate a way_ token by making a lightweight API call
|
|
28
|
-
*/
|
|
29
24
|
export declare function validateToken(apiUrl: string, token: string): Promise<void>;
|
|
30
|
-
/**
|
|
31
|
-
|
|
32
|
-
* Returns the authorization code and state received.
|
|
33
|
-
*/
|
|
25
|
+
/** Fixed port for OAuth callback — must match the redirect URI registered in WorkOS */
|
|
26
|
+
export declare const OAUTH_CALLBACK_PORT = 3829;
|
|
34
27
|
export declare function startCallbackServer(port: number, expectedState: string, timeoutMs?: number): Promise<{
|
|
35
28
|
code: string;
|
|
36
29
|
port: number;
|
|
37
30
|
}>;
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
*/
|
|
41
|
-
export declare function isPortAvailable(port: number): Promise<boolean>;
|
|
42
|
-
/**
|
|
43
|
-
* Find an available port by trying to listen on port 0
|
|
44
|
-
*/
|
|
45
|
-
export declare function findAvailablePort(): Promise<number>;
|
|
31
|
+
export declare function getAuthKitDomain(): string;
|
|
32
|
+
export declare function getAuthKitClientId(): string;
|
|
46
33
|
/**
|
|
47
34
|
* Get a valid access token from the current config.
|
|
48
|
-
*
|
|
35
|
+
* - For way_ tokens: returns directly (no refresh needed)
|
|
36
|
+
* - For OAuth JWT: checks expiry, refreshes if needed, updates config
|
|
49
37
|
*/
|
|
50
38
|
export declare function getAccessToken(config: CliConfig): Promise<string>;
|
|
51
|
-
/**
|
|
52
|
-
* Read config and get access token, or exit with error.
|
|
53
|
-
*/
|
|
54
39
|
export declare function requireAuth(): Promise<{
|
|
55
40
|
config: CliConfig;
|
|
56
41
|
accessToken: string;
|
package/dist/lib/auth.js
CHANGED
|
@@ -1,69 +1,91 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Authentication —
|
|
2
|
+
* Authentication — OAuth 2.1 + PKCE browser login + way_ token fallback
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* 1. Browser login (default):
|
|
6
|
-
* 2. Token login (--token): User pastes a way_ token directly
|
|
4
|
+
* Two login paths:
|
|
5
|
+
* 1. Browser login (default): OAuth 2.1 with PKCE → JWT + refresh token
|
|
6
|
+
* 2. Token login (--token): User pastes a way_ scoped token directly
|
|
7
|
+
*
|
|
8
|
+
* The CLI exchanges codes directly with AuthKit's token endpoint.
|
|
7
9
|
*/
|
|
8
10
|
import * as crypto from 'node:crypto';
|
|
9
11
|
import * as http from 'node:http';
|
|
10
|
-
import { readConfig } from './config.js';
|
|
12
|
+
import { readConfig, writeConfig } from './config.js';
|
|
11
13
|
import { setSentryUser } from './sentry.js';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// PKCE Utilities
|
|
16
|
+
// =============================================================================
|
|
17
|
+
export function generateCodeVerifier() {
|
|
18
|
+
return crypto.randomBytes(32).toString('base64url');
|
|
19
|
+
}
|
|
20
|
+
export async function generateCodeChallenge(verifier) {
|
|
21
|
+
const hash = crypto.createHash('sha256').update(verifier).digest();
|
|
22
|
+
return hash.toString('base64url');
|
|
23
|
+
}
|
|
15
24
|
export function generateState() {
|
|
16
25
|
return crypto.randomBytes(16).toString('base64url');
|
|
17
26
|
}
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
export async function
|
|
22
|
-
const
|
|
23
|
-
|
|
27
|
+
// =============================================================================
|
|
28
|
+
// AuthKit Token Exchange
|
|
29
|
+
// =============================================================================
|
|
30
|
+
export async function exchangeCodeForTokens(authkitDomain, clientId, code, codeVerifier, redirectUri) {
|
|
31
|
+
const response = await fetch(`${authkitDomain}/oauth2/token`, {
|
|
32
|
+
method: 'POST',
|
|
33
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
34
|
+
body: new URLSearchParams({
|
|
35
|
+
grant_type: 'authorization_code',
|
|
36
|
+
code,
|
|
37
|
+
code_verifier: codeVerifier,
|
|
38
|
+
redirect_uri: redirectUri,
|
|
39
|
+
client_id: clientId,
|
|
40
|
+
}).toString(),
|
|
41
|
+
});
|
|
24
42
|
if (!response.ok) {
|
|
25
43
|
const body = await response.text();
|
|
26
|
-
throw new Error(`
|
|
44
|
+
throw new Error(`Token exchange failed (${response.status}): ${body}`);
|
|
27
45
|
}
|
|
28
|
-
|
|
29
|
-
return data.url;
|
|
46
|
+
return response.json();
|
|
30
47
|
}
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
*/
|
|
34
|
-
export async function exchangeCodeForToken(apiUrl, code, redirectUri) {
|
|
35
|
-
const response = await fetch(`${apiUrl}/auth/cli/callback`, {
|
|
48
|
+
export async function refreshAccessToken(authkitDomain, clientId, refreshToken) {
|
|
49
|
+
const response = await fetch(`${authkitDomain}/oauth2/token`, {
|
|
36
50
|
method: 'POST',
|
|
37
|
-
headers: { 'Content-Type': 'application/
|
|
38
|
-
body:
|
|
51
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
52
|
+
body: new URLSearchParams({
|
|
53
|
+
grant_type: 'refresh_token',
|
|
54
|
+
refresh_token: refreshToken,
|
|
55
|
+
client_id: clientId,
|
|
56
|
+
}).toString(),
|
|
39
57
|
});
|
|
40
58
|
if (!response.ok) {
|
|
59
|
+
const status = response.status;
|
|
41
60
|
const body = await response.text();
|
|
42
|
-
|
|
61
|
+
if (status === 400 || status === 401) {
|
|
62
|
+
let isInvalidGrant = false;
|
|
63
|
+
try {
|
|
64
|
+
const parsed = JSON.parse(body);
|
|
65
|
+
if (parsed.error === 'invalid_grant')
|
|
66
|
+
isInvalidGrant = true;
|
|
67
|
+
}
|
|
68
|
+
catch { /* non-JSON body */ }
|
|
69
|
+
if (isInvalidGrant)
|
|
70
|
+
throw new Error('SESSION_EXPIRED');
|
|
71
|
+
}
|
|
72
|
+
throw new Error(`Token refresh failed (${status}): ${body}`);
|
|
43
73
|
}
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
token: data.data.token,
|
|
47
|
-
orgId: data.data.org_id,
|
|
48
|
-
userId: data.data.user_id,
|
|
49
|
-
email: data.data.email,
|
|
50
|
-
};
|
|
74
|
+
return response.json();
|
|
51
75
|
}
|
|
52
|
-
/**
|
|
53
|
-
* Validate a way_ token by making a lightweight API call
|
|
54
|
-
*/
|
|
55
76
|
export async function validateToken(apiUrl, token) {
|
|
56
|
-
const response = await fetch(`${apiUrl}/api/
|
|
77
|
+
const response = await fetch(`${apiUrl}/api/auth/me`, {
|
|
57
78
|
headers: { Authorization: `Bearer ${token}` },
|
|
58
79
|
});
|
|
59
80
|
if (!response.ok) {
|
|
60
81
|
throw new Error(`Token validation failed (${response.status})`);
|
|
61
82
|
}
|
|
62
83
|
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
*/
|
|
84
|
+
// =============================================================================
|
|
85
|
+
// Callback Server
|
|
86
|
+
// =============================================================================
|
|
87
|
+
/** Fixed port for OAuth callback — must match the redirect URI registered in WorkOS */
|
|
88
|
+
export const OAUTH_CALLBACK_PORT = 3829;
|
|
67
89
|
export function startCallbackServer(port, expectedState, timeoutMs = 120_000) {
|
|
68
90
|
return new Promise((resolve, reject) => {
|
|
69
91
|
const server = http.createServer((req, res) => {
|
|
@@ -80,7 +102,6 @@ export function startCallbackServer(port, expectedState, timeoutMs = 120_000) {
|
|
|
80
102
|
reject(new Error(`OAuth callback error: ${errorDescription || error}`));
|
|
81
103
|
return;
|
|
82
104
|
}
|
|
83
|
-
// Validate state to prevent CSRF
|
|
84
105
|
if (state !== expectedState) {
|
|
85
106
|
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
86
107
|
res.end('<html><body><h2>Login failed</h2><p>Invalid state parameter</p></body></html>');
|
|
@@ -122,50 +143,60 @@ export function startCallbackServer(port, expectedState, timeoutMs = 120_000) {
|
|
|
122
143
|
});
|
|
123
144
|
});
|
|
124
145
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
server.close(() => resolve(true));
|
|
133
|
-
});
|
|
134
|
-
server.on('error', () => resolve(false));
|
|
135
|
-
});
|
|
146
|
+
// =============================================================================
|
|
147
|
+
// Token Resolution (for API calls)
|
|
148
|
+
// =============================================================================
|
|
149
|
+
const AUTHKIT_DOMAIN = 'https://sprightly-comic-51.authkit.app';
|
|
150
|
+
const AUTHKIT_CLIENT_ID = 'client_01KMZHB50KENM5SV90ZA80VXK4'; // WayAI CLI Connect app (public, PKCE)
|
|
151
|
+
export function getAuthKitDomain() {
|
|
152
|
+
return process.env.WAYAI_AUTHKIT_DOMAIN || AUTHKIT_DOMAIN;
|
|
136
153
|
}
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
*/
|
|
140
|
-
export async function findAvailablePort() {
|
|
141
|
-
return new Promise((resolve, reject) => {
|
|
142
|
-
const server = http.createServer();
|
|
143
|
-
server.listen(0, '127.0.0.1', () => {
|
|
144
|
-
const addr = server.address();
|
|
145
|
-
if (addr && typeof addr === 'object') {
|
|
146
|
-
const port = addr.port;
|
|
147
|
-
server.close(() => resolve(port));
|
|
148
|
-
}
|
|
149
|
-
else {
|
|
150
|
-
server.close(() => reject(new Error('Could not find available port')));
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
server.on('error', reject);
|
|
154
|
-
});
|
|
154
|
+
export function getAuthKitClientId() {
|
|
155
|
+
return process.env.WAYAI_AUTHKIT_CLIENT_ID || AUTHKIT_CLIENT_ID;
|
|
155
156
|
}
|
|
156
157
|
/**
|
|
157
158
|
* Get a valid access token from the current config.
|
|
158
|
-
*
|
|
159
|
+
* - For way_ tokens: returns directly (no refresh needed)
|
|
160
|
+
* - For OAuth JWT: checks expiry, refreshes if needed, updates config
|
|
159
161
|
*/
|
|
160
162
|
export async function getAccessToken(config) {
|
|
161
|
-
|
|
163
|
+
// way_ token path — no refresh needed
|
|
164
|
+
if (config.token) {
|
|
165
|
+
return config.token;
|
|
166
|
+
}
|
|
167
|
+
// OAuth JWT path — check expiry and refresh if needed
|
|
168
|
+
if (!config.access_token || !config.refresh_token) {
|
|
162
169
|
throw new Error('No token found. Run `wayai login` to authenticate.');
|
|
163
170
|
}
|
|
164
|
-
|
|
171
|
+
if (!config.token_expires_at) {
|
|
172
|
+
return config.access_token;
|
|
173
|
+
}
|
|
174
|
+
const expiresAt = new Date(config.token_expires_at).getTime();
|
|
175
|
+
if (expiresAt > Date.now() + 60_000) {
|
|
176
|
+
return config.access_token;
|
|
177
|
+
}
|
|
178
|
+
// Token expired — refresh
|
|
179
|
+
try {
|
|
180
|
+
const result = await refreshAccessToken(getAuthKitDomain(), getAuthKitClientId(), config.refresh_token);
|
|
181
|
+
const updatedConfig = {
|
|
182
|
+
...config,
|
|
183
|
+
access_token: result.access_token,
|
|
184
|
+
token_expires_at: new Date(Date.now() + result.expires_in * 1000).toISOString(),
|
|
185
|
+
};
|
|
186
|
+
if (result.refresh_token) {
|
|
187
|
+
updatedConfig.refresh_token = result.refresh_token;
|
|
188
|
+
}
|
|
189
|
+
writeConfig(updatedConfig);
|
|
190
|
+
return result.access_token;
|
|
191
|
+
}
|
|
192
|
+
catch (err) {
|
|
193
|
+
if (err instanceof Error && err.message === 'SESSION_EXPIRED') {
|
|
194
|
+
writeConfig({ api_url: config.api_url });
|
|
195
|
+
throw new Error('Session expired. Please run `wayai login` again.');
|
|
196
|
+
}
|
|
197
|
+
throw err;
|
|
198
|
+
}
|
|
165
199
|
}
|
|
166
|
-
/**
|
|
167
|
-
* Read config and get access token, or exit with error.
|
|
168
|
-
*/
|
|
169
200
|
export async function requireAuth() {
|
|
170
201
|
const config = readConfig();
|
|
171
202
|
if (!config) {
|
package/dist/lib/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../../src/lib/auth.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/config.d.ts
CHANGED
|
@@ -1,10 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI configuration management — reads/writes ~/.wayai/config.json
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* CLI config supports two auth modes:
|
|
6
|
+
* - OAuth (browser login): access_token (JWT) + refresh_token + token_expires_at
|
|
7
|
+
* - Token (--token flag): token (way_ scoped token)
|
|
8
|
+
*/
|
|
4
9
|
export interface CliConfig {
|
|
5
10
|
api_url: string;
|
|
6
|
-
/**
|
|
7
|
-
token
|
|
11
|
+
/** way_ scoped token (from --token login) */
|
|
12
|
+
token?: string;
|
|
13
|
+
/** JWT access token (from OAuth browser login) */
|
|
14
|
+
access_token?: string;
|
|
15
|
+
/** OAuth refresh token */
|
|
16
|
+
refresh_token?: string;
|
|
17
|
+
/** ISO 8601 expiry of the access token */
|
|
18
|
+
token_expires_at?: string;
|
|
8
19
|
}
|
|
9
20
|
export declare function getConfigPath(): string;
|
|
10
21
|
export declare function readConfig(): CliConfig | null;
|
package/dist/lib/config.js
CHANGED
|
@@ -16,14 +16,11 @@ export function readConfig() {
|
|
|
16
16
|
try {
|
|
17
17
|
const content = fs.readFileSync(CONFIG_PATH, 'utf-8');
|
|
18
18
|
const parsed = JSON.parse(content);
|
|
19
|
-
//
|
|
20
|
-
if (
|
|
21
|
-
return
|
|
22
|
-
|
|
23
|
-
if (parsed.auth_method === 'oauth' && !parsed.token) {
|
|
24
|
-
// Legacy OAuth config — user needs to re-login
|
|
19
|
+
// Greenfield: reject old config formats — user must re-login
|
|
20
|
+
if (!parsed.api_url)
|
|
21
|
+
return null;
|
|
22
|
+
if (!parsed.token && !parsed.access_token)
|
|
25
23
|
return null;
|
|
26
|
-
}
|
|
27
24
|
return parsed;
|
|
28
25
|
}
|
|
29
26
|
catch {
|
package/dist/lib/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAmB9B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AACrD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,CAAC;AAEzD,MAAM,UAAU,aAAa;IAC3B,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IAED,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;QACtD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAEnC,6DAA6D;QAC7D,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,IAAI,CAAC;QACjC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,YAAY;YAAE,OAAO,IAAI,CAAC;QAEvD,OAAO,MAAmB,CAAC;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,MAAiB;IAC3C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAChD,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE;QACpE,IAAI,EAAE,KAAK,EAAE,wBAAwB;KACtC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,CAAC;IAC7B,CAAC;AACH,CAAC"}
|