@gojinko/api-client 0.2.0 → 0.3.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/dist/auth.d.ts +12 -4
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +60 -12
- package/dist/auth.js.map +1 -1
- package/dist/callback-server.d.ts +18 -0
- package/dist/callback-server.d.ts.map +1 -0
- package/dist/callback-server.js +85 -0
- package/dist/callback-server.js.map +1 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +36 -3
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/oauth.d.ts +41 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +111 -0
- package/dist/oauth.js.map +1 -0
- package/package.json +1 -1
package/dist/auth.d.ts
CHANGED
|
@@ -3,18 +3,22 @@ export interface ResolvedAuth {
|
|
|
3
3
|
readonly method: AuthMethod;
|
|
4
4
|
readonly token: string;
|
|
5
5
|
}
|
|
6
|
+
export interface OAuthConfig {
|
|
7
|
+
readonly access_token: string;
|
|
8
|
+
readonly refresh_token: string;
|
|
9
|
+
readonly expires_at: number;
|
|
10
|
+
}
|
|
6
11
|
interface ConfigFile {
|
|
7
12
|
readonly api_key?: string;
|
|
8
|
-
readonly
|
|
13
|
+
readonly oauth?: OAuthConfig;
|
|
9
14
|
}
|
|
10
15
|
declare const DEFAULT_BASE_URL = "https://mcp-bff.gojinko.com";
|
|
11
16
|
declare const CONFIG_DIR: string;
|
|
12
17
|
declare const CONFIG_FILE: string;
|
|
13
18
|
/**
|
|
14
|
-
* Resolve auth credentials with precedence: param > env > config file.
|
|
19
|
+
* Resolve auth credentials with precedence: param > env > config file (api_key) > config file (oauth).
|
|
15
20
|
*
|
|
16
|
-
*
|
|
17
|
-
* OAuth JWT support exists internally but is not exposed to users yet.
|
|
21
|
+
* OAuth tokens are auto-refreshed if expired.
|
|
18
22
|
*/
|
|
19
23
|
export declare function resolveAuth(paramToken?: string): Promise<ResolvedAuth | undefined>;
|
|
20
24
|
/**
|
|
@@ -29,5 +33,9 @@ export declare function readConfigFile(): Promise<ConfigFile | undefined>;
|
|
|
29
33
|
* Write a config value to ~/.jinko/config.yaml.
|
|
30
34
|
*/
|
|
31
35
|
export declare function writeConfigFile(updates: Partial<ConfigFile>): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Clear all auth credentials from config file.
|
|
38
|
+
*/
|
|
39
|
+
export declare function clearAuthConfig(): Promise<void>;
|
|
32
40
|
export { CONFIG_DIR, CONFIG_FILE, DEFAULT_BASE_URL };
|
|
33
41
|
//# sourceMappingURL=auth.d.ts.map
|
package/dist/auth.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAMA,MAAM,MAAM,UAAU,GAAG,SAAS,GAAG,OAAO,CAAC;AAE7C,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,UAAU,UAAU;IAClB,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,WAAW,CAAC;CAC9B;AAED,QAAA,MAAM,gBAAgB,gCAAgC,CAAC;AACvD,QAAA,MAAM,UAAU,QAA4B,CAAC;AAC7C,QAAA,MAAM,WAAW,QAAkC,CAAC;AAEpD;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAiDxF;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,CAEvC;AAED;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAOtE;AAED;;GAEG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CASjF;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC,CAYrD;AAED,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC"}
|
package/dist/auth.js
CHANGED
|
@@ -2,26 +2,60 @@ import { readFile } from 'node:fs/promises';
|
|
|
2
2
|
import { join } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
4
|
import { parse as parseYaml } from 'yaml';
|
|
5
|
+
import { isTokenExpired, refreshAccessToken } from './oauth.js';
|
|
5
6
|
const DEFAULT_BASE_URL = 'https://mcp-bff.gojinko.com';
|
|
6
7
|
const CONFIG_DIR = join(homedir(), '.jinko');
|
|
7
8
|
const CONFIG_FILE = join(CONFIG_DIR, 'config.yaml');
|
|
8
9
|
/**
|
|
9
|
-
* Resolve auth credentials with precedence: param > env > config file.
|
|
10
|
+
* Resolve auth credentials with precedence: param > env > config file (api_key) > config file (oauth).
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
* OAuth JWT support exists internally but is not exposed to users yet.
|
|
12
|
+
* OAuth tokens are auto-refreshed if expired.
|
|
13
13
|
*/
|
|
14
14
|
export async function resolveAuth(paramToken) {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
// 1. Explicit param or env — always API key
|
|
16
|
+
const explicitToken = paramToken ?? process.env['JINKO_API_KEY'];
|
|
17
|
+
if (explicitToken) {
|
|
18
|
+
return {
|
|
19
|
+
method: explicitToken.startsWith('jnk_') ? 'api_key' : 'oauth',
|
|
20
|
+
token: explicitToken,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// 2. Config file
|
|
24
|
+
const config = await readConfigFile();
|
|
25
|
+
if (!config)
|
|
19
26
|
return undefined;
|
|
20
|
-
//
|
|
21
|
-
|
|
22
|
-
method:
|
|
23
|
-
|
|
24
|
-
|
|
27
|
+
// 2a. API key in config
|
|
28
|
+
if (config.api_key) {
|
|
29
|
+
return { method: 'api_key', token: config.api_key };
|
|
30
|
+
}
|
|
31
|
+
// 2b. OAuth tokens in config
|
|
32
|
+
if (config.oauth) {
|
|
33
|
+
const tokens = {
|
|
34
|
+
access_token: config.oauth.access_token,
|
|
35
|
+
refresh_token: config.oauth.refresh_token,
|
|
36
|
+
expires_at: config.oauth.expires_at,
|
|
37
|
+
};
|
|
38
|
+
if (isTokenExpired(tokens)) {
|
|
39
|
+
try {
|
|
40
|
+
const refreshed = await refreshAccessToken(tokens.refresh_token);
|
|
41
|
+
// Persist refreshed tokens
|
|
42
|
+
await writeConfigFile({
|
|
43
|
+
oauth: {
|
|
44
|
+
access_token: refreshed.access_token,
|
|
45
|
+
refresh_token: refreshed.refresh_token,
|
|
46
|
+
expires_at: refreshed.expires_at,
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
return { method: 'oauth', token: refreshed.access_token };
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// Refresh failed — try with existing token, server will 401 if truly expired
|
|
53
|
+
return { method: 'oauth', token: tokens.access_token };
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
return { method: 'oauth', token: tokens.access_token };
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
25
59
|
}
|
|
26
60
|
/**
|
|
27
61
|
* Internal base URL — not configurable by users.
|
|
@@ -52,5 +86,19 @@ export async function writeConfigFile(updates) {
|
|
|
52
86
|
const merged = { ...existing, ...updates };
|
|
53
87
|
await writeFile(CONFIG_FILE, stringifyYaml(merged), 'utf-8');
|
|
54
88
|
}
|
|
89
|
+
/**
|
|
90
|
+
* Clear all auth credentials from config file.
|
|
91
|
+
*/
|
|
92
|
+
export async function clearAuthConfig() {
|
|
93
|
+
const config = await readConfigFile();
|
|
94
|
+
if (!config)
|
|
95
|
+
return;
|
|
96
|
+
const { api_key: _, oauth: __, ...rest } = config;
|
|
97
|
+
const { mkdir, writeFile } = await import('node:fs/promises');
|
|
98
|
+
const { stringify: stringifyYaml } = await import('yaml');
|
|
99
|
+
await mkdir(CONFIG_DIR, { recursive: true });
|
|
100
|
+
const cleaned = Object.keys(rest).length > 0 ? rest : {};
|
|
101
|
+
await writeFile(CONFIG_FILE, stringifyYaml(cleaned), 'utf-8');
|
|
102
|
+
}
|
|
55
103
|
export { CONFIG_DIR, CONFIG_FILE, DEFAULT_BASE_URL };
|
|
56
104
|
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,KAAK,IAAI,SAAS,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export interface CallbackResult {
|
|
2
|
+
readonly code: string;
|
|
3
|
+
readonly state: string;
|
|
4
|
+
}
|
|
5
|
+
export interface CallbackServer {
|
|
6
|
+
readonly port: number;
|
|
7
|
+
readonly result: Promise<CallbackResult>;
|
|
8
|
+
readonly close: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Start a local HTTP server on a random port to receive the OAuth callback.
|
|
12
|
+
* Returns after the server is listening and the port is known.
|
|
13
|
+
*/
|
|
14
|
+
export declare function startCallbackServer(options: {
|
|
15
|
+
readonly expectedState: string;
|
|
16
|
+
readonly timeoutMs?: number;
|
|
17
|
+
}): Promise<CallbackServer>;
|
|
18
|
+
//# sourceMappingURL=callback-server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback-server.d.ts","sourceRoot":"","sources":["../src/callback-server.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,QAAQ,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;CAC5B;AAsBD;;;GAGG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE;IACjD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;CAC7B,GAAG,OAAO,CAAC,cAAc,CAAC,CAuE1B"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createServer } from 'node:http';
|
|
2
|
+
import { OAuthError } from './oauth.js';
|
|
3
|
+
const SUCCESS_HTML = `<!DOCTYPE html>
|
|
4
|
+
<html><head><title>Jinko CLI</title><style>
|
|
5
|
+
body { font-family: -apple-system, system-ui, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #f8f9fa; }
|
|
6
|
+
.card { text-align: center; padding: 2rem 3rem; background: white; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
|
7
|
+
h1 { color: #1a1a1a; margin-bottom: 0.5rem; }
|
|
8
|
+
p { color: #666; }
|
|
9
|
+
</style></head><body>
|
|
10
|
+
<div class="card"><h1>Authenticated</h1><p>You can close this tab and return to the terminal.</p></div>
|
|
11
|
+
</body></html>`;
|
|
12
|
+
const ERROR_HTML = `<!DOCTYPE html>
|
|
13
|
+
<html><head><title>Jinko CLI — Error</title><style>
|
|
14
|
+
body { font-family: -apple-system, system-ui, sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; background: #f8f9fa; }
|
|
15
|
+
.card { text-align: center; padding: 2rem 3rem; background: white; border-radius: 12px; box-shadow: 0 2px 8px rgba(0,0,0,0.1); }
|
|
16
|
+
h1 { color: #c0392b; margin-bottom: 0.5rem; }
|
|
17
|
+
p { color: #666; }
|
|
18
|
+
</style></head><body>
|
|
19
|
+
<div class="card"><h1>Authentication Failed</h1><p>Please try again from the terminal.</p></div>
|
|
20
|
+
</body></html>`;
|
|
21
|
+
/**
|
|
22
|
+
* Start a local HTTP server on a random port to receive the OAuth callback.
|
|
23
|
+
* Returns after the server is listening and the port is known.
|
|
24
|
+
*/
|
|
25
|
+
export async function startCallbackServer(options) {
|
|
26
|
+
const { expectedState, timeoutMs = 120_000 } = options;
|
|
27
|
+
const server = createServer();
|
|
28
|
+
let timeoutHandle;
|
|
29
|
+
const result = new Promise((resolve, reject) => {
|
|
30
|
+
server.on('request', (req, res) => {
|
|
31
|
+
const url = new URL(req.url ?? '/', `http://localhost`);
|
|
32
|
+
if (url.pathname !== '/callback') {
|
|
33
|
+
res.writeHead(404);
|
|
34
|
+
res.end('Not found');
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
const code = url.searchParams.get('code');
|
|
38
|
+
const state = url.searchParams.get('state');
|
|
39
|
+
const error = url.searchParams.get('error');
|
|
40
|
+
if (error) {
|
|
41
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
42
|
+
res.end(ERROR_HTML);
|
|
43
|
+
reject(new OAuthError(`OAuth error: ${error}`));
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
if (!code || !state) {
|
|
47
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
48
|
+
res.end(ERROR_HTML);
|
|
49
|
+
reject(new OAuthError('Missing code or state in callback'));
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
if (state !== expectedState) {
|
|
53
|
+
res.writeHead(400, { 'Content-Type': 'text/html' });
|
|
54
|
+
res.end(ERROR_HTML);
|
|
55
|
+
reject(new OAuthError('State mismatch — possible CSRF attack'));
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
res.writeHead(200, { 'Content-Type': 'text/html' });
|
|
59
|
+
res.end(SUCCESS_HTML);
|
|
60
|
+
resolve({ code, state });
|
|
61
|
+
});
|
|
62
|
+
timeoutHandle = setTimeout(() => {
|
|
63
|
+
reject(new OAuthError(`OAuth callback timed out after ${timeoutMs / 1000}s`));
|
|
64
|
+
server.close();
|
|
65
|
+
}, timeoutMs);
|
|
66
|
+
}).finally(() => {
|
|
67
|
+
clearTimeout(timeoutHandle);
|
|
68
|
+
server.close();
|
|
69
|
+
});
|
|
70
|
+
// Wait for server to start listening so port is assigned
|
|
71
|
+
await new Promise((resolve) => {
|
|
72
|
+
server.listen(0, () => resolve());
|
|
73
|
+
});
|
|
74
|
+
const address = server.address();
|
|
75
|
+
const port = typeof address === 'object' && address ? address.port : 0;
|
|
76
|
+
return {
|
|
77
|
+
port,
|
|
78
|
+
result,
|
|
79
|
+
close: () => {
|
|
80
|
+
clearTimeout(timeoutHandle);
|
|
81
|
+
server.close();
|
|
82
|
+
},
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=callback-server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"callback-server.js","sourceRoot":"","sources":["../src/callback-server.ts"],"names":[],"mappings":"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"}
|
package/dist/client.d.ts
CHANGED
|
@@ -14,6 +14,7 @@ export interface JinkoClient extends JinkoTools {
|
|
|
14
14
|
* Create a configured openapi-fetch client for the Jinko BFF.
|
|
15
15
|
*
|
|
16
16
|
* Auth: pass an API key (jnk_...) via options, JINKO_API_KEY env, or ~/.jinko/config.yaml.
|
|
17
|
+
* OAuth tokens are auto-refreshed before each request when expired.
|
|
17
18
|
*/
|
|
18
19
|
export declare function createJinkoClient(options?: ClientOptions): Promise<JinkoClient>;
|
|
19
20
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,YAAiC,MAAM,eAAe,CAAC;AAC9D,OAAO,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,YAAiC,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAgD,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AAG5F,OAAO,EAAe,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC1D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAC;AAElD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,MAAM,cAAc,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC;AAEpE,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC7C,QAAQ,CAAC,GAAG,EAAE,cAAc,CAAC;IAC7B,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;CAC7B;AAQD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CAAC,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,WAAW,CAAC,CAkGzF"}
|
package/dist/client.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import createClient from 'openapi-fetch';
|
|
2
|
-
import { resolveAuth, resolveBaseUrl } from './auth.js';
|
|
2
|
+
import { resolveAuth, resolveBaseUrl, writeConfigFile } from './auth.js';
|
|
3
|
+
import { isTokenExpired, refreshAccessToken } from './oauth.js';
|
|
3
4
|
import { ApiError, AuthError } from './errors.js';
|
|
4
5
|
import { createTools } from './tools.js';
|
|
5
6
|
/**
|
|
6
7
|
* Create a configured openapi-fetch client for the Jinko BFF.
|
|
7
8
|
*
|
|
8
9
|
* Auth: pass an API key (jnk_...) via options, JINKO_API_KEY env, or ~/.jinko/config.yaml.
|
|
10
|
+
* OAuth tokens are auto-refreshed before each request when expired.
|
|
9
11
|
*/
|
|
10
12
|
export async function createJinkoClient(options = {}) {
|
|
11
13
|
const auth = await resolveAuth(options.apiKey);
|
|
@@ -14,7 +16,14 @@ export async function createJinkoClient(options = {}) {
|
|
|
14
16
|
}
|
|
15
17
|
const baseUrl = resolveBaseUrl();
|
|
16
18
|
const client = createClient({ baseUrl });
|
|
17
|
-
//
|
|
19
|
+
// Mutable token state for OAuth refresh — only used when method is oauth
|
|
20
|
+
let tokenState;
|
|
21
|
+
if (auth.method === 'oauth') {
|
|
22
|
+
// We don't have refresh_token/expires_at here from resolveAuth,
|
|
23
|
+
// but the token was already refreshed if needed during resolveAuth.
|
|
24
|
+
// For in-flight refresh during long-running sessions, we read config.
|
|
25
|
+
tokenState = undefined; // Will lazy-init on first refresh check
|
|
26
|
+
}
|
|
18
27
|
const authMiddleware = {
|
|
19
28
|
async onRequest({ request }) {
|
|
20
29
|
const headers = new Headers(request.headers);
|
|
@@ -25,7 +34,31 @@ export async function createJinkoClient(options = {}) {
|
|
|
25
34
|
headers.set('X-API-Key', auth.token);
|
|
26
35
|
}
|
|
27
36
|
else {
|
|
28
|
-
|
|
37
|
+
// OAuth — check if we need to refresh
|
|
38
|
+
let currentToken = auth.token;
|
|
39
|
+
if (tokenState && isTokenExpired({ access_token: tokenState.accessToken, refresh_token: tokenState.refreshToken, expires_at: tokenState.expiresAt })) {
|
|
40
|
+
try {
|
|
41
|
+
const refreshed = await refreshAccessToken(tokenState.refreshToken);
|
|
42
|
+
tokenState = {
|
|
43
|
+
accessToken: refreshed.access_token,
|
|
44
|
+
refreshToken: refreshed.refresh_token,
|
|
45
|
+
expiresAt: refreshed.expires_at,
|
|
46
|
+
};
|
|
47
|
+
currentToken = refreshed.access_token;
|
|
48
|
+
// Persist silently
|
|
49
|
+
await writeConfigFile({
|
|
50
|
+
oauth: {
|
|
51
|
+
access_token: refreshed.access_token,
|
|
52
|
+
refresh_token: refreshed.refresh_token,
|
|
53
|
+
expires_at: refreshed.expires_at,
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
// Proceed with current token
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
headers.set('Authorization', `Bearer ${currentToken}`);
|
|
29
62
|
}
|
|
30
63
|
return new Request(request.url, {
|
|
31
64
|
method: request.method,
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,YAAiC,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,cAAc,EAAqB,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { createJinkoClient, type ClientOptions, type JinkoClient, type JinkoRawClient } from './client.js';
|
|
2
2
|
export { type JinkoTools } from './tools.js';
|
|
3
|
-
export { resolveAuth, readConfigFile, writeConfigFile, CONFIG_DIR, CONFIG_FILE, type AuthMethod, type ResolvedAuth } from './auth.js';
|
|
3
|
+
export { resolveAuth, readConfigFile, writeConfigFile, clearAuthConfig, CONFIG_DIR, CONFIG_FILE, type AuthMethod, type ResolvedAuth, type OAuthConfig } from './auth.js';
|
|
4
4
|
export { ApiError, AuthError, ValidationError, type ApiErrorDetail } from './errors.js';
|
|
5
|
+
export { requestDeviceAuthorization, pollForToken, refreshAccessToken, isTokenExpired, OAuthError, OAuthRefreshError, type OAuthTokens, type DeviceAuthorization, } from './oauth.js';
|
|
5
6
|
export type { paths, components } from './types/generated.js';
|
|
6
7
|
export type { FlightPassengers, ShopPassengers, FlightSearchFilters, FlightPriceConstraints, DateRange, FlightFindRequest, FlightDestinationSearchRequest, FlightSearchRequest, FlightSearchLiveRequest, FlightSearchPriceCheckRequest, Traveler, Contact, TripUpsertTravelers, TripRequest, CheckoutRequest, BookRequest, } from './types/devplatform.js';
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3G,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,aAAa,EAAE,KAAK,WAAW,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC3G,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,UAAU,EAAE,KAAK,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,WAAW,CAAC;AACzK,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AACxF,OAAO,EACL,0BAA0B,EAC1B,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,iBAAiB,EACjB,KAAK,WAAW,EAChB,KAAK,mBAAmB,GACzB,MAAM,YAAY,CAAC;AACpB,YAAY,EAAE,KAAK,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC9D,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,mBAAmB,EACnB,sBAAsB,EACtB,SAAS,EACT,iBAAiB,EACjB,8BAA8B,EAC9B,mBAAmB,EACnB,uBAAuB,EACvB,6BAA6B,EAC7B,QAAQ,EACR,OAAO,EACP,mBAAmB,EACnB,WAAW,EACX,eAAe,EACf,WAAW,GACZ,MAAM,wBAAwB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { createJinkoClient } from './client.js';
|
|
2
|
-
export { resolveAuth, readConfigFile, writeConfigFile, CONFIG_DIR, CONFIG_FILE } from './auth.js';
|
|
2
|
+
export { resolveAuth, readConfigFile, writeConfigFile, clearAuthConfig, CONFIG_DIR, CONFIG_FILE } from './auth.js';
|
|
3
3
|
export { ApiError, AuthError, ValidationError } from './errors.js';
|
|
4
|
+
export { requestDeviceAuthorization, pollForToken, refreshAccessToken, isTokenExpired, OAuthError, OAuthRefreshError, } from './oauth.js';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA6D,MAAM,aAAa,CAAC;AAE3G,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA6D,MAAM,aAAa,CAAC;AAE3G,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,UAAU,EAAE,WAAW,EAAwD,MAAM,WAAW,CAAC;AACzK,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,eAAe,EAAuB,MAAM,aAAa,CAAC;AACxF,OAAO,EACL,0BAA0B,EAC1B,YAAY,EACZ,kBAAkB,EAClB,cAAc,EACd,UAAU,EACV,iBAAiB,GAGlB,MAAM,YAAY,CAAC"}
|
package/dist/oauth.d.ts
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
export interface OAuthTokens {
|
|
2
|
+
readonly access_token: string;
|
|
3
|
+
readonly refresh_token: string;
|
|
4
|
+
readonly expires_at: number;
|
|
5
|
+
}
|
|
6
|
+
export interface DeviceAuthorization {
|
|
7
|
+
readonly device_code: string;
|
|
8
|
+
readonly user_code: string;
|
|
9
|
+
readonly verification_uri: string;
|
|
10
|
+
readonly verification_uri_complete: string;
|
|
11
|
+
readonly expires_in: number;
|
|
12
|
+
readonly interval: number;
|
|
13
|
+
}
|
|
14
|
+
export declare class OAuthError extends Error {
|
|
15
|
+
constructor(message: string);
|
|
16
|
+
}
|
|
17
|
+
export declare class OAuthRefreshError extends OAuthError {
|
|
18
|
+
constructor(message?: string);
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Request device authorization — returns a user code and verification URL.
|
|
22
|
+
*/
|
|
23
|
+
export declare function requestDeviceAuthorization(): Promise<DeviceAuthorization>;
|
|
24
|
+
/**
|
|
25
|
+
* Poll the token endpoint until the user approves or the code expires.
|
|
26
|
+
* Calls onPoll() before each attempt (for progress indicators).
|
|
27
|
+
*/
|
|
28
|
+
export declare function pollForToken(deviceCode: string, options: {
|
|
29
|
+
readonly intervalSeconds: number;
|
|
30
|
+
readonly expiresIn: number;
|
|
31
|
+
readonly onPoll?: () => void;
|
|
32
|
+
}): Promise<OAuthTokens>;
|
|
33
|
+
/**
|
|
34
|
+
* Refresh an expired access token.
|
|
35
|
+
*/
|
|
36
|
+
export declare function refreshAccessToken(refreshToken: string): Promise<OAuthTokens>;
|
|
37
|
+
/**
|
|
38
|
+
* Check if tokens are expired (with buffer).
|
|
39
|
+
*/
|
|
40
|
+
export declare function isTokenExpired(tokens: OAuthTokens, bufferSeconds?: number): boolean;
|
|
41
|
+
//# sourceMappingURL=oauth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.d.ts","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,yBAAyB,EAAE,MAAM,CAAC;IAC3C,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAED,qBAAa,UAAW,SAAQ,KAAK;gBACvB,OAAO,EAAE,MAAM;CAI5B;AAED,qBAAa,iBAAkB,SAAQ,UAAU;gBACnC,OAAO,SAAwE;CAI5F;AAED;;GAEG;AACH,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,mBAAmB,CAAC,CAa/E;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE;IACP,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;CAC9B,GACA,OAAO,CAAC,WAAW,CAAC,CAqDtB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA0BnF;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,EAAE,aAAa,SAAK,GAAG,OAAO,CAE/E"}
|
package/dist/oauth.js
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// WorkOS AuthKit Device Authorization Flow (RFC 8628)
|
|
2
|
+
const DEVICE_AUTHORIZE_URL = 'https://api.workos.com/user_management/authorize/device';
|
|
3
|
+
const AUTHENTICATE_URL = 'https://api.workos.com/user_management/authenticate';
|
|
4
|
+
const TOKEN_URL = 'https://api.workos.com/user_management/authenticate';
|
|
5
|
+
const CLIENT_ID = 'client_01K6AG6ZM86FN92TGSW0VTZHVJ';
|
|
6
|
+
export class OAuthError extends Error {
|
|
7
|
+
constructor(message) {
|
|
8
|
+
super(message);
|
|
9
|
+
this.name = 'OAuthError';
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export class OAuthRefreshError extends OAuthError {
|
|
13
|
+
constructor(message = 'Failed to refresh OAuth token. Please run `jinko auth login` again.') {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = 'OAuthRefreshError';
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Request device authorization — returns a user code and verification URL.
|
|
20
|
+
*/
|
|
21
|
+
export async function requestDeviceAuthorization() {
|
|
22
|
+
const response = await fetch(DEVICE_AUTHORIZE_URL, {
|
|
23
|
+
method: 'POST',
|
|
24
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
25
|
+
body: new URLSearchParams({ client_id: CLIENT_ID }),
|
|
26
|
+
});
|
|
27
|
+
if (!response.ok) {
|
|
28
|
+
const body = await response.text();
|
|
29
|
+
throw new OAuthError(`Device authorization request failed (${response.status}): ${body}`);
|
|
30
|
+
}
|
|
31
|
+
return await response.json();
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Poll the token endpoint until the user approves or the code expires.
|
|
35
|
+
* Calls onPoll() before each attempt (for progress indicators).
|
|
36
|
+
*/
|
|
37
|
+
export async function pollForToken(deviceCode, options) {
|
|
38
|
+
const { intervalSeconds, expiresIn, onPoll } = options;
|
|
39
|
+
const deadline = Date.now() + expiresIn * 1000;
|
|
40
|
+
let interval = intervalSeconds;
|
|
41
|
+
while (Date.now() < deadline) {
|
|
42
|
+
onPoll?.();
|
|
43
|
+
await sleep(interval * 1000);
|
|
44
|
+
const response = await fetch(AUTHENTICATE_URL, {
|
|
45
|
+
method: 'POST',
|
|
46
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
47
|
+
body: new URLSearchParams({
|
|
48
|
+
grant_type: 'urn:ietf:params:oauth:grant-type:device_code',
|
|
49
|
+
device_code: deviceCode,
|
|
50
|
+
client_id: CLIENT_ID,
|
|
51
|
+
}),
|
|
52
|
+
});
|
|
53
|
+
if (response.ok) {
|
|
54
|
+
const data = await response.json();
|
|
55
|
+
return {
|
|
56
|
+
access_token: data.access_token,
|
|
57
|
+
refresh_token: data.refresh_token,
|
|
58
|
+
expires_at: Date.now() + data.expires_in * 1000,
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
const error = await response.json();
|
|
62
|
+
if (error.error === 'authorization_pending') {
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
if (error.error === 'slow_down') {
|
|
66
|
+
interval += 5;
|
|
67
|
+
continue;
|
|
68
|
+
}
|
|
69
|
+
if (error.error === 'access_denied') {
|
|
70
|
+
throw new OAuthError('Authorization was denied by the user.');
|
|
71
|
+
}
|
|
72
|
+
if (error.error === 'expired_token') {
|
|
73
|
+
throw new OAuthError('Device code expired. Please try again.');
|
|
74
|
+
}
|
|
75
|
+
throw new OAuthError(`Unexpected polling error: ${error.error ?? response.statusText}`);
|
|
76
|
+
}
|
|
77
|
+
throw new OAuthError('Device code expired. Please try again.');
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Refresh an expired access token.
|
|
81
|
+
*/
|
|
82
|
+
export async function refreshAccessToken(refreshToken) {
|
|
83
|
+
const response = await fetch(TOKEN_URL, {
|
|
84
|
+
method: 'POST',
|
|
85
|
+
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
|
|
86
|
+
body: new URLSearchParams({
|
|
87
|
+
grant_type: 'refresh_token',
|
|
88
|
+
client_id: CLIENT_ID,
|
|
89
|
+
refresh_token: refreshToken,
|
|
90
|
+
}),
|
|
91
|
+
});
|
|
92
|
+
if (!response.ok) {
|
|
93
|
+
throw new OAuthRefreshError();
|
|
94
|
+
}
|
|
95
|
+
const data = await response.json();
|
|
96
|
+
return {
|
|
97
|
+
access_token: data.access_token,
|
|
98
|
+
refresh_token: data.refresh_token,
|
|
99
|
+
expires_at: Date.now() + data.expires_in * 1000,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Check if tokens are expired (with buffer).
|
|
104
|
+
*/
|
|
105
|
+
export function isTokenExpired(tokens, bufferSeconds = 60) {
|
|
106
|
+
return Date.now() >= tokens.expires_at - bufferSeconds * 1000;
|
|
107
|
+
}
|
|
108
|
+
function sleep(ms) {
|
|
109
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
110
|
+
}
|
|
111
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../src/oauth.ts"],"names":[],"mappings":"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"}
|