Skip to content

Commit 26ad1a9

Browse files
committed
Merge branch 'main' of https://github.com/decentraland/js-sdk-toolchain into chore/sync-main-to-authserver
2 parents adf872c + 07a0182 commit 26ad1a9

5 files changed

Lines changed: 79 additions & 1 deletion

File tree

packages/@dcl/sdk-commands/src/commands/start/explorer-alpha.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ async function runApp(
7272
const landscapeTerrainEnabled = !!args['--landscape-terrain-enabled']
7373
const openDeeplinkInNewInstance = !!args['-n']
7474
const multiInstance = !!args['--multi-instance']
75+
const assetBundles = !!args['--asset-bundles']
7576
const mcp = !!args['--mcp']
7677
const mcpPort = args['--mcp-port']
7778

@@ -105,6 +106,11 @@ async function runApp(
105106
if (multiInstance) {
106107
params.set('multi-instance', 'true')
107108
}
109+
if (assetBundles) {
110+
// The explorer owns asset-bundle conversion: local-ab makes it spawn its own
111+
// JIT converter against this preview's content server. No sidecar runs here.
112+
params.set('local-ab', 'true')
113+
}
108114
if (mcp) {
109115
params.set('mcp', 'true')
110116
}

packages/@dcl/sdk-commands/src/commands/start/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ export const args = declareArgs({
7070
'--bevy-web': Boolean,
7171
'--web': '--bevy-web',
7272
'--multi-instance': Boolean,
73+
'--asset-bundles': Boolean,
7374
'--no-client': Boolean,
7475
'--mcp': Boolean,
7576
'--mcp-port': Number
@@ -100,6 +101,7 @@ export async function help(options: Options) {
100101
--web, --bevy-web Opens preview using the Bevy Web browser window.
101102
--mobile Show QR code for mobile preview on the same network.
102103
--multi-instance Allow running multiple Explorer instances simultaneously.
104+
--asset-bundles Preview with optimized asset bundles (forwarded as local-ab=true in the deep link; the Desktop Explorer converts the scene's assets itself).
103105
--no-client Suppress every auto-launch (desktop Explorer deeplink, browser open, mobile QR). The file watcher still notifies a desktop Explorer if it connects on its own — useful when an external tool owns the Explorer process.
104106
--mcp Enable the MCP server in the Explorer (forwarded as a deep link parameter).
105107
--mcp-port Port for the MCP server in the Explorer (forwarded as a deep link parameter).

packages/@dcl/sdk-commands/src/logic/get-free-port.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@ function tryListen(port: number): Promise<number> {
99
const server = net.createServer()
1010
server.unref()
1111
server.once('error', reject)
12-
server.listen(port, () => {
12+
// probe the same address the servers bind (HTTP_SERVER_HOST=0.0.0.0): a hostless
13+
// listen binds the IPv6 wildcard, which on macOS coexists with an IPv4 listener
14+
// and reports ports as free that the real server then fails to bind (EADDRINUSE)
15+
server.listen(port, '0.0.0.0', () => {
1316
const address = server.address()
1417
server.close(() => resolve(typeof address === 'object' && address ? address.port : port))
1518
})

test/sdk-commands/commands/start/explorer-alpha.spec.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,48 @@ describe('explorer-alpha', () => {
185185
})
186186
})
187187

188+
describe('assetBundles parameter', () => {
189+
it('should include local-ab parameter when --asset-bundles flag is provided', async () => {
190+
const args: any = {
191+
'--asset-bundles': true
192+
}
193+
194+
await runExplorerAlpha(mockComponents, {
195+
cwd: '/test',
196+
realm: 'test-realm',
197+
baseCoords: { x: 0, y: 0 },
198+
isHub: false,
199+
args
200+
})
201+
202+
expect(mockExec).toHaveBeenCalledWith(
203+
'/test',
204+
'open',
205+
expect.arrayContaining([expect.stringContaining('local-ab=true')]),
206+
{ silent: true }
207+
)
208+
})
209+
210+
it('should not include local-ab parameter when --asset-bundles flag is not provided', async () => {
211+
const args: any = {}
212+
213+
await runExplorerAlpha(mockComponents, {
214+
cwd: '/test',
215+
realm: 'test-realm',
216+
baseCoords: { x: 0, y: 0 },
217+
isHub: false,
218+
args
219+
})
220+
221+
expect(mockExec).toHaveBeenCalledWith(
222+
'/test',
223+
'open',
224+
expect.arrayContaining([expect.not.stringContaining('local-ab')]),
225+
{ silent: true }
226+
)
227+
})
228+
})
229+
188230
describe('mcp parameter', () => {
189231
it('should include mcp parameter when --mcp flag is provided', async () => {
190232
const args: any = {

test/sdk-commands/utils/get-free-port.spec.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,31 @@ describe('utils/get-free-port', () => {
2020
expect(result).toBeLessThan(65536)
2121
})
2222

23+
it('never returns a port that is taken on 0.0.0.0, the address the preview server binds', async () => {
24+
// occupy the base port (8000) with an IPv4-only listener, like a leftover preview server;
25+
// a hostless probe binds the IPv6 wildcard and, on macOS, misses this listener entirely
26+
const blocker = net.createServer()
27+
blocker.unref()
28+
const blocked = await new Promise<boolean>((resolve) => {
29+
blocker.once('error', () => resolve(false))
30+
blocker.listen(8000, '0.0.0.0', () => resolve(true))
31+
})
32+
try {
33+
const result = await getPort(NaN, 123)
34+
if (blocked) expect(result).not.toBe(8000)
35+
// the returned port must be bindable on 0.0.0.0, exactly like the real server binds it
36+
const server = net.createServer()
37+
server.unref()
38+
await new Promise<void>((resolve, reject) => {
39+
server.once('error', reject)
40+
server.listen(result, '0.0.0.0', () => resolve())
41+
})
42+
await new Promise((resolve) => server.close(resolve))
43+
} finally {
44+
if (blocked) await new Promise((resolve) => blocker.close(resolve))
45+
}
46+
})
47+
2348
it('should return the fail-over port when probing fails', async () => {
2449
jest.spyOn(net, 'createServer').mockImplementation(() => {
2550
throw new Error('probe failed')

0 commit comments

Comments
 (0)