oauth-callback 1.2.1 β 1.2.2
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/README.md +23 -38
- package/dist/error.test.d.ts +2 -0
- package/dist/error.test.d.ts.map +1 -0
- package/dist/index.js +205 -84
- package/dist/mcp.js +205 -84
- package/dist/server.d.ts.map +1 -1
- package/package.json +12 -11
- package/src/error.test.ts +204 -0
- package/src/server.ts +6 -1
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
[](https://npmjs.com/package/oauth-callback)
|
|
5
5
|
[](https://github.com/kriasoft/oauth-callback/blob/main/LICENSE)
|
|
6
6
|
[](https://www.typescriptlang.org/)
|
|
7
|
+
[](https://replit.com/@kriasoft/oauth-callback)
|
|
7
8
|
|
|
8
9
|
A lightweight OAuth 2.0 callback handler for Node.js, Deno, and Bun with built-in browser flow and MCP SDK integration. Perfect for CLI tools, desktop applications, and development environments that need to capture OAuth authorization codes.
|
|
9
10
|
|
|
@@ -16,7 +17,7 @@ A lightweight OAuth 2.0 callback handler for Node.js, Deno, and Bun with built-i
|
|
|
16
17
|
- π **Multi-runtime support** - Works with Node.js 18+, Deno, and Bun
|
|
17
18
|
- π **Secure localhost-only server** for OAuth callbacks
|
|
18
19
|
- π€ **MCP SDK integration** - Built-in OAuth provider for Model Context Protocol
|
|
19
|
-
- β‘ **
|
|
20
|
+
- β‘ **Single dependency** - Only requires `open` for browser launching
|
|
20
21
|
- π― **TypeScript support** out of the box
|
|
21
22
|
- π‘οΈ **Comprehensive OAuth error handling** with detailed error classes
|
|
22
23
|
- π **Automatic server cleanup** after callback
|
|
@@ -106,34 +107,6 @@ const result = await getAuthCode({
|
|
|
106
107
|
});
|
|
107
108
|
```
|
|
108
109
|
|
|
109
|
-
### Handling Different OAuth Providers
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
// Google OAuth
|
|
113
|
-
const googleAuth = await getAuthCode(
|
|
114
|
-
"https://accounts.google.com/o/oauth2/v2/auth?" +
|
|
115
|
-
new URLSearchParams({
|
|
116
|
-
client_id: process.env.GOOGLE_CLIENT_ID,
|
|
117
|
-
redirect_uri: "http://localhost:3000/callback",
|
|
118
|
-
response_type: "code",
|
|
119
|
-
scope: "openid email profile",
|
|
120
|
-
access_type: "offline",
|
|
121
|
-
}),
|
|
122
|
-
);
|
|
123
|
-
|
|
124
|
-
// Microsoft OAuth
|
|
125
|
-
const microsoftAuth = await getAuthCode(
|
|
126
|
-
"https://login.microsoftonline.com/common/oauth2/v2.0/authorize?" +
|
|
127
|
-
new URLSearchParams({
|
|
128
|
-
client_id: process.env.MICROSOFT_CLIENT_ID,
|
|
129
|
-
redirect_uri: "http://localhost:3000/callback",
|
|
130
|
-
response_type: "code",
|
|
131
|
-
scope: "user.read",
|
|
132
|
-
response_mode: "query",
|
|
133
|
-
}),
|
|
134
|
-
);
|
|
135
|
-
```
|
|
136
|
-
|
|
137
110
|
### MCP SDK Integration
|
|
138
111
|
|
|
139
112
|
The `browserAuth()` function provides a drop-in OAuth provider for the Model Context Protocol SDK:
|
|
@@ -327,18 +300,30 @@ TokenStore implementation for persistent token storage.
|
|
|
327
300
|
|
|
328
301
|
## How It Works
|
|
329
302
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
303
|
+
```
|
|
304
|
+
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
|
|
305
|
+
β Your App ββββββΆβLocal Server ββββββΆβ Browser ββββββΆβOAuth Server β
|
|
306
|
+
β β β :3000 β β β β β
|
|
307
|
+
β getAuthCode β β βββββββ Callback βββββββ Redirect β
|
|
308
|
+
β βΌ βββββββ Returns β β /callback β β with code β
|
|
309
|
+
β {code} β β auth code β β β β β
|
|
310
|
+
βββββββββββββββ βββββββββββββββ βββββββββββββββ βββββββββββββββ
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
1. **Server Creation** β Spins up a temporary localhost HTTP server
|
|
314
|
+
2. **Browser Launch** β Opens the authorization URL in the default browser
|
|
315
|
+
3. **User Authorization** β User grants permission on the OAuth provider's page
|
|
316
|
+
4. **Callback Capture** β Provider redirects to localhost with the authorization code
|
|
317
|
+
5. **Cleanup** β Server closes automatically, code is returned to your app
|
|
335
318
|
|
|
336
319
|
## Security Considerations
|
|
337
320
|
|
|
338
|
-
-
|
|
339
|
-
-
|
|
340
|
-
- No
|
|
341
|
-
- State parameter
|
|
321
|
+
- **Localhost-only binding** β Server rejects non-local connections
|
|
322
|
+
- **Ephemeral server** β Shuts down immediately after receiving the callback
|
|
323
|
+
- **No credential logging** β Tokens and codes are never written to logs
|
|
324
|
+
- **State parameter support** β Pass and validate state to prevent CSRF attacks
|
|
325
|
+
- **Configurable timeouts** β Server auto-terminates if callback isn't received
|
|
326
|
+
- **PKCE compatible** β Works with authorization servers that require PKCE
|
|
342
327
|
|
|
343
328
|
## Running the Examples
|
|
344
329
|
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.test.d.ts","sourceRoot":"","sources":["../src/error.test.ts"],"names":[],"mappings":""}
|
package/dist/index.js
CHANGED
|
@@ -27,16 +27,15 @@ var __export = (target, all) => {
|
|
|
27
27
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
28
28
|
|
|
29
29
|
// node_modules/open/index.js
|
|
30
|
-
import
|
|
31
|
-
import { Buffer } from "node:buffer";
|
|
30
|
+
import process7 from "node:process";
|
|
32
31
|
import path from "node:path";
|
|
33
32
|
import { fileURLToPath } from "node:url";
|
|
34
|
-
import
|
|
35
|
-
import childProcess from "node:child_process";
|
|
33
|
+
import childProcess3 from "node:child_process";
|
|
36
34
|
import fs5, { constants as fsConstants2 } from "node:fs/promises";
|
|
37
35
|
|
|
38
36
|
// node_modules/wsl-utils/index.js
|
|
39
|
-
import
|
|
37
|
+
import { promisify as promisify2 } from "node:util";
|
|
38
|
+
import childProcess2 from "node:child_process";
|
|
40
39
|
import fs4, { constants as fsConstants } from "node:fs/promises";
|
|
41
40
|
|
|
42
41
|
// node_modules/is-wsl/index.js
|
|
@@ -108,7 +107,54 @@ var isWsl = () => {
|
|
|
108
107
|
};
|
|
109
108
|
var is_wsl_default = process.env.__IS_WSL_TEST__ ? isWsl : isWsl();
|
|
110
109
|
|
|
110
|
+
// node_modules/powershell-utils/index.js
|
|
111
|
+
import process2 from "node:process";
|
|
112
|
+
import { Buffer } from "node:buffer";
|
|
113
|
+
import { promisify } from "node:util";
|
|
114
|
+
import childProcess from "node:child_process";
|
|
115
|
+
var execFile = promisify(childProcess.execFile);
|
|
116
|
+
var powerShellPath = () => `${process2.env.SYSTEMROOT || process2.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
117
|
+
var executePowerShell = async (command, options = {}) => {
|
|
118
|
+
const {
|
|
119
|
+
powerShellPath: psPath,
|
|
120
|
+
...execFileOptions
|
|
121
|
+
} = options;
|
|
122
|
+
const encodedCommand = executePowerShell.encodeCommand(command);
|
|
123
|
+
return execFile(psPath ?? powerShellPath(), [
|
|
124
|
+
...executePowerShell.argumentsPrefix,
|
|
125
|
+
encodedCommand
|
|
126
|
+
], {
|
|
127
|
+
encoding: "utf8",
|
|
128
|
+
...execFileOptions
|
|
129
|
+
});
|
|
130
|
+
};
|
|
131
|
+
executePowerShell.argumentsPrefix = [
|
|
132
|
+
"-NoProfile",
|
|
133
|
+
"-NonInteractive",
|
|
134
|
+
"-ExecutionPolicy",
|
|
135
|
+
"Bypass",
|
|
136
|
+
"-EncodedCommand"
|
|
137
|
+
];
|
|
138
|
+
executePowerShell.encodeCommand = (command) => Buffer.from(command, "utf16le").toString("base64");
|
|
139
|
+
executePowerShell.escapeArgument = (value) => `'${String(value).replaceAll("'", "''")}'`;
|
|
140
|
+
|
|
141
|
+
// node_modules/wsl-utils/utilities.js
|
|
142
|
+
function parseMountPointFromConfig(content) {
|
|
143
|
+
for (const line of content.split(`
|
|
144
|
+
`)) {
|
|
145
|
+
if (/^\s*#/.test(line)) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const match = /^\s*root\s*=\s*(?<mountPoint>"[^"]*"|'[^']*'|[^#]*)/.exec(line);
|
|
149
|
+
if (!match) {
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
return match.groups.mountPoint.trim().replaceAll(/^["']|["']$/g, "");
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
111
156
|
// node_modules/wsl-utils/index.js
|
|
157
|
+
var execFile2 = promisify2(childProcess2.execFile);
|
|
112
158
|
var wslDrivesMountPoint = (() => {
|
|
113
159
|
const defaultMountPoint = "/mnt/";
|
|
114
160
|
let mountPoint;
|
|
@@ -126,11 +172,11 @@ var wslDrivesMountPoint = (() => {
|
|
|
126
172
|
return defaultMountPoint;
|
|
127
173
|
}
|
|
128
174
|
const configContent = await fs4.readFile(configFilePath, { encoding: "utf8" });
|
|
129
|
-
const
|
|
130
|
-
if (
|
|
175
|
+
const parsedMountPoint = parseMountPointFromConfig(configContent);
|
|
176
|
+
if (parsedMountPoint === undefined) {
|
|
131
177
|
return defaultMountPoint;
|
|
132
178
|
}
|
|
133
|
-
mountPoint =
|
|
179
|
+
mountPoint = parsedMountPoint;
|
|
134
180
|
mountPoint = mountPoint.endsWith("/") ? mountPoint : `${mountPoint}/`;
|
|
135
181
|
return mountPoint;
|
|
136
182
|
};
|
|
@@ -139,11 +185,36 @@ var powerShellPathFromWsl = async () => {
|
|
|
139
185
|
const mountPoint = await wslDrivesMountPoint();
|
|
140
186
|
return `${mountPoint}c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`;
|
|
141
187
|
};
|
|
142
|
-
var
|
|
143
|
-
|
|
144
|
-
|
|
188
|
+
var powerShellPath2 = is_wsl_default ? powerShellPathFromWsl : powerShellPath;
|
|
189
|
+
var canAccessPowerShellPromise;
|
|
190
|
+
var canAccessPowerShell = async () => {
|
|
191
|
+
canAccessPowerShellPromise ??= (async () => {
|
|
192
|
+
try {
|
|
193
|
+
const psPath = await powerShellPath2();
|
|
194
|
+
await fs4.access(psPath, fsConstants.X_OK);
|
|
195
|
+
return true;
|
|
196
|
+
} catch {
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
})();
|
|
200
|
+
return canAccessPowerShellPromise;
|
|
201
|
+
};
|
|
202
|
+
var wslDefaultBrowser = async () => {
|
|
203
|
+
const psPath = await powerShellPath2();
|
|
204
|
+
const command = String.raw`(Get-ItemProperty -Path "HKCU:\Software\Microsoft\Windows\Shell\Associations\UrlAssociations\http\UserChoice").ProgId`;
|
|
205
|
+
const { stdout } = await executePowerShell(command, { powerShellPath: psPath });
|
|
206
|
+
return stdout.trim();
|
|
207
|
+
};
|
|
208
|
+
var convertWslPathToWindows = async (path) => {
|
|
209
|
+
if (/^[a-z]+:\/\//i.test(path)) {
|
|
210
|
+
return path;
|
|
211
|
+
}
|
|
212
|
+
try {
|
|
213
|
+
const { stdout } = await execFile2("wslpath", ["-aw", path], { encoding: "utf8" });
|
|
214
|
+
return stdout.trim();
|
|
215
|
+
} catch {
|
|
216
|
+
return path;
|
|
145
217
|
}
|
|
146
|
-
return `${process2.env.SYSTEMROOT || process2.env.windir || String.raw`C:\Windows`}\\System32\\WindowsPowerShell\\v1.0\\powershell.exe`;
|
|
147
218
|
};
|
|
148
219
|
|
|
149
220
|
// node_modules/define-lazy-prop/index.js
|
|
@@ -165,15 +236,15 @@ function defineLazyProperty(object, propertyName, valueGetter) {
|
|
|
165
236
|
}
|
|
166
237
|
|
|
167
238
|
// node_modules/default-browser/index.js
|
|
168
|
-
import { promisify as
|
|
239
|
+
import { promisify as promisify6 } from "node:util";
|
|
169
240
|
import process5 from "node:process";
|
|
170
|
-
import { execFile as
|
|
241
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
171
242
|
|
|
172
243
|
// node_modules/default-browser-id/index.js
|
|
173
|
-
import { promisify } from "node:util";
|
|
244
|
+
import { promisify as promisify3 } from "node:util";
|
|
174
245
|
import process3 from "node:process";
|
|
175
|
-
import { execFile } from "node:child_process";
|
|
176
|
-
var execFileAsync =
|
|
246
|
+
import { execFile as execFile3 } from "node:child_process";
|
|
247
|
+
var execFileAsync = promisify3(execFile3);
|
|
177
248
|
async function defaultBrowserId() {
|
|
178
249
|
if (process3.platform !== "darwin") {
|
|
179
250
|
throw new Error("macOS only");
|
|
@@ -185,9 +256,9 @@ async function defaultBrowserId() {
|
|
|
185
256
|
|
|
186
257
|
// node_modules/run-applescript/index.js
|
|
187
258
|
import process4 from "node:process";
|
|
188
|
-
import { promisify as
|
|
189
|
-
import { execFile as
|
|
190
|
-
var execFileAsync2 =
|
|
259
|
+
import { promisify as promisify4 } from "node:util";
|
|
260
|
+
import { execFile as execFile4, execFileSync } from "node:child_process";
|
|
261
|
+
var execFileAsync2 = promisify4(execFile4);
|
|
191
262
|
async function runAppleScript(script, { humanReadableOutput = true } = {}) {
|
|
192
263
|
if (process4.platform !== "darwin") {
|
|
193
264
|
throw new Error("macOS only");
|
|
@@ -204,20 +275,28 @@ tell application "System Events" to get value of property list item "CFBundleNam
|
|
|
204
275
|
}
|
|
205
276
|
|
|
206
277
|
// node_modules/default-browser/windows.js
|
|
207
|
-
import { promisify as
|
|
208
|
-
import { execFile as
|
|
209
|
-
var execFileAsync3 =
|
|
278
|
+
import { promisify as promisify5 } from "node:util";
|
|
279
|
+
import { execFile as execFile5 } from "node:child_process";
|
|
280
|
+
var execFileAsync3 = promisify5(execFile5);
|
|
210
281
|
var windowsBrowserProgIds = {
|
|
211
|
-
AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
|
|
212
|
-
MSEdgeDHTML: { name: "Edge", id: "com.microsoft.edge" },
|
|
213
282
|
MSEdgeHTM: { name: "Edge", id: "com.microsoft.edge" },
|
|
214
|
-
|
|
215
|
-
|
|
283
|
+
MSEdgeBHTML: { name: "Edge Beta", id: "com.microsoft.edge.beta" },
|
|
284
|
+
MSEdgeDHTML: { name: "Edge Dev", id: "com.microsoft.edge.dev" },
|
|
285
|
+
AppXq0fevzme2pys62n3e0fbqa7peapykr8v: { name: "Edge", id: "com.microsoft.edge.old" },
|
|
216
286
|
ChromeHTML: { name: "Chrome", id: "com.google.chrome" },
|
|
287
|
+
ChromeBHTML: { name: "Chrome Beta", id: "com.google.chrome.beta" },
|
|
288
|
+
ChromeDHTML: { name: "Chrome Dev", id: "com.google.chrome.dev" },
|
|
289
|
+
ChromiumHTM: { name: "Chromium", id: "org.chromium.Chromium" },
|
|
217
290
|
BraveHTML: { name: "Brave", id: "com.brave.Browser" },
|
|
218
291
|
BraveBHTML: { name: "Brave Beta", id: "com.brave.Browser.beta" },
|
|
219
|
-
|
|
292
|
+
BraveDHTML: { name: "Brave Dev", id: "com.brave.Browser.dev" },
|
|
293
|
+
BraveSSHTM: { name: "Brave Nightly", id: "com.brave.Browser.nightly" },
|
|
294
|
+
FirefoxURL: { name: "Firefox", id: "org.mozilla.firefox" },
|
|
295
|
+
OperaStable: { name: "Opera", id: "com.operasoftware.Opera" },
|
|
296
|
+
VivaldiHTM: { name: "Vivaldi", id: "com.vivaldi.Vivaldi" },
|
|
297
|
+
"IE.HTTP": { name: "Internet Explorer", id: "com.microsoft.ie" }
|
|
220
298
|
};
|
|
299
|
+
var _windowsBrowserProgIdMap = new Map(Object.entries(windowsBrowserProgIds));
|
|
221
300
|
|
|
222
301
|
class UnknownBrowserError extends Error {
|
|
223
302
|
}
|
|
@@ -241,7 +320,7 @@ async function defaultBrowser(_execFileAsync = execFileAsync3) {
|
|
|
241
320
|
}
|
|
242
321
|
|
|
243
322
|
// node_modules/default-browser/index.js
|
|
244
|
-
var execFileAsync4 =
|
|
323
|
+
var execFileAsync4 = promisify6(execFile6);
|
|
245
324
|
var titleize = (string) => string.toLowerCase().replaceAll(/(?:^|\s|-)\S/g, (x) => x.toUpperCase());
|
|
246
325
|
async function defaultBrowser2() {
|
|
247
326
|
if (process5.platform === "darwin") {
|
|
@@ -261,42 +340,29 @@ async function defaultBrowser2() {
|
|
|
261
340
|
throw new Error("Only macOS, Linux, and Windows are supported");
|
|
262
341
|
}
|
|
263
342
|
|
|
343
|
+
// node_modules/is-in-ssh/index.js
|
|
344
|
+
import process6 from "node:process";
|
|
345
|
+
var isInSsh = Boolean(process6.env.SSH_CONNECTION || process6.env.SSH_CLIENT || process6.env.SSH_TTY);
|
|
346
|
+
var is_in_ssh_default = isInSsh;
|
|
347
|
+
|
|
264
348
|
// node_modules/open/index.js
|
|
265
|
-
var
|
|
266
|
-
var __dirname2 = path.dirname(fileURLToPath(import.meta.url));
|
|
349
|
+
var fallbackAttemptSymbol = Symbol("fallbackAttempt");
|
|
350
|
+
var __dirname2 = import.meta.url ? path.dirname(fileURLToPath(import.meta.url)) : "";
|
|
267
351
|
var localXdgOpenPath = path.join(__dirname2, "xdg-open");
|
|
268
|
-
var { platform, arch } =
|
|
269
|
-
async
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
const
|
|
274
|
-
|
|
275
|
-
"-NonInteractive",
|
|
276
|
-
"-ExecutionPolicy",
|
|
277
|
-
"Bypass",
|
|
278
|
-
"-EncodedCommand",
|
|
279
|
-
encodedCommand
|
|
280
|
-
], { encoding: "utf8" });
|
|
281
|
-
const progId = stdout.trim();
|
|
282
|
-
const browserMap = {
|
|
283
|
-
ChromeHTML: "com.google.chrome",
|
|
284
|
-
BraveHTML: "com.brave.Browser",
|
|
285
|
-
MSEdgeHTM: "com.microsoft.edge",
|
|
286
|
-
FirefoxURL: "org.mozilla.firefox"
|
|
287
|
-
};
|
|
288
|
-
return browserMap[progId] ? { id: browserMap[progId] } : {};
|
|
289
|
-
}
|
|
290
|
-
var pTryEach = async (array, mapper) => {
|
|
291
|
-
let latestError;
|
|
292
|
-
for (const item of array) {
|
|
352
|
+
var { platform, arch } = process7;
|
|
353
|
+
var tryEachApp = async (apps, opener) => {
|
|
354
|
+
if (apps.length === 0) {
|
|
355
|
+
return;
|
|
356
|
+
}
|
|
357
|
+
const errors = [];
|
|
358
|
+
for (const app of apps) {
|
|
293
359
|
try {
|
|
294
|
-
return await
|
|
360
|
+
return await opener(app);
|
|
295
361
|
} catch (error) {
|
|
296
|
-
|
|
362
|
+
errors.push(error);
|
|
297
363
|
}
|
|
298
364
|
}
|
|
299
|
-
throw
|
|
365
|
+
throw new AggregateError(errors, "Failed to open in all supported apps");
|
|
300
366
|
};
|
|
301
367
|
var baseOpen = async (options) => {
|
|
302
368
|
options = {
|
|
@@ -306,34 +372,39 @@ var baseOpen = async (options) => {
|
|
|
306
372
|
allowNonzeroExitCode: false,
|
|
307
373
|
...options
|
|
308
374
|
};
|
|
375
|
+
const isFallbackAttempt = options[fallbackAttemptSymbol] === true;
|
|
376
|
+
delete options[fallbackAttemptSymbol];
|
|
309
377
|
if (Array.isArray(options.app)) {
|
|
310
|
-
return
|
|
378
|
+
return tryEachApp(options.app, (singleApp) => baseOpen({
|
|
311
379
|
...options,
|
|
312
|
-
app: singleApp
|
|
380
|
+
app: singleApp,
|
|
381
|
+
[fallbackAttemptSymbol]: true
|
|
313
382
|
}));
|
|
314
383
|
}
|
|
315
384
|
let { name: app, arguments: appArguments = [] } = options.app ?? {};
|
|
316
385
|
appArguments = [...appArguments];
|
|
317
386
|
if (Array.isArray(app)) {
|
|
318
|
-
return
|
|
387
|
+
return tryEachApp(app, (appName) => baseOpen({
|
|
319
388
|
...options,
|
|
320
389
|
app: {
|
|
321
390
|
name: appName,
|
|
322
391
|
arguments: appArguments
|
|
323
|
-
}
|
|
392
|
+
},
|
|
393
|
+
[fallbackAttemptSymbol]: true
|
|
324
394
|
}));
|
|
325
395
|
}
|
|
326
396
|
if (app === "browser" || app === "browserPrivate") {
|
|
327
397
|
const ids = {
|
|
328
398
|
"com.google.chrome": "chrome",
|
|
329
399
|
"google-chrome.desktop": "chrome",
|
|
330
|
-
"com.brave.
|
|
400
|
+
"com.brave.browser": "brave",
|
|
331
401
|
"org.mozilla.firefox": "firefox",
|
|
332
402
|
"firefox.desktop": "firefox",
|
|
333
403
|
"com.microsoft.msedge": "edge",
|
|
334
404
|
"com.microsoft.edge": "edge",
|
|
335
405
|
"com.microsoft.edgemac": "edge",
|
|
336
|
-
"microsoft-edge.desktop": "edge"
|
|
406
|
+
"microsoft-edge.desktop": "edge",
|
|
407
|
+
"com.apple.safari": "safari"
|
|
337
408
|
};
|
|
338
409
|
const flags = {
|
|
339
410
|
chrome: "--incognito",
|
|
@@ -341,10 +412,20 @@ var baseOpen = async (options) => {
|
|
|
341
412
|
firefox: "--private-window",
|
|
342
413
|
edge: "--inPrivate"
|
|
343
414
|
};
|
|
344
|
-
|
|
415
|
+
let browser;
|
|
416
|
+
if (is_wsl_default) {
|
|
417
|
+
const progId = await wslDefaultBrowser();
|
|
418
|
+
const browserInfo = _windowsBrowserProgIdMap.get(progId);
|
|
419
|
+
browser = browserInfo ?? {};
|
|
420
|
+
} else {
|
|
421
|
+
browser = await defaultBrowser2();
|
|
422
|
+
}
|
|
345
423
|
if (browser.id in ids) {
|
|
346
|
-
const browserName = ids[browser.id];
|
|
424
|
+
const browserName = ids[browser.id.toLowerCase()];
|
|
347
425
|
if (app === "browserPrivate") {
|
|
426
|
+
if (browserName === "safari") {
|
|
427
|
+
throw new Error("Safari doesn't support opening in private mode via command line");
|
|
428
|
+
}
|
|
348
429
|
appArguments.push(flags[browserName]);
|
|
349
430
|
}
|
|
350
431
|
return baseOpen({
|
|
@@ -360,6 +441,10 @@ var baseOpen = async (options) => {
|
|
|
360
441
|
let command;
|
|
361
442
|
const cliArguments = [];
|
|
362
443
|
const childProcessOptions = {};
|
|
444
|
+
let shouldUseWindowsInWsl = false;
|
|
445
|
+
if (is_wsl_default && !isInsideContainer() && !is_in_ssh_default && !app) {
|
|
446
|
+
shouldUseWindowsInWsl = await canAccessPowerShell();
|
|
447
|
+
}
|
|
363
448
|
if (platform === "darwin") {
|
|
364
449
|
command = "open";
|
|
365
450
|
if (options.wait) {
|
|
@@ -374,29 +459,35 @@ var baseOpen = async (options) => {
|
|
|
374
459
|
if (app) {
|
|
375
460
|
cliArguments.push("-a", app);
|
|
376
461
|
}
|
|
377
|
-
} else if (platform === "win32" ||
|
|
378
|
-
command = await
|
|
379
|
-
cliArguments.push(
|
|
462
|
+
} else if (platform === "win32" || shouldUseWindowsInWsl) {
|
|
463
|
+
command = await powerShellPath2();
|
|
464
|
+
cliArguments.push(...executePowerShell.argumentsPrefix);
|
|
380
465
|
if (!is_wsl_default) {
|
|
381
466
|
childProcessOptions.windowsVerbatimArguments = true;
|
|
382
467
|
}
|
|
383
|
-
|
|
468
|
+
if (is_wsl_default && options.target) {
|
|
469
|
+
options.target = await convertWslPathToWindows(options.target);
|
|
470
|
+
}
|
|
471
|
+
const encodedArguments = ["$ProgressPreference = 'SilentlyContinue';", "Start"];
|
|
384
472
|
if (options.wait) {
|
|
385
473
|
encodedArguments.push("-Wait");
|
|
386
474
|
}
|
|
387
475
|
if (app) {
|
|
388
|
-
encodedArguments.push(
|
|
476
|
+
encodedArguments.push(executePowerShell.escapeArgument(app));
|
|
389
477
|
if (options.target) {
|
|
390
478
|
appArguments.push(options.target);
|
|
391
479
|
}
|
|
392
480
|
} else if (options.target) {
|
|
393
|
-
encodedArguments.push(
|
|
481
|
+
encodedArguments.push(executePowerShell.escapeArgument(options.target));
|
|
394
482
|
}
|
|
395
483
|
if (appArguments.length > 0) {
|
|
396
|
-
appArguments = appArguments.map((argument) =>
|
|
484
|
+
appArguments = appArguments.map((argument) => executePowerShell.escapeArgument(argument));
|
|
397
485
|
encodedArguments.push("-ArgumentList", appArguments.join(","));
|
|
398
486
|
}
|
|
399
|
-
options.target =
|
|
487
|
+
options.target = executePowerShell.encodeCommand(encodedArguments.join(" "));
|
|
488
|
+
if (!options.wait) {
|
|
489
|
+
childProcessOptions.stdio = "ignore";
|
|
490
|
+
}
|
|
400
491
|
} else {
|
|
401
492
|
if (app) {
|
|
402
493
|
command = app;
|
|
@@ -407,7 +498,7 @@ var baseOpen = async (options) => {
|
|
|
407
498
|
await fs5.access(localXdgOpenPath, fsConstants2.X_OK);
|
|
408
499
|
exeLocalXdgOpen = true;
|
|
409
500
|
} catch {}
|
|
410
|
-
const useSystemXdgOpen =
|
|
501
|
+
const useSystemXdgOpen = process7.versions.electron ?? (platform === "android" || isBundled || !exeLocalXdgOpen);
|
|
411
502
|
command = useSystemXdgOpen ? "xdg-open" : localXdgOpenPath;
|
|
412
503
|
}
|
|
413
504
|
if (appArguments.length > 0) {
|
|
@@ -424,12 +515,12 @@ var baseOpen = async (options) => {
|
|
|
424
515
|
if (options.target) {
|
|
425
516
|
cliArguments.push(options.target);
|
|
426
517
|
}
|
|
427
|
-
const subprocess =
|
|
518
|
+
const subprocess = childProcess3.spawn(command, cliArguments, childProcessOptions);
|
|
428
519
|
if (options.wait) {
|
|
429
520
|
return new Promise((resolve, reject) => {
|
|
430
521
|
subprocess.once("error", reject);
|
|
431
522
|
subprocess.once("close", (exitCode) => {
|
|
432
|
-
if (!options.allowNonzeroExitCode && exitCode
|
|
523
|
+
if (!options.allowNonzeroExitCode && exitCode !== 0) {
|
|
433
524
|
reject(new Error(`Exited with code ${exitCode}`));
|
|
434
525
|
return;
|
|
435
526
|
}
|
|
@@ -437,8 +528,30 @@ var baseOpen = async (options) => {
|
|
|
437
528
|
});
|
|
438
529
|
});
|
|
439
530
|
}
|
|
531
|
+
if (isFallbackAttempt) {
|
|
532
|
+
return new Promise((resolve, reject) => {
|
|
533
|
+
subprocess.once("error", reject);
|
|
534
|
+
subprocess.once("spawn", () => {
|
|
535
|
+
subprocess.once("close", (exitCode) => {
|
|
536
|
+
subprocess.off("error", reject);
|
|
537
|
+
if (exitCode !== 0) {
|
|
538
|
+
reject(new Error(`Exited with code ${exitCode}`));
|
|
539
|
+
return;
|
|
540
|
+
}
|
|
541
|
+
subprocess.unref();
|
|
542
|
+
resolve(subprocess);
|
|
543
|
+
});
|
|
544
|
+
});
|
|
545
|
+
});
|
|
546
|
+
}
|
|
440
547
|
subprocess.unref();
|
|
441
|
-
return
|
|
548
|
+
return new Promise((resolve, reject) => {
|
|
549
|
+
subprocess.once("error", reject);
|
|
550
|
+
subprocess.once("spawn", () => {
|
|
551
|
+
subprocess.off("error", reject);
|
|
552
|
+
resolve(subprocess);
|
|
553
|
+
});
|
|
554
|
+
});
|
|
442
555
|
};
|
|
443
556
|
var open = (target, options) => {
|
|
444
557
|
if (typeof target !== "string") {
|
|
@@ -459,7 +572,7 @@ function detectArchBinary(binary) {
|
|
|
459
572
|
}
|
|
460
573
|
return archBinary;
|
|
461
574
|
}
|
|
462
|
-
function detectPlatformBinary({ [platform]: platformBinary }, { wsl }) {
|
|
575
|
+
function detectPlatformBinary({ [platform]: platformBinary }, { wsl } = {}) {
|
|
463
576
|
if (wsl && is_wsl_default) {
|
|
464
577
|
return detectArchBinary(wsl);
|
|
465
578
|
}
|
|
@@ -468,11 +581,14 @@ function detectPlatformBinary({ [platform]: platformBinary }, { wsl }) {
|
|
|
468
581
|
}
|
|
469
582
|
return detectArchBinary(platformBinary);
|
|
470
583
|
}
|
|
471
|
-
var apps = {
|
|
584
|
+
var apps = {
|
|
585
|
+
browser: "browser",
|
|
586
|
+
browserPrivate: "browserPrivate"
|
|
587
|
+
};
|
|
472
588
|
defineLazyProperty(apps, "chrome", () => detectPlatformBinary({
|
|
473
589
|
darwin: "google chrome",
|
|
474
590
|
win32: "chrome",
|
|
475
|
-
linux: ["google-chrome", "google-chrome-stable", "chromium"]
|
|
591
|
+
linux: ["google-chrome", "google-chrome-stable", "chromium", "chromium-browser"]
|
|
476
592
|
}, {
|
|
477
593
|
wsl: {
|
|
478
594
|
ia32: "/mnt/c/Program Files (x86)/Google/Chrome/Application/chrome.exe",
|
|
@@ -503,8 +619,9 @@ defineLazyProperty(apps, "edge", () => detectPlatformBinary({
|
|
|
503
619
|
}, {
|
|
504
620
|
wsl: "/mnt/c/Program Files (x86)/Microsoft/Edge/Application/msedge.exe"
|
|
505
621
|
}));
|
|
506
|
-
defineLazyProperty(apps, "
|
|
507
|
-
|
|
622
|
+
defineLazyProperty(apps, "safari", () => detectPlatformBinary({
|
|
623
|
+
darwin: "Safari"
|
|
624
|
+
}));
|
|
508
625
|
var open_default = open;
|
|
509
626
|
|
|
510
627
|
// src/errors.ts
|
|
@@ -675,6 +792,9 @@ class BunCallbackServer extends BaseCallbackServer {
|
|
|
675
792
|
async stopServer() {
|
|
676
793
|
if (!this.server)
|
|
677
794
|
return;
|
|
795
|
+
while (this.server.pendingRequests > 0) {
|
|
796
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
|
797
|
+
}
|
|
678
798
|
this.server.stop();
|
|
679
799
|
this.server = undefined;
|
|
680
800
|
}
|
|
@@ -725,6 +845,7 @@ class NodeCallbackServer extends BaseCallbackServer {
|
|
|
725
845
|
async stopServer() {
|
|
726
846
|
if (!this.server)
|
|
727
847
|
return;
|
|
848
|
+
this.server.closeAllConnections();
|
|
728
849
|
return new Promise((resolve) => {
|
|
729
850
|
this.server?.close(() => {
|
|
730
851
|
this.server = undefined;
|