Skip to content

Commit 62a030f

Browse files
committed
feat(dev): surface the stackblitz editor url in the dev url block
1 parent 29558d5 commit 62a030f

3 files changed

Lines changed: 75 additions & 3 deletions

File tree

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

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import { debug, logger } from '../utils/logger'
1616
import{resolveCertificate}from'./cert'
1717
import{detectIsolatedEnvironment,isWsl}from'./environment'
1818
import{resolvePortlessURLs}from'./portless'
19+
import{resolveStackblitzURL}from'./stackblitz'
1920
import{startTunnel}from'./tunnel'
2021

2122
exportinterfaceListenOptions{
@@ -164,6 +165,7 @@ export async function listen(handler: RequestListener, options: ListenOptions =
164165
constportless=resolvePortlessURLs()
165166
constportlessURL=portless.url&&portless.url+baseURL
166167
constportlessShareURL=portless.shareURL&&portless.shareURL+baseURL
168+
conststackblitzURL=resolveStackblitzURL()
167169

168170
functiongetURLs(): ListenURL[]{
169171
consturls: ListenURL[]=[]
@@ -173,6 +175,9 @@ export async function listen(handler: RequestListener, options: ListenOptions =
173175
for(constportlessURLofportless.all){
174176
urls.push({url: portlessURL+baseURL,type: 'public'})
175177
}
178+
if(stackblitzURL){
179+
urls.push({url: stackblitzURL,type: 'public'})
180+
}
176181
if(anyHost){
177182
urls.push({url: formatURL('localhost'),type: 'local'})
178183
for(constaddressofgetNetworkAddresses()){
@@ -185,11 +190,14 @@ export async function listen(handler: RequestListener, options: ListenOptions =
185190
returnurls
186191
}
187192

188-
constpublicURL=options.publicURL||tunnel?.url||portlessShareURL||portlessURL
193+
// The StackBlitz URL points at the editor rather than at a host another
194+
// device can open, so it is not a QR code candidate.
195+
constshareableURL=options.publicURL||tunnel?.url||portlessShareURL||portlessURL
196+
constpublicURL=shareableURL||stackblitzURL
189197

190198
constqrURL=options.qr===false
191199
? undefined
192-
: publicURL
200+
: shareableURL
193201
||getURLs().find(({ type })=>type==='network')?.url
194202
||(options.qr ? url : undefined)
195203

@@ -203,7 +211,7 @@ export async function listen(handler: RequestListener, options: ListenOptions =
203211
for(const{url: displayURL, type }ofurls){
204212
lines.push(line(labelColors[type],labels[type],colors.cyan(displayURL),qr&&displayURL===qrURL))
205213
}
206-
if(!anyHost&&!tunnel&&!portless.url){
214+
if(!anyHost&&!tunnel&&!portless.url&&!stackblitzURL){
207215
constisolated=LOOPBACK_HOSTS.has(hostname) ? detectIsolatedEnvironment() : undefined
208216
consthint=isolated
209217
? `use ${colors.white('--host')} to reach this server from outside ${isolated}`
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
importprocessfrom'node:process'
2+
3+
import{providerascurrentProvider}from'std-env'
4+
5+
/**
6+
* Resolve the reachable editor URL for a dev server running inside StackBlitz
7+
* or Codeflow, where the app is served through the editor rather than on a
8+
* port the user can open locally.
9+
*
10+
* The project is identified by the working directory: `/home/projects/<id>`
11+
* in the editor, `/home/<org>/<repo>` in Codeflow. `PWD` is used rather than
12+
* `process.cwd()` because the latter is resolved through symlinks.
13+
*/
14+
exportfunctionresolveStackblitzURL(
15+
env: NodeJS.ProcessEnv=process.env,
16+
provider: string|undefined=currentProvider,
17+
): string|undefined{
18+
if(provider!=='stackblitz'){
19+
returnundefined
20+
}
21+
22+
constcwd=env.PWD
23+
if(!cwd){
24+
returnundefined
25+
}
26+
27+
if(cwd.startsWith('/home/projects/')){
28+
constprojectId=cwd.split('/')[3]
29+
returnprojectId ? `https://stackblitz.com/edit/${projectId}` : undefined
30+
}
31+
32+
if(cwd.startsWith('/home/')){
33+
const[owner,repository]=cwd.split('/').slice(2)
34+
returnowner&&repository ? `https://stackblitz.com/edit/~/github.com/${owner}/${repository}` : undefined
35+
}
36+
37+
returnundefined
38+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import{describe,expect,it}from'vitest'
2+
3+
import{resolveStackblitzURL}from'../../src/dev/stackblitz'
4+
5+
describe('resolveStackblitzURL',()=>{
6+
it('should return nothing outside stackblitz',()=>{
7+
expect(resolveStackblitzURL({PWD: '/home/projects/abc123'},undefined)).toBeUndefined()
8+
expect(resolveStackblitzURL({PWD: '/home/projects/abc123'},'codesandbox')).toBeUndefined()
9+
})
10+
11+
it('should derive the editor url from the project directory',()=>{
12+
expect(resolveStackblitzURL({PWD: '/home/projects/abc123'},'stackblitz')).toBe('https://stackblitz.com/edit/abc123')
13+
expect(resolveStackblitzURL({PWD: '/home/projects/abc123/playground'},'stackblitz')).toBe('https://stackblitz.com/edit/abc123')
14+
})
15+
16+
it('should derive the codeflow url from the repository directory',()=>{
17+
expect(resolveStackblitzURL({PWD: '/home/nuxt/cli'},'stackblitz')).toBe('https://stackblitz.com/edit/~/github.com/nuxt/cli')
18+
expect(resolveStackblitzURL({PWD: '/home/nuxt/cli/packages/nuxt-cli'},'stackblitz')).toBe('https://stackblitz.com/edit/~/github.com/nuxt/cli')
19+
})
20+
21+
it('should return nothing for an unrecognised directory',()=>{
22+
expect(resolveStackblitzURL({PWD: '/home/daniel'},'stackblitz')).toBeUndefined()
23+
expect(resolveStackblitzURL({PWD: '/workspace/app'},'stackblitz')).toBeUndefined()
24+
expect(resolveStackblitzURL({},'stackblitz')).toBeUndefined()
25+
})
26+
})

0 commit comments

Comments
 (0)