Skip to content

Commit a25d9f5

Browse files
committed
Merge branch 'main' into perf/data-inspector-lazy-jora
2 parents c969ac2 + 1b4b9df commit a25d9f5

43 files changed

Lines changed: 307 additions & 101 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎packages/devframe/package.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@
4848
"./utils/colors": "./dist/utils/colors.mjs",
4949
"./utils/crypto-token": "./dist/utils/crypto-token.mjs",
5050
"./utils/events": "./dist/utils/events.mjs",
51+
"./utils/get-port": "./dist/utils/get-port.mjs",
5152
"./utils/hash": "./dist/utils/hash.mjs",
5253
"./utils/launch-editor": "./dist/utils/launch-editor.mjs",
5354
"./utils/nanoid": "./dist/utils/nanoid.mjs",
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// Re-exported so plugins and other `devframe/*` consumers can resolve a
2+
// free port without taking their own dependency on `get-port-please` — it
3+
// travels as a `devframe` devDependency instead, bundled into this
4+
// package's node build (see `tsdown.config.ts`'s `deps.onlyBundle`).
5+
export { getPort } from 'get-port-please'
6+
export type { GetPortInput, GetPortOptions } from 'get-port-please'

‎packages/devframe/src/utils/remote-assets.test.ts‎

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import type { AddressInfo } from 'node:net'
22
import type { MockInstance } from 'vitest'
33
import type { RemoteAssets, RemoteAssetsErrorMessage, RemoteAssetsStore } from '../types/remote-assets'
4-
import { existsSync, mkdirSync, mkdtempSync, readFileSync, writeFileSync } from 'node:fs'
4+
import { existsSync, mkdirSync, mkdtempSync, readFileSync, realpathSync, writeFileSync } from 'node:fs'
55
import { createServer } from 'node:http'
66
import { tmpdir } from 'node:os'
77
import { join } from 'node:path'
@@ -12,8 +12,11 @@ import { DEVFRAME_REMOTE_ASSETS_ERROR_MESSAGE_TYPE } from '../constants'
1212
import { resolveStaticAssetsSource } from './remote-assets'
1313
import { serveStaticHandler } from './serve-static'
1414

15+
// `realpathSync` because module resolution reports realpaths, while the system
16+
// temp dir is a symlink on macOS (`/var` → `/private/var`) — a path built from
17+
// the raw `mkdtempSync` result would never match a resolved one.
1518
function makeTmp(): string {
16-
return mkdtempSync(join(tmpdir(), 'devframe-remote-assets-'))
19+
return realpathSync(mkdtempSync(join(tmpdir(), 'devframe-remote-assets-')))
1720
}
1821

1922
/** A fake CDN over a flat `filePath -> contents` map, answering the jsDelivr listing API + per-file URLs. */

‎packages/devframe/tsdown.config.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,7 @@ const serverEntries = {
102102
'node/auth': 'src/node/auth/index.ts',
103103
'node/hub-internals': 'src/node/hub-internals/index.ts',
104104
'internal/index': 'src/internal/index.ts',
105+
'utils/get-port': 'src/utils/get-port.ts',
105106
'utils/launch-editor': 'src/utils/launch-editor.ts',
106107
'utils/nostics': 'src/utils/nostics.ts',
107108
'utils/open': 'src/utils/open.ts',

‎packages/hub-ui/src/client/components/dock/Dock.vue‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ const isRpcTrusted = useIsRpcTrusted(context, (isTrusted) => {
8686
else if (!isTrusted) {
8787
// On revocation: close current tab and panel
8888
context.docks.switchEntry(null)
89-
context.panel.store.open = false
89+
context.panel.session.open = false
9090
}
9191
})
9292
@@ -183,7 +183,7 @@ const isMinimized = computed(() => {
183183
// @ts-expect-error compatibility
184184
const isTouchDevice = 'ontouchstart' in window || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0
185185
return !context.panel.isDragging
186-
&& !context.panel.store.open
186+
&& !context.panel.session.open
187187
&& !isHovering.value
188188
&& !isTouchDevice
189189
&& context.panel.store.inactiveTimeout
@@ -218,8 +218,8 @@ whenever(isMinimized, () => {
218218
})
219219
220220
onMounted(() => {
221-
if (context.panel.store.open && !isRpcTrusted.value)
222-
context.panel.store.open = false
221+
if (context.panel.session.open && !isRpcTrusted.value)
222+
context.panel.session.open = false
223223
if (isRpcTrusted.value)
224224
bringUp()
225225
recalculateCounter.value++

‎packages/hub-ui/src/client/components/dock/DockEdge.stories.ts‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ function edgeStory(position: 'top' | 'right' | 'bottom' | 'left', open = true) {
3838
{
3939
entries: categorizedEntries,
4040
selectedId: open ? 'overview' : null,
41-
panel: { mode: 'edge', position, open, height: 40, width: 30 },
41+
panel: { mode: 'edge', position, height: 40, width: 30 },
42+
session: { open },
4243
},
4344
ctx => [
4445
h(DockEdge, { context: ctx }, { view: ({ entry }: any) => body(entry) }),
@@ -75,7 +76,8 @@ export const CollapsedIdle: Story = {
7576
{
7677
entries: categorizedEntries,
7778
selectedId: null,
78-
panel: { mode: 'edge', position: 'bottom', open: false, inactiveTimeout: 0 },
79+
panel: { mode: 'edge', position: 'bottom', inactiveTimeout: 0 },
80+
session: { open: false },
7981
settings: { autoCollapseEdgeToolbar: true },
8082
},
8183
ctx => [
@@ -93,7 +95,7 @@ export const WithGroup: Story = {
9395
{
9496
entries: groupedEntries,
9597
selectedId: 'nuxt:overview',
96-
panel: { mode: 'edge', position: 'bottom', open: true, height: 45 },
98+
panel: { mode: 'edge', position: 'bottom', height: 45 },
9799
},
98100
ctx => [
99101
h(DockEdge, { context: ctx }, { view: ({ entry }: any) => body(entry) }),

‎packages/hub-ui/src/client/components/dock/DockEdge.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ const selectedEntry = computed(() => context.docks.selected)
3737
const activeGroup = computed(() => getEntryGroup(context.docks.entries, selectedEntry.value))
3838
const hasPanelContent = computed(() => {
3939
const entry = selectedEntry.value
40-
return context.panel.store.open
40+
return context.panel.session.open
4141
&& !!entry
4242
&& entry.type !== 'action'
4343
})

‎packages/hub-ui/src/client/components/dock/DockEmbedded.stories.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export const FloatReducedOverlap: Story = {
6969
export const Edge: Story = {
7070
render: () => ({
7171
setup: () => mountWithContext(
72-
{ entries: blankEntries, selectedId: 'overview', panel: { mode: 'edge', position: 'bottom', open: true, height: 45 } },
72+
{ entries: blankEntries, selectedId: 'overview', panel: { mode: 'edge', position: 'bottom', height: 45 } },
7373
ctx => h(DockEmbedded, { context: ctx }),
7474
),
7575
}),

‎packages/hub-ui/src/client/components/dock/DockEmbedded.vue‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ useEventListener(window, 'mousedown', (e: MouseEvent) => {
3333
return
3434
if (isDockPopupOpen.value)
3535
return
36-
if (!props.context.panel.store.open || props.context.panel.isDragging || props.context.panel.isResizing)
36+
if (!props.context.panel.session.open || props.context.panel.isDragging || props.context.panel.isResizing)
3737
return
3838
3939
const matched = e.composedPath().find((_el) => {

‎packages/hub-ui/src/client/components/views/ViewIframe.vue‎

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,19 +224,37 @@ let onIframeLoad: (() => void) | undefined
224224
225225
onMounted(() => {
226226
const existed = props.panes.has(paneKey.value)
227+
// Restore the address-bar route persisted before the last reload: the dock
228+
// that was selected then boots deep-linked to where the developer left it,
229+
// instead of the entry's default url. `consumeBootRoute` hands the saved URL
230+
// back only for that dock, and only once, so a later switch can't reuse it.
231+
const bootUrl = props.context.panel.consumeBootRoute?.(props.entry.id) ?? props.entry.url
232+
if (!existed && bootUrl !== currentUrl.value) {
233+
currentUrl.value = bootUrl
234+
editingUrl.value = bootUrl
235+
}
227236
// `src` is only assigned when the pane is first created, so re-mounting an
228237
// existing iframe (tab switch) preserves its navigation/scroll/JS state. For
229238
// a shared frame this is also the boot deep-link: the first member (or the
230239
// anchor) to become visible seeds the src, and every later switch soft-navs.
231240
const pane = props.panes.ensure(paneKey.value, {
232-
src: props.entry.url,
241+
src: bootUrl,
233242
style: { boxShadow: 'none', outline: 'none' },
234243
})
235244
const iframe = pane.iframe
236245
237246
if (existed)
238247
updateCurrentUrl()
239248
249+
// Persist this dock's live route while it is the selected one, so the next
250+
// reload can restore it. Only the selected dock writes, so switching docks
251+
// never overwrites another's saved route.
252+
const panelSession = props.context.panel.session
253+
watchEffect(() => {
254+
if (props.context.docks.selectedId === props.entry.id)
255+
panelSession.selectedDockRoute = currentUrl.value
256+
})
257+
240258
// Listen for iframe load events
241259
onIframeLoad = () => {
242260
isIframeLoading.value = false

0 commit comments

Comments
 (0)