@pnpm/network.web-auth 1100.0.0 → 1101.1.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/lib/index.d.ts +2 -2
- package/lib/promptBrowserOpen.d.ts +5 -11
- package/lib/promptBrowserOpen.js +19 -64
- package/lib/withOtpHandling.d.ts +4 -11
- package/lib/withOtpHandling.js +13 -7
- package/package.json +3 -2
package/lib/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { generateQrCode } from './generateQrCode.js';
|
|
2
2
|
export { pollForWebAuthToken, type PollForWebAuthTokenParams, type WebAuthContext, type WebAuthFetchOptions, type WebAuthFetchResponse, type WebAuthFetchResponseHeaders, } from './pollForWebAuthToken.js';
|
|
3
|
-
export { promptBrowserOpen, type PromptBrowserOpenContext, type
|
|
3
|
+
export { promptBrowserOpen, type PromptBrowserOpenContext, type PromptBrowserOpenParams, type PromptBrowserOpenReadlineInterface, } from './promptBrowserOpen.js';
|
|
4
4
|
export { WebAuthTimeoutError } from './WebAuthTimeoutError.js';
|
|
5
|
-
export { isOtpError, type OtpContext, type OtpEnquirer, type OtpHandlingParams, OtpNonInteractiveError, type OtpProcess,
|
|
5
|
+
export { isOtpError, type OtpContext, type OtpEnquirer, type OtpHandlingParams, OtpNonInteractiveError, type OtpProcess, OtpSecondChallengeError, SyntheticOtpError, withOtpHandling, } from './withOtpHandling.js';
|
|
@@ -2,21 +2,15 @@ export interface PromptBrowserOpenReadlineInterface {
|
|
|
2
2
|
once: (event: string, listener: () => void) => void;
|
|
3
3
|
close: () => void;
|
|
4
4
|
}
|
|
5
|
-
export interface PromptBrowserOpenExecFile {
|
|
6
|
-
(file: string, args: readonly string[], callback: (error: Error | null) => void): unknown;
|
|
7
|
-
}
|
|
8
|
-
export interface PromptBrowserOpenProcess {
|
|
9
|
-
platform?: NodeJS.Platform;
|
|
10
|
-
stdin: {
|
|
11
|
-
isTTY?: boolean;
|
|
12
|
-
};
|
|
13
|
-
}
|
|
14
5
|
export interface PromptBrowserOpenContext {
|
|
15
6
|
createReadlineInterface?: () => PromptBrowserOpenReadlineInterface;
|
|
16
|
-
execFile?: PromptBrowserOpenExecFile;
|
|
17
7
|
globalInfo: (message: string) => void;
|
|
18
8
|
globalWarn: (message: string) => void;
|
|
19
|
-
process:
|
|
9
|
+
process: {
|
|
10
|
+
stdin: {
|
|
11
|
+
isTTY?: boolean;
|
|
12
|
+
};
|
|
13
|
+
};
|
|
20
14
|
}
|
|
21
15
|
export interface PromptBrowserOpenParams {
|
|
22
16
|
authUrl: string;
|
package/lib/promptBrowserOpen.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import open from 'open';
|
|
1
2
|
/**
|
|
2
3
|
* Wraps a token-polling promise with an optional "Press ENTER to open in
|
|
3
4
|
* browser" prompt.
|
|
@@ -11,65 +12,23 @@
|
|
|
11
12
|
* logged as warnings and do not interrupt the poll.
|
|
12
13
|
*/
|
|
13
14
|
export async function promptBrowserOpen({ authUrl, context, pollPromise, }) {
|
|
14
|
-
const { createReadlineInterface,
|
|
15
|
-
if (!createReadlineInterface || !
|
|
15
|
+
const { createReadlineInterface, globalInfo, globalWarn, process } = context;
|
|
16
|
+
if (!createReadlineInterface || !process.stdin.isTTY) {
|
|
16
17
|
return pollPromise;
|
|
17
18
|
}
|
|
18
|
-
//
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
let parsedUrl;
|
|
19
|
+
// The authUrl comes from an untrusted registry response, so only allow
|
|
20
|
+
// http(s) URLs through to `open()`.
|
|
21
|
+
let canonicalUrl;
|
|
22
22
|
try {
|
|
23
|
-
|
|
23
|
+
const parsed = new URL(authUrl);
|
|
24
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
25
|
+
return pollPromise;
|
|
26
|
+
}
|
|
27
|
+
canonicalUrl = parsed.href;
|
|
24
28
|
}
|
|
25
29
|
catch {
|
|
26
30
|
return pollPromise;
|
|
27
31
|
}
|
|
28
|
-
if (parsedUrl.protocol !== 'https:' && parsedUrl.protocol !== 'http:') {
|
|
29
|
-
return pollPromise;
|
|
30
|
-
}
|
|
31
|
-
const canonicalUrl = parsedUrl.href;
|
|
32
|
-
let cmd;
|
|
33
|
-
let args;
|
|
34
|
-
switch (process.platform) {
|
|
35
|
-
case 'darwin':
|
|
36
|
-
cmd = 'open';
|
|
37
|
-
args = [canonicalUrl];
|
|
38
|
-
break;
|
|
39
|
-
case 'win32': {
|
|
40
|
-
cmd = 'cmd';
|
|
41
|
-
// Windows edge cases for opening URLs from Node.js:
|
|
42
|
-
//
|
|
43
|
-
// The clean approach would be calling the Win32 ShellExecuteW API
|
|
44
|
-
// directly, which is what native Windows programs use. However,
|
|
45
|
-
// ShellExecuteW is a native API, not an executable — Node.js cannot
|
|
46
|
-
// call it from child_process without a native addon.
|
|
47
|
-
//
|
|
48
|
-
// All process-spawning alternatives have drawbacks:
|
|
49
|
-
// - cmd /c start: cmd.exe re-parses args; special characters in
|
|
50
|
-
// URLs (&, |, ^, %, etc.) are treated as shell
|
|
51
|
-
// operators
|
|
52
|
-
// - explorer.exe: breaks on URLs with query strings (?key=value),
|
|
53
|
-
// opening File Explorer instead of the browser
|
|
54
|
-
// (https://github.com/dotnet/runtime/issues/108817)
|
|
55
|
-
// - url.dll: undocumented, can strip query params on Win 7+
|
|
56
|
-
// - PowerShell: slow startup, own escaping issues
|
|
57
|
-
//
|
|
58
|
-
// Since pnpm already ships native addons, a small Rust/N-API addon
|
|
59
|
-
// calling ShellExecuteW directly could replace this in the future.
|
|
60
|
-
//
|
|
61
|
-
// For now, use cmd /c start with ^ escaping for special characters.
|
|
62
|
-
const escapedUrl = canonicalUrl.replace(/[&|<>^%()!]/g, '^$&');
|
|
63
|
-
args = ['/c', 'start', '', escapedUrl];
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
case 'linux':
|
|
67
|
-
cmd = 'xdg-open';
|
|
68
|
-
args = [canonicalUrl];
|
|
69
|
-
break;
|
|
70
|
-
default:
|
|
71
|
-
return pollPromise;
|
|
72
|
-
}
|
|
73
32
|
let rl;
|
|
74
33
|
try {
|
|
75
34
|
rl = createReadlineInterface();
|
|
@@ -80,10 +39,16 @@ export async function promptBrowserOpen({ authUrl, context, pollPromise, }) {
|
|
|
80
39
|
}
|
|
81
40
|
globalInfo('Press ENTER to open the URL in your browser.');
|
|
82
41
|
rl.once('line', () => {
|
|
83
|
-
|
|
42
|
+
const handleOpenError = (err) => {
|
|
84
43
|
globalWarn(`Could not open browser automatically: ${String(err)}`);
|
|
85
44
|
globalInfo('Please open the URL shown above manually.');
|
|
86
|
-
}
|
|
45
|
+
};
|
|
46
|
+
try {
|
|
47
|
+
open(canonicalUrl).catch(handleOpenError);
|
|
48
|
+
}
|
|
49
|
+
catch (err) {
|
|
50
|
+
handleOpenError(err);
|
|
51
|
+
}
|
|
87
52
|
});
|
|
88
53
|
// Only await pollPromise — do NOT await the Enter keypress.
|
|
89
54
|
//
|
|
@@ -101,14 +66,4 @@ export async function promptBrowserOpen({ authUrl, context, pollPromise, }) {
|
|
|
101
66
|
rl.close();
|
|
102
67
|
}
|
|
103
68
|
}
|
|
104
|
-
function runExecFile(execFile, cmd, args) {
|
|
105
|
-
return new Promise((resolve, reject) => {
|
|
106
|
-
execFile(cmd, args, (err) => {
|
|
107
|
-
if (err)
|
|
108
|
-
reject(err);
|
|
109
|
-
else
|
|
110
|
-
resolve();
|
|
111
|
-
});
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
69
|
//# sourceMappingURL=promptBrowserOpen.js.map
|
package/lib/withOtpHandling.d.ts
CHANGED
|
@@ -1,16 +1,10 @@
|
|
|
1
1
|
import { PnpmError } from '@pnpm/error';
|
|
2
2
|
import type { WebAuthFetchOptions, WebAuthFetchResponse } from './pollForWebAuthToken.js';
|
|
3
|
-
import type {
|
|
3
|
+
import type { PromptBrowserOpenReadlineInterface } from './promptBrowserOpen.js';
|
|
4
4
|
export interface OtpEnquirer {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
message: string;
|
|
9
|
-
name: 'otp';
|
|
10
|
-
type: 'input';
|
|
11
|
-
}
|
|
12
|
-
export interface OtpPromptResponse {
|
|
13
|
-
otp?: string;
|
|
5
|
+
input: (options: {
|
|
6
|
+
message: string;
|
|
7
|
+
}) => Promise<string | undefined>;
|
|
14
8
|
}
|
|
15
9
|
interface OtpDate {
|
|
16
10
|
now: () => number;
|
|
@@ -29,7 +23,6 @@ export interface OtpContext {
|
|
|
29
23
|
setTimeout: (cb: () => void, ms: number) => void;
|
|
30
24
|
createReadlineInterface?: () => PromptBrowserOpenReadlineInterface;
|
|
31
25
|
enquirer: OtpEnquirer;
|
|
32
|
-
execFile?: PromptBrowserOpenExecFile;
|
|
33
26
|
fetch: (url: string, options: WebAuthFetchOptions) => Promise<WebAuthFetchResponse>;
|
|
34
27
|
globalInfo: (message: string) => void;
|
|
35
28
|
globalWarn: (message: string) => void;
|
package/lib/withOtpHandling.js
CHANGED
|
@@ -48,13 +48,19 @@ export async function withOtpHandling({ context, fetchOptions, operation, }) {
|
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
else {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
51
|
+
let otpValue;
|
|
52
|
+
try {
|
|
53
|
+
otpValue = await enquirer.input({
|
|
54
|
+
message: 'This operation requires a one-time password.\nEnter OTP:',
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
if (err instanceof Error && err.name === 'ExitPromptError') {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
throw err;
|
|
62
|
+
}
|
|
63
|
+
otp = otpValue || undefined;
|
|
58
64
|
}
|
|
59
65
|
if (otp != null) {
|
|
60
66
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pnpm/network.web-auth",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1101.1.0",
|
|
4
4
|
"description": "Web-based authentication flow with QR code display and token polling",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pnpm",
|
|
@@ -25,13 +25,14 @@
|
|
|
25
25
|
"!*.map"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"open": "^7.4.2",
|
|
28
29
|
"qrcode-terminal": "^0.12.0",
|
|
29
30
|
"@pnpm/error": "1100.0.0"
|
|
30
31
|
},
|
|
31
32
|
"devDependencies": {
|
|
32
33
|
"@jest/globals": "30.3.0",
|
|
33
34
|
"@types/qrcode-terminal": "^0.12.2",
|
|
34
|
-
"@pnpm/network.web-auth": "
|
|
35
|
+
"@pnpm/network.web-auth": "1101.1.0"
|
|
35
36
|
},
|
|
36
37
|
"engines": {
|
|
37
38
|
"node": ">=22.13"
|