Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions deep-sea-stories/packages/backend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
"type": "module",
"dependencies": {
"@fishjam-cloud/js-server-sdk": "^0.21.0",
"@trpc/server": "^11.6.0",
"dotenv": "^17.2.3",
"fastify": "^5.6.1",
"fastify-plugin": "^5.1.0",
"fastify-type-provider-zod": "^6.0.0",
"pino-pretty": "^13.1.1",
"zod": "^4.1.11"
},
Expand Down
14 changes: 1 addition & 13 deletions deep-sea-stories/packages/backend/src/config.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,13 @@
import dotenv from 'dotenv';
import type { FastifyInstance } from 'fastify';
import fp from 'fastify-plugin';
import z from 'zod';

dotenv.config();

declare module 'fastify' {
interface FastifyInstance {
config: ConfigSchema;
}
}

export const configSchema = z.object({
PORT: z.coerce.number().int().default(8000),
FISHJAM_ID: z.string(),
FISHJAM_URL: z.string().optional(),
FISHJAM_MANAGEMENT_TOKEN: z.string(),
});

type ConfigSchema = z.infer<typeof configSchema>;

export const fastifyConfig = fp((fastify: FastifyInstance) => {
fastify.decorate('config', configSchema.parse(process.env));
});
export const CONFIG = configSchema.parse(process.env);
15 changes: 15 additions & 0 deletions deep-sea-stories/packages/backend/src/context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { FishjamClient } from '@fishjam-cloud/js-server-sdk';
import type { CreateFastifyContextOptions } from '@trpc/server/adapters/fastify';
import { CONFIG } from './config.js';

const fishjam = new FishjamClient({
fishjamId: CONFIG.FISHJAM_ID,
fishjamUrl: CONFIG.FISHJAM_URL,
managementToken: CONFIG.FISHJAM_MANAGEMENT_TOKEN,
});

export function createContext({ req, res }: CreateFastifyContextOptions) {
return { req, res, fishjam };
}

export type Context = Awaited<ReturnType<typeof createContext>>;
18 changes: 11 additions & 7 deletions deep-sea-stories/packages/backend/src/controllers/rooms.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import type { FishjamClient, RoomId } from '@fishjam-cloud/js-server-sdk';
import type { RoomId } from '@fishjam-cloud/js-server-sdk';
import { getRoomInputSchema } from '../schemas.js';
import { publicProcedure } from '../trpc.js';

export async function createRoom(fishjam: FishjamClient) {
return await fishjam.createRoom();
}
export const createRoom = publicProcedure.mutation(async ({ ctx }) => {
return await ctx.fishjam.createRoom();
});

export async function getRoom(fishjam: FishjamClient, roomId: RoomId) {
return await fishjam.getRoom(roomId);
}
export const getRoom = publicProcedure
.input(getRoomInputSchema)
.query(async ({ ctx, input }) => {
return await ctx.fishjam.getRoom(input.roomId as RoomId);
});
38 changes: 21 additions & 17 deletions deep-sea-stories/packages/backend/src/main.ts
Original file line number Diff line number Diff line change
@@ -1,29 +1,33 @@
import Fastify from 'fastify';
import {
serializerCompiler,
validatorCompiler,
type ZodTypeProvider,
} from 'fastify-type-provider-zod';
import { fastifyConfig } from './config.js';
import { fishjamPlugin } from './plugins/fishjam.js';
import routes from './routes/index.js';
type FastifyTRPCPluginOptions,
fastifyTRPCPlugin,
} from '@trpc/server/adapters/fastify';
import Fastify from 'fastify';
import { CONFIG } from './config.js';
import { createContext } from './context.js';
import { type AppRouter, appRouter } from './router.js';

const fastify = Fastify({
logger: { transport: { target: 'pino-pretty' } },
}).withTypeProvider<ZodTypeProvider>();

fastify.setValidatorCompiler(validatorCompiler);
fastify.setSerializerCompiler(serializerCompiler);
});

fastify.register(fastifyConfig);
fastify.register(fishjamPlugin);

fastify.register(routes, { prefix: '/api/v1' });
fastify.register(fastifyTRPCPlugin, {
prefix: '/api/v1',
trpcOptions: {
router: appRouter,
createContext,
onError({ path, error }) {
fastify.log.error('Error in tRPC handler on path %s: %O', path, error);
},
} satisfies FastifyTRPCPluginOptions<AppRouter>['trpcOptions'],
});

try {
await fastify.ready();
await fastify.listen({ port: fastify.config.PORT });
await fastify.listen({ port: CONFIG.PORT });
} catch (err) {
fastify.log.error(err);
process.exit(1);
}

export type { AppRouter };
29 changes: 0 additions & 29 deletions deep-sea-stories/packages/backend/src/plugins/fishjam.ts

This file was deleted.

9 changes: 9 additions & 0 deletions deep-sea-stories/packages/backend/src/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { createRoom, getRoom } from './controllers/rooms.js';
import { router } from './trpc.js';

export const appRouter = router({
createRoom,
getRoom,
});

export type AppRouter = typeof appRouter;
6 changes: 0 additions & 6 deletions deep-sea-stories/packages/backend/src/routes/index.ts

This file was deleted.

38 changes: 0 additions & 38 deletions deep-sea-stories/packages/backend/src/routes/rooms.ts

This file was deleted.

9 changes: 1 addition & 8 deletions deep-sea-stories/packages/backend/src/schemas.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,3 @@
import z from 'zod';

export const peerSchema = z.object({
id: z.string(),
});

export const roomSchema = z.object({
id: z.string(),
peers: peerSchema.array(),
});
export const getRoomInputSchema = z.object({ roomId: z.string() });
7 changes: 7 additions & 0 deletions deep-sea-stories/packages/backend/src/trpc.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { initTRPC } from '@trpc/server';
import type { Context } from './context.js';

const t = initTRPC.context<Context>().create();

export const router = t.router;
export const publicProcedure = t.procedure;
5 changes: 5 additions & 0 deletions deep-sea-stories/packages/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@
"preview": "vite preview"
},
"dependencies": {
"@tanstack/react-query": "^5.90.2",
"@trpc/client": "^11.6.0",
"@trpc/server": "^11.6.0",
"@trpc/tanstack-react-query": "^11.6.0",
"backend": "workspace:*",
"react": "^19.1.1",
"react-dom": "^19.1.1"
},
Expand Down
33 changes: 33 additions & 0 deletions deep-sea-stories/packages/web/src/contexts/trpc.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import type { QueryClient } from '@tanstack/react-query';
import { createTRPCClient, httpBatchLink } from '@trpc/client';
import { createTRPCContext } from '@trpc/tanstack-react-query';
import type { AppRouter } from 'backend';
import { type FC, type PropsWithChildren, useState } from 'react';

export const { TRPCProvider, useTRPC, useTRPCClient } =
createTRPCContext<AppRouter>();

interface TRPCClientProviderProps extends PropsWithChildren {
queryClient: QueryClient;
}

export const TRPCClientProvider: FC<TRPCClientProviderProps> = ({
queryClient,
children,
}) => {
const [trpcClient] = useState(() =>
createTRPCClient<AppRouter>({
links: [
httpBatchLink({
url: import.meta.env.VITE_BACKEND_URL,
}),
],
}),
);

return (
<TRPCProvider queryClient={queryClient} trpcClient={trpcClient}>
{children}
</TRPCProvider>
);
};
16 changes: 15 additions & 1 deletion deep-sea-stories/packages/web/src/main.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,25 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import './index.css';
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from './App.tsx';
import { TRPCClientProvider } from './contexts/trpc.tsx';

const queryClient = new QueryClient({
defaultOptions: {
queries: {
retryDelay: 2000,
},
},
});

// biome-ignore lint/style/noNonNullAssertion: root always exists
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
<QueryClientProvider client={queryClient}>
<TRPCClientProvider queryClient={queryClient}>
<App />
</TRPCClientProvider>
</QueryClientProvider>
</StrictMode>,
);
14 changes: 14 additions & 0 deletions deep-sea-stories/packages/web/src/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/// <reference types="vite/client" />

interface ViteTypeOptions {
strictImportMetaEnv: unknown;
}

interface ImportMetaEnv {
readonly VITE_BACKEND_URL: string;
readonly VITE_FISHJAM_ID: string;
}

interface ImportMeta {
readonly env: ImportMetaEnv;
}
2 changes: 1 addition & 1 deletion deep-sea-stories/packages/web/vite.config.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';

// https://vite.dev/config/
export default defineConfig({
Expand Down
Loading