From c9af23c921112537e3c5e27fd6dd5d23fe543254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mime=20=C4=8Cuvalo?= Date: Sat, 27 Apr 2024 11:57:55 +0100 Subject: [PATCH] make route prefixes have a single place where they are defined (#3624) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is for maintainabilty of the paths. It's hard to track down all the places where a route is being referenced. This helps unify them so that it's easily searchable in the codebase. This came up during the readonly room refactor and being able to find the way a particular route was wired through the codebase. ### Change Type - [x] `sdk` — Changes the tldraw SDK - [ ] `dotcom` — Changes the tldraw.com web app - [ ] `docs` — Changes to the documentation, examples, or templates. - [ ] `vs code` — Changes to the vscode plugin - [ ] `internal` — Does not affect user-facing stuff - [ ] `bugfix` — Bug fix - [ ] `feature` — New feature - [ ] `improvement` — Improving existing features - [x] `chore` — Updating dependencies, other boring stuff - [ ] `galaxy brain` — Architectural changes - [ ] `tests` — Changes to any test code - [ ] `tools` — Changes to infrastructure, CI, internal scripts, debugging tools, etc. - [ ] `dunno` — I don't know --- .../src/lib/TLDrawDurableObject.ts | 16 ++++++++---- .../src/lib/routes/forwardRoomRequest.ts | 3 ++- .../src/lib/routes/joinExistingRoom.ts | 4 +-- apps/dotcom-worker/src/lib/worker.ts | 25 +++++++++++++------ .../BoardHistorySnapshot.tsx | 3 ++- apps/dotcom/src/components/ShareMenu.tsx | 3 ++- apps/dotcom/src/pages/history-snapshot.tsx | 3 ++- apps/dotcom/src/pages/history.tsx | 3 ++- apps/dotcom/src/pages/new.tsx | 4 +-- apps/dotcom/src/routes.tsx | 25 +++++++++++++------ apps/dotcom/src/utils/sharing.ts | 6 +++-- packages/dotcom-shared/src/index.ts | 10 +++++++- packages/dotcom-shared/src/routes.ts | 15 ++++++++--- 13 files changed, 85 insertions(+), 35 deletions(-) diff --git a/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts b/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts index 4746320dc..af2dfd5e0 100644 --- a/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts +++ b/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts @@ -2,7 +2,13 @@ /// import { SupabaseClient } from '@supabase/supabase-js' -import { ROOM_OPEN_MODE, type RoomOpenMode } from '@tldraw/dotcom-shared' +import { + READ_ONLY_LEGACY_PREFIX, + READ_ONLY_PREFIX, + ROOM_OPEN_MODE, + ROOM_PREFIX, + type RoomOpenMode, +} from '@tldraw/dotcom-shared' import { DBLoadResultType, RoomSnapshot, @@ -91,22 +97,22 @@ export class TLDrawDurableObject extends TLServer { readonly router = Router() .get( - '/r/:roomId', + `/${ROOM_PREFIX}/:roomId`, (req) => this.extractDocumentInfoFromRequest(req, ROOM_OPEN_MODE.READ_WRITE), (req) => this.onRequest(req) ) .get( - '/v/:roomId', + `/${READ_ONLY_LEGACY_PREFIX}/:roomId`, (req) => this.extractDocumentInfoFromRequest(req, ROOM_OPEN_MODE.READ_ONLY_LEGACY), (req) => this.onRequest(req) ) .get( - '/ro/:roomId', + `/${READ_ONLY_PREFIX}/:roomId`, (req) => this.extractDocumentInfoFromRequest(req, ROOM_OPEN_MODE.READ_ONLY), (req) => this.onRequest(req) ) .post( - '/r/:roomId/restore', + `/${ROOM_PREFIX}/:roomId/restore`, (req) => this.extractDocumentInfoFromRequest(req, ROOM_OPEN_MODE.READ_WRITE), (req) => this.onRestore(req) ) diff --git a/apps/dotcom-worker/src/lib/routes/forwardRoomRequest.ts b/apps/dotcom-worker/src/lib/routes/forwardRoomRequest.ts index fc3befcc4..350c445f3 100644 --- a/apps/dotcom-worker/src/lib/routes/forwardRoomRequest.ts +++ b/apps/dotcom-worker/src/lib/routes/forwardRoomRequest.ts @@ -1,3 +1,4 @@ +import { ROOM_PREFIX } from '@tldraw/dotcom-shared' import { IRequest } from 'itty-router' import { Environment } from '../types' import { fourOhFour } from '../utils/fourOhFour' @@ -11,6 +12,6 @@ export async function forwardRoomRequest(request: IRequest, env: Environment): P if (isRoomIdTooLong(roomId)) return roomIdIsTooLong() // Set up the durable object for this room - const id = env.TLDR_DOC.idFromName(`/r/${roomId}`) + const id = env.TLDR_DOC.idFromName(`/${ROOM_PREFIX}/${roomId}`) return env.TLDR_DOC.get(id).fetch(request) } diff --git a/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts b/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts index b90b87113..eab25c614 100644 --- a/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts +++ b/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts @@ -1,4 +1,4 @@ -import { RoomOpenMode } from '@tldraw/dotcom-shared' +import { ROOM_PREFIX, RoomOpenMode } from '@tldraw/dotcom-shared' import { IRequest } from 'itty-router' import { Environment } from '../types' import { fourOhFour } from '../utils/fourOhFour' @@ -17,7 +17,7 @@ export async function joinExistingRoom( // This needs to be a websocket request! if (request.headers.get('upgrade')?.toLowerCase() === 'websocket') { // Set up the durable object for this room - const id = env.TLDR_DOC.idFromName(`/r/${roomId}`) + const id = env.TLDR_DOC.idFromName(`/${ROOM_PREFIX}/${roomId}`) return env.TLDR_DOC.get(id).fetch(request) } diff --git a/apps/dotcom-worker/src/lib/worker.ts b/apps/dotcom-worker/src/lib/worker.ts index d2100e10a..88bbc4e9e 100644 --- a/apps/dotcom-worker/src/lib/worker.ts +++ b/apps/dotcom-worker/src/lib/worker.ts @@ -1,6 +1,11 @@ /// /// -import { ROOM_OPEN_MODE } from '@tldraw/dotcom-shared' +import { + READ_ONLY_LEGACY_PREFIX, + READ_ONLY_PREFIX, + ROOM_OPEN_MODE, + ROOM_PREFIX, +} from '@tldraw/dotcom-shared' import { Router, createCors } from 'itty-router' import { env } from 'process' import Toucan from 'toucan-js' @@ -26,13 +31,19 @@ const router = Router() .post('/new-room', createRoom) .post('/snapshots', createRoomSnapshot) .get('/snapshot/:roomId', getRoomSnapshot) - .get('/r/:roomId', (req, env) => joinExistingRoom(req, env, ROOM_OPEN_MODE.READ_WRITE)) - .get('/v/:roomId', (req, env) => joinExistingRoom(req, env, ROOM_OPEN_MODE.READ_ONLY_LEGACY)) - .get('/ro/:roomId', (req, env) => joinExistingRoom(req, env, ROOM_OPEN_MODE.READ_ONLY)) - .get('/r/:roomId/history', getRoomHistory) - .get('/r/:roomId/history/:timestamp', getRoomHistorySnapshot) + .get(`/${ROOM_PREFIX}/:roomId`, (req, env) => + joinExistingRoom(req, env, ROOM_OPEN_MODE.READ_WRITE) + ) + .get(`/${READ_ONLY_LEGACY_PREFIX}/:roomId`, (req, env) => + joinExistingRoom(req, env, ROOM_OPEN_MODE.READ_ONLY_LEGACY) + ) + .get(`/${READ_ONLY_PREFIX}/:roomId`, (req, env) => + joinExistingRoom(req, env, ROOM_OPEN_MODE.READ_ONLY) + ) + .get(`/${ROOM_PREFIX}/:roomId/history`, getRoomHistory) + .get(`/${ROOM_PREFIX}/:roomId/history/:timestamp`, getRoomHistorySnapshot) .get('/readonly-slug/:roomId', getReadonlySlug) - .post('/r/:roomId/restore', forwardRoomRequest) + .post(`/${ROOM_PREFIX}/:roomId/restore`, forwardRoomRequest) .all('*', fourOhFour) const Worker = { diff --git a/apps/dotcom/src/components/BoardHistorySnapshot/BoardHistorySnapshot.tsx b/apps/dotcom/src/components/BoardHistorySnapshot/BoardHistorySnapshot.tsx index 300740bdf..e8a07d470 100644 --- a/apps/dotcom/src/components/BoardHistorySnapshot/BoardHistorySnapshot.tsx +++ b/apps/dotcom/src/components/BoardHistorySnapshot/BoardHistorySnapshot.tsx @@ -1,3 +1,4 @@ +import { ROOM_PREFIX } from '@tldraw/dotcom-shared' import { RoomSnapshot } from '@tldraw/tlsync' import { useCallback, useState } from 'react' import { Tldraw, createTLStore, defaultShapeUtils } from 'tldraw' @@ -31,7 +32,7 @@ export function BoardHistorySnapshot({ const sure = window.confirm('Are you sure?') if (!sure) return - const res = await fetch(`/api/r/${roomId}/restore`, { + const res = await fetch(`/api/${ROOM_PREFIX}/${roomId}/restore`, { method: 'POST', headers: { 'Content-Type': 'application/json', diff --git a/apps/dotcom/src/components/ShareMenu.tsx b/apps/dotcom/src/components/ShareMenu.tsx index 0e44a8a98..65a229703 100644 --- a/apps/dotcom/src/components/ShareMenu.tsx +++ b/apps/dotcom/src/components/ShareMenu.tsx @@ -2,6 +2,7 @@ import * as Popover from '@radix-ui/react-popover' import { GetReadonlySlugResponseBody, ROOM_OPEN_MODE, + ROOM_PREFIX, RoomOpenModeToPath, } from '@tldraw/dotcom-shared' import React, { useEffect, useState } from 'react' @@ -43,7 +44,7 @@ function isSharedReadonlyUrl(pathname: string) { } function isSharedReadWriteUrl(pathname: string) { - return pathname.startsWith('/r/') + return pathname.startsWith(`/${ROOM_PREFIX}/`) } function getFreshShareState(): ShareState { diff --git a/apps/dotcom/src/pages/history-snapshot.tsx b/apps/dotcom/src/pages/history-snapshot.tsx index b8d900d0a..90d861608 100644 --- a/apps/dotcom/src/pages/history-snapshot.tsx +++ b/apps/dotcom/src/pages/history-snapshot.tsx @@ -1,3 +1,4 @@ +import { ROOM_PREFIX } from '@tldraw/dotcom-shared' import { RoomSnapshot } from '@tldraw/tlsync' import '../../styles/globals.css' import { BoardHistorySnapshot } from '../components/BoardHistorySnapshot/BoardHistorySnapshot' @@ -11,7 +12,7 @@ const { loader, useData } = defineLoader(async (args) => { if (!roomId) return null - const result = await fetch(`/api/r/${roomId}/history/${timestamp}`, { + const result = await fetch(`/api/${ROOM_PREFIX}/${roomId}/history/${timestamp}`, { headers: {}, }) if (!result.ok) return null diff --git a/apps/dotcom/src/pages/history.tsx b/apps/dotcom/src/pages/history.tsx index 758a15e8e..cbe37b800 100644 --- a/apps/dotcom/src/pages/history.tsx +++ b/apps/dotcom/src/pages/history.tsx @@ -1,3 +1,4 @@ +import { ROOM_PREFIX } from '@tldraw/dotcom-shared' import { BoardHistoryLog } from '../components/BoardHistoryLog/BoardHistoryLog' import { ErrorPage } from '../components/ErrorPage/ErrorPage' import { IFrameProtector, ROOM_CONTEXT } from '../components/IFrameProtector' @@ -8,7 +9,7 @@ const { loader, useData } = defineLoader(async (args) => { if (!boardId) return null - const result = await fetch(`/api/r/${boardId}/history`, { + const result = await fetch(`/api/${ROOM_PREFIX}/${boardId}/history`, { headers: {}, }) if (!result.ok) return null diff --git a/apps/dotcom/src/pages/new.tsx b/apps/dotcom/src/pages/new.tsx index a09dcc768..6dd611b07 100644 --- a/apps/dotcom/src/pages/new.tsx +++ b/apps/dotcom/src/pages/new.tsx @@ -1,4 +1,4 @@ -import { Snapshot } from '@tldraw/dotcom-shared' +import { ROOM_PREFIX, Snapshot } from '@tldraw/dotcom-shared' import { schema } from '@tldraw/tlsync' import { Navigate } from 'react-router-dom' import '../../styles/globals.css' @@ -36,5 +36,5 @@ export function Component() { }} /> ) - return + return } diff --git a/apps/dotcom/src/routes.tsx b/apps/dotcom/src/routes.tsx index 764f6b170..a89245bfc 100644 --- a/apps/dotcom/src/routes.tsx +++ b/apps/dotcom/src/routes.tsx @@ -1,6 +1,12 @@ import { captureException } from '@sentry/react' +import { + READ_ONLY_LEGACY_PREFIX, + READ_ONLY_PREFIX, + ROOM_PREFIX, + SNAPSHOT_PREFIX, +} from '@tldraw/dotcom-shared' import { useEffect } from 'react' -import { createRoutesFromElements, Outlet, Route, useRouteError } from 'react-router-dom' +import { Outlet, Route, createRoutesFromElements, useRouteError } from 'react-router-dom' import { DefaultErrorFallback } from './components/DefaultErrorFallback/DefaultErrorFallback' import { ErrorPage } from './components/ErrorPage/ErrorPage' @@ -29,17 +35,20 @@ export const router = createRoutesFromElements( > }> import('./pages/root')} /> - import('./pages/new')} /> + import('./pages/new')} /> import('./pages/new')} /> - import('./pages/public-multiplayer')} /> - import('./pages/history')} /> + import('./pages/public-multiplayer')} /> + import('./pages/history')} /> import('./pages/history-snapshot')} /> - import('./pages/public-snapshot')} /> - import('./pages/public-readonly-legacy')} /> - import('./pages/public-readonly')} /> + import('./pages/public-snapshot')} /> + import('./pages/public-readonly-legacy')} + /> + import('./pages/public-readonly')} /> import('./pages/not-found')} /> diff --git a/apps/dotcom/src/utils/sharing.ts b/apps/dotcom/src/utils/sharing.ts index e60887dce..193fdd9cf 100644 --- a/apps/dotcom/src/utils/sharing.ts +++ b/apps/dotcom/src/utils/sharing.ts @@ -2,6 +2,8 @@ import { CreateRoomRequestBody, CreateSnapshotRequestBody, CreateSnapshotResponseBody, + ROOM_PREFIX, + SNAPSHOT_PREFIX, Snapshot, } from '@tldraw/dotcom-shared' import { useMemo } from 'react' @@ -69,7 +71,7 @@ async function getSnapshotLink( } const paramsToUse = getViewportUrlQuery(editor) const params = paramsToUse ? `?${new URLSearchParams(paramsToUse).toString()}` : '' - return new Blob([`${window.location.origin}/s/${response.roomId}${params}`], { + return new Blob([`${window.location.origin}/${SNAPSHOT_PREFIX}/${response.roomId}${params}`], { type: 'text/plain', }) } @@ -132,7 +134,7 @@ export function useSharing(): TLUiOverrides { const query = getViewportUrlQuery(editor) const origin = window.location.origin - const pathname = `/r/${response.slug}?${new URLSearchParams(query ?? {}).toString()}` + const pathname = `/${ROOM_PREFIX}/${response.slug}?${new URLSearchParams(query ?? {}).toString()}` if (runningInIFrame) { window.open(`${origin}${pathname}`) } else { diff --git a/packages/dotcom-shared/src/index.ts b/packages/dotcom-shared/src/index.ts index d93e440fc..5d9360f06 100644 --- a/packages/dotcom-shared/src/index.ts +++ b/packages/dotcom-shared/src/index.ts @@ -1,4 +1,12 @@ -export { ROOM_OPEN_MODE, RoomOpenModeToPath, type RoomOpenMode } from './routes' +export { + READ_ONLY_LEGACY_PREFIX, + READ_ONLY_PREFIX, + ROOM_OPEN_MODE, + ROOM_PREFIX, + RoomOpenModeToPath, + SNAPSHOT_PREFIX, + type RoomOpenMode, +} from './routes' export type { CreateRoomRequestBody, CreateSnapshotRequestBody, diff --git a/packages/dotcom-shared/src/routes.ts b/packages/dotcom-shared/src/routes.ts index 88336e068..3b31b6d25 100644 --- a/packages/dotcom-shared/src/routes.ts +++ b/packages/dotcom-shared/src/routes.ts @@ -6,9 +6,18 @@ export const ROOM_OPEN_MODE = { } as const export type RoomOpenMode = (typeof ROOM_OPEN_MODE)[keyof typeof ROOM_OPEN_MODE] +/** @public */ +export const READ_ONLY_PREFIX = 'ro' +/** @public */ +export const READ_ONLY_LEGACY_PREFIX = 'v' +/** @public */ +export const ROOM_PREFIX = 'r' +/** @public */ +export const SNAPSHOT_PREFIX = 's' + /** @public */ export const RoomOpenModeToPath: Record = { - [ROOM_OPEN_MODE.READ_ONLY]: 'ro', - [ROOM_OPEN_MODE.READ_ONLY_LEGACY]: 'v', - [ROOM_OPEN_MODE.READ_WRITE]: 'r', + [ROOM_OPEN_MODE.READ_ONLY]: READ_ONLY_PREFIX, + [ROOM_OPEN_MODE.READ_ONLY_LEGACY]: READ_ONLY_LEGACY_PREFIX, + [ROOM_OPEN_MODE.READ_WRITE]: ROOM_PREFIX, }