From ca5309b1e7fdd0b843ce96d9565f2f5238c6d83e Mon Sep 17 00:00:00 2001 From: Tomas Francisco <4301103+tomasfrancisco@users.noreply.github.com> Date: Thu, 22 Aug 2024 12:04:00 +0200 Subject: [PATCH] add auth refresh to trpc in figma --- apps/dashboard/src/types/kv-types.ts | 1 - package.json | 6 + packages/api/package.json | 4 +- packages/api/src/query-client.ts | 2 +- packages/api/src/react.tsx | 64 +++--- packages/figma-plugin/eslint.config.js | 13 +- packages/figma-plugin/package.json | 5 +- packages/figma-plugin/src/plugin/plugin.ts | 2 - .../figma-plugin/src/types/credentials.ts | 1 + packages/figma-plugin/src/ui/app.tsx | 4 +- packages/figma-plugin/src/ui/lib/api.tsx | 65 ------ .../link-design-system/link-design-system.tsx | 2 +- .../src/ui/modules/providers/api-provider.tsx | 41 ++++ .../ui/modules/providers/auth-provider.tsx | 57 ++--- .../src/ui/modules/providers/index.tsx | 7 +- pnpm-lock.yaml | 206 ++++-------------- pnpm-workspace.yaml | 1 - 17 files changed, 173 insertions(+), 308 deletions(-) delete mode 100644 packages/figma-plugin/src/ui/lib/api.tsx create mode 100644 packages/figma-plugin/src/ui/modules/providers/api-provider.tsx diff --git a/apps/dashboard/src/types/kv-types.ts b/apps/dashboard/src/types/kv-types.ts index 13d5e65..58718d4 100644 --- a/apps/dashboard/src/types/kv-types.ts +++ b/apps/dashboard/src/types/kv-types.ts @@ -5,7 +5,6 @@ export interface KVCredentialsRead { export interface KVCredentials { accessToken: string; refreshToken: string; - expiresAt: number; } diff --git a/package.json b/package.json index d5e25a3..8ab08df 100644 --- a/package.json +++ b/package.json @@ -21,5 +21,11 @@ "packageManager": "pnpm@9.5.0", "engines": { "node": "^20" + }, + "pnpm": { + "overrides": { + "@trpc/client": "11.0.0-rc.482", + "@trpc/server": "11.0.0-rc.482" + } } } diff --git a/packages/api/package.json b/packages/api/package.json index 85e223e..7b921d9 100644 --- a/packages/api/package.json +++ b/packages/api/package.json @@ -26,16 +26,16 @@ "author": "", "license": "ISC", "dependencies": { - "style-dictionary": "catalog:", - "@ds-project/services": "workspace:*", "@ds-project/auth": "workspace:*", "@ds-project/database": "workspace:*", + "@ds-project/services": "workspace:*", "@tanstack/react-query": "^5.51.24", "@trpc/client": "catalog:", "@trpc/react-query": "catalog:", "@trpc/server": "catalog:", "next": "catalog:", "react": "catalog:", + "style-dictionary": "catalog:", "superjson": "^2.2.1", "zod": "catalog:" }, diff --git a/packages/api/src/query-client.ts b/packages/api/src/query-client.ts index 6e4781f..5fb5c2b 100644 --- a/packages/api/src/query-client.ts +++ b/packages/api/src/query-client.ts @@ -10,7 +10,7 @@ export const createQueryClient = () => queries: { // With SSR, we usually want to set some default staleTime // above 0 to avoid refetching immediately on the client - staleTime: 30 * 1000, + staleTime: 30 * 1000, // 30 seconds }, dehydrate: { serializeData: SuperJSON.serialize, diff --git a/packages/api/src/react.tsx b/packages/api/src/react.tsx index 033390a..4d18a46 100644 --- a/packages/api/src/react.tsx +++ b/packages/api/src/react.tsx @@ -1,14 +1,15 @@ 'use client'; import type { QueryClient } from '@tanstack/react-query'; -import { useState } from 'react'; import { QueryClientProvider } from '@tanstack/react-query'; +import type { TRPCLink } from '@trpc/client'; import { loggerLink, unstable_httpBatchStreamLink } from '@trpc/client'; import { createTRPCReact } from '@trpc/react-query'; import SuperJSON from 'superjson'; import { createQueryClient } from './query-client'; import type { AppRouter } from './app-router'; +import { useMemo } from 'react'; let clientQueryClientSingleton: QueryClient | undefined = undefined; const getQueryClient = () => { @@ -23,33 +24,40 @@ const getQueryClient = () => { export const api = createTRPCReact(); -export function TRPCReactProvider(props: { children: React.ReactNode }) { +export function TRPCReactProvider(props: { + children: React.ReactNode; + source: string; + accessToken?: string; + trpcLinks?: TRPCLink[]; +}) { const queryClient = getQueryClient(); - const [trpcClient] = useState(() => - api.createClient({ - links: [ - loggerLink({ - enabled: (op) => - // eslint-disable-next-line turbo/no-undeclared-env-vars - process.env.NODE_ENV === 'development' || - (op.direction === 'down' && op.result instanceof Error), - }), - unstable_httpBatchStreamLink({ - transformer: SuperJSON, - url: getBaseUrl() + '/api/trpc', - headers() { - const headerObject: Record = {}; - const headers = new Headers(); - headers.set('x-trpc-source', 'nextjs-react'); - headers.forEach((header, value) => { - headerObject[header] = value; - }); - return headerObject; - }, - }), - ], - }) + const trpcClient = useMemo( + () => + api.createClient({ + links: [ + ...(props.trpcLinks ?? []), + loggerLink({ + enabled: (op) => + // eslint-disable-next-line turbo/no-undeclared-env-vars + process.env.NODE_ENV === 'development' || + (op.direction === 'down' && op.result instanceof Error), + }), + unstable_httpBatchStreamLink({ + transformer: SuperJSON, + url: getBaseUrl() + '/api/v1', + headers() { + return { + 'x-trpc-source': props.source, + ...(props.accessToken + ? { Authorization: `Bearer ${props.accessToken}` } + : {}), + }; + }, + }), + ], + }), + [props.accessToken, props.source, props.trpcLinks] ); return ( @@ -62,10 +70,10 @@ export function TRPCReactProvider(props: { children: React.ReactNode }) { } const getBaseUrl = () => { - if (typeof window !== 'undefined') return window.location.origin; + // if (typeof window !== 'undefined') return window.location.origin; // eslint-disable-next-line turbo/no-undeclared-env-vars if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; // eslint-disable-next-line turbo/no-undeclared-env-vars - return `http://localhost:${process.env.PORT ?? 3000}`; + return `https://localhost:${process.env.PORT ?? 3000}`; }; diff --git a/packages/figma-plugin/eslint.config.js b/packages/figma-plugin/eslint.config.js index 49e620b..6596cb1 100644 --- a/packages/figma-plugin/eslint.config.js +++ b/packages/figma-plugin/eslint.config.js @@ -1,14 +1,19 @@ import baseConfig from '@ds-project/eslint/base'; import reactConfig from '@ds-project/eslint/react'; +// import figmaPlugin from '@figma/eslint-plugin-figma-plugins'; /** @type {import('typescript-eslint').Config} */ export default [ { ignores: ['dist/**'], - extends: ['plugin:@figma/figma-plugins/recommended'], - globals: { - figma: 'readable', - __html__: 'readable', + languageOptions: { + globals: { + figma: 'readable', + __html__: 'readable', + }, + }, + rules: { + // ...figmaPlugin.configs.recommended.rules, }, }, ...baseConfig, diff --git a/packages/figma-plugin/package.json b/packages/figma-plugin/package.json index 7be34c0..4db25e1 100644 --- a/packages/figma-plugin/package.json +++ b/packages/figma-plugin/package.json @@ -14,10 +14,10 @@ "type-check": "tsc --noEmit --emitDeclarationOnly false" }, "dependencies": { - "@ds-project/types": "workspace:*", "@apollo/client": "^3.7.11", "@ds-project/api": "workspace:*", "@ds-project/components": "workspace:*", + "@ds-project/types": "workspace:*", "@octokit/core": "^6.1.2", "@octokit/request": "^9.1.3", "@octokit/types": "^13.5.0", @@ -35,7 +35,8 @@ "sass": "^1.60.0", "style-dictionary": "catalog:", "superjson": "^2.2.1", - "tailwindcss": "catalog:" + "tailwindcss": "catalog:", + "trpc-token-refresh-link": "^0.5.0" }, "devDependencies": { "@ds-project/eslint": "workspace:*", diff --git a/packages/figma-plugin/src/plugin/plugin.ts b/packages/figma-plugin/src/plugin/plugin.ts index e86b49e..423b3d7 100644 --- a/packages/figma-plugin/src/plugin/plugin.ts +++ b/packages/figma-plugin/src/plugin/plugin.ts @@ -27,8 +27,6 @@ AsyncMessage.plugin.handle(AsyncMessageTypes.GetCredentials, async () => { throw new Error('No DS Credentials found'); } - console.log(credentialsString); - return { credentials }; }); diff --git a/packages/figma-plugin/src/types/credentials.ts b/packages/figma-plugin/src/types/credentials.ts index bbecf8e..35dcdad 100644 --- a/packages/figma-plugin/src/types/credentials.ts +++ b/packages/figma-plugin/src/types/credentials.ts @@ -1,4 +1,5 @@ export interface Credentials { accessToken: string; refreshToken: string; + expireAt: number; } diff --git a/packages/figma-plugin/src/ui/app.tsx b/packages/figma-plugin/src/ui/app.tsx index be25090..82c446e 100644 --- a/packages/figma-plugin/src/ui/app.tsx +++ b/packages/figma-plugin/src/ui/app.tsx @@ -6,8 +6,8 @@ import { AsyncMessageTypes } from '../message.types'; import { AsyncMessage } from '../message'; import { LinkDesignSystem } from './modules/link-design-system'; import { useAuth } from './modules/providers/auth-provider'; -import { api } from '@ds-project/api/react'; import { useConfig } from './modules/providers/config-provider'; +import { api } from '@ds-project/api/react'; function App() { const { login, logout, state } = useAuth(); @@ -22,7 +22,7 @@ function App() { }) .then(({ designTokens }) => { if (fileName) { - void updateDesignTokens({ designTokens, name: fileName }); + // void updateDesignTokens({ designTokens, name: fileName }); } }) .catch((error) => { diff --git a/packages/figma-plugin/src/ui/lib/api.tsx b/packages/figma-plugin/src/ui/lib/api.tsx deleted file mode 100644 index 396c0f4..0000000 --- a/packages/figma-plugin/src/ui/lib/api.tsx +++ /dev/null @@ -1,65 +0,0 @@ -import type { QueryClient } from '@tanstack/react-query'; -import { useMemo } from 'react'; -import { QueryClientProvider } from '@tanstack/react-query'; -import { loggerLink, unstable_httpBatchStreamLink } from '@trpc/client'; -import { createTRPCReact } from '@trpc/react-query'; -import SuperJSON from 'superjson'; - -import { createQueryClient } from './query-client'; -import type { AppRouter } from '@ds-project/api'; -import { config } from '../config'; -import { useAuth } from '../modules/providers/auth-provider'; - -let clientQueryClientSingleton: QueryClient | undefined = undefined; -const getQueryClient = () => { - // Browser: use singleton pattern to keep the same query client - return (clientQueryClientSingleton ??= createQueryClient()); -}; - -export const api = createTRPCReact(); - -export function TRPCReactProvider(props: { children: React.ReactNode }) { - const queryClient = getQueryClient(); - const { accessToken } = useAuth(); - - const trpcClient = useMemo( - () => - api.createClient({ - links: [ - loggerLink({ - enabled: (op) => - // eslint-disable-next-line turbo/no-undeclared-env-vars - process.env.NODE_ENV === 'development' || - (op.direction === 'down' && op.result instanceof Error), - }), - unstable_httpBatchStreamLink({ - transformer: SuperJSON, - url: getBaseUrl() + '/api/v1', - headers() { - return { - 'x-trpc-source': 'figma-react', - Authorization: `Bearer ${accessToken}`, - }; - }, - }), - ], - }), - [accessToken] - ); - - return ( - - - {props.children} - - - ); -} - -const getBaseUrl = () => { - // if (typeof window !== 'undefined') return window.location.origin; - // // eslint-disable-next-line turbo/no-undeclared-env-vars - // if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`; - - return config.AUTH_API_HOST; -}; diff --git a/packages/figma-plugin/src/ui/modules/link-design-system/link-design-system.tsx b/packages/figma-plugin/src/ui/modules/link-design-system/link-design-system.tsx index 4a7c3de..b7f9dbc 100644 --- a/packages/figma-plugin/src/ui/modules/link-design-system/link-design-system.tsx +++ b/packages/figma-plugin/src/ui/modules/link-design-system/link-design-system.tsx @@ -8,8 +8,8 @@ import { import { useCallback, useEffect, useState } from 'react'; import { AsyncMessage } from '../../../message'; import { AsyncMessageTypes } from '../../../message.types'; -import { api } from '@ds-project/api/react'; import { useConfig } from '../providers/config-provider'; +import { api } from '@ds-project/api/react'; export function LinkDesignSystem() { const { fileName } = useConfig(); diff --git a/packages/figma-plugin/src/ui/modules/providers/api-provider.tsx b/packages/figma-plugin/src/ui/modules/providers/api-provider.tsx new file mode 100644 index 0000000..6c74006 --- /dev/null +++ b/packages/figma-plugin/src/ui/modules/providers/api-provider.tsx @@ -0,0 +1,41 @@ +import { useMemo } from 'react'; +import { TRPCReactProvider } from '@ds-project/api/react'; +import { useAuth } from './auth-provider'; +import { tokenRefreshLink } from 'trpc-token-refresh-link'; +import type { AppRouter } from '../../../../../api/src/app-router'; + +export function ApiProvider({ children }: { children: React.ReactNode }) { + const { credentials, refreshAccessToken, logout } = useAuth(); + + const authTrpcLink = useMemo( + () => + tokenRefreshLink({ + tokenRefreshNeeded: () => { + if (!credentials) { + return false; + } + + return credentials.expireAt - Date.now() < 0; + }, + fetchAccessToken: async () => { + console.log('✨ Refreshing token...'); + try { + void refreshAccessToken(); + } catch (error) { + await logout(); + } + }, + }), + [credentials, logout, refreshAccessToken] + ); + + return ( + + {children} + + ); +} diff --git a/packages/figma-plugin/src/ui/modules/providers/auth-provider.tsx b/packages/figma-plugin/src/ui/modules/providers/auth-provider.tsx index e93bd7a..d778912 100644 --- a/packages/figma-plugin/src/ui/modules/providers/auth-provider.tsx +++ b/packages/figma-plugin/src/ui/modules/providers/auth-provider.tsx @@ -17,8 +17,7 @@ interface AuthStartResponse { } interface ContextType { - accessToken?: string; - refreshToken?: string; + credentials: Credentials | undefined; state: | 'initializing' | 'authorizing' @@ -31,6 +30,7 @@ interface ContextType { } const Context = createContext({ + credentials: undefined, state: 'initializing', refreshAccessToken: () => Promise.resolve(), login: () => Promise.resolve(), @@ -41,10 +41,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const [state, setState] = useState< 'initializing' | 'authorizing' | 'authorized' | 'unauthorized' | 'failed' >('initializing'); - const [accessToken, setAccessToken] = useState(); - const [refreshToken, setRefreshToken] = - useState(); const [shouldUpdatePlugin, setShouldUpdatePlugin] = useState(false); + const [credentials, setCredentials] = useState(); useEffect(() => { // Try to get credentials from plugin if they exist. @@ -55,9 +53,8 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { AsyncMessage.ui .request({ type: AsyncMessageTypes.GetCredentials }) - .then(({ credentials }) => { - setAccessToken(credentials.accessToken); - setRefreshToken(credentials.refreshToken); + .then(({ credentials: _credentials }) => { + setCredentials(_credentials); setState('authorized'); }) .catch((error) => { @@ -73,27 +70,23 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { return; } - if (state === 'authorized' && accessToken && refreshToken) { + if (state === 'authorized' && credentials) { void AsyncMessage.ui.request({ type: AsyncMessageTypes.SetCredentials, - credentials: { - accessToken, - refreshToken, - }, + credentials, }); - } else if (state === 'unauthorized' && !accessToken && !refreshToken) { + } else if (state === 'unauthorized' && !credentials) { void AsyncMessage.ui.request({ type: AsyncMessageTypes.DeleteCredentials, }); } setShouldUpdatePlugin(false); - }, [accessToken, refreshToken, shouldUpdatePlugin, state]); + }, [credentials, shouldUpdatePlugin, state]); const refreshAccessToken = useCallback(async () => { - if (!refreshToken) { - setAccessToken(undefined); - setRefreshToken(undefined); + if (!credentials) { + setCredentials(undefined); setState('unauthorized'); setShouldUpdatePlugin(true); return; @@ -101,37 +94,33 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const response = await fetch(`${config.AUTH_API_HOST}/api/auth/refresh`, { method: 'POST', - body: JSON.stringify({ refreshToken }), + body: JSON.stringify({ refreshToken: credentials.refreshToken }), }); if (!response.ok) { - setAccessToken(undefined); - setRefreshToken(undefined); + setCredentials(undefined); setState('unauthorized'); setShouldUpdatePlugin(true); return; } - const credentials = (await response.json()) as Credentials; - setAccessToken(credentials.accessToken); - setRefreshToken(credentials.refreshToken); + const _credentials = (await response.json()) as Credentials; + setCredentials(_credentials); setState('authorized'); setShouldUpdatePlugin(true); - }, [refreshToken]); + }, [credentials]); const logout = useCallback(async () => { await AsyncMessage.ui.request({ type: AsyncMessageTypes.DeleteCredentials, }); - setAccessToken(undefined); - setRefreshToken(undefined); + setCredentials(undefined); setState('unauthorized'); setShouldUpdatePlugin(true); }, []); const login = useCallback(async () => { - setAccessToken(undefined); - setRefreshToken(undefined); + setCredentials(undefined); setState('authorizing'); setShouldUpdatePlugin(true); @@ -169,10 +158,9 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { clearInterval(interval); - const credentials = (await exchangeResponse.json()) as Credentials; + const _credentials = (await exchangeResponse.json()) as Credentials; - setAccessToken(credentials.accessToken); - setRefreshToken(credentials.refreshToken); + setCredentials(_credentials); setState('authorized'); setShouldUpdatePlugin(true); }, config.READ_INTERVAL); @@ -181,13 +169,12 @@ export function AuthProvider({ children }: { children: React.ReactNode }) { const contextValue = useMemo( () => ({ state, - accessToken, - refreshToken, + credentials, refreshAccessToken, login, logout, }), - [accessToken, login, logout, refreshAccessToken, refreshToken, state] + [credentials, login, logout, refreshAccessToken, , state] ); return {children}; diff --git a/packages/figma-plugin/src/ui/modules/providers/index.tsx b/packages/figma-plugin/src/ui/modules/providers/index.tsx index e2afbfa..39b1b97 100644 --- a/packages/figma-plugin/src/ui/modules/providers/index.tsx +++ b/packages/figma-plugin/src/ui/modules/providers/index.tsx @@ -1,13 +1,14 @@ -import { TRPCReactProvider } from '../../lib/api'; +import { ApiProvider } from './api-provider'; import { AuthProvider } from './auth-provider'; import { ConfigProvider } from './config-provider'; +import { TRPCReactProvider } from '@ds-project/api/react'; export function Providers({ children }: { children: React.ReactNode }) { return ( - + {children} - + ); } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0e9c894..adec55b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,15 +9,9 @@ catalogs: '@figma/plugin-typings': specifier: ^1.98.0 version: 1.98.0 - '@trpc/client': - specifier: 11.0.0-rc.482 - version: 11.0.0-rc.482 '@trpc/react-query': specifier: 11.0.0-rc.482 version: 11.0.0-rc.482 - '@trpc/server': - specifier: 11.0.0-rc.482 - version: 11.0.0-rc.482 '@types/node': specifier: ^22.4.1 version: 22.4.1 @@ -64,6 +58,10 @@ catalogs: specifier: ^3.23.8 version: 3.23.8 +overrides: + '@trpc/client': 11.0.0-rc.482 + '@trpc/server': 11.0.0-rc.482 + importers: .: @@ -123,7 +121,7 @@ importers: specifier: 'catalog:' version: 11.0.0-rc.482(@tanstack/react-query@5.51.24(react@18.3.1))(@trpc/client@11.0.0-rc.482(@trpc/server@11.0.0-rc.482))(@trpc/server@11.0.0-rc.482)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@trpc/server': - specifier: 'catalog:' + specifier: 11.0.0-rc.482 version: 11.0.0-rc.482 '@vercel/kv': specifier: ^2.0.0 @@ -341,13 +339,13 @@ importers: specifier: ^5.51.24 version: 5.51.24(react@18.3.1) '@trpc/client': - specifier: 'catalog:' + specifier: 11.0.0-rc.482 version: 11.0.0-rc.482(@trpc/server@11.0.0-rc.482) '@trpc/react-query': specifier: 'catalog:' version: 11.0.0-rc.482(@tanstack/react-query@5.51.24(react@18.3.1))(@trpc/client@11.0.0-rc.482(@trpc/server@11.0.0-rc.482))(@trpc/server@11.0.0-rc.482)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@trpc/server': - specifier: 'catalog:' + specifier: 11.0.0-rc.482 version: 11.0.0-rc.482 next: specifier: 'catalog:' @@ -621,7 +619,7 @@ importers: specifier: ^5.51.24 version: 5.51.24(react@18.3.1) '@trpc/client': - specifier: 'catalog:' + specifier: 11.0.0-rc.482 version: 11.0.0-rc.482(@trpc/server@11.0.0-rc.482) '@trpc/react-query': specifier: 'catalog:' @@ -662,6 +660,9 @@ importers: tailwindcss: specifier: 'catalog:' version: 3.4.7 + trpc-token-refresh-link: + specifier: ^0.5.0 + version: 0.5.0 devDependencies: '@ds-project/eslint': specifier: workspace:* @@ -3038,111 +3039,56 @@ packages: rollup: optional: true - '@rollup/rollup-android-arm-eabi@4.17.2': - resolution: {integrity: sha512-NM0jFxY8bB8QLkoKxIQeObCaDlJKewVlIEkuyYKm5An1tdVZ966w2+MPQ2l8LBZLjR+SgyV+nRkTIunzOYBMLQ==} - cpu: [arm] - os: [android] - '@rollup/rollup-android-arm-eabi@4.21.0': resolution: {integrity: sha512-WTWD8PfoSAJ+qL87lE7votj3syLavxunWhzCnx3XFxFiI/BA/r3X7MUM8dVrH8rb2r4AiO8jJsr3ZjdaftmnfA==} cpu: [arm] os: [android] - '@rollup/rollup-android-arm64@4.17.2': - resolution: {integrity: sha512-yeX/Usk7daNIVwkq2uGoq2BYJKZY1JfyLTaHO/jaiSwi/lsf8fTFoQW/n6IdAsx5tx+iotu2zCJwz8MxI6D/Bw==} - cpu: [arm64] - os: [android] - '@rollup/rollup-android-arm64@4.21.0': resolution: {integrity: sha512-a1sR2zSK1B4eYkiZu17ZUZhmUQcKjk2/j9Me2IDjk1GHW7LB5Z35LEzj9iJch6gtUfsnvZs1ZNyDW2oZSThrkA==} cpu: [arm64] os: [android] - '@rollup/rollup-darwin-arm64@4.17.2': - resolution: {integrity: sha512-kcMLpE6uCwls023+kknm71ug7MZOrtXo+y5p/tsg6jltpDtgQY1Eq5sGfHcQfb+lfuKwhBmEURDga9N0ol4YPw==} - cpu: [arm64] - os: [darwin] - '@rollup/rollup-darwin-arm64@4.21.0': resolution: {integrity: sha512-zOnKWLgDld/svhKO5PD9ozmL6roy5OQ5T4ThvdYZLpiOhEGY+dp2NwUmxK0Ld91LrbjrvtNAE0ERBwjqhZTRAA==} cpu: [arm64] os: [darwin] - '@rollup/rollup-darwin-x64@4.17.2': - resolution: {integrity: sha512-AtKwD0VEx0zWkL0ZjixEkp5tbNLzX+FCqGG1SvOu993HnSz4qDI6S4kGzubrEJAljpVkhRSlg5bzpV//E6ysTQ==} - cpu: [x64] - os: [darwin] - '@rollup/rollup-darwin-x64@4.21.0': resolution: {integrity: sha512-7doS8br0xAkg48SKE2QNtMSFPFUlRdw9+votl27MvT46vo44ATBmdZdGysOevNELmZlfd+NEa0UYOA8f01WSrg==} cpu: [x64] os: [darwin] - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - resolution: {integrity: sha512-3reX2fUHqN7sffBNqmEyMQVj/CKhIHZd4y631duy0hZqI8Qoqf6lTtmAKvJFYa6bhU95B1D0WgzHkmTg33In0A==} - cpu: [arm] - os: [linux] - '@rollup/rollup-linux-arm-gnueabihf@4.21.0': resolution: {integrity: sha512-pWJsfQjNWNGsoCq53KjMtwdJDmh/6NubwQcz52aEwLEuvx08bzcy6tOUuawAOncPnxz/3siRtd8hiQ32G1y8VA==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - resolution: {integrity: sha512-uSqpsp91mheRgw96xtyAGP9FW5ChctTFEoXP0r5FAzj/3ZRv3Uxjtc7taRQSaQM/q85KEKjKsZuiZM3GyUivRg==} - cpu: [arm] - os: [linux] - '@rollup/rollup-linux-arm-musleabihf@4.21.0': resolution: {integrity: sha512-efRIANsz3UHZrnZXuEvxS9LoCOWMGD1rweciD6uJQIx2myN3a8Im1FafZBzh7zk1RJ6oKcR16dU3UPldaKd83w==} cpu: [arm] os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.17.2': - resolution: {integrity: sha512-EMMPHkiCRtE8Wdk3Qhtciq6BndLtstqZIroHiiGzB3C5LDJmIZcSzVtLRbwuXuUft1Cnv+9fxuDtDxz3k3EW2A==} - cpu: [arm64] - os: [linux] - '@rollup/rollup-linux-arm64-gnu@4.21.0': resolution: {integrity: sha512-ZrPhydkTVhyeGTW94WJ8pnl1uroqVHM3j3hjdquwAcWnmivjAwOYjTEAuEDeJvGX7xv3Z9GAvrBkEzCgHq9U1w==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-arm64-musl@4.17.2': - resolution: {integrity: sha512-NMPylUUZ1i0z/xJUIx6VUhISZDRT+uTWpBcjdv0/zkp7b/bQDF+NfnfdzuTiB1G6HTodgoFa93hp0O1xl+/UbA==} - cpu: [arm64] - os: [linux] - '@rollup/rollup-linux-arm64-musl@4.21.0': resolution: {integrity: sha512-cfaupqd+UEFeURmqNP2eEvXqgbSox/LHOyN9/d2pSdV8xTrjdg3NgOFJCtc1vQ/jEke1qD0IejbBfxleBPHnPw==} cpu: [arm64] os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - resolution: {integrity: sha512-T19My13y8uYXPw/L/k0JYaX1fJKFT/PWdXiHr8mTbXWxjVF1t+8Xl31DgBBvEKclw+1b00Chg0hxE2O7bTG7GQ==} - cpu: [ppc64] - os: [linux] - '@rollup/rollup-linux-powerpc64le-gnu@4.21.0': resolution: {integrity: sha512-ZKPan1/RvAhrUylwBXC9t7B2hXdpb/ufeu22pG2psV7RN8roOfGurEghw1ySmX/CmDDHNTDDjY3lo9hRlgtaHg==} cpu: [ppc64] os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - resolution: {integrity: sha512-BOaNfthf3X3fOWAB+IJ9kxTgPmMqPPH5f5k2DcCsRrBIbWnaJCgX2ll77dV1TdSy9SaXTR5iDXRL8n7AnoP5cg==} - cpu: [riscv64] - os: [linux] - '@rollup/rollup-linux-riscv64-gnu@4.21.0': resolution: {integrity: sha512-H1eRaCwd5E8eS8leiS+o/NqMdljkcb1d6r2h4fKSsCXQilLKArq6WS7XBLDu80Yz+nMqHVFDquwcVrQmGr28rg==} cpu: [riscv64] os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.17.2': - resolution: {integrity: sha512-W0UP/x7bnn3xN2eYMql2T/+wpASLE5SjObXILTMPUBDB/Fg/FxC+gX4nvCfPBCbNhz51C+HcqQp2qQ4u25ok6g==} - cpu: [s390x] - os: [linux] - '@rollup/rollup-linux-s390x-gnu@4.21.0': resolution: {integrity: sha512-zJ4hA+3b5tu8u7L58CCSI0A9N1vkfwPhWd/puGXwtZlsB5bTkwDNW/+JCU84+3QYmKpLi+XvHdmrlwUwDA6kqw==} cpu: [s390x] @@ -3158,41 +3104,21 @@ packages: cpu: [x64] os: [linux] - '@rollup/rollup-linux-x64-musl@4.17.2': - resolution: {integrity: sha512-h1+yTWeYbRdAyJ/jMiVw0l6fOOm/0D1vNLui9iPuqgRGnXA0u21gAqOyB5iHjlM9MMfNOm9RHCQ7zLIzT0x11Q==} - cpu: [x64] - os: [linux] - '@rollup/rollup-linux-x64-musl@4.21.0': resolution: {integrity: sha512-1vvmgDdUSebVGXWX2lIcgRebqfQSff0hMEkLJyakQ9JQUbLDkEaMsPTLOmyccyC6IJ/l3FZuJbmrBw/u0A0uCQ==} cpu: [x64] os: [linux] - '@rollup/rollup-win32-arm64-msvc@4.17.2': - resolution: {integrity: sha512-tmdtXMfKAjy5+IQsVtDiCfqbynAQE/TQRpWdVataHmhMb9DCoJxp9vLcCBjEQWMiUYxO1QprH/HbY9ragCEFLA==} - cpu: [arm64] - os: [win32] - '@rollup/rollup-win32-arm64-msvc@4.21.0': resolution: {integrity: sha512-s5oFkZ/hFcrlAyBTONFY1TWndfyre1wOMwU+6KCpm/iatybvrRgmZVM+vCFwxmC5ZhdlgfE0N4XorsDpi7/4XQ==} cpu: [arm64] os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.17.2': - resolution: {integrity: sha512-7II/QCSTAHuE5vdZaQEwJq2ZACkBpQDOmQsE6D6XUbnBHW8IAhm4eTufL6msLJorzrHDFv3CF8oCA/hSIRuZeQ==} - cpu: [ia32] - os: [win32] - '@rollup/rollup-win32-ia32-msvc@4.21.0': resolution: {integrity: sha512-G9+TEqRnAA6nbpqyUqgTiopmnfgnMkR3kMukFBDsiyy23LZvUCpiUwjTRx6ezYCjJODXrh52rBR9oXvm+Fp5wg==} cpu: [ia32] os: [win32] - '@rollup/rollup-win32-x64-msvc@4.17.2': - resolution: {integrity: sha512-TGGO7v7qOq4CYmSBVEYpI1Y5xDuCEnbVC5Vth8mOsW0gDSzxNrVERPc790IGHsrT2dQSimgMr9Ub3Y1Jci5/8w==} - cpu: [x64] - os: [win32] - '@rollup/rollup-win32-x64-msvc@4.21.0': resolution: {integrity: sha512-2jsCDZwtQvRhejHLfZ1JY6w6kEuEtfF9nzYsZxzSlNVKDX+DpsDJ+Rbjkm74nvg2rdx0gwBS+IMdvwJuq3S9pQ==} cpu: [x64] @@ -3485,14 +3411,14 @@ packages: '@trpc/client@11.0.0-rc.482': resolution: {integrity: sha512-G08bQe8zSSK6baavNTzlsGIXUuUJyRmbC7YCwIg/eYh01nah/loxh4Cg8NDtTLzOvwmUOyQaU3XcMyhywwC4/g==} peerDependencies: - '@trpc/server': 11.0.0-rc.482+930e652bf + '@trpc/server': 11.0.0-rc.482 '@trpc/react-query@11.0.0-rc.482': resolution: {integrity: sha512-pmXStCkoxs7AJoP8oM9hnEXoYYYQbp/5kbA507R4Hd/P2tniBFe6aKFg4bXqeV+bWOi7qPNGSa5+IDH64WPRBg==} peerDependencies: '@tanstack/react-query': ^5.49.2 - '@trpc/client': 11.0.0-rc.482+930e652bf - '@trpc/server': 11.0.0-rc.482+930e652bf + '@trpc/client': 11.0.0-rc.482 + '@trpc/server': 11.0.0-rc.482 react: '>=18.2.0' react-dom: '>=18.2.0' @@ -5046,6 +4972,9 @@ packages: resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} engines: {node: '>= 0.6'} + eventemitter3@5.0.1: + resolution: {integrity: sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==} + events@3.3.0: resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} engines: {node: '>=0.8.x'} @@ -6191,6 +6120,14 @@ packages: resolution: {integrity: sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==} engines: {node: '>=10'} + p-queue@7.4.1: + resolution: {integrity: sha512-vRpMXmIkYF2/1hLBKisKeVYJZ8S2tZ0zEAmIJgdVKP2nq0nh4qCdf8bgw+ZgKrkh71AOCaqzwbJJk1WtdcF3VA==} + engines: {node: '>=12'} + + p-timeout@5.1.0: + resolution: {integrity: sha512-auFDyzzzGZZZdHz3BtET9VEz0SE/uMEAx7uWfGPucfzEwwe/xH0iVeZibQmANYE/hp9T2+UUZT5m+BKyrDp3Ew==} + engines: {node: '>=12'} + p-try@2.2.0: resolution: {integrity: sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==} engines: {node: '>=6'} @@ -6723,11 +6660,6 @@ packages: peerDependencies: rollup: ^2.0.0 || ^3.0.0 || ^4.0.0 - rollup@4.17.2: - resolution: {integrity: sha512-/9ClTJPByC0U4zNLowV1tMBe8yMEAxewtR3cUNX5BoEpGH3dQEWpJLr6CLp0fPdYRF/fzVOgvDb1zXuakwF5kQ==} - engines: {node: '>=18.0.0', npm: '>=8.0.0'} - hasBin: true - rollup@4.21.0: resolution: {integrity: sha512-vo+S/lfA2lMS7rZ2Qoubi6I5hwZwzXeUIctILZLbHI+laNtvhhOIon2S1JksA5UEDQ7l3vberd0fxK44lTYjbQ==} engines: {node: '>=18.0.0', npm: '>=8.0.0'} @@ -7135,6 +7067,9 @@ packages: resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} hasBin: true + trpc-token-refresh-link@0.5.0: + resolution: {integrity: sha512-yXPrGjYnXafDfjOYV29bcHYlfMmCnpCFhrDSI5fxJJlYamClHhyTgHjd+VHov/EJvwVu4Z+cp7FgIkL7Q6rKuQ==} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -9811,69 +9746,36 @@ snapshots: optionalDependencies: rollup: 4.21.0 - '@rollup/rollup-android-arm-eabi@4.17.2': - optional: true - '@rollup/rollup-android-arm-eabi@4.21.0': optional: true - '@rollup/rollup-android-arm64@4.17.2': - optional: true - '@rollup/rollup-android-arm64@4.21.0': optional: true - '@rollup/rollup-darwin-arm64@4.17.2': - optional: true - '@rollup/rollup-darwin-arm64@4.21.0': optional: true - '@rollup/rollup-darwin-x64@4.17.2': - optional: true - '@rollup/rollup-darwin-x64@4.21.0': optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.17.2': - optional: true - '@rollup/rollup-linux-arm-gnueabihf@4.21.0': optional: true - '@rollup/rollup-linux-arm-musleabihf@4.17.2': - optional: true - '@rollup/rollup-linux-arm-musleabihf@4.21.0': optional: true - '@rollup/rollup-linux-arm64-gnu@4.17.2': - optional: true - '@rollup/rollup-linux-arm64-gnu@4.21.0': optional: true - '@rollup/rollup-linux-arm64-musl@4.17.2': - optional: true - '@rollup/rollup-linux-arm64-musl@4.21.0': optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.17.2': - optional: true - '@rollup/rollup-linux-powerpc64le-gnu@4.21.0': optional: true - '@rollup/rollup-linux-riscv64-gnu@4.17.2': - optional: true - '@rollup/rollup-linux-riscv64-gnu@4.21.0': optional: true - '@rollup/rollup-linux-s390x-gnu@4.17.2': - optional: true - '@rollup/rollup-linux-s390x-gnu@4.21.0': optional: true @@ -9883,27 +9785,15 @@ snapshots: '@rollup/rollup-linux-x64-gnu@4.21.0': optional: true - '@rollup/rollup-linux-x64-musl@4.17.2': - optional: true - '@rollup/rollup-linux-x64-musl@4.21.0': optional: true - '@rollup/rollup-win32-arm64-msvc@4.17.2': - optional: true - '@rollup/rollup-win32-arm64-msvc@4.21.0': optional: true - '@rollup/rollup-win32-ia32-msvc@4.17.2': - optional: true - '@rollup/rollup-win32-ia32-msvc@4.21.0': optional: true - '@rollup/rollup-win32-x64-msvc@4.17.2': - optional: true - '@rollup/rollup-win32-x64-msvc@4.21.0': optional: true @@ -12363,6 +12253,8 @@ snapshots: etag@1.8.1: {} + eventemitter3@5.0.1: {} + events@3.3.0: {} execa@5.1.1: @@ -13551,6 +13443,13 @@ snapshots: dependencies: p-limit: 3.1.0 + p-queue@7.4.1: + dependencies: + eventemitter3: 5.0.1 + p-timeout: 5.1.0 + + p-timeout@5.1.0: {} + p-try@2.2.0: {} package-json-from-dist@1.0.0: {} @@ -14083,28 +13982,6 @@ snapshots: magic-string: 0.30.10 rollup: 4.21.0 - rollup@4.17.2: - dependencies: - '@types/estree': 1.0.5 - optionalDependencies: - '@rollup/rollup-android-arm-eabi': 4.17.2 - '@rollup/rollup-android-arm64': 4.17.2 - '@rollup/rollup-darwin-arm64': 4.17.2 - '@rollup/rollup-darwin-x64': 4.17.2 - '@rollup/rollup-linux-arm-gnueabihf': 4.17.2 - '@rollup/rollup-linux-arm-musleabihf': 4.17.2 - '@rollup/rollup-linux-arm64-gnu': 4.17.2 - '@rollup/rollup-linux-arm64-musl': 4.17.2 - '@rollup/rollup-linux-powerpc64le-gnu': 4.17.2 - '@rollup/rollup-linux-riscv64-gnu': 4.17.2 - '@rollup/rollup-linux-s390x-gnu': 4.17.2 - '@rollup/rollup-linux-x64-gnu': 4.17.2 - '@rollup/rollup-linux-x64-musl': 4.17.2 - '@rollup/rollup-win32-arm64-msvc': 4.17.2 - '@rollup/rollup-win32-ia32-msvc': 4.17.2 - '@rollup/rollup-win32-x64-msvc': 4.17.2 - fsevents: 2.3.3 - rollup@4.21.0: dependencies: '@types/estree': 1.0.5 @@ -14609,6 +14486,13 @@ snapshots: tree-kill@1.2.2: {} + trpc-token-refresh-link@0.5.0: + dependencies: + '@trpc/client': 11.0.0-rc.482(@trpc/server@11.0.0-rc.482) + '@trpc/server': 11.0.0-rc.482 + date-fns: 2.30.0 + p-queue: 7.4.1 + ts-api-utils@1.3.0(typescript@5.5.4): dependencies: typescript: 5.5.4 @@ -14946,7 +14830,7 @@ snapshots: dependencies: esbuild: 0.21.5 postcss: 8.4.39 - rollup: 4.17.2 + rollup: 4.21.0 optionalDependencies: '@types/node': 22.4.1 fsevents: 2.3.3 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index c08db66..5e24858 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -23,4 +23,3 @@ catalog: typescript: ^5.5.4 vite: ^5.3.1 zod: ^3.23.8 -