From 0b319989016e77642242a7ae58c4fff728395199 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mitja=20Bezen=C5=A1ek?= Date: Thu, 18 Apr 2024 12:04:04 +0200 Subject: [PATCH] Simplify. --- .../src/lib/TLDrawDurableObject.ts | 19 ++++-- .../src/lib/routes/joinExistingRoom.ts | 35 ++--------- apps/dotcom-worker/src/lib/utils/readonly.ts | 18 ++++++ apps/dotcom-worker/src/lib/worker.ts | 12 ++-- .../src/components/MultiplayerEditor.tsx | 16 +---- apps/dotcom/src/components/ShareMenu.tsx | 3 +- packages/utils/api-report.md | 6 ++ packages/utils/api/api.json | 63 +++++++++++++++++++ packages/utils/src/index.ts | 1 + packages/utils/src/lib/routes.ts | 8 +++ 10 files changed, 124 insertions(+), 57 deletions(-) create mode 100644 apps/dotcom-worker/src/lib/utils/readonly.ts create mode 100644 packages/utils/src/lib/routes.ts diff --git a/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts b/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts index fd31b0d72..58faf2255 100644 --- a/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts +++ b/apps/dotcom-worker/src/lib/TLDrawDurableObject.ts @@ -19,6 +19,7 @@ import { PERSIST_INTERVAL_MS } from './config' import { getR2KeyForRoom } from './r2' import { Analytics, Environment } from './types' import { createSupabaseClient } from './utils/createSupabaseClient' +import { getSlug } from './utils/readonly' import { throttle } from './utils/throttle' const MAX_CONNECTIONS = 50 @@ -88,17 +89,22 @@ export class TLDrawDurableObject extends TLServer { readonly router = Router() .get( '/r/:roomId', - (req) => this.extractDocumentInfoFromRequest(req, false), + (req) => this.extractDocumentInfoFromRequest(req, 'non-readonly'), (req) => this.onRequest(req) ) .get( '/v/:roomId', - (req) => this.extractDocumentInfoFromRequest(req, true), + (req) => this.extractDocumentInfoFromRequest(req, 'readonly-legacy'), + (req) => this.onRequest(req) + ) + .get( + '/o/:roomId', + (req) => this.extractDocumentInfoFromRequest(req, 'readonly'), (req) => this.onRequest(req) ) .post( '/r/:roomId/restore', - (req) => this.extractDocumentInfoFromRequest(req, false), + (req) => this.extractDocumentInfoFromRequest(req, 'non-readonly'), (req) => this.onRestore(req) ) .all('*', () => new Response('Not found', { status: 404 })) @@ -118,9 +124,12 @@ export class TLDrawDurableObject extends TLServer { get documentInfo() { return assertExists(this._documentInfo, 'documentInfo must be present') } - extractDocumentInfoFromRequest = async (req: IRequest, isReadonly: boolean) => { + extractDocumentInfoFromRequest = async ( + req: IRequest, + readonlyStatus: 'non-readonly' | 'readonly' | 'readonly-legacy' + ) => { const slug = assertExists( - isReadonly ? await this.env.READONLY_SLUG_TO_SLUG.get(req.params.roomId) : req.params.roomId, + await getSlug(this.env, req.params.roomId, readonlyStatus), 'roomId must be present' ) if (this._documentInfo) { diff --git a/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts b/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts index 6f4695fae..04bfbbd21 100644 --- a/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts +++ b/apps/dotcom-worker/src/lib/routes/joinExistingRoom.ts @@ -1,41 +1,16 @@ -import { lns } from '@tldraw/utils' +import { ReadonlyStatus } from '@tldraw/utils' import { IRequest } from 'itty-router' import { Environment } from '../types' import { fourOhFour } from '../utils/fourOhFour' +import { getSlug } from '../utils/readonly' import { isRoomIdTooLong, roomIdIsTooLong } from '../utils/roomIdIsTooLong' -// This is the entry point for joining an existing room (non-readonly) -export async function joinExistingRegularRoom( - request: IRequest, - env: Environment -): Promise { - return joinExistingRoom(request, env, request.params.roomId) -} - -// This is the entry point for joining an existing readonly room -export async function joinExistingLegacyReadonlyRoom( - request: IRequest, - env: Environment -): Promise { - const roomId = request.params.roomId && lns(request.params.roomId) - return joinExistingRoom(request, env, roomId) -} - -// This is the entry point for joining an existing readonly room -export async function joinExistingReadonlyRoom( - request: IRequest, - env: Environment -): Promise { - const roomId = - request.params.roomId && (await env.READONLY_SLUG_TO_SLUG.get(request.params.roomId)) - return joinExistingRoom(request, env, roomId) -} - -async function joinExistingRoom( +export async function joinExistingRoom( request: IRequest, env: Environment, - roomId: string | null + readonlyStatus: ReadonlyStatus ): Promise { + const roomId = await getSlug(env, request.params.roomId, readonlyStatus) if (!roomId) return fourOhFour() if (isRoomIdTooLong(roomId)) return roomIdIsTooLong() diff --git a/apps/dotcom-worker/src/lib/utils/readonly.ts b/apps/dotcom-worker/src/lib/utils/readonly.ts new file mode 100644 index 000000000..cfe7890f6 --- /dev/null +++ b/apps/dotcom-worker/src/lib/utils/readonly.ts @@ -0,0 +1,18 @@ +import { ReadonlyStatus, lns } from '@tldraw/utils' +import { Environment } from '../types' + +export async function getSlug( + env: Environment, + slug: string | null, + readonlyStatus: ReadonlyStatus +) { + if (!slug) return null + switch (readonlyStatus) { + case 'non-readonly': + return slug + case 'readonly': + return await env.READONLY_SLUG_TO_SLUG.get(slug) + case 'readonly-legacy': + return lns(slug) + } +} diff --git a/apps/dotcom-worker/src/lib/worker.ts b/apps/dotcom-worker/src/lib/worker.ts index 0d08fdea5..1ac2bd47f 100644 --- a/apps/dotcom-worker/src/lib/worker.ts +++ b/apps/dotcom-worker/src/lib/worker.ts @@ -10,11 +10,7 @@ import { getReadonlySlug } from './routes/getReadonlySlug' import { getRoomHistory } from './routes/getRoomHistory' import { getRoomHistorySnapshot } from './routes/getRoomHistorySnapshot' import { getRoomSnapshot } from './routes/getRoomSnapshot' -import { - joinExistingLegacyReadonlyRoom, - joinExistingReadonlyRoom, - joinExistingRegularRoom, -} from './routes/joinExistingRoom' +import { joinExistingRoom } from './routes/joinExistingRoom' import { Environment } from './types' import { fourOhFour } from './utils/fourOhFour' export { TLDrawDurableObject } from './TLDrawDurableObject' @@ -29,9 +25,9 @@ const router = Router() .post('/new-room', createRoom) .post('/snapshots', createRoomSnapshot) .get('/snapshot/:roomId', getRoomSnapshot) - .get('/r/:roomId', joinExistingRegularRoom) - .get('/v/:roomId', joinExistingLegacyReadonlyRoom) - .get('/o/:roomId', joinExistingReadonlyRoom) + .get('/r/:roomId', (req, env) => joinExistingRoom(req, env, 'non-readonly')) + .get('/v/:roomId', (req, env) => joinExistingRoom(req, env, 'readonly-legacy')) + .get('/o/:roomId', (req, env) => joinExistingRoom(req, env, 'readonly')) .get('/r/:roomId/history', getRoomHistory) .get('/r/:roomId/history/:timestamp', getRoomHistorySnapshot) .get('/readonly-slug/:roomId', getReadonlySlug) diff --git a/apps/dotcom/src/components/MultiplayerEditor.tsx b/apps/dotcom/src/components/MultiplayerEditor.tsx index ab55e0d80..503b1d713 100644 --- a/apps/dotcom/src/components/MultiplayerEditor.tsx +++ b/apps/dotcom/src/components/MultiplayerEditor.tsx @@ -12,6 +12,8 @@ import { ExportFileContentSubMenu, ExtrasGroup, PreferencesGroup, + ReadonlyStatus, + ReadonlyStatusToPath, TLComponents, Tldraw, TldrawUiMenuGroup, @@ -43,7 +45,6 @@ import { StoreErrorScreen } from './StoreErrorScreen' import { ThemeUpdater } from './ThemeUpdater/ThemeUpdater' const shittyOfflineAtom = atom('shitty offline atom', false) -type ReadonlyStatus = 'non-readonly' | 'readonly' | 'readonly-legacy' const components: TLComponents = { ErrorFallback: ({ error }) => { @@ -103,17 +104,6 @@ const components: TLComponents = { }, } -function getRoutePrefix(status: ReadonlyStatus) { - switch (status) { - case 'non-readonly': - return 'r' - case 'readonly': - return 'o' - case 'readonly-legacy': - return 'v' - } -} - export function MultiplayerEditor({ readonlyStatus, roomSlug, @@ -124,7 +114,7 @@ export function MultiplayerEditor({ const handleUiEvent = useHandleUiEvents() const storeWithStatus = useRemoteSyncClient({ - uri: `${MULTIPLAYER_SERVER}/${getRoutePrefix(readonlyStatus)}/${roomSlug}`, + uri: `${MULTIPLAYER_SERVER}/${ReadonlyStatusToPath[readonlyStatus]}/${roomSlug}`, roomId: roomSlug, }) diff --git a/apps/dotcom/src/components/ShareMenu.tsx b/apps/dotcom/src/components/ShareMenu.tsx index ae513fac1..fa7d251d8 100644 --- a/apps/dotcom/src/components/ShareMenu.tsx +++ b/apps/dotcom/src/components/ShareMenu.tsx @@ -1,6 +1,7 @@ import * as Popover from '@radix-ui/react-popover' import React, { useEffect, useState } from 'react' import { + ReadonlyStatusToPath, TldrawUiMenuContextProvider, TldrawUiMenuGroup, TldrawUiMenuItem, @@ -51,7 +52,7 @@ async function getReadonlyUrl() { if (isReadOnly) return href const segs = href.split('/') - segs[segs.length - 2] = 'o' + segs[segs.length - 2] = ReadonlyStatusToPath['readonly'] const [roomId, params] = segs[segs.length - 1].split('?') const result = await fetch(`/api/readonly-slug/${roomId}`) diff --git a/packages/utils/api-report.md b/packages/utils/api-report.md index 961caae88..6e81f47bd 100644 --- a/packages/utils/api-report.md +++ b/packages/utils/api-report.md @@ -276,6 +276,12 @@ export function promiseWithResolve(): Promise & { resolve: (value: T) => void; }; +// @public (undocumented) +export type ReadonlyStatus = 'non-readonly' | 'readonly-legacy' | 'readonly'; + +// @public (undocumented) +export const ReadonlyStatusToPath: Record; + // @public (undocumented) export type RecursivePartial = { [P in keyof T]?: RecursivePartial; diff --git a/packages/utils/api/api.json b/packages/utils/api/api.json index 6d94200c1..328f69c81 100644 --- a/packages/utils/api/api.json +++ b/packages/utils/api/api.json @@ -2785,6 +2785,69 @@ ], "implementsTokenRanges": [] }, + { + "kind": "TypeAlias", + "canonicalReference": "@tldraw/utils!ReadonlyStatus:type", + "docComment": "/**\n * @public\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "export type ReadonlyStatus = " + }, + { + "kind": "Content", + "text": "'non-readonly' | 'readonly-legacy' | 'readonly'" + }, + { + "kind": "Content", + "text": ";" + } + ], + "fileUrlPath": "packages/utils/src/lib/routes.ts", + "releaseTag": "Public", + "name": "ReadonlyStatus", + "typeTokenRange": { + "startIndex": 1, + "endIndex": 2 + } + }, + { + "kind": "Variable", + "canonicalReference": "@tldraw/utils!ReadonlyStatusToPath:var", + "docComment": "/**\n * @public\n */\n", + "excerptTokens": [ + { + "kind": "Content", + "text": "ReadonlyStatusToPath: " + }, + { + "kind": "Reference", + "text": "Record", + "canonicalReference": "!Record:type" + }, + { + "kind": "Content", + "text": "<" + }, + { + "kind": "Reference", + "text": "ReadonlyStatus", + "canonicalReference": "@tldraw/utils!ReadonlyStatus:type" + }, + { + "kind": "Content", + "text": ", string>" + } + ], + "fileUrlPath": "packages/utils/src/lib/routes.ts", + "isReadonly": true, + "releaseTag": "Public", + "name": "ReadonlyStatusToPath", + "variableTypeTokenRange": { + "startIndex": 1, + "endIndex": 5 + } + }, { "kind": "TypeAlias", "canonicalReference": "@tldraw/utils!RecursivePartial:type", diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts index 90273933b..ca533d08c 100644 --- a/packages/utils/src/index.ts +++ b/packages/utils/src/index.ts @@ -51,6 +51,7 @@ export { sortByIndex, validateIndexKey, } from './lib/reordering/reordering' +export { ReadonlyStatusToPath, type ReadonlyStatus } from './lib/routes' export { sortById } from './lib/sort' export { clearLocalStorage, diff --git a/packages/utils/src/lib/routes.ts b/packages/utils/src/lib/routes.ts new file mode 100644 index 000000000..bc5c8c1e0 --- /dev/null +++ b/packages/utils/src/lib/routes.ts @@ -0,0 +1,8 @@ +/** @public */ +export type ReadonlyStatus = 'readonly' | 'readonly-legacy' | 'non-readonly' +/** @public */ +export const ReadonlyStatusToPath: Record = { + readonly: 'o', + 'readonly-legacy': 'v', + 'non-readonly': 'r', +}