From a3e83e0fef2ea5daaace8c33be1cc36a29d35030 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Tue, 16 Jun 2026 19:39:51 -0700 Subject: [PATCH 1/2] chore(electron): Hotload UI --- packages/electron/README.md | 63 +++++++++ packages/electron/package.json | 2 +- packages/electron/src/global.d.ts | 3 + .../react/__tests__/ClerkProvider.test.tsx | 12 +- packages/electron/src/react/index.tsx | 39 +++++- pnpm-lock.yaml | 125 +++++++++--------- 6 files changed, 175 insertions(+), 69 deletions(-) diff --git a/packages/electron/README.md b/packages/electron/README.md index 29b755f2581..42757cb949a 100644 --- a/packages/electron/README.md +++ b/packages/electron/README.md @@ -88,6 +88,69 @@ import { ClerkProvider } from '@clerk/electron/react'; {/* ... */}; ``` +## Content Security Policy + +`@clerk/electron` loads Clerk's prebuilt UI from Clerk's CDN at runtime rather than bundling it, so your renderer's Content Security Policy must allow Clerk's Frontend API host. If it doesn't, the UI script fails to load and Clerk components never render. + +Replace `{fapi_host}` below with your instance's **Frontend API** host, found in the [Clerk Dashboard](https://dashboard.clerk.com) under **API keys**. It includes a `clerk.` segment (for example, `clerk.your-app.com` in production or `your-slug.clerk.accounts.dev` in development). This is _not_ the Account Portal URL (`your-slug.accounts.dev`) — using that host blocks the UI script from loading. + +``` +default-src 'self'; +script-src 'self' 'unsafe-inline' https://{fapi_host} https://challenges.cloudflare.com; +connect-src 'self' https://{fapi_host}; +img-src 'self' https://img.clerk.com data:; +style-src 'self' 'unsafe-inline'; +worker-src 'self' blob:; +frame-src 'self' https://challenges.cloudflare.com; +form-action 'self'; +``` + +> [!NOTE] +> This covers sign-in/up and the hotloaded UI. If you use Clerk Billing (Stripe) or other features, you'll need to allow additional origins; see Clerk's [CSP guide](https://clerk.com/docs/guides/secure/best-practices/csp-headers) for the full list. + +Apply it either with a `` tag in your renderer HTML: + +```html + +``` + +or, as [Electron's security guide](https://www.electronjs.org/docs/latest/tutorial/security#7-define-a-content-security-policy) recommends, as a response header from the main process: + +```ts +// main.ts +import { app, session } from 'electron'; + +const fapiHost = 'clerk.your-app.com'; + +app.whenReady().then(() => { + session.defaultSession.webRequest.onHeadersReceived((details, callback) => { + callback({ + responseHeaders: { + ...details.responseHeaders, + 'Content-Security-Policy': [ + [ + "default-src 'self'", + `script-src 'self' 'unsafe-inline' https://${fapiHost} https://challenges.cloudflare.com`, + `connect-src 'self' https://${fapiHost}`, + "img-src 'self' https://img.clerk.com data:", + "style-src 'self' 'unsafe-inline'", + "worker-src 'self' blob:", + "frame-src 'self' https://challenges.cloudflare.com", + "form-action 'self'", + ].join('; '), + ], + }, + }); + }); +}); +``` + +> [!NOTE] +> Loading the renderer from a dev server (such as Vite) requires looser rules for HMR: add `'unsafe-eval'` to `script-src` and your dev server's origin to `connect-src` (for example, `ws://localhost:5173 http://localhost:5173`). Many apps skip CSP during development and apply it only to packaged builds. + ## Support For help, visit our [support page](https://clerk.com/contact/support?utm_source=github&utm_medium=clerk_electron). diff --git a/packages/electron/package.json b/packages/electron/package.json index 5347bcfed38..113888786a5 100644 --- a/packages/electron/package.json +++ b/packages/electron/package.json @@ -90,7 +90,7 @@ "dependencies": { "@clerk/clerk-js": "workspace:^", "@clerk/react": "workspace:^", - "@clerk/ui": "workspace:^", + "@clerk/shared": "workspace:^", "tslib": "catalog:repo" }, "devDependencies": { diff --git a/packages/electron/src/global.d.ts b/packages/electron/src/global.d.ts index f14b55c0736..03252a51ccb 100644 --- a/packages/electron/src/global.d.ts +++ b/packages/electron/src/global.d.ts @@ -1,3 +1,5 @@ +import type { ClerkUIConstructor } from '@clerk/shared/ui'; + import type { OAuthTransport, TokenCache } from './shared/types'; declare const PACKAGE_NAME: string; @@ -10,5 +12,6 @@ declare global { tokenCache: TokenCache; oauthTransport: OAuthTransport; }; + __internal_ClerkUICtor?: ClerkUIConstructor; } } diff --git a/packages/electron/src/react/__tests__/ClerkProvider.test.tsx b/packages/electron/src/react/__tests__/ClerkProvider.test.tsx index 8bfab7bc695..0914feef2ed 100644 --- a/packages/electron/src/react/__tests__/ClerkProvider.test.tsx +++ b/packages/electron/src/react/__tests__/ClerkProvider.test.tsx @@ -10,6 +10,7 @@ let beforeRequest: let afterResponse: ((request: unknown, response: Response) => Promise) | null = null; const clerkConstructor = vi.hoisted(() => vi.fn()); +const loadClerkUIScript = vi.hoisted(() => vi.fn()); vi.mock('@clerk/clerk-js', () => ({ Clerk: class MockClerk { @@ -34,8 +35,9 @@ vi.mock('@clerk/react/internal', () => ({ }, })); -vi.mock('@clerk/ui', () => ({ - ui: { ClerkUI: 'mock-ui' }, +vi.mock('@clerk/shared/loadClerkJsScript', async importOriginal => ({ + ...(await importOriginal>()), + loadClerkUIScript, })); describe('Electron ClerkProvider', () => { @@ -60,6 +62,11 @@ describe('Electron ClerkProvider', () => { oauthTransport, }, }); + // Resolve the UI hotload so the provider's `ui.ClerkUI` promise does not reject during render. + loadClerkUIScript.mockImplementation(() => { + (window as unknown as { __internal_ClerkUICtor?: unknown }).__internal_ClerkUICtor = 'mock-ui-ctor'; + return Promise.resolve(null); + }); }); it('renders React ClerkProvider with Electron defaults', () => { @@ -77,7 +84,6 @@ describe('Electron ClerkProvider', () => { publishableKey: 'pk_test_provider', signInUrl: '/sign-in', standardBrowser: false, - ui: { ClerkUI: 'mock-ui' }, }); expect(capturedProviderProps?.Clerk).toBeDefined(); expect(capturedProviderProps?.__internal_oauthTransport).toEqual({ diff --git a/packages/electron/src/react/index.tsx b/packages/electron/src/react/index.tsx index 8f185655e92..a4efb14ed61 100644 --- a/packages/electron/src/react/index.tsx +++ b/packages/electron/src/react/index.tsx @@ -1,6 +1,7 @@ import type { ClerkProviderProps as ReactClerkProviderProps } from '@clerk/react'; import { InternalClerkProvider as ReactClerkProvider } from '@clerk/react/internal'; -import { ui } from '@clerk/ui'; +import { loadClerkUIScript } from '@clerk/shared/loadClerkJsScript'; +import type { ClerkUIConstructor } from '@clerk/shared/ui'; import type { ReactNode } from 'react'; import { createClerkInstance } from './create-clerk-instance'; @@ -18,6 +19,39 @@ export type ClerkProviderProps = Omit< publishableKey: string; }; +let cachedClerkUI: { promise: Promise; publishableKey: string } | null = null; + +function loadClerkUI(publishableKey: string, props: Partial): Promise { + if (cachedClerkUI?.publishableKey === publishableKey) { + return cachedClerkUI.promise; + } + + // Undocumented escape hatch for self-hosting/proxying the UI bundle; not part of the public props. + const { __internal_clerkUIUrl, __internal_clerkUIVersion } = props as { + __internal_clerkUIUrl?: string; + __internal_clerkUIVersion?: string; + }; + + const promise = loadClerkUIScript({ + publishableKey, + proxyUrl: typeof props.proxyUrl === 'string' ? props.proxyUrl : undefined, + domain: typeof props.domain === 'string' ? props.domain : undefined, + nonce: props.nonce, + __internal_clerkUIUrl, + __internal_clerkUIVersion, + }).then(() => { + if (!window.__internal_ClerkUICtor) { + throw new Error( + 'Clerk: Failed to load Clerk UI from the CDN. Ensure your Content Security Policy allows the Clerk Frontend API host in `script-src`. Contact support@clerk.com.', + ); + } + return window.__internal_ClerkUICtor; + }); + + cachedClerkUI = { promise, publishableKey }; + return promise; +} + function createOAuthTransport(): ClerkOAuthTransport | undefined { const bridge = window.__clerk_internal_electron?.oauthTransport; @@ -34,6 +68,7 @@ function createOAuthTransport(): ClerkOAuthTransport | undefined { export function ClerkProvider({ children, publishableKey, ...props }: ClerkProviderProps): JSX.Element { const clerk = createClerkInstance(publishableKey); const oauthTransport = createOAuthTransport(); + const clerkUI = loadClerkUI(publishableKey, props); return ( {children} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8aff7afae3b..94f99883a57 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -388,7 +388,7 @@ importers: version: 9.0.2 vitest-environment-miniflare: specifier: 2.14.4 - version: 2.14.4(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@25.6.0)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) + version: 2.14.4(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vitest@4.1.4) packages/chrome-extension: dependencies: @@ -532,9 +532,9 @@ importers: '@clerk/react': specifier: workspace:^ version: link:../react - '@clerk/ui': + '@clerk/shared': specifier: workspace:^ - version: link:../ui + version: link:../shared react: specifier: 18.3.1 version: 18.3.1 @@ -2955,7 +2955,7 @@ packages: '@expo/bunyan@4.0.1': resolution: {integrity: sha512-+Lla7nYSiHZirgK+U/uYzsLv/X+HaJienbD5AKX1UQZHYfWaP+9uuQluRB4GrEVWF0GZ7vEVp/jzaOT9k/SQlg==} - engines: {node: '>=0.10.0'} + engines: {'0': node >=0.10.0} '@expo/cli@0.22.28': resolution: {integrity: sha512-lvt72KNitGuixYD2l3SZmRKVu2G4zJpmg5V7WfUBNpmUU5oODBw/6qmiJ6kSLAlfDozscUk+BBGknBBzxUrwrA==} @@ -21971,6 +21971,20 @@ snapshots: - vite optional: true + '@vitest/browser-playwright@4.1.4(bufferutil@4.1.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(playwright@1.59.1)(utf-8-validate@5.0.10)(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))(vitest@4.1.4)': + dependencies: + '@vitest/browser': 4.1.4(bufferutil@4.1.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(utf-8-validate@5.0.10)(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))(vitest@4.1.4) + '@vitest/mocker': 4.1.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) + playwright: 1.59.1 + tinyrainbow: 3.1.0 + vitest: 4.1.4(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)))(happy-dom@18.0.1)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + optional: true + '@vitest/browser@4.1.4(bufferutil@4.1.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(utf-8-validate@5.0.10)(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))(vitest@4.1.4)': dependencies: '@blazediff/core': 1.9.1 @@ -21989,6 +22003,24 @@ snapshots: - vite optional: true + '@vitest/browser@4.1.4(bufferutil@4.1.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(utf-8-validate@5.0.10)(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))(vitest@4.1.4)': + dependencies: + '@blazediff/core': 1.9.1 + '@vitest/mocker': 4.1.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) + '@vitest/utils': 4.1.4 + magic-string: 0.30.21 + pngjs: 7.0.0 + sirv: 3.0.2 + tinyrainbow: 3.1.0 + vitest: 4.1.4(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)))(happy-dom@18.0.1)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) + ws: 8.20.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) + transitivePeerDependencies: + - bufferutil + - msw + - utf-8-validate + - vite + optional: true + '@vitest/coverage-v8@3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))': dependencies: '@ampproject/remapping': 2.3.0 @@ -22034,23 +22066,23 @@ snapshots: msw: 2.14.2(@types/node@22.19.17)(typescript@6.0.3) vite: 6.4.2(@types/node@22.19.17)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) - '@vitest/mocker@3.2.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))': + '@vitest/mocker@4.1.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))': dependencies: - '@vitest/spy': 3.2.4 + '@vitest/spy': 4.1.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.14.2(@types/node@25.6.0)(typescript@6.0.3) vite: 6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) - '@vitest/mocker@4.1.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))': + '@vitest/mocker@4.1.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))': dependencies: '@vitest/spy': 4.1.4 estree-walker: 3.0.3 magic-string: 0.30.21 optionalDependencies: msw: 2.14.2(@types/node@25.6.0)(typescript@6.0.3) - vite: 6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) + vite: 7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) '@vitest/pretty-format@3.2.4': dependencies: @@ -32664,27 +32696,6 @@ snapshots: - tsx - yaml - vite-node@3.2.4(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0): - dependencies: - cac: 6.7.14 - debug: 4.4.3(supports-color@8.1.1) - es-module-lexer: 1.7.0 - pathe: 2.0.3 - vite: 6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) - transitivePeerDependencies: - - '@types/node' - - jiti - - less - - lightningcss - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - vite-node@5.3.0(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0): dependencies: cac: 6.7.14 @@ -32856,14 +32867,14 @@ snapshots: dependencies: '@types/chrome': 0.0.114 - vitest-environment-miniflare@2.14.4(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@25.6.0)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)): + vitest-environment-miniflare@2.14.4(bufferutil@4.1.0)(utf-8-validate@5.0.10)(vitest@4.1.4): dependencies: '@miniflare/queues': 2.14.4 '@miniflare/runner-vm': 2.14.4 '@miniflare/shared': 2.14.4 '@miniflare/shared-test-environment': 2.14.4(bufferutil@4.1.0)(utf-8-validate@5.0.10) undici: 5.28.4 - vitest: 3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@25.6.0)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) + vitest: 4.1.4(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)))(happy-dom@18.0.1)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) transitivePeerDependencies: - bufferutil - utf-8-validate @@ -32913,55 +32924,43 @@ snapshots: - tsx - yaml - vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@25.6.0)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0): + vitest@4.1.4(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)))(happy-dom@18.0.1)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)): dependencies: - '@types/chai': 5.2.3 - '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) - '@vitest/pretty-format': 3.2.4 - '@vitest/runner': 3.2.4 - '@vitest/snapshot': 3.2.4 - '@vitest/spy': 3.2.4 - '@vitest/utils': 3.2.4 - chai: 5.3.3 - debug: 4.4.3(supports-color@8.1.1) + '@vitest/expect': 4.1.4 + '@vitest/mocker': 4.1.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) + '@vitest/pretty-format': 4.1.4 + '@vitest/runner': 4.1.4 + '@vitest/snapshot': 4.1.4 + '@vitest/spy': 4.1.4 + '@vitest/utils': 4.1.4 + es-module-lexer: 2.1.0 expect-type: 1.3.0 magic-string: 0.30.21 + obug: 2.1.1 pathe: 2.0.3 picomatch: 4.0.4 - std-env: 3.10.0 + std-env: 4.1.0 tinybench: 2.9.0 - tinyexec: 0.3.2 + tinyexec: 1.2.4 tinyglobby: 0.2.17 - tinypool: 1.1.1 - tinyrainbow: 2.0.0 + tinyrainbow: 3.1.0 vite: 6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) - vite-node: 3.2.4(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@edge-runtime/vm': 5.0.0 - '@types/debug': 4.1.12 + '@opentelemetry/api': 1.9.0 '@types/node': 25.6.0 + '@vitest/browser-playwright': 4.1.4(bufferutil@4.1.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(playwright@1.59.1)(utf-8-validate@5.0.10)(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))(vitest@4.1.4) + '@vitest/coverage-v8': 3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) happy-dom: 18.0.1 jsdom: 27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) transitivePeerDependencies: - - jiti - - less - - lightningcss - msw - - sass - - sass-embedded - - stylus - - sugarss - - supports-color - - terser - - tsx - - yaml - vitest@4.1.4(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)))(happy-dom@18.0.1)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)): + vitest@4.1.4(@edge-runtime/vm@5.0.0)(@opentelemetry/api@1.9.0)(@types/node@25.6.0)(@vitest/browser-playwright@4.1.4)(@vitest/coverage-v8@3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)))(happy-dom@18.0.1)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)): dependencies: '@vitest/expect': 4.1.4 - '@vitest/mocker': 4.1.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) + '@vitest/mocker': 4.1.4(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) '@vitest/pretty-format': 4.1.4 '@vitest/runner': 4.1.4 '@vitest/snapshot': 4.1.4 @@ -32978,13 +32977,13 @@ snapshots: tinyexec: 1.2.4 tinyglobby: 0.2.17 tinyrainbow: 3.1.0 - vite: 6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) + vite: 7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0) why-is-node-running: 2.3.0 optionalDependencies: '@edge-runtime/vm': 5.0.0 '@opentelemetry/api': 1.9.0 '@types/node': 25.6.0 - '@vitest/browser-playwright': 4.1.4(bufferutil@4.1.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(playwright@1.59.1)(utf-8-validate@5.0.10)(vite@6.4.2(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))(vitest@4.1.4) + '@vitest/browser-playwright': 4.1.4(bufferutil@4.1.0)(msw@2.14.2(@types/node@25.6.0)(typescript@6.0.3))(playwright@1.59.1)(utf-8-validate@5.0.10)(vite@7.3.5(@types/node@25.6.0)(jiti@2.7.0)(lightningcss@1.32.0)(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0))(vitest@4.1.4) '@vitest/coverage-v8': 3.2.4(vitest@3.2.4(@edge-runtime/vm@5.0.0)(@types/debug@4.1.12)(@types/node@22.19.17)(happy-dom@18.0.1)(jiti@2.7.0)(jsdom@27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10))(lightningcss@1.32.0)(msw@2.14.2(@types/node@22.19.17)(typescript@6.0.3))(terser@5.46.1)(tsx@4.20.6)(yaml@2.9.0)) happy-dom: 18.0.1 jsdom: 27.0.0(bufferutil@4.1.0)(utf-8-validate@5.0.10) From 451f82a6329038c7bbe821c936046427aa9cf3a2 Mon Sep 17 00:00:00 2001 From: wobsoriano Date: Tue, 16 Jun 2026 20:51:17 -0700 Subject: [PATCH 2/2] chore: update readme --- packages/electron/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/electron/README.md b/packages/electron/README.md index 42757cb949a..e2d51ee052d 100644 --- a/packages/electron/README.md +++ b/packages/electron/README.md @@ -149,7 +149,7 @@ app.whenReady().then(() => { ``` > [!NOTE] -> Loading the renderer from a dev server (such as Vite) requires looser rules for HMR: add `'unsafe-eval'` to `script-src` and your dev server's origin to `connect-src` (for example, `ws://localhost:5173 http://localhost:5173`). Many apps skip CSP during development and apply it only to packaged builds. +> Loading the renderer from a dev server (such as Vite) requires looser rules for HMR: add `'unsafe-eval'` to `script-src` and your dev server's origin to `connect-src` (for example, `ws://localhost: http://localhost:`). Many apps skip CSP during development and apply it only to packaged builds. ## Support