diff --git a/packages/backend/server/package.json b/packages/backend/server/package.json index 872e79ee317a8..3488346604552 100644 --- a/packages/backend/server/package.json +++ b/packages/backend/server/package.json @@ -71,7 +71,7 @@ "@opentelemetry/semantic-conventions": "^1.38.0", "@prisma/client": "^6.6.0", "@prisma/instrumentation": "^6.7.0", - "@queuedash/api": "^3.14.0", + "@queuedash/api": "^3.16.0", "@react-email/components": "0.0.38", "@socket.io/redis-adapter": "^8.3.0", "ai": "^5.0.118", diff --git a/packages/backend/server/src/__tests__/app/selfhost.e2e.ts b/packages/backend/server/src/__tests__/app/selfhost.e2e.ts index 088dbdaaeb845..bf7a74bd0b604 100644 --- a/packages/backend/server/src/__tests__/app/selfhost.e2e.ts +++ b/packages/backend/server/src/__tests__/app/selfhost.e2e.ts @@ -97,7 +97,7 @@ test('should always return static asset files', async t => { t.is(res.text, "const name = 'affine'"); res = await request(t.context.app.getHttpServer()) - .get('/main.b.js') + .get('/admin/main.b.js') .expect(200); t.is(res.text, "const name = 'affine-admin'"); @@ -119,7 +119,7 @@ test('should always return static asset files', async t => { t.is(res.text, "const name = 'affine'"); res = await request(t.context.app.getHttpServer()) - .get('/main.b.js') + .get('/admin/main.b.js') .expect(200); t.is(res.text, "const name = 'affine-admin'"); diff --git a/packages/backend/server/src/core/selfhost/static.ts b/packages/backend/server/src/core/selfhost/static.ts index a04c248a7c815..5faf2920459ee 100644 --- a/packages/backend/server/src/core/selfhost/static.ts +++ b/packages/backend/server/src/core/selfhost/static.ts @@ -52,7 +52,7 @@ export class StaticFilesResolver implements OnModuleInit { // serve all static files app.use( - basePath, + basePath + '/admin', serveStatic(join(staticPath, 'admin'), { redirect: false, index: false, diff --git a/packages/frontend/admin/package.json b/packages/frontend/admin/package.json index df71544e5d113..1fdcc1d8701a9 100644 --- a/packages/frontend/admin/package.json +++ b/packages/frontend/admin/package.json @@ -9,7 +9,7 @@ "@affine/graphql": "workspace:*", "@affine/routes": "workspace:*", "@blocksuite/icons": "^2.2.17", - "@queuedash/ui": "^3.14.0", + "@queuedash/ui": "^3.16.0", "@radix-ui/react-accordion": "^1.2.2", "@radix-ui/react-alert-dialog": "^1.1.3", "@radix-ui/react-aspect-ratio": "^1.1.1", @@ -74,7 +74,7 @@ "scripts": { "build": "affine bundle", "dev": "affine bundle --dev", - "update-shadcn": "shadcn-ui add -p src/components/ui" + "update-shadcn": "yarn dlx shadcn@latest add -p src/components/ui" }, "exports": { "./*": "./src/*.ts", diff --git a/packages/frontend/admin/src/global.css b/packages/frontend/admin/src/global.css index d556415adfe4a..ac09ba4c4fcee 100644 --- a/packages/frontend/admin/src/global.css +++ b/packages/frontend/admin/src/global.css @@ -1,5 +1,7 @@ @config '../tailwind.config.js'; +@layer properties, theme, base, components, utilities, queuedash; + @import 'tailwindcss'; @import 'tailwindcss/utilities'; @import '@toeverything/theme/style.css'; diff --git a/packages/frontend/admin/src/modules/queue/index.tsx b/packages/frontend/admin/src/modules/queue/index.tsx index ea3b2c233e614..0e269a176114b 100644 --- a/packages/frontend/admin/src/modules/queue/index.tsx +++ b/packages/frontend/admin/src/modules/queue/index.tsx @@ -1,19 +1,98 @@ -import '@queuedash/ui/dist/styles.css'; -import './queue.css'; +import './queuedash.css'; import { QueueDashApp } from '@queuedash/ui'; +import { useEffect } from 'react'; import { Header } from '../header'; +const QUEUEDASH_SCOPE_CLASS = 'affine-queuedash'; +const PORTAL_CONTENT_SELECTOR = + '.react-aria-ModalOverlay, .react-aria-Menu, [data-rac][data-placement][data-trigger]'; + export function QueuePage() { + useEffect(() => { + const marked = new Set(); + + const markScopeRoot = (el: Element) => { + if (!(el instanceof HTMLElement)) { + return; + } + + if (el.classList.contains(QUEUEDASH_SCOPE_CLASS)) { + return; + } + + el.classList.add(QUEUEDASH_SCOPE_CLASS); + marked.add(el); + }; + + const isPortalContent = (el: Element) => { + return ( + el.matches(PORTAL_CONTENT_SELECTOR) || + !!el.querySelector(PORTAL_CONTENT_SELECTOR) + ); + }; + + const markIfPortalRoot = (el: Element) => { + if (!isPortalContent(el)) { + return; + } + markScopeRoot(el); + }; + + const getBodyChildRoot = (el: Element) => { + let current: Element | null = el; + while ( + current?.parentElement && + current.parentElement !== document.body + ) { + current = current.parentElement; + } + return current?.parentElement === document.body ? current : null; + }; + + Array.from(document.body.children).forEach(child => { + if (child.id === 'app') { + return; + } + markIfPortalRoot(child); + }); + + const observer = new MutationObserver(mutations => { + const appRoot = document.getElementById('app'); + for (const mutation of mutations) { + for (const node of mutation.addedNodes) { + if (!(node instanceof Element)) { + continue; + } + + const root = getBodyChildRoot(node) ?? node; + if (appRoot && root === appRoot) { + continue; + } + markIfPortalRoot(root); + } + } + }); + + observer.observe(document.body, { childList: true, subtree: true }); + + return () => { + observer.disconnect(); + marked.forEach(el => el.classList.remove(QUEUEDASH_SCOPE_CLASS)); + }; + }, []); + return (
- +
+ +
); diff --git a/packages/frontend/admin/src/modules/queue/queue.css b/packages/frontend/admin/src/modules/queue/queue.css deleted file mode 100644 index 64d120f7ceaaa..0000000000000 --- a/packages/frontend/admin/src/modules/queue/queue.css +++ /dev/null @@ -1,5 +0,0 @@ -/* Scoped queuedash modal alignment */ - -.react-aria-ModalOverlay section[role='dialog'] { - transform: unset; -} diff --git a/packages/frontend/admin/src/modules/queue/queuedash.css b/packages/frontend/admin/src/modules/queue/queuedash.css new file mode 100644 index 0000000000000..4580e21953362 --- /dev/null +++ b/packages/frontend/admin/src/modules/queue/queuedash.css @@ -0,0 +1,14 @@ +@import '@queuedash/ui/dist/styles.css' layer(queuedash); + +/* + * QueueDash UI is built with Tailwind v3 (translate via `transform`), while AFFiNE Admin + * uses Tailwind v4 (translate via the individual `translate` property). When QueueDash + * overlays are portaled to `document.body`, both utility sets can apply at once and + * result in double transforms (mis-centered dialogs, etc). Reset individual transform + * properties within the queuedash scope so Tailwind v3 styles win. + */ +:where(.affine-queuedash) * { + translate: none; + rotate: none; + scale: none; +} diff --git a/packages/frontend/apps/electron/src/helper/index.ts b/packages/frontend/apps/electron/src/helper/index.ts index bda534d3dcd69..40c87964f0b3e 100644 --- a/packages/frontend/apps/electron/src/helper/index.ts +++ b/packages/frontend/apps/electron/src/helper/index.ts @@ -25,6 +25,9 @@ function setupRendererConnection(rendererPort: Electron.MessagePortMain) { return result; } catch (error) { logger.error('[async-api]', `${namespace}.${name}`, error); + // Propagate errors to the renderer so callers don't receive `undefined` + // and fail with confusing TypeErrors. + throw error instanceof Error ? error : new Error(String(error)); } }; return [`${namespace}:${name}`, handlerWithLog]; diff --git a/packages/frontend/native/nbstore/src/storage.rs b/packages/frontend/native/nbstore/src/storage.rs index 71ad15ef4c3fb..0e5622845e277 100644 --- a/packages/frontend/native/nbstore/src/storage.rs +++ b/packages/frontend/native/nbstore/src/storage.rs @@ -4,7 +4,7 @@ use affine_schema::get_migrator; use memory_indexer::InMemoryIndex; use sqlx::{ Pool, Row, - migrate::MigrateDatabase, + migrate::{MigrateDatabase, Migration, Migrator}, sqlite::{Sqlite, SqliteConnectOptions, SqlitePoolOptions}, }; use tokio::sync::RwLock; @@ -75,11 +75,74 @@ impl SqliteDocStorage { async fn migrate(&self) -> Result<()> { let migrator = get_migrator(); - migrator.run(&self.pool).await?; + if let Err(err) = migrator.run(&self.pool).await { + // Compatibility: migration 3 (`add_idx_snapshots`) had a whitespace-only SQL + // change (trailing space) between releases, which causes sqlx to reject + // existing DBs with: `VersionMismatch(3)`. It's safe to fix by updating + // the stored checksum. + if matches!(err, sqlx::migrate::MigrateError::VersionMismatch(3)) + && self.try_repair_migration_3_checksum(&migrator).await? + { + migrator.run(&self.pool).await?; + } else { + return Err(err.into()); + } + } Ok(()) } + async fn try_repair_migration_3_checksum(&self, migrator: &Migrator) -> Result { + let Some(migration) = migrator.iter().find(|m| m.version == 3) else { + return Ok(false); + }; + + // We're only prepared to repair the known `add_idx_snapshots` whitespace-only + // mismatch. + if migration.description.as_ref() != "add_idx_snapshots" { + return Ok(false); + } + + let row = sqlx::query("SELECT description, checksum FROM _sqlx_migrations WHERE version = 3") + .fetch_optional(&self.pool) + .await?; + + let Some(row) = row else { + return Ok(false); + }; + + let applied_description: String = row.try_get("description")?; + if applied_description != migration.description.as_ref() { + return Ok(false); + } + + let applied_checksum: Vec = row.try_get("checksum")?; + let expected_checksum = migration.checksum.as_ref(); + + // sqlx computes the checksum as SHA-384 of the raw SQL bytes. The legacy + // variant had an extra trailing space at the end of the SQL string (after + // the final newline). + let legacy_sql = format!("{} ", migration.sql); + let legacy_migration = Migration::new( + migration.version, + migration.description.clone(), + migration.migration_type, + std::borrow::Cow::Owned(legacy_sql), + migration.no_tx, + ); + + if applied_checksum.as_slice() != legacy_migration.checksum.as_ref() { + return Ok(false); + } + + sqlx::query("UPDATE _sqlx_migrations SET checksum = ? WHERE version = 3") + .bind(expected_checksum) + .execute(&self.pool) + .await?; + + Ok(true) + } + pub async fn close(&self) { self.pool.close().await } @@ -100,6 +163,11 @@ impl SqliteDocStorage { #[cfg(test)] mod tests { + use std::borrow::Cow; + + use affine_schema::get_migrator; + use sqlx::migrate::{Migration, Migrator}; + use super::*; async fn get_storage() -> SqliteDocStorage { @@ -135,4 +203,57 @@ mod tests { let storage = SqliteDocStorage::new(":memory:".to_string()); assert!(!storage.validate().await.unwrap()); } + + #[tokio::test] + async fn connect_repairs_whitespace_only_migration_checksum_mismatch() { + // Simulate a DB migrated with an older `add_idx_snapshots` SQL that had a + // trailing space. + let storage = SqliteDocStorage::new(":memory:".to_string()); + + let new_migrator = get_migrator(); + let mut migrations = new_migrator.migrations.to_vec(); + assert!(migrations.len() >= 3); + + let mig3 = migrations[2].clone(); + assert_eq!(mig3.version, 3); + assert_eq!(mig3.description.as_ref(), "add_idx_snapshots"); + + let legacy_sql = format!("{} ", mig3.sql); + migrations[2] = Migration::new( + mig3.version, + mig3.description.clone(), + mig3.migration_type, + Cow::Owned(legacy_sql), + mig3.no_tx, + ); + + // The legacy DB didn't have newer migrations. + migrations.truncate(3); + let legacy_migrator = Migrator { + migrations: Cow::Owned(migrations), + ..Migrator::DEFAULT + }; + + legacy_migrator.run(&storage.pool).await.unwrap(); + + // Now connecting with the current code should auto-repair the checksum and + // succeed. + storage.connect().await.unwrap(); + + let expected_checksum = get_migrator() + .iter() + .find(|m| m.version == 3) + .unwrap() + .checksum + .as_ref() + .to_vec(); + + let row = sqlx::query("SELECT checksum FROM _sqlx_migrations WHERE version = 3") + .fetch_one(&storage.pool) + .await + .unwrap(); + let checksum: Vec = row.get("checksum"); + + assert_eq!(checksum, expected_checksum); + } } diff --git a/tools/cli/bin/cli.js b/tools/cli/bin/cli.js index be4c9ecf2465f..60c59c1d5bcb6 100755 --- a/tools/cli/bin/cli.js +++ b/tools/cli/bin/cli.js @@ -1,3 +1,4 @@ +#!/usr/bin/env node import { spawnSync } from 'node:child_process'; spawnSync('yarn', ['r', 'affine.ts', ...process.argv.slice(2)], { diff --git a/tools/cli/package.json b/tools/cli/package.json index 6eec88262a4b1..9131ca0218668 100644 --- a/tools/cli/package.json +++ b/tools/cli/package.json @@ -39,6 +39,7 @@ "node-loader": "^2.1.0", "postcss": "^8.4.49", "postcss-loader": "^8.1.1", + "postcss-selector-parser": "^7.1.0", "prettier": "^3.7.4", "react-refresh": "^0.17.0", "source-map-loader": "^5.0.0", diff --git a/tools/cli/src/bundle.ts b/tools/cli/src/bundle.ts index 182a56b578a34..43a0756434d40 100644 --- a/tools/cli/src/bundle.ts +++ b/tools/cli/src/bundle.ts @@ -88,7 +88,11 @@ function getWebpackBundleConfigs(pkg: Package): webpack.MultiConfiguration { switch (pkg.name) { case '@affine/admin': { return [ - createWebpackHTMLTargetConfig(pkg, pkg.srcPath.join('index.tsx').value), + createWebpackHTMLTargetConfig( + pkg, + pkg.srcPath.join('index.tsx').value, + { selfhostPublicPath: '/admin/' } + ), ] as webpack.MultiConfiguration; } case '@affine/web': @@ -158,7 +162,9 @@ function getRspackBundleConfigs(pkg: Package): MultiRspackOptions { switch (pkg.name) { case '@affine/admin': { return [ - createRspackHTMLTargetConfig(pkg, pkg.srcPath.join('index.tsx').value), + createRspackHTMLTargetConfig(pkg, pkg.srcPath.join('index.tsx').value, { + selfhostPublicPath: '/admin/', + }), ] as MultiRspackOptions; } case '@affine/web': diff --git a/tools/cli/src/postcss/queuedash-scope.ts b/tools/cli/src/postcss/queuedash-scope.ts new file mode 100644 index 0000000000000..e9eca5b0c090e --- /dev/null +++ b/tools/cli/src/postcss/queuedash-scope.ts @@ -0,0 +1,111 @@ +import type { AtRule, Container, Node, PluginCreator, Rule } from 'postcss'; +import selectorParser from 'postcss-selector-parser'; + +export interface QueuedashScopeOptions { + scopeClass?: string; +} + +function normalizeFilePath(filePath: string) { + return filePath.replaceAll('\\', '/').split('?')[0]; +} + +function isInKeyframes(rule: Rule) { + let parent: Node | undefined = rule.parent; + while (parent) { + if (parent.type === 'atrule') { + const name = (parent as AtRule).name?.toLowerCase(); + if (name && name.endsWith('keyframes')) { + return true; + } + } + parent = parent.parent; + } + return false; +} + +const DEFAULT_SCOPE_CLASS = 'affine-queuedash'; + +export const queuedashScopePostcssPlugin: PluginCreator< + QueuedashScopeOptions +> = (options = {}) => { + const scopeClass = options.scopeClass ?? DEFAULT_SCOPE_CLASS; + const scopeSelector = `:where(.${scopeClass})`; + + const scopeAst = selectorParser().astSync(scopeSelector); + const scopeNodes = scopeAst.nodes[0]?.nodes; + + if (!scopeNodes) { + throw new Error( + `[queuedashScopePostcssPlugin] Failed to parse scope selector: ${scopeSelector}` + ); + } + + const scopeProcessor = selectorParser(selectors => { + selectors.each(selector => { + const raw = selector.toString().trim(); + + if ( + raw.startsWith(scopeSelector) || + raw.startsWith(`.${scopeClass}`) || + raw.startsWith(`:where(.${scopeClass})`) + ) { + return; + } + + if ( + raw === 'html' || + raw === 'body' || + raw === ':host' || + raw === ':root' + ) { + selector.nodes = scopeNodes.map(node => node.clone()); + return; + } + + const prefixNodes = scopeNodes.map(node => node.clone()); + const space = selectorParser.combinator({ value: ' ' }); + selector.nodes = [...prefixNodes, space, ...selector.nodes]; + }); + }); + + return { + postcssPlugin: 'affine-queuedash-scope', + Once(root, { result }) { + const from = + root.source?.input.file || + root.source?.input.from || + result.opts.from || + ''; + + const normalized = from ? normalizeFilePath(from) : ''; + const isQueuedashVendorCss = normalized.endsWith( + '/@queuedash/ui/dist/styles.css' + ); + + const queuedashLayers: AtRule[] = []; + root.walkAtRules('layer', atRule => { + if (atRule.params?.trim() === 'queuedash' && atRule.nodes?.length) { + queuedashLayers.push(atRule); + } + }); + + if (!isQueuedashVendorCss && queuedashLayers.length === 0) { + return; + } + + const targets: Container[] = + queuedashLayers.length > 0 ? queuedashLayers : [root]; + + targets.forEach(container => { + container.walkRules(rule => { + if (!rule.selector || isInKeyframes(rule)) { + return; + } + rule.selector = scopeProcessor.processSync(rule.selector); + }); + }); + }, + }; +}; + +queuedashScopePostcssPlugin.postcss = true; diff --git a/tools/cli/src/rspack/index.ts b/tools/cli/src/rspack/index.ts index e1c3cffcc9943..62af85842e4f4 100644 --- a/tools/cli/src/rspack/index.ts +++ b/tools/cli/src/rspack/index.ts @@ -12,6 +12,7 @@ import { VanillaExtractPlugin } from '@vanilla-extract/webpack-plugin'; import cssnano from 'cssnano'; import { compact, merge } from 'lodash-es'; +import { queuedashScopePostcssPlugin } from '../postcss/queuedash-scope.js'; import { productionCacheGroups } from '../webpack/cache-group.js'; import { type CreateHTMLPluginConfig, @@ -228,6 +229,9 @@ export function createHTMLTargetConfig( require(pkg.join('tailwind.config.js').value), ], ['autoprefixer'], + ...(buildConfig.isAdmin + ? [queuedashScopePostcssPlugin()] + : []), ] : [ cssnano({ diff --git a/tools/cli/src/webpack/html-plugin.ts b/tools/cli/src/webpack/html-plugin.ts index 85c8e34f81278..e6286122d4609 100644 --- a/tools/cli/src/webpack/html-plugin.ts +++ b/tools/cli/src/webpack/html-plugin.ts @@ -79,6 +79,7 @@ const currentDir = Path.dir(import.meta.url); export interface CreateHTMLPluginConfig { filename?: string; additionalEntryForSelfhost?: boolean; + selfhostPublicPath?: string; injectGlobalErrorHandler?: boolean; emitAssetsManifest?: boolean; } @@ -206,6 +207,7 @@ export function createHTMLPlugins( ): WebpackPluginInstance[] { const publicPath = getPublicPath(BUILD_CONFIG); const htmlPluginOptions = getHTMLPluginOptions(BUILD_CONFIG); + const selfhostPublicPath = config.selfhostPublicPath ?? '/'; const plugins: WebpackPluginInstance[] = []; plugins.push( @@ -269,9 +271,10 @@ export function createHTMLPlugins( new HTMLPlugin({ ...htmlPluginOptions, chunks: ['index'], + publicPath: selfhostPublicPath, meta: { 'env:isSelfHosted': 'true', - 'env:publicPath': '/', + 'env:publicPath': selfhostPublicPath, }, filename: 'selfhost.html', templateParameters: { diff --git a/tools/cli/src/webpack/index.ts b/tools/cli/src/webpack/index.ts index a28300b505025..c3473b94d56bf 100644 --- a/tools/cli/src/webpack/index.ts +++ b/tools/cli/src/webpack/index.ts @@ -13,6 +13,7 @@ import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import TerserPlugin from 'terser-webpack-plugin'; import webpack from 'webpack'; +import { queuedashScopePostcssPlugin } from '../postcss/queuedash-scope.js'; import { productionCacheGroups } from './cache-group.js'; import { type CreateHTMLPluginConfig, @@ -230,6 +231,9 @@ export function createHTMLTargetConfig( require(pkg.join('tailwind.config.js').value), ], ['autoprefixer'], + ...(buildConfig.isAdmin + ? [queuedashScopePostcssPlugin()] + : []), ] : [ cssnano({ diff --git a/yarn.lock b/yarn.lock index 789a33c3ddb86..a1e91ef5fde27 100644 --- a/yarn.lock +++ b/yarn.lock @@ -143,6 +143,7 @@ __metadata: node-loader: "npm:^2.1.0" postcss: "npm:^8.4.49" postcss-loader: "npm:^8.1.1" + postcss-selector-parser: "npm:^7.1.0" prettier: "npm:^3.7.4" react-refresh: "npm:^0.17.0" source-map-loader: "npm:^5.0.0" @@ -185,7 +186,7 @@ __metadata: "@affine/graphql": "workspace:*" "@affine/routes": "workspace:*" "@blocksuite/icons": "npm:^2.2.17" - "@queuedash/ui": "npm:^3.14.0" + "@queuedash/ui": "npm:^3.16.0" "@radix-ui/react-accordion": "npm:^1.2.2" "@radix-ui/react-alert-dialog": "npm:^1.1.3" "@radix-ui/react-aspect-ratio": "npm:^1.1.1" @@ -1022,7 +1023,7 @@ __metadata: "@opentelemetry/semantic-conventions": "npm:^1.38.0" "@prisma/client": "npm:^6.6.0" "@prisma/instrumentation": "npm:^6.7.0" - "@queuedash/api": "npm:^3.14.0" + "@queuedash/api": "npm:^3.16.0" "@react-email/components": "npm:0.0.38" "@socket.io/redis-adapter": "npm:^8.3.0" "@types/cookie-parser": "npm:^1.4.8" @@ -11676,11 +11677,11 @@ __metadata: languageName: node linkType: hard -"@queuedash/api@npm:3.14.0, @queuedash/api@npm:^3.14.0": - version: 3.14.0 - resolution: "@queuedash/api@npm:3.14.0" +"@queuedash/api@npm:3.16.0, @queuedash/api@npm:^3.16.0": + version: 3.16.0 + resolution: "@queuedash/api@npm:3.16.0" dependencies: - "@trpc/server": "npm:^11.6.0" + "@trpc/server": "npm:^11.8.1" redis: "npm:^4.7.0" redis-info: "npm:^3.1.0" zod: "npm:^3.24.2" @@ -11713,23 +11714,23 @@ __metadata: optional: true hono: optional: true - checksum: 10/d0117ab10c4a59ea0b3d29bc783b273b7b2b08290e122ed1b05bbf185f44ba87b5229ae8e98ce41692de334548c02bf8f7980f7b42a623352d0a048b74966a36 + checksum: 10/84c3b552450a72a76245930caab2371aabe85168a2accaa9bc3aefa7e4ea22e99a0e77005f528995e66f39adb63a109721ff89cb556565292d7429c22c5254ec languageName: node linkType: hard -"@queuedash/ui@npm:^3.14.0": - version: 3.14.0 - resolution: "@queuedash/ui@npm:3.14.0" +"@queuedash/ui@npm:^3.16.0": + version: 3.16.0 + resolution: "@queuedash/ui@npm:3.16.0" dependencies: "@monaco-editor/react": "npm:^4.7.0" - "@queuedash/api": "npm:3.14.0" + "@queuedash/api": "npm:3.16.0" "@radix-ui/react-checkbox": "npm:^1.3.3" "@radix-ui/react-icons": "npm:^1.3.2" "@tanstack/react-query": "npm:^5.90.5" "@tanstack/react-table": "npm:^8.21.3" - "@trpc/client": "npm:^11.6.0" - "@trpc/react-query": "npm:^11.6.0" - "@trpc/server": "npm:^11.6.0" + "@trpc/client": "npm:^11.8.1" + "@trpc/react-query": "npm:^11.8.1" + "@trpc/server": "npm:^11.8.1" clsx: "npm:^2.1.1" cronstrue: "npm:^2.61.0" date-fns: "npm:^4.1.0" @@ -11744,7 +11745,7 @@ __metadata: peerDependencies: react: ">=18" react-dom: ">=18" - checksum: 10/d35dd553bc5a8896d93b1ef6bbd1c7801e5a6ac8e91f392b107d4c4681aa0d46e933ae9c258f2ef0611bd7a1bbc8279506168461ec390afbe3c5a90931c71579 + checksum: 10/a3be3e738e281cde533ccadefadaeae1a324fec7658ed38d5e942bd965a4866f5a335f6b4b9a6701386a9cf74a8b931faac45662f8e895df467a2cff75584dd0 languageName: node linkType: hard @@ -16711,36 +16712,35 @@ __metadata: languageName: node linkType: hard -"@trpc/client@npm:^11.6.0": - version: 11.8.1 - resolution: "@trpc/client@npm:11.8.1" +"@trpc/client@npm:^11.8.1": + version: 11.10.0 + resolution: "@trpc/client@npm:11.10.0" peerDependencies: - "@trpc/server": 11.8.1 + "@trpc/server": 11.10.0 typescript: ">=5.7.2" - checksum: 10/1411acb66ad8c94cb5cf90386fcca2cf0f67a7d6a7ca90e42b23e737f39d1e8079e8c9088d9b46d3643a57e6eefbf721f83b372624cb0062b371e4c362d2bd98 + checksum: 10/91c6c7bf8ac471e4e15042097eace3cfbed10e9af986bef57dfa320c55802aeabe45fbc0bed785bd42b18e8158dd5d8b89709d6bc41c595d4cab70f72f0c3dc9 languageName: node linkType: hard -"@trpc/react-query@npm:^11.6.0": - version: 11.8.1 - resolution: "@trpc/react-query@npm:11.8.1" +"@trpc/react-query@npm:^11.8.1": + version: 11.10.0 + resolution: "@trpc/react-query@npm:11.10.0" peerDependencies: "@tanstack/react-query": ^5.80.3 - "@trpc/client": 11.8.1 - "@trpc/server": 11.8.1 + "@trpc/client": 11.10.0 + "@trpc/server": 11.10.0 react: ">=18.2.0" - react-dom: ">=18.2.0" typescript: ">=5.7.2" - checksum: 10/6244083404ff0f9e218a6239af43f84941cf20fe30ea6a8b02655649ea627161294360228c54070b0bde6332252c26545b53c7e2148c67afe691863a976422b2 + checksum: 10/80b76ad84915a693504545cde5d8d8d9c0f26beefea7809c852d44779e27d01e6af95d0154546887ecdc22f2f747dec7d26a609527a627f7eea198990867f0af languageName: node linkType: hard -"@trpc/server@npm:^11.6.0": - version: 11.8.1 - resolution: "@trpc/server@npm:11.8.1" +"@trpc/server@npm:^11.8.1": + version: 11.10.0 + resolution: "@trpc/server@npm:11.10.0" peerDependencies: typescript: ">=5.7.2" - checksum: 10/074b7bd564d0821cbd0711486fb51ee5733d13afe894e5f3e4b0b5ff5c1b71b156d820322e068763b47e076e5cd22a81f8c1df085834cc4ff93c4a1e0005e1de + checksum: 10/e50d2aaefa7b40ef1a270d209ea7b37f37d3990dd15008fc5069c73cf2f108fe3a8777c7c498a1950a984f34f7a26e3922f03a2e87a8ba05d8bc5f2c82f04ff3 languageName: node linkType: hard