ts / dist / esm / auth.js
399 words
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import { isApiError } from './errors.js';
import * as http from './http.js';
/** POST /auth/device/start — Start a device login. Anonymous allowed. */
export const deviceStart = (client) => http.post(client, '/auth/device/start');
/** POST /auth/device/poll — Poll a device login. Anonymous allowed. */
export const devicePoll = (client, deviceCode) => http.post(client, '/auth/device/poll', { body: { device_code: deviceCode } });
/** POST /auth/device/complete — Complete a device login. Anonymous allowed. */
export const deviceComplete = (client, deviceCode, confirmationCode) => http.post(client, '/auth/device/complete', {
    body: { device_code: deviceCode, confirmation_code: confirmationCode },
});
/** GET /auth/api-keys — List API keys (account JWT only). */
export const listApiKeys = (client) => http.get(client, '/auth/api-keys');
/** POST /auth/api-keys — Create an API key (account JWT only). */
export const createApiKey = (client, body) => http.post(client, '/auth/api-keys', { body });
/** POST /auth/api-keys/{id}/revoke — Revoke an API key (account JWT only). */
export const revokeApiKey = (client, id) => http.post(client, '/auth/api-keys/{id}/revoke', { params: { id } });
const defaultPrompt = (start) => {
    console.log(`To sign in, open: ${start.verification_uri_complete ?? start.verification_uri}`);
    console.log(`Code: ${start.user_code}`);
};
const defaultConfirm = async () => {
    const { createInterface } = await import('node:readline/promises');
    const rl = createInterface({ input: process.stdin, output: process.stdout });
    try {
        return (await rl.question('Enter the confirmation code shown after approving: ')).trim();
    }
    finally {
        rl.close();
    }
};
/**
 * Run the whole device login flow: start, prompt, poll until approved,
 * complete. Returns the completion body; feed its `access_token` to
 * `createClient` as `apiKey`. Throws a timeout error when the login is not
 * approved in time.
 */
export const deviceLogin = async (client, options = {}) => {
    const start = await deviceStart(client);
    const { onPrompt = defaultPrompt, confirm = defaultConfirm } = options;
    const intervalMs = options.intervalMs ?? 1000 * (start.interval ?? 5);
    const timeoutMs = options.timeoutMs ?? 1000 * (start.expires_in ?? 600);
    // While the user hasn't approved, the API answers 400 authorization-pending;
    // 429 slow-down asks for a longer interval (pollUntil's backoff grows it).
    // Anything else (401 expired, 403 denied) is terminal and rethrown.
    const poll = async () => {
        try {
            return await devicePoll(client, start.device_code);
        }
        catch (e) {
            if (isApiError(e) && (e.status === 400 || e.status === 429))
                return { approved: false };
            throw e;
        }
    };
    await onPrompt(start);
    await http.pollUntil(poll, (r) => r.approved, {
        intervalMs,
        timeoutMs,
        message: 'Device login timed out before approval',
        sleep: client.sleep,
    });
    return deviceComplete(client, start.device_code, await confirm(start));
};

static mirror of HEAD · about · clone: git clone https://ird.cod-sursa.ro/ts.git