From 1e797970541b3646fcd2b4997b32282ab52bd887 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rge=20N=C3=A6ss?= Date: Mon, 30 Sep 2024 15:53:26 +0200 Subject: [PATCH 1/9] fix(core): emit setting from localStorage immediately upon subscription (#7560) --- .../src/core/store/key-value/localStorageSWR.ts | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/packages/sanity/src/core/store/key-value/localStorageSWR.ts b/packages/sanity/src/core/store/key-value/localStorageSWR.ts index d4a4273d6ea..366e428e926 100644 --- a/packages/sanity/src/core/store/key-value/localStorageSWR.ts +++ b/packages/sanity/src/core/store/key-value/localStorageSWR.ts @@ -1,27 +1,16 @@ import {isEqual} from 'lodash' -import {fromEvent, merge, NEVER} from 'rxjs' -import {distinctUntilChanged, filter, map, tap} from 'rxjs/operators' +import {merge, of} from 'rxjs' +import {distinctUntilChanged, tap} from 'rxjs/operators' import {localStoreStorage} from './storage/localStoreStorage' import {type KeyValueStore, type KeyValueStoreValue} from './types' -// Whether or not to enable instant user sync between tabs -// if set to true, the setting will update instantly across all tabs -const ENABLE_CROSS_TAB_SYNC = false - /** * Wraps a KeyValueStore and adds Stale-While-Revalidate (SWR) behavior to it */ export function withLocalStorageSWR(wrappedStore: KeyValueStore): KeyValueStore { - const storageEvent = ENABLE_CROSS_TAB_SYNC ? fromEvent(window, 'storage') : NEVER - function getKey(key: string) { - const lsUpdates = storageEvent.pipe( - filter((event) => event.key === key), - map(() => localStoreStorage.getKey(key)), - ) - - return merge(lsUpdates, wrappedStore.getKey(key)).pipe( + return merge(of(localStoreStorage.getKey(key)), wrappedStore.getKey(key)).pipe( distinctUntilChanged(isEqual), tap((value) => { localStoreStorage.setKey(key, value) From ae1c9c28b8fce496483a1c9512f593009f478171 Mon Sep 17 00:00:00 2001 From: RitaDias Date: Mon, 30 Sep 2024 16:05:39 +0200 Subject: [PATCH 2/9] chore(sanity): update naming of draft created telemetry event (#7561) --- .../panes/document/__telemetry__/documentPanes.telemetry.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/sanity/src/structure/panes/document/__telemetry__/documentPanes.telemetry.ts b/packages/sanity/src/structure/panes/document/__telemetry__/documentPanes.telemetry.ts index 5718de4f404..ef604a2aed1 100644 --- a/packages/sanity/src/structure/panes/document/__telemetry__/documentPanes.telemetry.ts +++ b/packages/sanity/src/structure/panes/document/__telemetry__/documentPanes.telemetry.ts @@ -14,7 +14,7 @@ export const DocumentURLCopied = defineEvent({ * @internal */ export const CreatedDraft = defineEvent({ - name: 'Create a new draft', + name: 'New Draft Created', version: 1, description: 'User created a new draft', }) From 7fcf22a948a1806c7c7409355df5d0b8617c576e Mon Sep 17 00:00:00 2001 From: Jordan Lawrence Date: Mon, 30 Sep 2024 16:26:13 +0100 Subject: [PATCH 3/9] feat(core): specific error when dev server is stopped (#7476) * feat(core): when dev server stops, highlight this with own error boundary * feat(core): simplified, and using nested error boundary for catching dev server stop error * refactor(core): simplifying use of DevServerStatus as lazy import * refactor(core): naming refactor * feat(core): removing dev server stopped toast as unnecessary * refactor(core): using built ins from vite; making more explicit this is only for default vite * chore: moving babel vite transform to test-config package * chore: moving babel deps to test-config * chore: tidy to lock and named export for type used * fix: ignoring un-identified uses of babel presets and plugins in test-config * chore: naming of vite dev server stopped error --- package.json | 3 - packages/@repo/test-config/.depcheckrc.json | 8 +++ .../test-config/jest/createJestConfig.mjs | 7 +- packages/@repo/test-config/package.json | 4 ++ .../sanity/src/core/error/ErrorLogger.tsx | 4 ++ .../src/core/studio/StudioErrorBoundary.tsx | 24 ++++++- .../sanity/src/core/studio/StudioLayout.tsx | 11 ++- .../src/core/studio/ViteDevServerStopped.tsx | 69 +++++++++++++++++++ pnpm-lock.yaml | 29 +++++--- 9 files changed, 142 insertions(+), 17 deletions(-) create mode 100644 packages/@repo/test-config/.depcheckrc.json create mode 100644 packages/sanity/src/core/studio/ViteDevServerStopped.tsx diff --git a/package.json b/package.json index 90b1b6822ee..162e8f0ae74 100644 --- a/package.json +++ b/package.json @@ -99,9 +99,6 @@ }, "prettier": "@sanity/prettier-config", "devDependencies": { - "@babel/preset-env": "^7.24.7", - "@babel/preset-react": "^7.24.7", - "@babel/preset-typescript": "^7.24.7", "@google-cloud/storage": "^7.11.0", "@playwright/test": "1.44.1", "@repo/dev-aliases": "workspace:*", diff --git a/packages/@repo/test-config/.depcheckrc.json b/packages/@repo/test-config/.depcheckrc.json new file mode 100644 index 00000000000..6f9da0ba787 --- /dev/null +++ b/packages/@repo/test-config/.depcheckrc.json @@ -0,0 +1,8 @@ +{ + "ignores": [ + "@babel/preset-env", + "@babel/preset-react", + "@babel/preset-typescript", + "babel-plugin-transform-vite-meta-hot" + ] +} diff --git a/packages/@repo/test-config/jest/createJestConfig.mjs b/packages/@repo/test-config/jest/createJestConfig.mjs index 174738b1f3d..8d1f3fbbd6a 100644 --- a/packages/@repo/test-config/jest/createJestConfig.mjs +++ b/packages/@repo/test-config/jest/createJestConfig.mjs @@ -1,9 +1,10 @@ /* eslint-disable tsdoc/syntax */ -import devAliases from '@repo/dev-aliases' - import path from 'node:path' + +import devAliases from '@repo/dev-aliases' import {escapeRegExp, omit} from 'lodash-es' + import {resolveDirName} from './resolveDirName.mjs' const dirname = resolveDirName(import.meta.url) @@ -71,7 +72,6 @@ export function createJestConfig(config = {}) { resolver: path.resolve(dirname, './resolver.cjs'), testEnvironment: path.resolve(dirname, './jsdom.jest.env.ts'), setupFiles: [...setupFiles, path.resolve(dirname, './setup.ts')], - // testEnvironment: 'jsdom', testEnvironmentOptions: { url: 'http://localhost:3333', }, @@ -103,6 +103,7 @@ export function createJestConfig(config = {}) { '@babel/preset-typescript', ['@babel/preset-react', {runtime: 'automatic'}], ], + plugins: ['babel-plugin-transform-vite-meta-hot'], }, ], }, diff --git a/packages/@repo/test-config/package.json b/packages/@repo/test-config/package.json index 8c8c09da1e3..536754f7f34 100644 --- a/packages/@repo/test-config/package.json +++ b/packages/@repo/test-config/package.json @@ -9,8 +9,12 @@ "./vitest": "./vitest/index.mjs" }, "devDependencies": { + "@babel/preset-env": "^7.24.7", + "@babel/preset-react": "^7.24.7", + "@babel/preset-typescript": "^7.24.7", "@jest/globals": "^29.7.0", "@repo/dev-aliases": "workspace:*", + "babel-plugin-transform-vite-meta-hot": "^1.0.0", "dotenv": "^16.4.5", "jest-environment-jsdom": "^29.7.0", "lodash-es": "^4.17.21", diff --git a/packages/sanity/src/core/error/ErrorLogger.tsx b/packages/sanity/src/core/error/ErrorLogger.tsx index 708699b8baf..87dbfb75a50 100644 --- a/packages/sanity/src/core/error/ErrorLogger.tsx +++ b/packages/sanity/src/core/error/ErrorLogger.tsx @@ -64,5 +64,9 @@ function isKnownError(err: Error): boolean { return true } + if ('ViteDevServerStoppedError' in err && err.ViteDevServerStoppedError) { + return true + } + return false } diff --git a/packages/sanity/src/core/studio/StudioErrorBoundary.tsx b/packages/sanity/src/core/studio/StudioErrorBoundary.tsx index 7c26dc8179f..32b0de92a00 100644 --- a/packages/sanity/src/core/studio/StudioErrorBoundary.tsx +++ b/packages/sanity/src/core/studio/StudioErrorBoundary.tsx @@ -11,7 +11,14 @@ import { Stack, Text, } from '@sanity/ui' -import {type ComponentType, type ErrorInfo, type ReactNode, useCallback, useState} from 'react' +import { + type ComponentType, + type ErrorInfo, + lazy, + type ReactNode, + useCallback, + useState, +} from 'react' import {ErrorActions, isDev, isProd} from 'sanity' import {styled} from 'styled-components' import {useHotModuleReload} from 'use-hot-module-reload' @@ -22,6 +29,17 @@ import {CorsOriginError} from '../store' import {isRecord} from '../util' import {CorsOriginErrorScreen, SchemaErrorsScreen} from './screens' +/** + * The DevServerStoppedErrorScreen will always have been lazy loaded to client + * in instances where it is used, since DevServerStoppedError is only thrown + * when this module is loaded, and this screen is also conditional on this error type + */ +const DevServerStoppedErrorScreen = lazy(() => + import('./ViteDevServerStopped').then((DevServerStopped) => ({ + default: DevServerStopped.DevServerStoppedErrorScreen, + })), +) + interface StudioErrorBoundaryProps { children: ReactNode heading?: string @@ -80,6 +98,10 @@ export const StudioErrorBoundary: ComponentType = ({ return } + if (error && 'ViteDevServerStoppedError' in error && error.ViteDevServerStoppedError) { + return + } + if (!error) { return {children} } diff --git a/packages/sanity/src/core/studio/StudioLayout.tsx b/packages/sanity/src/core/studio/StudioLayout.tsx index 5641104e904..9c992354bcc 100644 --- a/packages/sanity/src/core/studio/StudioLayout.tsx +++ b/packages/sanity/src/core/studio/StudioLayout.tsx @@ -1,7 +1,7 @@ /* eslint-disable i18next/no-literal-string, @sanity/i18n/no-attribute-template-literals */ import {Card, Flex} from '@sanity/ui' import {startCase} from 'lodash' -import {Suspense, useCallback, useEffect, useMemo, useState} from 'react' +import {lazy, Suspense, useCallback, useEffect, useMemo, useState} from 'react' import {NavbarContext} from 'sanity/_singletons' import {RouteScope, useRouter, useRouterState} from 'sanity/router' import {styled} from 'styled-components' @@ -18,6 +18,14 @@ import { import {StudioErrorBoundary} from './StudioErrorBoundary' import {useWorkspace} from './workspace' +const DetectViteDevServerStopped = lazy(() => + import('./ViteDevServerStopped').then((DevServerStopped) => ({ + default: DevServerStopped.DetectViteDevServerStopped, + })), +) + +const detectViteDevServerStopped = import.meta.hot && process.env.NODE_ENV === 'development' + const SearchFullscreenPortalCard = styled(Card)` height: 100%; left: 0; @@ -173,6 +181,7 @@ export function StudioLayoutComponent() { {/* By using the tool name as the key on the error boundary, we force it to re-render when switching tools, which ensures we don't show the wrong tool having crashed */} + {detectViteDevServerStopped && }