mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 23:01:29 +03:00
Local Dashboard fixes (#10958)
- Fix most of https://github.com/enso-org/cloud-v2/issues/1459 - Prevent click + click from triggering rename on Windows and Linux. Behavior is preserved on macOS. - Fix text in Drive when root folder is empty - Properly remove the "Drop here to upload box" after a file is dropped - "Copy as path" now unconditionally uses `/` for path delimiters, even on Windows - Duplicating a project in the root folder on Windows no longer errors - Extra folders in the sidebar now (correctly) show folder name, rather than path, on Windows - Mouse pointer when dragging to a folder is now move, not copy Not addressed: - [no-repro] Tooltips should have some latency before showing up - This should already be the case, although it may work weirdly (once the tooltip opens, there is no delay on subsequent tooltips opening until the last tooltip closes.) - [no-repro] Ctrl-click should add to selection - Column width should be resizable - This requires a refactor and therefore is considered out of scope for this PR - [no-repro] Choosing root folder needs a file browser - [no-repro] Choosing root folder doesn't do anything get the same list as we had before - [no-repro] Open in explorer didn't work in a file but did on project - possibly fixed by path changes. - [no-repro] Opening an enso-project by double clicking resulted on it being renamed with a (2) Related changes: - Make "root directory" picker's file browser default to the current root directory # Important Notes None
This commit is contained in:
parent
6f97e8041b
commit
9ec60299e4
@ -36,8 +36,8 @@
|
||||
"@sentry/react": "^7.74.0",
|
||||
"@stripe/react-stripe-js": "^2.7.1",
|
||||
"@stripe/stripe-js": "^3.5.0",
|
||||
"@tanstack/react-query": "5.45.1",
|
||||
"@tanstack/vue-query": ">= 5.45.0 < 5.46.0",
|
||||
"@tanstack/react-query": "5.55.0",
|
||||
"@tanstack/vue-query": ">= 5.54.0 < 5.56.0",
|
||||
"ajv": "^8.12.0",
|
||||
"clsx": "^2.1.1",
|
||||
"enso-common": "workspace:*",
|
||||
|
@ -86,15 +86,16 @@ import LocalBackend from '#/services/LocalBackend'
|
||||
import ProjectManager, * as projectManager from '#/services/ProjectManager'
|
||||
import RemoteBackend from '#/services/RemoteBackend'
|
||||
|
||||
import { FeatureFlagsProvider } from '#/providers/FeatureFlagsProvider'
|
||||
import * as appBaseUrl from '#/utilities/appBaseUrl'
|
||||
import * as eventModule from '#/utilities/event'
|
||||
import LocalStorage from '#/utilities/LocalStorage'
|
||||
import * as object from '#/utilities/object'
|
||||
import { Path } from '#/utilities/path'
|
||||
import { STATIC_QUERY_OPTIONS } from '#/utilities/reactQuery'
|
||||
|
||||
import { useInitAuthService } from '#/authentication/service'
|
||||
import { InvitedToOrganizationModal } from '#/modals/InvitedToOrganizationModal'
|
||||
import { FeatureFlagsProvider } from '#/providers/FeatureFlagsProvider'
|
||||
|
||||
// ============================
|
||||
// === Global configuration ===
|
||||
@ -178,14 +179,8 @@ export default function App(props: AppProps) {
|
||||
supportsLocalBackend: props.supportsLocalBackend,
|
||||
},
|
||||
] as const,
|
||||
meta: { persist: false },
|
||||
networkMode: 'always',
|
||||
staleTime: Infinity,
|
||||
gcTime: Infinity,
|
||||
refetchOnMount: false,
|
||||
refetchInterval: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchIntervalInBackground: false,
|
||||
...STATIC_QUERY_OPTIONS,
|
||||
behavior: {
|
||||
onFetch: ({ state }) => {
|
||||
const instance = state.data?.projectManagerInstance ?? null
|
||||
|
@ -252,23 +252,25 @@ export function Dialog(props: DialogProps) {
|
||||
{(opts) => {
|
||||
return (
|
||||
<dialogProvider.DialogProvider value={{ close: opts.close, dialogId }}>
|
||||
<aria.Header className={styles.header({ scrolledToTop: isScrolledToTop })}>
|
||||
<ariaComponents.CloseButton
|
||||
className={styles.closeButton()}
|
||||
onPress={opts.close}
|
||||
/>
|
||||
{((!hideCloseButton && closeButton !== 'floating') || title != null) && (
|
||||
<aria.Header className={styles.header({ scrolledToTop: isScrolledToTop })}>
|
||||
<ariaComponents.CloseButton
|
||||
className={styles.closeButton()}
|
||||
onPress={opts.close}
|
||||
/>
|
||||
|
||||
{title != null && (
|
||||
<ariaComponents.Text.Heading
|
||||
id={titleId}
|
||||
level={2}
|
||||
className={styles.heading()}
|
||||
weight="semibold"
|
||||
>
|
||||
{title}
|
||||
</ariaComponents.Text.Heading>
|
||||
)}
|
||||
</aria.Header>
|
||||
{title != null && (
|
||||
<ariaComponents.Text.Heading
|
||||
id={titleId}
|
||||
level={2}
|
||||
className={styles.heading()}
|
||||
weight="semibold"
|
||||
>
|
||||
{title}
|
||||
</ariaComponents.Text.Heading>
|
||||
)}
|
||||
</aria.Header>
|
||||
)}
|
||||
|
||||
<div
|
||||
ref={(ref) => {
|
||||
|
@ -120,6 +120,7 @@ export default function AssetRow(props: AssetRowProps) {
|
||||
driveStore,
|
||||
({ selectedKeys }) => selectedKeys.size === 0 || !selected || isSoleSelected,
|
||||
)
|
||||
const wasSoleSelectedRef = React.useRef(isSoleSelected)
|
||||
const draggableProps = dragAndDropHooks.useDraggable()
|
||||
const { setModal, unsetModal } = modalProvider.useSetModal()
|
||||
const { getText } = textProvider.useText()
|
||||
@ -563,7 +564,12 @@ export default function AssetRow(props: AssetRowProps) {
|
||||
rootRef.current = element
|
||||
|
||||
requestAnimationFrame(() => {
|
||||
if (isSoleSelected && element != null && scrollContainerRef.current != null) {
|
||||
if (
|
||||
isSoleSelected &&
|
||||
!wasSoleSelectedRef.current &&
|
||||
element != null &&
|
||||
scrollContainerRef.current != null
|
||||
) {
|
||||
const rect = element.getBoundingClientRect()
|
||||
const scrollRect = scrollContainerRef.current.getBoundingClientRect()
|
||||
const scrollUp = rect.top - (scrollRect.top + HEADER_HEIGHT_PX)
|
||||
@ -576,6 +582,7 @@ export default function AssetRow(props: AssetRowProps) {
|
||||
})
|
||||
}
|
||||
}
|
||||
wasSoleSelectedRef.current = isSoleSelected
|
||||
})
|
||||
|
||||
if (isKeyboardSelected && element?.contains(document.activeElement) === false) {
|
||||
|
@ -1,6 +1,4 @@
|
||||
/** @file The icon and name of a {@link backendModule.SecretAsset}. */
|
||||
import * as React from 'react'
|
||||
|
||||
import DatalinkIcon from '#/assets/datalink.svg'
|
||||
|
||||
import * as setAssetHooks from '#/hooks/setAssetHooks'
|
||||
@ -16,6 +14,7 @@ import * as eventModule from '#/utilities/event'
|
||||
import * as indent from '#/utilities/indent'
|
||||
import * as object from '#/utilities/object'
|
||||
import * as tailwindMerge from '#/utilities/tailwindMerge'
|
||||
import { isOnMacOS } from 'enso-common/src/detect'
|
||||
|
||||
// ====================
|
||||
// === DatalinkName ===
|
||||
@ -69,7 +68,7 @@ export default function DatalinkNameColumn(props: DatalinkNameColumnProps) {
|
||||
onClick={(event) => {
|
||||
if (handleClick(event)) {
|
||||
// Already handled.
|
||||
} else if (eventModule.isSingleClick(event) && selected) {
|
||||
} else if (eventModule.isSingleClick(event) && isOnMacOS() && selected) {
|
||||
setIsEditing(true)
|
||||
} else if (eventModule.isDoubleClick(event)) {
|
||||
event.stopPropagation()
|
||||
|
@ -25,6 +25,7 @@ import * as object from '#/utilities/object'
|
||||
import * as string from '#/utilities/string'
|
||||
import * as tailwindMerge from '#/utilities/tailwindMerge'
|
||||
import * as validation from '#/utilities/validation'
|
||||
import { isOnMacOS } from 'enso-common/src/detect'
|
||||
|
||||
// =====================
|
||||
// === DirectoryName ===
|
||||
@ -108,6 +109,7 @@ export default function DirectoryNameColumn(props: DirectoryNameColumnProps) {
|
||||
// Already handled.
|
||||
} else if (
|
||||
eventModule.isSingleClick(event) &&
|
||||
isOnMacOS() &&
|
||||
selected &&
|
||||
driveStore.getState().selectedKeys.size === 1
|
||||
) {
|
||||
|
@ -1,6 +1,4 @@
|
||||
/** @file The icon and name of a {@link backendModule.FileAsset}. */
|
||||
import * as React from 'react'
|
||||
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
|
||||
import { backendMutationOptions } from '#/hooks/backendHooks'
|
||||
@ -21,6 +19,7 @@ import * as indent from '#/utilities/indent'
|
||||
import * as object from '#/utilities/object'
|
||||
import * as string from '#/utilities/string'
|
||||
import * as tailwindMerge from '#/utilities/tailwindMerge'
|
||||
import { isOnMacOS } from 'enso-common/src/detect'
|
||||
|
||||
// ================
|
||||
// === FileName ===
|
||||
@ -95,7 +94,7 @@ export default function FileNameColumn(props: FileNameColumnProps) {
|
||||
onClick={(event) => {
|
||||
if (handleClick(event)) {
|
||||
// Already handled.
|
||||
} else if (eventModule.isSingleClick(event) && selected) {
|
||||
} else if (eventModule.isSingleClick(event) && isOnMacOS() && selected) {
|
||||
if (!isCloud) {
|
||||
setIsEditing(true)
|
||||
}
|
||||
|
@ -1,6 +1,4 @@
|
||||
/** @file The icon and name of a {@link backendModule.ProjectAsset}. */
|
||||
import * as React from 'react'
|
||||
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
|
||||
import NetworkIcon from '#/assets/network.svg'
|
||||
@ -29,6 +27,7 @@ import * as permissions from '#/utilities/permissions'
|
||||
import * as string from '#/utilities/string'
|
||||
import * as tailwindMerge from '#/utilities/tailwindMerge'
|
||||
import * as validation from '#/utilities/validation'
|
||||
import { isOnMacOS } from 'enso-common/src/detect'
|
||||
|
||||
// ===================
|
||||
// === ProjectName ===
|
||||
@ -130,7 +129,7 @@ export default function ProjectNameColumn(props: ProjectNameColumnProps) {
|
||||
indent.indentClass(item.depth),
|
||||
)}
|
||||
onKeyDown={(event) => {
|
||||
if (rowState.isEditingName && event.key === 'Enter') {
|
||||
if (rowState.isEditingName && isOnMacOS() && event.key === 'Enter') {
|
||||
event.stopPropagation()
|
||||
}
|
||||
}}
|
||||
|
@ -1,6 +1,4 @@
|
||||
/** @file The icon and name of a {@link backendModule.SecretAsset}. */
|
||||
import * as React from 'react'
|
||||
|
||||
import { useMutation } from '@tanstack/react-query'
|
||||
|
||||
import KeyIcon from '#/assets/key.svg'
|
||||
@ -23,6 +21,7 @@ import * as eventModule from '#/utilities/event'
|
||||
import * as indent from '#/utilities/indent'
|
||||
import * as object from '#/utilities/object'
|
||||
import * as tailwindMerge from '#/utilities/tailwindMerge'
|
||||
import { isOnMacOS } from 'enso-common/src/detect'
|
||||
|
||||
// =====================
|
||||
// === ConnectorName ===
|
||||
@ -74,7 +73,7 @@ export default function SecretNameColumn(props: SecretNameColumnProps) {
|
||||
onClick={(event) => {
|
||||
if (handleClick(event)) {
|
||||
// Already handled.
|
||||
} else if (eventModule.isSingleClick(event) && selected) {
|
||||
} else if (eventModule.isSingleClick(event) && isOnMacOS() && selected) {
|
||||
setIsEditing(true)
|
||||
} else if (eventModule.isDoubleClick(event) && isEditable) {
|
||||
event.stopPropagation()
|
||||
|
2
app/dashboard/src/globals.d.ts
vendored
2
app/dashboard/src/globals.d.ts
vendored
@ -35,7 +35,7 @@ interface BackendApi {
|
||||
openedPath: string,
|
||||
directory: string | null,
|
||||
name: string,
|
||||
) => Promise<string>
|
||||
) => Promise<ProjectInfo>
|
||||
}
|
||||
|
||||
// ==========================
|
||||
|
@ -37,6 +37,8 @@ import UpsertSecretModal from '#/modals/UpsertSecretModal'
|
||||
import * as backendModule from '#/services/Backend'
|
||||
import * as localBackendModule from '#/services/LocalBackend'
|
||||
|
||||
import { normalizePath } from '#/utilities/fileInfo'
|
||||
import { mapNonNullish } from '#/utilities/nullable'
|
||||
import * as object from '#/utilities/object'
|
||||
import * as permissions from '#/utilities/permissions'
|
||||
|
||||
@ -86,8 +88,8 @@ export default function AssetContextMenu(props: AssetContextMenuProps) {
|
||||
category.type === 'recent' || category.type === 'trash' ? null
|
||||
: isCloud ? `${item.path}${item.type === backendModule.AssetType.datalink ? '.datalink' : ''}`
|
||||
: asset.type === backendModule.AssetType.project ?
|
||||
localBackend?.getProjectPath(asset.id) ?? null
|
||||
: localBackendModule.extractTypeAndId(asset.id).id
|
||||
mapNonNullish(localBackend?.getProjectPath(asset.id) ?? null, normalizePath)
|
||||
: normalizePath(localBackendModule.extractTypeAndId(asset.id).id)
|
||||
const copyMutation = copyHooks.useCopy({ copyText: path ?? '' })
|
||||
|
||||
const { isFeatureUnderPaywall } = billingHooks.usePaywall({ plan: user.plan })
|
||||
|
@ -1731,7 +1731,12 @@ export default function AssetsTable(props: AssetsTableProps) {
|
||||
// This non-standard property is defined in Electron.
|
||||
'path' in file
|
||||
) {
|
||||
id = await window.backendApi.importProjectFromPath(file.path, directory, title)
|
||||
const projectInfo = await window.backendApi.importProjectFromPath(
|
||||
file.path,
|
||||
directory,
|
||||
title,
|
||||
)
|
||||
id = projectInfo.id
|
||||
} else {
|
||||
const searchParams = new URLSearchParams({ directory, name: title }).toString()
|
||||
// Ideally this would use `file.stream()`, to minimize RAM
|
||||
@ -2571,6 +2576,7 @@ export default function AssetsTable(props: AssetsTableProps) {
|
||||
onDragStart={(event) => {
|
||||
startAutoScroll()
|
||||
onMouseEvent(event)
|
||||
event.dataTransfer.effectAllowed = 'move'
|
||||
let newSelectedKeys = driveStore.getState().selectedKeys
|
||||
if (!newSelectedKeys.has(item.key)) {
|
||||
setMostRecentlySelectedIndex(visibleItems.indexOf(item))
|
||||
@ -2659,7 +2665,11 @@ export default function AssetsTable(props: AssetsTableProps) {
|
||||
}
|
||||
}
|
||||
}}
|
||||
onDragLeave={() => {
|
||||
setIsDraggingFiles(false)
|
||||
}}
|
||||
onDragEnd={() => {
|
||||
setIsDraggingFiles(false)
|
||||
endAutoScroll()
|
||||
lastSelectedIdsRef.current = null
|
||||
const { selectedKeys } = driveStore.getState()
|
||||
@ -2670,6 +2680,7 @@ export default function AssetsTable(props: AssetsTableProps) {
|
||||
})
|
||||
}}
|
||||
onDrop={(event) => {
|
||||
setIsDraggingFiles(false)
|
||||
endAutoScroll()
|
||||
const { selectedKeys } = driveStore.getState()
|
||||
const ids = new Set(selectedKeys.has(item.key) ? selectedKeys : [item.key])
|
||||
@ -2946,8 +2957,13 @@ export default function AssetsTable(props: AssetsTableProps) {
|
||||
className="flex items-center justify-center gap-3 rounded-default bg-selected-frame px-8 py-6 text-primary/50 backdrop-blur-3xl transition-all"
|
||||
onDragEnter={onDropzoneDragOver}
|
||||
onDragOver={onDropzoneDragOver}
|
||||
onDrop={(event) => {
|
||||
onDragLeave={() => {
|
||||
setIsDraggingFiles(false)
|
||||
}}
|
||||
onDragEnd={() => {
|
||||
setIsDraggingFiles(false)
|
||||
}}
|
||||
onDrop={(event) => {
|
||||
handleFileDrop(event)
|
||||
}}
|
||||
>
|
||||
|
@ -40,6 +40,7 @@ import * as backend from '#/services/Backend'
|
||||
import type LocalBackend from '#/services/LocalBackend'
|
||||
import type RemoteBackend from '#/services/RemoteBackend'
|
||||
|
||||
import { normalizePath } from '#/utilities/fileInfo'
|
||||
import * as object from '#/utilities/object'
|
||||
|
||||
// =========================
|
||||
@ -259,7 +260,7 @@ export const SETTINGS_TAB_DATA: Readonly<Record<SettingsTabType, SettingsTabData
|
||||
const [newDirectory] =
|
||||
(await window.fileBrowserApi?.openFileBrowser('directory')) ?? []
|
||||
if (newDirectory != null) {
|
||||
context.updateLocalRootPath(newDirectory)
|
||||
context.updateLocalRootPath(normalizePath(newDirectory))
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
@ -2,7 +2,6 @@
|
||||
* interactive components. */
|
||||
import * as React from 'react'
|
||||
|
||||
import * as validator from 'validator'
|
||||
import * as z from 'zod'
|
||||
|
||||
import * as detect from 'enso-common/src/detect'
|
||||
@ -56,9 +55,12 @@ import * as backendModule from '#/services/Backend'
|
||||
import * as localBackendModule from '#/services/LocalBackend'
|
||||
import * as projectManager from '#/services/ProjectManager'
|
||||
|
||||
import { baseName } from '#/utilities/fileInfo'
|
||||
import LocalStorage from '#/utilities/LocalStorage'
|
||||
import * as object from '#/utilities/object'
|
||||
import { STATIC_QUERY_OPTIONS } from '#/utilities/reactQuery'
|
||||
import * as sanitizedEventTargets from '#/utilities/sanitizedEventTargets'
|
||||
import { usePrefetchQuery } from '@tanstack/react-query'
|
||||
|
||||
// ============================
|
||||
// === Global configuration ===
|
||||
@ -113,11 +115,11 @@ function DashboardInner(props: DashboardProps) {
|
||||
const dispatchAssetListEvent = eventListProvider.useDispatchAssetListEvent()
|
||||
const assetManagementApiRef = React.useRef<assetTable.AssetManagementApi | null>(null)
|
||||
|
||||
const initialLocalProjectId =
|
||||
initialProjectNameRaw != null && validator.isUUID(initialProjectNameRaw) ?
|
||||
localBackendModule.newProjectId(projectManager.UUID(initialProjectNameRaw))
|
||||
const initialLocalProjectPath =
|
||||
initialProjectNameRaw != null && initialProjectNameRaw.startsWith('file://') ?
|
||||
projectManager.Path(decodeURI(new URL(initialProjectNameRaw).pathname))
|
||||
: null
|
||||
const initialProjectName = initialLocalProjectId ?? initialProjectNameRaw
|
||||
const initialProjectName = initialLocalProjectPath != null ? null : initialProjectNameRaw
|
||||
|
||||
const [category, setCategory] = searchParamsState.useSearchParamsState<categoryModule.Category>(
|
||||
'driveCategory',
|
||||
@ -140,6 +142,30 @@ function DashboardInner(props: DashboardProps) {
|
||||
const openProjectMutation = projectHooks.useOpenProjectMutation()
|
||||
const renameProjectMutation = projectHooks.useRenameProjectMutation()
|
||||
|
||||
usePrefetchQuery({
|
||||
queryKey: ['loadInitialLocalProject'],
|
||||
networkMode: 'always',
|
||||
...STATIC_QUERY_OPTIONS,
|
||||
queryFn: async () => {
|
||||
if (initialLocalProjectPath != null && window.backendApi && localBackend) {
|
||||
const projectName = baseName(initialLocalProjectPath)
|
||||
const { id } = await window.backendApi.importProjectFromPath(
|
||||
initialLocalProjectPath,
|
||||
localBackend.rootPath(),
|
||||
projectName,
|
||||
)
|
||||
openProject({
|
||||
type: backendModule.BackendType.local,
|
||||
id: localBackendModule.newProjectId(projectManager.UUID(id)),
|
||||
title: projectName,
|
||||
parentId: localBackendModule.newDirectoryId(localBackend.rootPath()),
|
||||
})
|
||||
}
|
||||
return null
|
||||
},
|
||||
staleTime: Infinity,
|
||||
})
|
||||
|
||||
React.useEffect(() => {
|
||||
window.projectManagementApi?.setOpenProjectHandler((project) => {
|
||||
setCategory({ type: 'local' })
|
||||
|
@ -12,6 +12,7 @@ import * as localStorageProvider from '#/providers/LocalStorageProvider'
|
||||
|
||||
import * as backendModule from '#/services/Backend'
|
||||
|
||||
import { useMounted } from '#/hooks/mountHooks'
|
||||
import * as array from '#/utilities/array'
|
||||
import LocalStorage from '#/utilities/LocalStorage'
|
||||
|
||||
@ -107,6 +108,28 @@ const ProjectsContext = React.createContext<ProjectsContextType | null>(null)
|
||||
/** Props for a {@link ProjectsProvider}. */
|
||||
export interface ProjectsProviderProps extends Readonly<React.PropsWithChildren> {}
|
||||
|
||||
const STORE = zustand.createStore<ProjectsStore>((set) => ({
|
||||
page: TabType.drive,
|
||||
setPage: (page) => {
|
||||
set({ page })
|
||||
},
|
||||
launchedProjects: [],
|
||||
updateLaunchedProjects: (update) => {
|
||||
set(({ launchedProjects }) => ({ launchedProjects: update(launchedProjects) }))
|
||||
},
|
||||
addLaunchedProject: (project) => {
|
||||
set(({ launchedProjects }) => ({ launchedProjects: [...launchedProjects, project] }))
|
||||
},
|
||||
removeLaunchedProject: (projectId) => {
|
||||
set(({ launchedProjects }) => ({
|
||||
launchedProjects: launchedProjects.filter(({ id }) => id !== projectId),
|
||||
}))
|
||||
},
|
||||
clearLaunchedProjects: () => {
|
||||
set({ launchedProjects: [] })
|
||||
},
|
||||
}))
|
||||
|
||||
// ========================
|
||||
// === ProjectsProvider ===
|
||||
// ========================
|
||||
@ -116,28 +139,15 @@ export interface ProjectsProviderProps extends Readonly<React.PropsWithChildren>
|
||||
export default function ProjectsProvider(props: ProjectsProviderProps) {
|
||||
const { children } = props
|
||||
const { localStorage } = localStorageProvider.useLocalStorage()
|
||||
const [store] = React.useState(() => {
|
||||
return zustand.createStore<ProjectsStore>((set) => ({
|
||||
page: TabType.drive,
|
||||
setPage: (page) => {
|
||||
set({ page })
|
||||
},
|
||||
launchedProjects: localStorage.get('launchedProjects') ?? [],
|
||||
updateLaunchedProjects: (update) => {
|
||||
set(({ launchedProjects }) => ({ launchedProjects: update(launchedProjects) }))
|
||||
},
|
||||
addLaunchedProject: (project) => {
|
||||
set(({ launchedProjects }) => ({ launchedProjects: [...launchedProjects, project] }))
|
||||
},
|
||||
removeLaunchedProject: (projectId) => {
|
||||
set(({ launchedProjects }) => ({
|
||||
launchedProjects: launchedProjects.filter(({ id }) => id !== projectId),
|
||||
}))
|
||||
},
|
||||
clearLaunchedProjects: () => {
|
||||
set({ launchedProjects: [] })
|
||||
},
|
||||
}))
|
||||
const store = STORE
|
||||
|
||||
useMounted(() => {
|
||||
const launchedProjects = localStorage.get('launchedProjects')
|
||||
if (launchedProjects) {
|
||||
store
|
||||
.getState()
|
||||
.updateLaunchedProjects((projects) => (projects.length === 0 ? launchedProjects : projects))
|
||||
}
|
||||
})
|
||||
|
||||
return (
|
||||
|
@ -401,12 +401,17 @@ export default class ProjectManager {
|
||||
state: backend.ProjectState.openInProgress,
|
||||
data: promise,
|
||||
})
|
||||
const result = await promise
|
||||
this.internalProjects.set(params.projectId, {
|
||||
state: backend.ProjectState.opened,
|
||||
data: result,
|
||||
})
|
||||
return result
|
||||
try {
|
||||
const result = await promise
|
||||
this.internalProjects.set(params.projectId, {
|
||||
state: backend.ProjectState.opened,
|
||||
data: result,
|
||||
})
|
||||
return result
|
||||
} catch (error) {
|
||||
this.internalProjects.delete(params.projectId)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -6,17 +6,22 @@
|
||||
|
||||
/** Return just the file name, including the extension. */
|
||||
export function getFileName(filePath: string) {
|
||||
return filePath.match(/(?:[/]|^)([^/]+)[/]?$/)?.[1] ?? filePath
|
||||
return filePath.match(/(?:[/\\]|^)([^/\\]+)[/\\]?$/)?.[1] ?? filePath
|
||||
}
|
||||
|
||||
/** Return the entire path, without the file name. */
|
||||
export function getFolderPath(filePath: string) {
|
||||
return filePath.match(/^.+[/]/)?.[0] ?? filePath
|
||||
return filePath.match(/^.+[/\\]/)?.[0] ?? filePath
|
||||
}
|
||||
|
||||
/** Return just the file name, without the path and without the extension. */
|
||||
export function baseName(fileNameOrPath: string) {
|
||||
return fileNameOrPath.match(/(?:[/]|^)([^./]+)(?:[.][^/]*)?$/)?.[1] ?? fileNameOrPath
|
||||
return fileNameOrPath.match(/(?:[\\/]|^)([^./\\]+)(?:[.][^/\\]*)?$/)?.[1] ?? fileNameOrPath
|
||||
}
|
||||
|
||||
/** Normalize a path to use `/` instead of `\`. */
|
||||
export function normalizePath(path: string) {
|
||||
return path.replace(/\\/g, '/')
|
||||
}
|
||||
|
||||
/** Extract the file extension from a file name. */
|
||||
|
7
app/dashboard/src/utilities/nullable.ts
Normal file
7
app/dashboard/src/utilities/nullable.ts
Normal file
@ -0,0 +1,7 @@
|
||||
/** @file Functions related to nullable types. */
|
||||
|
||||
/** Call a transformation function when the value is non-nullish. */
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
export function mapNonNullish<T extends {}, R>(value: T | null | undefined, map: (value: T) => R) {
|
||||
return value != null ? map(value) : value
|
||||
}
|
12
app/dashboard/src/utilities/reactQuery.ts
Normal file
12
app/dashboard/src/utilities/reactQuery.ts
Normal file
@ -0,0 +1,12 @@
|
||||
/** @file Utilities related to the `react-query` library. */
|
||||
import type { DefinedInitialDataOptions } from '@tanstack/react-query'
|
||||
|
||||
export const STATIC_QUERY_OPTIONS = {
|
||||
meta: { persist: false },
|
||||
staleTime: Infinity,
|
||||
gcTime: Infinity,
|
||||
refetchOnMount: false,
|
||||
refetchInterval: false,
|
||||
refetchOnReconnect: false,
|
||||
refetchIntervalInBackground: false,
|
||||
} as const satisfies Partial<DefinedInitialDataOptions>
|
@ -61,7 +61,7 @@
|
||||
"@lezer/common": "^1.1.0",
|
||||
"@lezer/highlight": "^1.1.6",
|
||||
"@noble/hashes": "^1.4.0",
|
||||
"@tanstack/vue-query": ">= 5.45.0 < 5.46.0",
|
||||
"@tanstack/vue-query": ">= 5.54.0 < 5.56.0",
|
||||
"@vueuse/core": "^10.4.1",
|
||||
"ag-grid-community": "^30.2.1",
|
||||
"ag-grid-enterprise": "^30.2.1",
|
||||
|
@ -75,6 +75,9 @@ function main() {
|
||||
const projectManagerUrl = config.engine.projectManagerUrl || PROJECT_MANAGER_URL
|
||||
const ydocUrl = config.engine.ydocUrl === '' ? YDOC_SERVER_URL : config.engine.ydocUrl
|
||||
const initialProjectName = config.startup.project || null
|
||||
const urlWithoutStartupProject = new URL(location.toString())
|
||||
urlWithoutStartupProject.searchParams.delete('startup.project')
|
||||
history.replaceState(null, '', urlWithoutStartupProject)
|
||||
const queryClient = commonQuery.createQueryClient()
|
||||
|
||||
const registerPlugins = (app: App) => {
|
||||
|
@ -38,6 +38,7 @@
|
||||
"@types/semver": "^7.5.8",
|
||||
"@types/tar": "^6.1.4",
|
||||
"@types/yargs": "^17.0.30",
|
||||
"cross-env": "^7.0.3",
|
||||
"electron": "31.2.0",
|
||||
"electron-builder": "^24.13.3",
|
||||
"enso-common": "workspace:*",
|
||||
@ -59,8 +60,8 @@
|
||||
"typecheck": "tsc --build",
|
||||
"build": "tsx bundle.ts",
|
||||
"dist": "tsx dist.ts",
|
||||
"watch:windows": "cross-env ENSO_BUILD_IDE=%LOCALAPPDATA%/Temp/enso/dist/ide ENSO_BUILD_PROJECT_MANAGER=%CD%/../../../dist/backend ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH=bin/project-manager.exe ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION=0 tsx watch.ts",
|
||||
"watch:linux": "ENSO_BUILD_IDE=\"${ENSO_BUILD_IDE:-/tmp/enso/dist/ide}\" ENSO_BUILD_PROJECT_MANAGER=\"${ENSO_BUILD_PROJECT_MANAGER:-\"$(pwd)/../../../dist/backend\"}\" ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH=\"${ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH:-bin/project-manager}\" ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION=\"${ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION:-0}\" tsx watch.ts \"$@\"",
|
||||
"watch:macos": "ENSO_BUILD_IDE=\"${ENSO_BUILD_IDE:-/tmp/enso/dist/ide}\" ENSO_BUILD_PROJECT_MANAGER=\"${ENSO_BUILD_PROJECT_MANAGER:-\"$(pwd)/../../../dist/backend\"}\" ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH=\"${ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH:-bin/project-manager}\" ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION=\"${ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION:-0}\" tsx watch.ts \"$@\""
|
||||
"watch:windows": "cross-env ENSO_BUILD_IDE=%LOCALAPPDATA%\\Temp\\enso\\dist\\ide ENSO_BUILD_PROJECT_MANAGER=%CD%\\..\\..\\..\\dist\\backend ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH=bin\\project-manager.exe ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION=0 ENSO_POLYGLOT_YDOC_SERVER=wss://localhost:8080 tsx watch.ts",
|
||||
"watch:linux": "ENSO_BUILD_IDE=\"${ENSO_BUILD_IDE:-/tmp/enso/dist/ide}\" ENSO_BUILD_PROJECT_MANAGER=\"${ENSO_BUILD_PROJECT_MANAGER:-\"$(pwd)/../../../dist/backend\"}\" ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH=\"${ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH:-bin/project-manager}\" ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION=\"${ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION:-0}\" ENSO_POLYGLOT_YDOC_SERVER=\"${ENSO_POLYGLOT_YDOC_SERVER:-wss://localhost:8080}\" tsx watch.ts \"$@\"",
|
||||
"watch:macos": "ENSO_BUILD_IDE=\"${ENSO_BUILD_IDE:-/tmp/enso/dist/ide}\" ENSO_BUILD_PROJECT_MANAGER=\"${ENSO_BUILD_PROJECT_MANAGER:-\"$(pwd)/../../../dist/backend\"}\" ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH=\"${ENSO_BUILD_PROJECT_MANAGER_IN_BUNDLE_PATH:-bin/project-manager}\" ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION=\"${ENSO_BUILD_IDE_BUNDLED_ENGINE_VERSION:-0}\" ENSO_POLYGLOT_YDOC_SERVER=\"${ENSO_POLYGLOT_YDOC_SERVER:-wss://localhost:8080}\" tsx watch.ts \"$@\""
|
||||
}
|
||||
}
|
||||
|
@ -13,7 +13,6 @@ import electronIsDev from 'electron-is-dev'
|
||||
|
||||
import * as common from 'enso-common'
|
||||
|
||||
import type * as clientConfig from '@/config'
|
||||
import * as contentConfig from '@/contentConfig'
|
||||
import * as project from '@/projectManagement'
|
||||
import * as fileAssociations from '../fileAssociations'
|
||||
@ -100,13 +99,13 @@ export function isFileOpenable(path: string): boolean {
|
||||
}
|
||||
|
||||
/** Callback called when a file is opened via the `open-file` event. */
|
||||
export function onFileOpened(event: electron.Event, path: string): project.ProjectInfo | null {
|
||||
export function onFileOpened(event: electron.Event, path: string): string | null {
|
||||
logger.log(`Received 'open-file' event for path '${path}'.`)
|
||||
if (isFileOpenable(path)) {
|
||||
logger.log(`The file '${path}' is openable.`)
|
||||
event.preventDefault()
|
||||
logger.log(`Opening file '${path}'.`)
|
||||
return handleOpenFile(path)
|
||||
return path
|
||||
} else {
|
||||
logger.log(`The file '${path}' is not openable, ignoring the 'open-file' event.`)
|
||||
return null
|
||||
@ -116,13 +115,10 @@ export function onFileOpened(event: electron.Event, path: string): project.Proje
|
||||
/** Set up the `open-file` event handler that might import a project and invoke the given callback,
|
||||
* if this IDE instance should load the project. See {@link onFileOpened} for more details.
|
||||
* @param setProjectToOpen - A function that will be called with the ID of the project to open. */
|
||||
export function setOpenFileEventHandler(setProjectToOpen: (info: project.ProjectInfo) => void) {
|
||||
electron.app.on('open-file', (event, path) => {
|
||||
export function setOpenFileEventHandler(setProjectToOpen: (path: string) => void) {
|
||||
electron.app.on('open-file', (_event, path) => {
|
||||
logger.log(`Opening file '${path}'.`)
|
||||
const projectInfo = onFileOpened(event, path)
|
||||
if (projectInfo) {
|
||||
setProjectToOpen(projectInfo)
|
||||
}
|
||||
setProjectToOpen(path)
|
||||
})
|
||||
|
||||
electron.app.on('second-instance', (event, _argv, _workingDir, additionalData) => {
|
||||
@ -140,9 +136,9 @@ export function setOpenFileEventHandler(setProjectToOpen: (info: project.Project
|
||||
if (path != null) {
|
||||
logger.log(`Got path '${path.toString()}' from second instance.`)
|
||||
event.preventDefault()
|
||||
const projectInfo = onFileOpened(event, path)
|
||||
if (projectInfo) {
|
||||
setProjectToOpen(projectInfo)
|
||||
const file = onFileOpened(event, path)
|
||||
if (file) {
|
||||
setProjectToOpen(file)
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -171,24 +167,3 @@ export function handleOpenFile(openedFile: string): project.ProjectInfo {
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
/** Handle the file to open, if any. See {@link handleOpenFile} for details.
|
||||
*
|
||||
* If no file to open is provided, does nothing.
|
||||
*
|
||||
* Handles all errors internally.
|
||||
* @param openedFile - The file to open (null if none).
|
||||
* @param args - The parsed application arguments. */
|
||||
export function handleFileArguments(openedFile: string | null, args: clientConfig.Args): void {
|
||||
if (openedFile != null) {
|
||||
try {
|
||||
// This makes the IDE open the relevant project. Also, this prevents us from using this
|
||||
// method after IDE has been fully set up, as the initializing code would have already
|
||||
// read the value of this argument.
|
||||
args.groups.startup.options.project.value = handleOpenFile(openedFile).id
|
||||
} catch (e) {
|
||||
// If we failed to open the file, we should enter the usual welcome screen.
|
||||
// The `handleOpenFile` function will have already displayed an error message.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
app/ide-desktop/client/src/globals.d.ts
vendored
2
app/ide-desktop/client/src/globals.d.ts
vendored
@ -33,7 +33,7 @@ interface BackendApi {
|
||||
openedPath: string,
|
||||
directory: string | null,
|
||||
name: string,
|
||||
) => Promise<string>
|
||||
) => Promise<ProjectInfo>
|
||||
}
|
||||
|
||||
// ==========================
|
||||
|
@ -58,11 +58,12 @@ class App {
|
||||
log.addFileLog()
|
||||
urlAssociations.registerAssociations()
|
||||
// Register file associations for macOS.
|
||||
fileAssociations.setOpenFileEventHandler(project => {
|
||||
fileAssociations.setOpenFileEventHandler(path => {
|
||||
if (electron.app.isReady()) {
|
||||
const project = fileAssociations.handleOpenFile(path)
|
||||
this.window?.webContents.send(ipc.Channel.openProject, project)
|
||||
} else {
|
||||
this.setProjectToOpenOnStartup(project.id)
|
||||
this.setProjectToOpenOnStartup(path)
|
||||
}
|
||||
})
|
||||
|
||||
@ -170,11 +171,9 @@ class App {
|
||||
logger.log('Opening file or URL.', { fileToOpen, urlToOpen })
|
||||
try {
|
||||
if (fileToOpen != null) {
|
||||
// This makes the IDE open the relevant project. Also, this prevents us from using
|
||||
// this method after the IDE has been fully set up, as the initializing code
|
||||
// would have already read the value of this argument.
|
||||
const projectInfo = fileAssociations.handleOpenFile(fileToOpen)
|
||||
this.setProjectToOpenOnStartup(projectInfo.id)
|
||||
// The IDE must receive the project path, otherwise if the IDE has a custom root directory
|
||||
// set then it is added to the (incorrect) default root directory.
|
||||
this.setProjectToOpenOnStartup(`file://${encodeURI(fileToOpen)}`)
|
||||
}
|
||||
|
||||
if (urlToOpen != null) {
|
||||
|
@ -14,6 +14,7 @@ import type * as projectManagement from '@/projectManagement'
|
||||
// esbuild, we have to manually use "require". Switch this to an import once new electron version
|
||||
// actually honours ".mjs" files for sandboxed preloading (this will likely become an error at that time).
|
||||
// https://www.electronjs.org/fr/docs/latest/tutorial/esm#sandboxed-preload-scripts-cant-use-esm-imports
|
||||
// eslint-disable-next-line no-restricted-syntax, @typescript-eslint/no-var-requires
|
||||
const electron = require('electron')
|
||||
|
||||
// =================
|
||||
@ -45,12 +46,15 @@ function exposeInMainWorld<Key extends string & keyof typeof window>(
|
||||
// === importProjectFromPath ===
|
||||
// =============================
|
||||
|
||||
const IMPORT_PROJECT_RESOLVE_FUNCTIONS = new Map<string, (projectId: string) => void>()
|
||||
const IMPORT_PROJECT_RESOLVE_FUNCTIONS = new Map<
|
||||
string,
|
||||
(projectId: projectManagement.ProjectInfo) => void
|
||||
>()
|
||||
|
||||
exposeInMainWorld(BACKEND_API_KEY, {
|
||||
importProjectFromPath: (projectPath: string, directory: string | null = null) => {
|
||||
electron.ipcRenderer.send(ipc.Channel.importProjectFromPath, projectPath, directory)
|
||||
return new Promise<string>(resolve => {
|
||||
return new Promise<projectManagement.ProjectInfo>(resolve => {
|
||||
IMPORT_PROJECT_RESOLVE_FUNCTIONS.set(projectPath, resolve)
|
||||
})
|
||||
},
|
||||
@ -67,10 +71,10 @@ exposeInMainWorld(NAVIGATION_API_KEY, {
|
||||
|
||||
electron.ipcRenderer.on(
|
||||
ipc.Channel.importProjectFromPath,
|
||||
(_event, projectPath: string, projectId: string) => {
|
||||
(_event, projectPath: string, projectInfo: projectManagement.ProjectInfo) => {
|
||||
const resolveFunction = IMPORT_PROJECT_RESOLVE_FUNCTIONS.get(projectPath)
|
||||
IMPORT_PROJECT_RESOLVE_FUNCTIONS.delete(projectPath)
|
||||
resolveFunction?.(projectId)
|
||||
resolveFunction?.(projectInfo)
|
||||
},
|
||||
)
|
||||
|
||||
|
@ -22,7 +22,8 @@ import { pathToFileURL } from 'node:url'
|
||||
|
||||
const logger = contentConfig.logger
|
||||
|
||||
ydocServer.configureAllDebugLogs(process.env.ENSO_YDOC_LS_DEBUG === 'true', logger.log)
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
ydocServer.configureAllDebugLogs(process.env.ENSO_YDOC_LS_DEBUG === 'true', logger.log.bind(logger))
|
||||
|
||||
// =================
|
||||
// === Constants ===
|
||||
@ -94,7 +95,7 @@ export class Server {
|
||||
|
||||
/** Create a simple HTTP server. */
|
||||
constructor(public config: Config) {
|
||||
this.projectsRootDirectory = projectManagement.getProjectsDirectory()
|
||||
this.projectsRootDirectory = projectManagement.getProjectsDirectory().replace(/\\/g, '/')
|
||||
}
|
||||
|
||||
/** Server constructor. */
|
||||
@ -147,8 +148,10 @@ export class Server {
|
||||
logger.log(`Server started on port ${this.config.port}.`)
|
||||
logger.log(`Serving files from '${path.join(process.cwd(), this.config.dir)}'.`)
|
||||
if (process.env.ELECTRON_DEV_MODE === 'true') {
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
const vite = (await import(
|
||||
pathToFileURL(process.env.NODE_MODULES_PATH + '/vite/dist/node/index.js').href
|
||||
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
||||
)) as typeof import('vite')
|
||||
this.devServer = await vite.createServer({
|
||||
server: {
|
||||
|
@ -94,7 +94,7 @@ const ELECTRON_ARGS = [
|
||||
path.join(IDE_DIR_PATH, 'index.mjs'),
|
||||
...ELECTRON_FLAGS,
|
||||
'--',
|
||||
...process.argv.slice(2),
|
||||
...process.argv.slice(2).map(arg => `'${arg}'`),
|
||||
]
|
||||
|
||||
process.on('SIGINT', () => {
|
||||
|
@ -28,14 +28,14 @@
|
||||
"test": "vitest run"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@tanstack/query-core": "5.45.0",
|
||||
"@tanstack/vue-query": ">= 5.45.0 < 5.46.0"
|
||||
"@tanstack/query-core": "5.54.1",
|
||||
"@tanstack/vue-query": ">= 5.54.0 < 5.56.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"idb-keyval": "^6.2.1",
|
||||
"react": "^18.3.1",
|
||||
"@tanstack/query-persist-client-core": "^5.45.0",
|
||||
"@tanstack/vue-query": ">= 5.45.0 < 5.46.0",
|
||||
"@tanstack/query-persist-client-core": "^5.54.0",
|
||||
"@tanstack/vue-query": ">= 5.54.0 < 5.56.0",
|
||||
"vue": "^3.4.19",
|
||||
"vitest": "^1.3.1"
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
import * as queryCore from '@tanstack/query-core'
|
||||
import * as persistClientCore from '@tanstack/query-persist-client-core'
|
||||
import * as vueQuery from '@tanstack/vue-query'
|
||||
import * as idbKeyval from 'idb-keyval'
|
||||
import * as vueQuery from './vueQuery'
|
||||
|
||||
declare module '@tanstack/query-core' {
|
||||
/**
|
||||
|
@ -410,7 +410,7 @@
|
||||
"organizationProfilePictureWarning": "Your organization’s profile picture is visible to everyone in your organization.",
|
||||
"noFilesMatchTheCurrentFilters": "No files match the current filters.",
|
||||
"youHaveNoRecentProjects": "You have no recent projects. Switch to another category to create a project.",
|
||||
"youHaveNoFiles": "This folder is empty. Go ahead and create one using the buttons above, or open a template from the home screen.",
|
||||
"youHaveNoFiles": "This folder is empty. You can create a project using the buttons above.",
|
||||
"placeholderChatPrompt": "Login or register to access live chat with our support team.",
|
||||
"confirmPrompt": "Are you sure you want to $0?",
|
||||
"couldNotInviteUser": "Could not invite user $0",
|
||||
|
@ -1,98 +0,0 @@
|
||||
/** @file QueryClient based on the '@tanstack/vue-query' implementation. */
|
||||
|
||||
import * as queryCore from '@tanstack/query-core'
|
||||
import * as vueQuery from '@tanstack/vue-query'
|
||||
import * as vue from 'vue'
|
||||
|
||||
/** The QueryClient from vue-query, but with immediate query invalidation. */
|
||||
export class QueryClient extends vueQuery.QueryClient {
|
||||
/** Like the `invalidateQueries` method of `vueQuery.QueryClient`, but invalidates queries immediately. */
|
||||
// Workaround for https://github.com/TanStack/query/issues/7694
|
||||
override invalidateQueries(
|
||||
filters: MaybeRefDeep<queryCore.InvalidateQueryFilters> = {},
|
||||
options: MaybeRefDeep<queryCore.InvalidateOptions> = {},
|
||||
): Promise<void> {
|
||||
const filtersValue = cloneDeepUnref(filters)
|
||||
const optionsValue = cloneDeepUnref(options)
|
||||
queryCore.notifyManager.batch(() => {
|
||||
this.getQueryCache()
|
||||
.findAll(filtersValue)
|
||||
.forEach(query => {
|
||||
query.invalidate()
|
||||
})
|
||||
})
|
||||
if (filtersValue.refetchType === 'none') {
|
||||
return Promise.resolve()
|
||||
} else {
|
||||
const refetchType = filtersValue.refetchType
|
||||
return vue.nextTick(() =>
|
||||
queryCore.notifyManager.batch(() => {
|
||||
const refetchFilters: queryCore.RefetchQueryFilters = {
|
||||
...filtersValue,
|
||||
type: refetchType ?? filtersValue.type ?? 'active',
|
||||
}
|
||||
return this.refetchQueries(refetchFilters, optionsValue)
|
||||
}),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-disable */
|
||||
|
||||
function isPlainObject(value: unknown): value is Object {
|
||||
if (Object.prototype.toString.call(value) !== '[object Object]') {
|
||||
return false
|
||||
}
|
||||
|
||||
const prototype = Object.getPrototypeOf(value)
|
||||
return prototype === null || prototype === Object.prototype
|
||||
}
|
||||
|
||||
function cloneDeep<T>(
|
||||
value: MaybeRefDeep<T>,
|
||||
customize?: (val: MaybeRefDeep<T>) => T | undefined,
|
||||
): T {
|
||||
if (customize) {
|
||||
const result = customize(value)
|
||||
// If it's a ref of undefined, return undefined
|
||||
if (result === undefined && vue.isRef(value)) {
|
||||
return result as T
|
||||
}
|
||||
if (result !== undefined) {
|
||||
return result
|
||||
}
|
||||
}
|
||||
|
||||
if (Array.isArray(value)) {
|
||||
return value.map(val => cloneDeep(val, customize)) as unknown as T
|
||||
}
|
||||
|
||||
if (typeof value === 'object' && isPlainObject(value)) {
|
||||
const entries = Object.entries(value).map(([key, val]) => [key, cloneDeep(val, customize)])
|
||||
return Object.fromEntries(entries)
|
||||
}
|
||||
|
||||
return value as T
|
||||
}
|
||||
|
||||
function cloneDeepUnref<T>(obj: MaybeRefDeep<T>): T {
|
||||
return cloneDeep(obj, val => {
|
||||
if (vue.isRef(val)) {
|
||||
return cloneDeepUnref(vue.unref(val))
|
||||
}
|
||||
|
||||
return undefined
|
||||
})
|
||||
}
|
||||
|
||||
type MaybeRefDeep<T> = vue.MaybeRef<
|
||||
T extends Function ? T
|
||||
: T extends object ?
|
||||
{
|
||||
[Property in keyof T]: MaybeRefDeep<T[Property]>
|
||||
}
|
||||
: T
|
||||
>
|
||||
|
||||
/* eslint-enable */
|
209
pnpm-lock.yaml
209
pnpm-lock.yaml
@ -71,11 +71,11 @@ importers:
|
||||
specifier: ^3.5.0
|
||||
version: 3.5.0
|
||||
'@tanstack/react-query':
|
||||
specifier: 5.45.1
|
||||
version: 5.45.1(react@18.3.1)
|
||||
specifier: 5.55.0
|
||||
version: 5.55.0(react@18.3.1)
|
||||
'@tanstack/vue-query':
|
||||
specifier: '>= 5.45.0 < 5.46.0'
|
||||
version: 5.45.0(vue@3.4.31(typescript@5.5.3))
|
||||
specifier: '>= 5.54.0 < 5.56.0'
|
||||
version: 5.54.2(vue@3.4.31(typescript@5.5.3))
|
||||
ajv:
|
||||
specifier: ^8.12.0
|
||||
version: 8.16.0
|
||||
@ -160,7 +160,7 @@ importers:
|
||||
version: 3.23.1(react@18.3.1)
|
||||
'@tanstack/react-query-devtools':
|
||||
specifier: 5.45.1
|
||||
version: 5.45.1(@tanstack/react-query@5.45.1(react@18.3.1))(react@18.3.1)
|
||||
version: 5.45.1(@tanstack/react-query@5.55.0(react@18.3.1))(react@18.3.1)
|
||||
'@types/eslint__js':
|
||||
specifier: ^8.42.3
|
||||
version: 8.42.3
|
||||
@ -315,8 +315,8 @@ importers:
|
||||
specifier: ^1.4.0
|
||||
version: 1.4.0
|
||||
'@tanstack/vue-query':
|
||||
specifier: '>= 5.45.0 < 5.46.0'
|
||||
version: 5.45.0(vue@3.4.31(typescript@5.5.3))
|
||||
specifier: '>= 5.54.0 < 5.56.0'
|
||||
version: 5.54.2(vue@3.4.31(typescript@5.5.3))
|
||||
'@vueuse/core':
|
||||
specifier: ^10.4.1
|
||||
version: 10.11.0(vue@3.4.31(typescript@5.5.3))
|
||||
@ -640,6 +640,9 @@ importers:
|
||||
'@types/yargs':
|
||||
specifier: ^17.0.30
|
||||
version: 17.0.32
|
||||
cross-env:
|
||||
specifier: ^7.0.3
|
||||
version: 7.0.3
|
||||
electron:
|
||||
specifier: 31.2.0
|
||||
version: 31.2.0
|
||||
@ -680,14 +683,14 @@ importers:
|
||||
app/ide-desktop/common:
|
||||
dependencies:
|
||||
'@tanstack/query-core':
|
||||
specifier: 5.45.0
|
||||
version: 5.45.0
|
||||
specifier: 5.54.1
|
||||
version: 5.54.1
|
||||
'@tanstack/query-persist-client-core':
|
||||
specifier: ^5.45.0
|
||||
version: 5.45.0
|
||||
specifier: ^5.54.0
|
||||
version: 5.54.1
|
||||
'@tanstack/vue-query':
|
||||
specifier: '>= 5.45.0 < 5.46.0'
|
||||
version: 5.45.0(vue@3.4.31(typescript@5.5.3))
|
||||
specifier: '>= 5.54.0 < 5.56.0'
|
||||
version: 5.54.2(vue@3.4.31(typescript@5.5.3))
|
||||
idb-keyval:
|
||||
specifier: ^6.2.1
|
||||
version: 6.2.1
|
||||
@ -1145,8 +1148,8 @@ packages:
|
||||
resolution: {integrity: sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/compat-data@7.25.2':
|
||||
resolution: {integrity: sha512-bYcppcpKBvX4znYaPEeFau03bp89ShqNMLs+rmdptMw+heSZh9+z84d2YG+K7cYLbWwzdjtDoW/uqZmPjulClQ==}
|
||||
'@babel/compat-data@7.25.4':
|
||||
resolution: {integrity: sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/core@7.24.7':
|
||||
@ -1161,8 +1164,8 @@ packages:
|
||||
resolution: {integrity: sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/generator@7.25.0':
|
||||
resolution: {integrity: sha512-3LEEcj3PVW8pW2R1SR1M89g/qrYk/m/mB/tLqn7dn4sbBUQyTqnlod+II2U4dqiGtUmkcnAmkMDralTFZttRiw==}
|
||||
'@babel/generator@7.25.6':
|
||||
resolution: {integrity: sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helper-annotate-as-pure@7.24.7':
|
||||
@ -1269,8 +1272,8 @@ packages:
|
||||
resolution: {integrity: sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/helpers@7.25.0':
|
||||
resolution: {integrity: sha512-MjgLZ42aCm0oGjJj8CtSM3DB8NOOf8h2l7DCTePJs29u+v7yO/RBX9nShlKMgFnRks/Q4tBAe7Hxnov9VkGwLw==}
|
||||
'@babel/helpers@7.25.6':
|
||||
resolution: {integrity: sha512-Xg0tn4HcfTijTwfDwYlvVCl43V6h4KyVVX2aEm4qdO/PC6L2YvzLHFdmxhoeSA3eslcE6+ZVXHgWwopXYLNq4Q==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/highlight@7.24.7':
|
||||
@ -1282,8 +1285,8 @@ packages:
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
'@babel/parser@7.25.3':
|
||||
resolution: {integrity: sha512-iLTJKDbJ4hMvFPgQwwsVoxtHyWpKKPBrxkANrSYewDPaPpT5py5yeVkgPIJ7XYXhndxJpaA3PyALSXQ7u8e/Dw==}
|
||||
'@babel/parser@7.25.6':
|
||||
resolution: {integrity: sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
hasBin: true
|
||||
|
||||
@ -1356,16 +1359,16 @@ packages:
|
||||
resolution: {integrity: sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/traverse@7.25.3':
|
||||
resolution: {integrity: sha512-HefgyP1x754oGCsKmV5reSmtV7IXj/kpaE1XYY+D9G5PvKKoFfSbiS4M77MdjuwlZKDIKFCffq9rPU+H/s3ZdQ==}
|
||||
'@babel/traverse@7.25.6':
|
||||
resolution: {integrity: sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/types@7.24.7':
|
||||
resolution: {integrity: sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@babel/types@7.25.2':
|
||||
resolution: {integrity: sha512-YTnYtra7W9e6/oAZEHj0bJehPRUlLH9/fbpT5LfB0NhQXyALCRkRs3zH9v07IYhkgpqX6Z78FnuccZr/l4Fs4Q==}
|
||||
'@babel/types@7.25.6':
|
||||
resolution: {integrity: sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==}
|
||||
engines: {node: '>=6.9.0'}
|
||||
|
||||
'@bcoe/v8-coverage@0.2.3':
|
||||
@ -2913,14 +2916,14 @@ packages:
|
||||
resolution: {integrity: sha512-PnVV3d2poenUM31ZbZi/yXkBu3J7kd5k2u51CGwwNojag451AjTH9N6n41yjXz2fpLeewleyLBmNS6+HcGDlXw==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
'@tanstack/query-core@5.45.0':
|
||||
resolution: {integrity: sha512-RVfIZQmFUTdjhSAAblvueimfngYyfN6HlwaJUPK71PKd7yi43Vs1S/rdimmZedPWX/WGppcq/U1HOj7O7FwYxw==}
|
||||
'@tanstack/query-core@5.54.1':
|
||||
resolution: {integrity: sha512-hKS+WRpT5zBFip21pB6Jx1C0hranWQrbv5EJ7qPoiV5MYI3C8rTCqWC9DdBseiPT1JgQWh8Y55YthuYZNiw3Xw==}
|
||||
|
||||
'@tanstack/query-devtools@5.37.1':
|
||||
resolution: {integrity: sha512-XcG4IIHIv0YQKrexTqo2zogQWR1Sz672tX2KsfE9kzB+9zhx44vRKH5si4WDILE1PIWQpStFs/NnrDQrBAUQpg==}
|
||||
|
||||
'@tanstack/query-persist-client-core@5.45.0':
|
||||
resolution: {integrity: sha512-iAETglkRB6FR1//185TcWGnMxkisJPnCrlvIhLpHzT4eKLmh4n4vq1Cys42YIJzM2il4YWf8P4refzdq4D5Vdw==}
|
||||
'@tanstack/query-persist-client-core@5.54.1':
|
||||
resolution: {integrity: sha512-qmBkrC5HA3XHwwrx/pWjegncQFcmuoAaffwbrXm07OrsOxxeTGLt8aFl8RYbWAs75a8+9uneqVFQfgv5QRqxBA==}
|
||||
|
||||
'@tanstack/react-query-devtools@5.45.1':
|
||||
resolution: {integrity: sha512-4mrbk1g5jqlqh0pifZNsKzy7FtgeqgwzMICL4d6IJGayrrcrKq9K4N/OzRNbgRWrTn6YTY63qcAcKo+NJU2QMw==}
|
||||
@ -2928,13 +2931,13 @@ packages:
|
||||
'@tanstack/react-query': ^5.45.1
|
||||
react: ^18 || ^19
|
||||
|
||||
'@tanstack/react-query@5.45.1':
|
||||
resolution: {integrity: sha512-mYYfJujKg2kxmkRRjA6nn4YKG3ITsKuH22f1kteJ5IuVQqgKUgbaSQfYwVP0gBS05mhwxO03HVpD0t7BMN7WOA==}
|
||||
'@tanstack/react-query@5.55.0':
|
||||
resolution: {integrity: sha512-2uYuxEbRQD8TORUiTUacEOwt1e8aoSqUOJFGY5TUrh6rQ3U85zrMS2wvbNhBhXGh6Vj69QDCP2yv8tIY7joo6Q==}
|
||||
peerDependencies:
|
||||
react: ^18.0.0
|
||||
react: ^18 || ^19
|
||||
|
||||
'@tanstack/vue-query@5.45.0':
|
||||
resolution: {integrity: sha512-WogAH4+xDPWbiK9CUXAE4cQiCyvWeYZI3g3/onKbkb3tVnoEPRhbGHANgxpfAEFY165Vj4afKnI3hkVQvr7aHA==}
|
||||
'@tanstack/vue-query@5.54.2':
|
||||
resolution: {integrity: sha512-GYIYee9WkUbPDD28t1kdNNtLCioiIva0MhKCvODGWoEML5MNONCX4/i4y2GGFi8i9nSbcA8MpvD+nt/tdZ+yJw==}
|
||||
peerDependencies:
|
||||
'@vue/composition-api': ^1.1.2
|
||||
vue: ^2.6.0 || ^3.3.0
|
||||
@ -3781,8 +3784,8 @@ packages:
|
||||
caniuse-lite@1.0.30001639:
|
||||
resolution: {integrity: sha512-eFHflNTBIlFwP2AIKaYuBQN/apnUoKNhBdza8ZnW/h2di4LCZ4xFqYlxUxo+LQ76KFI1PGcC1QDxMbxTZpSCAg==}
|
||||
|
||||
caniuse-lite@1.0.30001651:
|
||||
resolution: {integrity: sha512-9Cf+Xv1jJNe1xPZLGuUXLNkE1BoDkqRqYyFJ9TDYSqhduqA4hu4oR9HluGoWYQC/aj8WHjsGVV+bwkh0+tegRg==}
|
||||
caniuse-lite@1.0.30001658:
|
||||
resolution: {integrity: sha512-N2YVqWbJELVdrnsW5p+apoQyYt51aBMSsBZki1XZEfeBCexcM/sf4xiAHcXQBkuOwJBXtWF7aW1sYX6tKebPHw==}
|
||||
|
||||
capital-case@1.0.4:
|
||||
resolution: {integrity: sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==}
|
||||
@ -4200,6 +4203,15 @@ packages:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
debug@4.3.7:
|
||||
resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==}
|
||||
engines: {node: '>=6.0'}
|
||||
peerDependencies:
|
||||
supports-color: '*'
|
||||
peerDependenciesMeta:
|
||||
supports-color:
|
||||
optional: true
|
||||
|
||||
decimal.js@10.4.3:
|
||||
resolution: {integrity: sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==}
|
||||
|
||||
@ -4389,8 +4401,8 @@ packages:
|
||||
electron-to-chromium@1.4.815:
|
||||
resolution: {integrity: sha512-OvpTT2ItpOXJL7IGcYakRjHCt8L5GrrN/wHCQsRB4PQa1X9fe+X9oen245mIId7s14xvArCGSTIq644yPUKKLg==}
|
||||
|
||||
electron-to-chromium@1.5.12:
|
||||
resolution: {integrity: sha512-tIhPkdlEoCL1Y+PToq3zRNehUaKp3wBX/sr7aclAWdIWjvqAe/Im/H0SiCM4c1Q8BLPHCdoJTol+ZblflydehA==}
|
||||
electron-to-chromium@1.5.16:
|
||||
resolution: {integrity: sha512-2gQpi2WYobXmz2q23FrOBYTLcI1O/P4heW3eqX+ldmPVDQELRqhiebV380EhlGG12NtnX1qbK/FHpN0ba+7bLA==}
|
||||
|
||||
electron@31.2.0:
|
||||
resolution: {integrity: sha512-5w+kjOsGiTXytPSErBPNp/3znnuEMKc42RD41MqRoQkiYaR8x/Le2+qWk1cL60UwE/67oeKnOHnnol8xEuldGg==}
|
||||
@ -4509,6 +4521,10 @@ packages:
|
||||
resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
escalade@3.2.0:
|
||||
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
escape-html@1.0.3:
|
||||
resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==}
|
||||
|
||||
@ -5905,6 +5921,9 @@ packages:
|
||||
ms@2.1.2:
|
||||
resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==}
|
||||
|
||||
ms@2.1.3:
|
||||
resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==}
|
||||
|
||||
muggle-string@0.4.1:
|
||||
resolution: {integrity: sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==}
|
||||
|
||||
@ -6204,6 +6223,9 @@ packages:
|
||||
picocolors@1.0.1:
|
||||
resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==}
|
||||
|
||||
picocolors@1.1.0:
|
||||
resolution: {integrity: sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==}
|
||||
|
||||
picomatch@2.3.1:
|
||||
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
|
||||
engines: {node: '>=8.6'}
|
||||
@ -7472,6 +7494,17 @@ packages:
|
||||
vue-component-type-helpers@2.0.29:
|
||||
resolution: {integrity: sha512-58i+ZhUAUpwQ+9h5Hck0D+jr1qbYl4voRt5KffBx8qzELViQ4XdT/Tuo+mzq8u63teAG8K0lLaOiL5ofqW38rg==}
|
||||
|
||||
vue-demi@0.14.10:
|
||||
resolution: {integrity: sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==}
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@vue/composition-api': ^1.0.0-rc.1
|
||||
vue: ^3.0.0-0 || ^2.6.0
|
||||
peerDependenciesMeta:
|
||||
'@vue/composition-api':
|
||||
optional: true
|
||||
|
||||
vue-demi@0.14.8:
|
||||
resolution: {integrity: sha512-Uuqnk9YE9SsWeReYqK2alDI5YzciATE0r2SkA6iMAtuXvNTMNACJLJEXNXaEy94ECuBe4Sk6RzRU80kjdbIo1Q==}
|
||||
engines: {node: '>=12'}
|
||||
@ -8128,7 +8161,7 @@ snapshots:
|
||||
|
||||
'@babel/compat-data@7.24.7': {}
|
||||
|
||||
'@babel/compat-data@7.25.2': {}
|
||||
'@babel/compat-data@7.25.4': {}
|
||||
|
||||
'@babel/core@7.24.7':
|
||||
dependencies:
|
||||
@ -8154,16 +8187,16 @@ snapshots:
|
||||
dependencies:
|
||||
'@ampproject/remapping': 2.3.0
|
||||
'@babel/code-frame': 7.24.7
|
||||
'@babel/generator': 7.25.0
|
||||
'@babel/generator': 7.25.6
|
||||
'@babel/helper-compilation-targets': 7.25.2
|
||||
'@babel/helper-module-transforms': 7.25.2(@babel/core@7.25.2)
|
||||
'@babel/helpers': 7.25.0
|
||||
'@babel/parser': 7.25.3
|
||||
'@babel/helpers': 7.25.6
|
||||
'@babel/parser': 7.25.6
|
||||
'@babel/template': 7.25.0
|
||||
'@babel/traverse': 7.25.3
|
||||
'@babel/types': 7.25.2
|
||||
'@babel/traverse': 7.25.6
|
||||
'@babel/types': 7.25.6
|
||||
convert-source-map: 2.0.0
|
||||
debug: 4.3.6
|
||||
debug: 4.3.7
|
||||
gensync: 1.0.0-beta.2
|
||||
json5: 2.2.3
|
||||
semver: 6.3.1
|
||||
@ -8177,9 +8210,9 @@ snapshots:
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
jsesc: 2.5.2
|
||||
|
||||
'@babel/generator@7.25.0':
|
||||
'@babel/generator@7.25.6':
|
||||
dependencies:
|
||||
'@babel/types': 7.25.2
|
||||
'@babel/types': 7.25.6
|
||||
'@jridgewell/gen-mapping': 0.3.5
|
||||
'@jridgewell/trace-mapping': 0.3.25
|
||||
jsesc: 2.5.2
|
||||
@ -8198,7 +8231,7 @@ snapshots:
|
||||
|
||||
'@babel/helper-compilation-targets@7.25.2':
|
||||
dependencies:
|
||||
'@babel/compat-data': 7.25.2
|
||||
'@babel/compat-data': 7.25.4
|
||||
'@babel/helper-validator-option': 7.24.8
|
||||
browserslist: 4.23.3
|
||||
lru-cache: 5.1.1
|
||||
@ -8267,7 +8300,7 @@ snapshots:
|
||||
'@babel/helper-module-imports': 7.24.7
|
||||
'@babel/helper-simple-access': 7.24.7
|
||||
'@babel/helper-validator-identifier': 7.24.7
|
||||
'@babel/traverse': 7.25.3
|
||||
'@babel/traverse': 7.25.6
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
@ -8319,10 +8352,10 @@ snapshots:
|
||||
'@babel/template': 7.24.7
|
||||
'@babel/types': 7.24.7
|
||||
|
||||
'@babel/helpers@7.25.0':
|
||||
'@babel/helpers@7.25.6':
|
||||
dependencies:
|
||||
'@babel/template': 7.25.0
|
||||
'@babel/types': 7.25.2
|
||||
'@babel/types': 7.25.6
|
||||
|
||||
'@babel/highlight@7.24.7':
|
||||
dependencies:
|
||||
@ -8335,9 +8368,9 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/types': 7.24.7
|
||||
|
||||
'@babel/parser@7.25.3':
|
||||
'@babel/parser@7.25.6':
|
||||
dependencies:
|
||||
'@babel/types': 7.25.2
|
||||
'@babel/types': 7.25.6
|
||||
|
||||
'@babel/plugin-proposal-decorators@7.24.7(@babel/core@7.24.7)':
|
||||
dependencies:
|
||||
@ -8411,8 +8444,8 @@ snapshots:
|
||||
'@babel/template@7.25.0':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.24.7
|
||||
'@babel/parser': 7.25.3
|
||||
'@babel/types': 7.25.2
|
||||
'@babel/parser': 7.25.6
|
||||
'@babel/types': 7.25.6
|
||||
|
||||
'@babel/traverse@7.24.7':
|
||||
dependencies:
|
||||
@ -8429,14 +8462,14 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
'@babel/traverse@7.25.3':
|
||||
'@babel/traverse@7.25.6':
|
||||
dependencies:
|
||||
'@babel/code-frame': 7.24.7
|
||||
'@babel/generator': 7.25.0
|
||||
'@babel/parser': 7.25.3
|
||||
'@babel/generator': 7.25.6
|
||||
'@babel/parser': 7.25.6
|
||||
'@babel/template': 7.25.0
|
||||
'@babel/types': 7.25.2
|
||||
debug: 4.3.6
|
||||
'@babel/types': 7.25.6
|
||||
debug: 4.3.7
|
||||
globals: 11.12.0
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
@ -8447,7 +8480,7 @@ snapshots:
|
||||
'@babel/helper-validator-identifier': 7.24.7
|
||||
to-fast-properties: 2.0.0
|
||||
|
||||
'@babel/types@7.25.2':
|
||||
'@babel/types@7.25.6':
|
||||
dependencies:
|
||||
'@babel/helper-string-parser': 7.24.8
|
||||
'@babel/helper-validator-identifier': 7.24.7
|
||||
@ -9025,10 +9058,10 @@ snapshots:
|
||||
'@ianvs/prettier-plugin-sort-imports@4.3.0(prettier@3.3.2)':
|
||||
dependencies:
|
||||
'@babel/core': 7.25.2
|
||||
'@babel/generator': 7.25.0
|
||||
'@babel/parser': 7.25.3
|
||||
'@babel/traverse': 7.25.3
|
||||
'@babel/types': 7.25.2
|
||||
'@babel/generator': 7.25.6
|
||||
'@babel/parser': 7.25.6
|
||||
'@babel/traverse': 7.25.6
|
||||
'@babel/types': 7.25.6
|
||||
prettier: 3.3.2
|
||||
semver: 7.6.3
|
||||
transitivePeerDependencies:
|
||||
@ -10423,32 +10456,32 @@ snapshots:
|
||||
dependencies:
|
||||
remove-accents: 0.5.0
|
||||
|
||||
'@tanstack/query-core@5.45.0': {}
|
||||
'@tanstack/query-core@5.54.1': {}
|
||||
|
||||
'@tanstack/query-devtools@5.37.1': {}
|
||||
|
||||
'@tanstack/query-persist-client-core@5.45.0':
|
||||
'@tanstack/query-persist-client-core@5.54.1':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 5.45.0
|
||||
'@tanstack/query-core': 5.54.1
|
||||
|
||||
'@tanstack/react-query-devtools@5.45.1(@tanstack/react-query@5.45.1(react@18.3.1))(react@18.3.1)':
|
||||
'@tanstack/react-query-devtools@5.45.1(@tanstack/react-query@5.55.0(react@18.3.1))(react@18.3.1)':
|
||||
dependencies:
|
||||
'@tanstack/query-devtools': 5.37.1
|
||||
'@tanstack/react-query': 5.45.1(react@18.3.1)
|
||||
'@tanstack/react-query': 5.55.0(react@18.3.1)
|
||||
react: 18.3.1
|
||||
|
||||
'@tanstack/react-query@5.45.1(react@18.3.1)':
|
||||
'@tanstack/react-query@5.55.0(react@18.3.1)':
|
||||
dependencies:
|
||||
'@tanstack/query-core': 5.45.0
|
||||
'@tanstack/query-core': 5.54.1
|
||||
react: 18.3.1
|
||||
|
||||
'@tanstack/vue-query@5.45.0(vue@3.4.31(typescript@5.5.3))':
|
||||
'@tanstack/vue-query@5.54.2(vue@3.4.31(typescript@5.5.3))':
|
||||
dependencies:
|
||||
'@tanstack/match-sorter-utils': 8.15.1
|
||||
'@tanstack/query-core': 5.45.0
|
||||
'@tanstack/query-core': 5.54.1
|
||||
'@vue/devtools-api': 6.6.3
|
||||
vue: 3.4.31(typescript@5.5.3)
|
||||
vue-demi: 0.14.8(vue@3.4.31(typescript@5.5.3))
|
||||
vue-demi: 0.14.10(vue@3.4.31(typescript@5.5.3))
|
||||
|
||||
'@tootallnate/once@2.0.0': {}
|
||||
|
||||
@ -11461,8 +11494,8 @@ snapshots:
|
||||
|
||||
browserslist@4.23.3:
|
||||
dependencies:
|
||||
caniuse-lite: 1.0.30001651
|
||||
electron-to-chromium: 1.5.12
|
||||
caniuse-lite: 1.0.30001658
|
||||
electron-to-chromium: 1.5.16
|
||||
node-releases: 2.0.18
|
||||
update-browserslist-db: 1.1.0(browserslist@4.23.3)
|
||||
|
||||
@ -11567,7 +11600,7 @@ snapshots:
|
||||
|
||||
caniuse-lite@1.0.30001639: {}
|
||||
|
||||
caniuse-lite@1.0.30001651: {}
|
||||
caniuse-lite@1.0.30001658: {}
|
||||
|
||||
capital-case@1.0.4:
|
||||
dependencies:
|
||||
@ -12029,6 +12062,10 @@ snapshots:
|
||||
dependencies:
|
||||
ms: 2.1.2
|
||||
|
||||
debug@4.3.7:
|
||||
dependencies:
|
||||
ms: 2.1.3
|
||||
|
||||
decimal.js@10.4.3: {}
|
||||
|
||||
decompress-response@6.0.0:
|
||||
@ -12258,7 +12295,7 @@ snapshots:
|
||||
|
||||
electron-to-chromium@1.4.815: {}
|
||||
|
||||
electron-to-chromium@1.5.12: {}
|
||||
electron-to-chromium@1.5.16: {}
|
||||
|
||||
electron@31.2.0:
|
||||
dependencies:
|
||||
@ -12499,6 +12536,8 @@ snapshots:
|
||||
|
||||
escalade@3.1.2: {}
|
||||
|
||||
escalade@3.2.0: {}
|
||||
|
||||
escape-html@1.0.3: {}
|
||||
|
||||
escape-string-regexp@1.0.5: {}
|
||||
@ -14017,6 +14056,8 @@ snapshots:
|
||||
|
||||
ms@2.1.2: {}
|
||||
|
||||
ms@2.1.3: {}
|
||||
|
||||
muggle-string@0.4.1: {}
|
||||
|
||||
murmurhash@2.0.1: {}
|
||||
@ -14309,6 +14350,8 @@ snapshots:
|
||||
|
||||
picocolors@1.0.1: {}
|
||||
|
||||
picocolors@1.1.0: {}
|
||||
|
||||
picomatch@2.3.1: {}
|
||||
|
||||
pidtree@0.3.1: {}
|
||||
@ -15519,8 +15562,8 @@ snapshots:
|
||||
update-browserslist-db@1.1.0(browserslist@4.23.3):
|
||||
dependencies:
|
||||
browserslist: 4.23.3
|
||||
escalade: 3.1.2
|
||||
picocolors: 1.0.1
|
||||
escalade: 3.2.0
|
||||
picocolors: 1.1.0
|
||||
|
||||
upper-case-first@2.0.2:
|
||||
dependencies:
|
||||
@ -15751,6 +15794,10 @@ snapshots:
|
||||
|
||||
vue-component-type-helpers@2.0.29: {}
|
||||
|
||||
vue-demi@0.14.10(vue@3.4.31(typescript@5.5.3)):
|
||||
dependencies:
|
||||
vue: 3.4.31(typescript@5.5.3)
|
||||
|
||||
vue-demi@0.14.8(vue@3.4.31(typescript@5.5.3)):
|
||||
dependencies:
|
||||
vue: 3.4.31(typescript@5.5.3)
|
||||
|
Loading…
Reference in New Issue
Block a user