Skip to content

Commit f693d33

Browse files
committed
feat(dev): support opening a custom path or url
1 parent b6ee3b9 commit f693d33

3 files changed

Lines changed: 37 additions & 2 deletions

File tree

‎packages/nuxt-cli/src/commands/dev.ts‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ const command = defineCommand({
6565
alias: ['o'],
6666
default: false,
6767
},
68+
'open.url': {
69+
type: 'string',
70+
description: 'Path or URL to open instead of the dev server root',
71+
},
6872
'clipboard': {
6973
type: 'boolean',
7074
description: 'Copy the URL to the clipboard',
@@ -298,7 +302,8 @@ function resolveListenOverrides(args: ParsedArgs<ArgsT>): DevListenOverrides {
298302
||undefined,
299303
strictPort: args.strictPort,
300304
hostname: host===true||host==='' ? '' : host||undefined,
301-
open: args.open,
305+
open: args.open||!!args['open.url'],
306+
openURL: args['open.url']||undefined,
302307
clipboard: args.clipboard,
303308
qr: args.qr,
304309
tunnel: args.tunnel,

‎packages/nuxt-cli/src/dev/listen.ts‎

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ export interface ListenOptions {
2525
baseURL?: string
2626
showURL?: boolean
2727
open?: boolean
28+
/** Path (resolved against the dev server URL) or absolute URL to open. */
29+
openURL?: string
2830
clipboard?: boolean
2931
qr?: boolean
3032
tunnel?: boolean
@@ -202,7 +204,7 @@ export async function listen(handler: RequestListener, options: ListenOptions =
202204
}
203205

204206
if(options.open){
205-
openBrowser(url)
207+
openBrowser(options.openURL ? resolveOpenURL(options.openURL,url) : url)
206208
}
207209

208210
return{
@@ -253,6 +255,16 @@ function centerBlock(block: string): string {
253255
returnlines.map(line=>indent+line).join('\n')
254256
}
255257

258+
functionresolveOpenURL(target: string,baseURL: string): string{
259+
try{
260+
returnnewURL(target,baseURL).href
261+
}
262+
catch{
263+
logger.warn(`Ignoring invalid \`--open.url\` value: ${target}`)
264+
returnbaseURL
265+
}
266+
}
267+
256268
/**
257269
* Resolve the command that opens `url`, honouring the de facto `BROWSER` and
258270
* `BROWSER_ARGS` environment variables (`BROWSER=none` disables opening).

‎packages/nuxt-cli/test/unit/listen.spec.ts‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ import { afterEach, describe, expect, it, vi } from 'vitest'
66

77
import{getNetworkAddresses,listen,resolveOpenCommand}from'../../src/dev/listen'
88

9+
constspawn=vi.hoisted(()=>vi.fn((_command: string,_args: string[])=>({on: ()=>({unref: ()=>{}})})))
10+
11+
vi.mock('node:child_process',()=>({ spawn }))
12+
913
vi.mock('node:os',()=>({
1014
networkInterfaces: vi.fn(()=>({})),
1115
release: ()=>'test',
@@ -91,6 +95,20 @@ describe('listen', () => {
9195
awaitexpect(start({port: first.address.port,strictPort: true})).rejects.toThrow(/alreadyinuse/)
9296
})
9397

98+
it('should open the dev server URL',async()=>{
99+
constlistener=awaitstart({port: 0,open: true})
100+
101+
expect(spawn.mock.lastCall?.[1]).toContain(listener.url)
102+
})
103+
104+
it('should open a path or URL relative to the dev server',async()=>{
105+
constlistener=awaitstart({port: 0,open: true,openURL: '/dashboard'})
106+
expect(spawn.mock.lastCall?.[1]).toContain(`${listener.url}dashboard`)
107+
108+
awaitstart({port: 0,open: true,openURL: 'https://example.com/foo'})
109+
expect(spawn.mock.lastCall?.[1]).toContain('https://example.com/foo')
110+
})
111+
94112
it('should use the requested port with `strictPort`',async()=>{
95113
const{ address }=awaitstart({port: 0})
96114
constport=address.port

0 commit comments

Comments
 (0)