diff --git a/integrations/trpc/package.json b/integrations/trpc/package.json index 60e1066b6..fcb0ecb2c 100644 --- a/integrations/trpc/package.json +++ b/integrations/trpc/package.json @@ -37,8 +37,8 @@ }, "dependencies": {}, "peerDependencies": { - "@trpc/client": "^10.0.0", - "@trpc/server": "^10.0.0" + "@trpc/client": "^10.0.0 || ^11.0.0", + "@trpc/server": "^10.0.0 || ^11.0.0" }, "peerDependenciesMeta": { "@trpc/client": { @@ -49,7 +49,7 @@ } }, "devDependencies": { - "@trpc/client": "^10.31.0", - "@trpc/server": "^10.31.0" + "@trpc/client": "next", + "@trpc/server": "next" } } diff --git a/integrations/trpc/source/server.ts b/integrations/trpc/source/server.ts index d086b2dab..c26d92807 100644 --- a/integrations/trpc/source/server.ts +++ b/integrations/trpc/source/server.ts @@ -1,4 +1,4 @@ -import {callProcedure, type AnyRouter} from '@trpc/server'; +import {callProcedure, type AnyTRPCRouter} from '@trpc/server'; import {observable} from '@trpc/server/observable'; import { TRPCClientError, @@ -6,32 +6,28 @@ import { type CreateTRPCClientOptions, type TRPCLink, } from '@trpc/client'; -import {transformResult} from '@trpc/client/shared'; +import {transformResult} from '@trpc/server/unstable-core-do-not-import'; -export function createDirectClient( +export function createDirectClient( router: Router, - { - links = [] as any, - transformer, - }: Partial> = {}, + {links = [] as any}: Partial> = {}, ) { return createTRPCClient({ - transformer, links: [...links, directLink(router)], } as any); } -export function directLink( +export function directLink( router: Router, ): TRPCLink { - return function fancyLink(runtime) { + return function fancyLink() { return function operationLink({op}) { return observable((observer) => { const {path, input, type} = op; const result = callProcedure({ path, - rawInput: input, + getRawInput: () => Promise.resolve(input), type, ctx: {}, procedures: router._def.procedures, @@ -41,7 +37,7 @@ export function directLink( .then((result) => { const transformed = transformResult( {result: {data: result, type: 'data'}}, - runtime, + router._def._config.transformer.output, ); if (!transformed.ok) { diff --git a/packages/create/package.json b/packages/create/package.json index 2704083ff..be154e373 100644 --- a/packages/create/package.json +++ b/packages/create/package.json @@ -29,6 +29,9 @@ "devDependencies": { "@quilted/cli-kit": "workspace:^0.2.0", "@types/common-tags": "^1.8.0", + "@trpc/client": "next", + "@trpc/react-query": "next", + "@trpc/server": "next", "@types/fs-extra": "^9.0.11", "@types/minimatch": "^3.0.5", "@types/prompts": "^2.0.13", @@ -41,6 +44,7 @@ "pkg-dir": "^6.0.0", "prettier": "^3.0.0", "prompts": "^2.4.0", - "yaml": "^2.1.0" + "yaml": "^2.1.0", + "zod": "^3.23.8" } } diff --git a/packages/create/templates/app-trpc/shared/trpc.ts b/packages/create/templates/app-trpc/shared/trpc.ts index 879b01dff..8566a166b 100644 --- a/packages/create/templates/app-trpc/shared/trpc.ts +++ b/packages/create/templates/app-trpc/shared/trpc.ts @@ -1,4 +1,4 @@ -import type {TRPCClient} from '@trpc/client'; +import type {CreateTRPCClient} from '@trpc/client'; import {createTRPCReact, type CreateTRPCReact} from '@trpc/react-query'; import type {QueryClient} from '@tanstack/react-query'; @@ -7,12 +7,12 @@ import type {QueryClient} from '@tanstack/react-query'; // perform. import type {AppRouter} from '../trpc.ts'; -export const trpc: CreateTRPCReact = +export const trpc: CreateTRPCReact = createTRPCReact(); declare module '~/shared/context.ts' { interface AppContext { - trpc: TRPCClient; + trpc: CreateTRPCClient; queryClient: QueryClient; } } diff --git a/packages/create/templates/app-trpc/trpc.ts b/packages/create/templates/app-trpc/trpc.ts index b12aabe37..3a5da4a41 100644 --- a/packages/create/templates/app-trpc/trpc.ts +++ b/packages/create/templates/app-trpc/trpc.ts @@ -11,3 +11,5 @@ export const appRouter = t.router({ // Our client-side code will use this type to infer the // procedures that are defined. export type AppRouter = typeof appRouter; + +export const createCaller = t.createCallerFactory(appRouter); diff --git a/packages/create/templates/workspace/package.json b/packages/create/templates/workspace/package.json index 461278775..8394326c0 100644 --- a/packages/create/templates/workspace/package.json +++ b/packages/create/templates/workspace/package.json @@ -16,11 +16,11 @@ "@quilted/rollup": "^0.2.0", "@quilted/vite": "^0.1.0", "@quilted/typescript": "^0.4.0", - "rollup": "^4.14.0", - "prettier": "^3.0.0", - "tsx": "^4.9.0", + "rollup": "^4.21.0", + "prettier": "^3.3.0", + "tsx": "^4.19.0", "typescript": "^5.5.0", - "vite": "^5.3.0", + "vite": "^5.4.0", "vitest": "^2.0.0" }, "prettier": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index c664d21f7..0774bbb73 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -166,11 +166,11 @@ importers: integrations/trpc: devDependencies: '@trpc/client': - specifier: ^10.31.0 - version: 10.31.0(@trpc/server@10.31.0) + specifier: next + version: 11.0.0-rc.498(@trpc/server@11.0.0-rc.498) '@trpc/server': - specifier: ^10.31.0 - version: 10.31.0 + specifier: next + version: 11.0.0-rc.498 packages/assets: {} @@ -268,6 +268,15 @@ importers: '@quilted/cli-kit': specifier: workspace:^0.2.0 version: link:../cli-kit + '@trpc/client': + specifier: next + version: 11.0.0-rc.498(@trpc/server@11.0.0-rc.498) + '@trpc/react-query': + specifier: next + version: 11.0.0-rc.498(@tanstack/react-query@5.53.3(react@18.2.0))(@trpc/client@11.0.0-rc.498(@trpc/server@11.0.0-rc.498))(@trpc/server@11.0.0-rc.498)(react-dom@18.2.0(react@18.2.0))(react@18.2.0) + '@trpc/server': + specifier: next + version: 11.0.0-rc.498 '@types/common-tags': specifier: ^1.8.0 version: 1.8.1 @@ -310,6 +319,9 @@ importers: yaml: specifier: ^2.1.0 version: 2.1.1 + zod: + specifier: ^3.23.8 + version: 3.23.8 packages/events: dependencies: @@ -931,21 +943,33 @@ importers: '@quilted/react-query': specifier: workspace:* version: link:../../integrations/react-query + '@quilted/trpc': + specifier: workspace:* + version: link:../../integrations/trpc '@tanstack/react-query': - specifier: ^5.34.1 - version: 5.34.1(react@packages+react) + specifier: ^5.53.0 + version: 5.53.3(react@packages+react) + '@trpc/client': + specifier: 11.0.0-rc.498 + version: 11.0.0-rc.498(@trpc/server@11.0.0-rc.498) + '@trpc/react-query': + specifier: 11.0.0-rc.498 + version: 11.0.0-rc.498(@tanstack/react-query@5.53.3(react@packages+react))(@trpc/client@11.0.0-rc.498(@trpc/server@11.0.0-rc.498))(@trpc/server@11.0.0-rc.498)(react-dom@18.2.0(react@packages+react))(react@packages+react) + '@trpc/server': + specifier: 11.0.0-rc.498 + version: 11.0.0-rc.498 '@types/common-tags': specifier: ^1.8.0 version: 1.8.1 '@types/fs-extra': - specifier: ^9.0.13 - version: 9.0.13 + specifier: ^11.0.0 + version: 11.0.4 common-tags: specifier: ^1.8.0 version: 1.8.2 fs-extra: - specifier: ^10.0.0 - version: 10.1.0 + specifier: ^11.2.0 + version: 11.2.0 get-port: specifier: ^5.0.0 version: 5.1.1 @@ -953,11 +977,11 @@ importers: specifier: ^1.9.10 version: 1.9.10 nanoid: - specifier: ^3.1.30 - version: 3.3.4 + specifier: ^5.0.0 + version: 5.0.7 playwright: - specifier: ^1.32.0 - version: 1.32.1 + specifier: ^1.46.0 + version: 1.46.1 react: specifier: workspace:@quilted/react@^18.2.0 version: link:../../packages/react @@ -2595,18 +2619,35 @@ packages: '@tanstack/query-core@5.34.1': resolution: {integrity: sha512-/a4yTnX525QUl8rFULrDLIogjqqcY/CiVvS/vWMgl477mO4WIIDxwQsLvEgb7vzlW8FqX/9CiCmaiAUnYVgB1w==} + '@tanstack/query-core@5.53.3': + resolution: {integrity: sha512-ZfjAgd7NpqDx0e4aYBt7EmS2enbulPrJwowTy+mayRE93WUUH+sIYHun1TdRjpGwDPMNNZ5D6goh7n3CwoO+HA==} + '@tanstack/react-query@5.34.1': resolution: {integrity: sha512-5DWzrK+ou5maZqVoIY0S26TYNpnA7re6JlviXVOe/4OBPtlvd4WEHJmyeLZhE43piJvrsKMxemp/f6Q2RPfebA==} peerDependencies: react: ^18.0.0 - '@trpc/client@10.31.0': - resolution: {integrity: sha512-VCqbJEvFJb8C4hQFw7AD+dkQTjgEdV/QAzO4D+/cX5e93u5NpfNXI+PKS0QFXwG/zqgwQwVV6OkYc/D/MFwA6g==} + '@tanstack/react-query@5.53.3': + resolution: {integrity: sha512-286mN/91CeM7vC6CZFLKYDHSw+WyMX6ekIvzoTbpM4xyPb99VSyCKPLyPgaOatKqYm6ooMBquSq9NGRdKgsJfg==} + peerDependencies: + react: ^18 || ^19 + + '@trpc/client@11.0.0-rc.498': + resolution: {integrity: sha512-a1VjvLHCo8gPENMfzI8lVF1ys6kOGI3f/cIAZUMB0d2TlkDERlFYANnSnzFvmiKy6ICh3lsQQ3OIMmIfyd8OtQ==} + peerDependencies: + '@trpc/server': 11.0.0-rc.498+5714423cc + + '@trpc/react-query@11.0.0-rc.498': + resolution: {integrity: sha512-il/fgO9DSTHmrJbDInGNl8PymLo19CEfIjBXmerTm4hg/p438fQb4ZKDVbpBxEThgAaaP6D0HTELWn5VDWG3VQ==} peerDependencies: - '@trpc/server': 10.31.0 + '@tanstack/react-query': ^5.49.2 + '@trpc/client': 11.0.0-rc.498+5714423cc + '@trpc/server': 11.0.0-rc.498+5714423cc + react: '>=18.2.0' + react-dom: '>=18.2.0' - '@trpc/server@10.31.0': - resolution: {integrity: sha512-9EnRTSDE9nF11LZsvSOqNKqkRYzHqFX4ch5AJ6VIu8uta2vxVTN4FxxsNRSOluTzVYZDeaCISbwmOJ5iihCCIg==} + '@trpc/server@11.0.0-rc.498': + resolution: {integrity: sha512-LECCOz8JNB67CBasPA6fkLbhJIbUQRP1wq02xUfUMeaSEZFWJL+7fcTgLaWFQSHMMnMsvkLuDuDDkUSCF2SXmg==} '@types/babel__core@7.20.0': resolution: {integrity: sha512-+n8dL/9GWblDO0iU6eZAwEIJVr5DWigtle+Q6HLOrh/pdbXOhOtqzq8VPPE2zvNJzSKY4vH/z3iT3tn0A3ypiQ==} @@ -2641,6 +2682,9 @@ packages: '@types/estree@1.0.5': resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + '@types/fs-extra@9.0.13': resolution: {integrity: sha512-nEnwB++1u5lVDM2UI4c1+5R+FYaKfaAzS4OococimjVm3nQw3TuzH5UNsocrcTBbhnerblyHj4A49qXbIiZdpA==} @@ -2665,6 +2709,9 @@ packages: '@types/js-cookie@3.0.6': resolution: {integrity: sha512-wkw9yd1kEXOPnvEeEV1Go1MmxtBJL0RR79aOTAApecWFVu7w0NNXNqhcWgvw2YgZDYadliXkl14pa3WXw5jlCQ==} + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + '@types/mime@1.3.2': resolution: {integrity: sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==} @@ -3309,6 +3356,10 @@ packages: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} + fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -3320,6 +3371,11 @@ packages: fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + fsevents@2.3.2: + resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + fsevents@2.3.3: resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} @@ -3985,16 +4041,16 @@ packages: resolution: {integrity: sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ==} hasBin: true - nanoid@3.3.4: - resolution: {integrity: sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw==} - engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} - hasBin: true - nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + nanoid@5.0.7: + resolution: {integrity: sha512-oLxFY2gd2IqnjcYyOXD8XGCftpGtZP2AbHbOkthDkvRywH5ayNtPVy9YlOPcHckXzbLTCHpkb7FB+yuxKV13pQ==} + engines: {node: ^18 || >=20} + hasBin: true + node-fetch@2.6.7: resolution: {integrity: sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==} engines: {node: 4.x || >=6.0.0} @@ -4184,14 +4240,14 @@ packages: resolution: {integrity: sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==} engines: {node: '>=14.16'} - playwright-core@1.32.1: - resolution: {integrity: sha512-KZYUQC10mXD2Am1rGlidaalNGYk3LU1vZqqNk0gT4XPty1jOqgup8KDP8l2CUlqoNKhXM5IfGjWgW37xvGllBA==} - engines: {node: '>=14'} + playwright-core@1.46.1: + resolution: {integrity: sha512-h9LqIQaAv+CYvWzsZ+h3RsrqCStkBHlgo6/TJlFst3cOTlLghBQlJwPOZKQJTKNaD3QIB7aAVQ+gfWbN3NXB7A==} + engines: {node: '>=18'} hasBin: true - playwright@1.32.1: - resolution: {integrity: sha512-GnEizysWMvoqHC3I9l8+4/ZxeLwLNdJJG76xdKGxzOcIZDcw5RSk/FKrFb5CuA+zcLpjIM2p9eR9Z4CuUDkWXg==} - engines: {node: '>=14'} + playwright@1.46.1: + resolution: {integrity: sha512-oPcr1yqoXLCkgKtD5eNUPLiN40rYEM39odNpIb6VE6S7/15gJmA1NzVv6zJYusV0e7tzvkU/utBFNa/Kpxmwng==} + engines: {node: '>=18'} hasBin: true postcss@8.4.39: @@ -5002,6 +5058,9 @@ packages: youch@2.2.2: resolution: {integrity: sha512-/FaCeG3GkuJwaMR34GHVg0l8jCbafZLHiFowSjqLlqhC6OMyf2tPJBu8UirF7/NI9X/R5ai4QfEKUCOxMAGxZQ==} + zod@3.23.8: + resolution: {integrity: sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==} + snapshots: '@actions/core@1.10.0': @@ -6746,16 +6805,44 @@ snapshots: '@tanstack/query-core@5.34.1': {} + '@tanstack/query-core@5.53.3': {} + '@tanstack/react-query@5.34.1(react@packages+react)': dependencies: '@tanstack/query-core': 5.34.1 react: link:packages/react - '@trpc/client@10.31.0(@trpc/server@10.31.0)': + '@tanstack/react-query@5.53.3(react@18.2.0)': dependencies: - '@trpc/server': 10.31.0 + '@tanstack/query-core': 5.53.3 + react: 18.2.0 - '@trpc/server@10.31.0': {} + '@tanstack/react-query@5.53.3(react@packages+react)': + dependencies: + '@tanstack/query-core': 5.53.3 + react: link:packages/react + + '@trpc/client@11.0.0-rc.498(@trpc/server@11.0.0-rc.498)': + dependencies: + '@trpc/server': 11.0.0-rc.498 + + '@trpc/react-query@11.0.0-rc.498(@tanstack/react-query@5.53.3(react@18.2.0))(@trpc/client@11.0.0-rc.498(@trpc/server@11.0.0-rc.498))(@trpc/server@11.0.0-rc.498)(react-dom@18.2.0(react@18.2.0))(react@18.2.0)': + dependencies: + '@tanstack/react-query': 5.53.3(react@18.2.0) + '@trpc/client': 11.0.0-rc.498(@trpc/server@11.0.0-rc.498) + '@trpc/server': 11.0.0-rc.498 + react: 18.2.0 + react-dom: 18.2.0(react@18.2.0) + + '@trpc/react-query@11.0.0-rc.498(@tanstack/react-query@5.53.3(react@packages+react))(@trpc/client@11.0.0-rc.498(@trpc/server@11.0.0-rc.498))(@trpc/server@11.0.0-rc.498)(react-dom@18.2.0(react@packages+react))(react@packages+react)': + dependencies: + '@tanstack/react-query': 5.53.3(react@packages+react) + '@trpc/client': 11.0.0-rc.498(@trpc/server@11.0.0-rc.498) + '@trpc/server': 11.0.0-rc.498 + react: link:packages/react + react-dom: 18.2.0(react@packages+react) + + '@trpc/server@11.0.0-rc.498': {} '@types/babel__core@7.20.0': dependencies: @@ -6798,6 +6885,11 @@ snapshots: '@types/estree@1.0.5': {} + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 20.8.10 + '@types/fs-extra@9.0.13': dependencies: '@types/node': 20.8.10 @@ -6825,6 +6917,10 @@ snapshots: '@types/js-cookie@3.0.6': {} + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 20.8.10 + '@types/mime@1.3.2': {} '@types/mime@2.0.3': {} @@ -7553,6 +7649,12 @@ snapshots: jsonfile: 6.1.0 universalify: 2.0.0 + fs-extra@11.2.0: + dependencies: + graceful-fs: 4.2.10 + jsonfile: 6.1.0 + universalify: 2.0.0 + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.10 @@ -7567,6 +7669,9 @@ snapshots: fs.realpath@1.0.0: {} + fsevents@2.3.2: + optional: true + fsevents@2.3.3: optional: true @@ -8241,10 +8346,10 @@ snapshots: mustache@4.2.0: {} - nanoid@3.3.4: {} - nanoid@3.3.7: {} + nanoid@5.0.7: {} + node-fetch@2.6.7: dependencies: whatwg-url: 5.0.0 @@ -8401,11 +8506,13 @@ snapshots: dependencies: find-up: 6.3.0 - playwright-core@1.32.1: {} + playwright-core@1.46.1: {} - playwright@1.32.1: + playwright@1.46.1: dependencies: - playwright-core: 1.32.1 + playwright-core: 1.46.1 + optionalDependencies: + fsevents: 2.3.2 postcss@8.4.39: dependencies: @@ -8474,6 +8581,12 @@ snapshots: react: 18.2.0 scheduler: 0.23.0 + react-dom@18.2.0(react@packages+react): + dependencies: + loose-envify: 1.4.0 + react: link:packages/react + scheduler: 0.23.0 + react-is@17.0.2: {} react-is@18.2.0: {} @@ -9187,3 +9300,5 @@ snapshots: cookie: 0.4.2 mustache: 4.2.0 stack-trace: 0.0.10 + + zod@3.23.8: {} diff --git a/tests/e2e/integrations/react-query.test.ts b/tests/e2e/integrations/react-query.test.ts index 3e5d8635c..3fb114a44 100644 --- a/tests/e2e/integrations/react-query.test.ts +++ b/tests/e2e/integrations/react-query.test.ts @@ -7,21 +7,26 @@ describe('react-query', () => { await workspace.fs.write({ 'App.tsx': multiline` + import {Suspense} from 'preact/compat'; import {useMemo} from 'preact/hooks'; import {QueryClient, useSuspenseQuery} from '@tanstack/react-query'; import {ReactQueryContext} from '@quilted/react-query'; import {useBrowserRequest} from '@quilted/quilt/browser'; - export default function App() { + export function App() { const client = useMemo(() => new QueryClient(), []); return ( - + + + ); } + export default App; + function UI() { const {url} = useBrowserRequest(); @@ -54,7 +59,7 @@ describe('react-query', () => { }); router.get(async (request) => { - const [{default: App}, {renderToResponse}] = await Promise.all([ + const [{App}, {renderToResponse}] = await Promise.all([ import('./App.tsx'), import('@quilted/quilt/server'), ]); diff --git a/tests/e2e/integrations/trpc.test.ts b/tests/e2e/integrations/trpc.test.ts new file mode 100644 index 000000000..a2331d139 --- /dev/null +++ b/tests/e2e/integrations/trpc.test.ts @@ -0,0 +1,143 @@ +import {describe, it, expect} from 'vitest'; +import {multiline, createWorkspace, startServer} from '../utilities.ts'; + +describe('trpc', () => { + it('can server and client render a trpc query', async () => { + await using workspace = await createWorkspace({ + fixture: 'basic-app', + debug: true, + }); + + await workspace.fs.write({ + 'trpc.ts': multiline` + import {initTRPC} from '@trpc/server'; + + const t = initTRPC.create(); + + export const appRouter = t.router({ + message: t.procedure + .input((v) => { + if (typeof v === 'string') return v; + throw new Error('Invalid input: Expected string'); + }) + .query(({input}) => \`Hello \${input}!\`), + }); + + export type AppRouter = typeof appRouter; + + export const createCaller = t.createCallerFactory(appRouter); + `, + 'App.tsx': multiline` + import {Suspense} from 'preact/compat'; + import {useMemo} from 'preact/hooks'; + import {QueryClient} from '@tanstack/react-query'; + import {createTRPCReact} from '@trpc/react-query'; + import {httpBatchLink} from '@trpc/client'; + import {ReactQueryContext} from '@quilted/react-query'; + import {useBrowserRequest} from '@quilted/quilt/browser'; + + import type {AppRouter} from './trpc.ts'; + + export const trpc = createTRPCReact(); + + export function App({trpcClient, queryClient}) { + return ( + + + + + + + + ); + } + + export default App; + + function UI() { + const [data] = trpc.message.useSuspenseQuery('world'); + return
{data}
; + } + `, + 'browser.tsx': multiline` + import '@quilted/quilt/globals'; + import {hydrate} from 'preact'; + import {Browser, BrowserContext} from '@quilted/quilt/browser'; + import {httpBatchLink} from '@trpc/client'; + import {QueryClient} from '@tanstack/react-query'; + + import {App, trpc} from './App.tsx'; + + const element = document.querySelector('#app')!; + const browser = new Browser(); + + const trpcClient = trpc.createClient({ + links: [ + httpBatchLink({ + url: new URL('/api', url).href, + }), + ], + }); + + const queryClient = new QueryClient(); + + hydrate( + + + , + element, + ); + `, + 'server.tsx': multiline` + import '@quilted/quilt/globals'; + import {RequestRouter, JSONResponse} from '@quilted/quilt/request-router'; + import {renderToResponse} from '@quilted/quilt/server'; + import {fetchRequestHandler} from '@trpc/server/adapters/fetch'; + + import {BrowserAssets} from 'quilt:module/assets'; + + import {appRouter, createCaller} from './trpc.ts'; + + const router = new RequestRouter(); + const assets = new BrowserAssets(); + + router.any('/api', (request) => { + return fetchRequestHandler({ + endpoint: '/api', + req: request, + router: appRouter, + createContext: () => ({}), + }); + }, {exact: false}); + + router.get(async (request) => { + const [{App}, {createDirectClient}, {QueryClient}] = await Promise.all([ + import('./App.tsx'), + import('@quilted/trpc/server'), + import('@tanstack/react-query'), + ]); + + const queryClient = new QueryClient(); + const trpcClient = createDirectClient(appRouter); + + const response = await renderToResponse( + , + { + request, + assets, + }, + ); + + return response; + }); + + export default router; + `, + }); + + const server = await startServer(workspace); + const page = await server.openPage(); + + expect(await page.textContent('div')).toBe('Hello world!'); + }); +}); diff --git a/tests/e2e/package.json b/tests/e2e/package.json index 46206e4a7..60adc33b2 100644 --- a/tests/e2e/package.json +++ b/tests/e2e/package.json @@ -6,15 +6,19 @@ "@quilted/htmx": "workspace:*", "@quilted/quilt": "workspace:*", "@quilted/react-query": "workspace:*", - "@tanstack/react-query": "^5.34.1", + "@quilted/trpc": "workspace:*", + "@tanstack/react-query": "^5.53.0", + "@trpc/client": "11.0.0-rc.498", + "@trpc/react-query": "11.0.0-rc.498", + "@trpc/server": "11.0.0-rc.498", "@types/common-tags": "^1.8.0", - "@types/fs-extra": "^9.0.13", + "@types/fs-extra": "^11.0.0", "common-tags": "^1.8.0", - "htmx.org": "^1.9.10", - "fs-extra": "^10.0.0", + "fs-extra": "^11.2.0", "get-port": "^5.0.0", - "nanoid": "^3.1.30", - "playwright": "^1.32.0", + "htmx.org": "^1.9.10", + "nanoid": "^5.0.0", + "playwright": "^1.46.0", "react": "workspace:@quilted/react@^18.2.0" } }