reflet-sdk 0.7.1 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +5 -3
- package/dist/{devtools-layer-BI_hut0i.js → devtools-layer-CsIcpepI.js} +54 -50
- package/dist/devtools-layer-CsIcpepI.js.map +1 -0
- package/dist/devtools-next.js +1 -1
- package/dist/devtools-vite.js +1 -1
- package/dist/feedback.js +8 -8
- package/dist/feedback.js.map +1 -1
- package/dist/{handler-B4Z6jkYX.js → handler-17FmwoSX.js} +3 -3
- package/dist/handler-17FmwoSX.js.map +1 -0
- package/dist/{sessions-panel-CDrnOEwi.js → sessions-panel-BYM0UUgT.js} +1787 -1006
- package/dist/sessions-panel-BYM0UUgT.js.map +1 -0
- package/dist/{submit-DBy9TCSq.js → submit-Dl0rm6TV.js} +2 -2
- package/dist/{submit-DBy9TCSq.js.map → submit-Dl0rm6TV.js.map} +1 -1
- package/dist/{team-activation-DCqh71bl.js → team-activation-Cv5U7OF1.js} +3 -3
- package/dist/team-activation-Cv5U7OF1.js.map +1 -0
- package/dist/{team-layer-D-6Il66z.js → team-layer-Dvjkh-_y.js} +106 -80
- package/dist/team-layer-Dvjkh-_y.js.map +1 -0
- package/package.json +1 -1
- package/dist/devtools-layer-BI_hut0i.js.map +0 -1
- package/dist/handler-B4Z6jkYX.js.map +0 -1
- package/dist/sessions-panel-CDrnOEwi.js.map +0 -1
- package/dist/team-activation-DCqh71bl.js.map +0 -1
- package/dist/team-layer-D-6Il66z.js.map +0 -1
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"handler-B4Z6jkYX.js","names":["TRAILING_SLASHES","QUERY_OR_HASH"],"sources":["../src/devtools/server/json-response.ts","../src/devtools/server/request-guard.ts","../src/devtools/server/connect/connectable-host.ts","../src/devtools/server/connect/connection-store.ts","../src/devtools/server/connect/board-credential.ts","../src/devtools/server/connect/html-page.ts","../src/devtools/server/connect/pending-connects.ts","../src/devtools/server/connect/connect-routes.ts","../src/devtools/server/options.ts","../src/devtools/server/reflet-proxy.ts","../src/devtools/server/source/code-search.ts","../src/devtools/server/source/project-roots.ts","../src/devtools/server/source/jsx-range.ts","../src/devtools/server/source/workspace-path.ts","../src/devtools/server/source/server-frame.ts","../src/devtools/server/source/source-file.ts","../src/devtools/server/handler.ts"],"sourcesContent":["import type { DevtoolsErrorBody } from \"../protocol\";\n\nexport type DevtoolsOutcome<T> =\n | { ok: true; value: T }\n | { error: string; ok: false; status: number };\n\nexport const JSON_RESPONSE_HEADERS = {\n \"cache-control\": \"no-store\",\n \"content-type\": \"application/json; charset=utf-8\",\n \"x-content-type-options\": \"nosniff\",\n};\n\nexport function jsonTextResponse(\n text: string | null,\n status: number\n): Response {\n return new Response(text, { headers: JSON_RESPONSE_HEADERS, status });\n}\n\nexport function jsonResponse(body: unknown, status = 200): Response {\n return jsonTextResponse(JSON.stringify(body), status);\n}\n\nexport function errorResponse(error: string, status: number): Response {\n const body: DevtoolsErrorBody = { error };\n return jsonResponse(body, status);\n}\n\nexport function failure<T>(error: string, status: number): DevtoolsOutcome<T> {\n return { error, ok: false, status };\n}\n","import { DEVTOOLS_REQUEST_HEADER } from \"../protocol\";\nimport { errorResponse } from \"./json-response\";\n\nconst LOOPBACK_HOSTNAMES = [\"localhost\", \"[::1]\"];\nconst LOOPBACK_IPV4 = /^127(?:\\.\\d{1,3}){3}$/;\nconst IPV4_MAPPED_PREFIX = \"::ffff:\";\nconst TRUSTED_FETCH_SITES = [\"same-origin\", \"none\"];\n\nfunction hostnameOf(request: Request): string | null {\n const host = request.headers.get(\"host\") ?? new URL(request.url).host;\n try {\n return new URL(`http://${host}`).hostname.toLowerCase();\n } catch {\n return null;\n }\n}\n\nexport function isLoopbackHostname(hostname: string): boolean {\n return (\n LOOPBACK_HOSTNAMES.includes(hostname) ||\n hostname.endsWith(\".localhost\") ||\n LOOPBACK_IPV4.test(hostname)\n );\n}\n\nexport function isLoopbackAddress(address: string | undefined): boolean {\n if (!address) {\n return false;\n }\n const ipv4 = address.startsWith(IPV4_MAPPED_PREFIX)\n ? address.slice(IPV4_MAPPED_PREFIX.length)\n : address;\n return address === \"::1\" || LOOPBACK_IPV4.test(ipv4);\n}\n\n/**\n * The Host check stops DNS rebinding: a hostile domain resolved to 127.0.0.1\n * is same-origin with itself, so origin checks alone would let it through.\n * Host and header checks only stop browsers; keeping other machines out is the\n * job of a dev server bound to loopback.\n */\nexport function rejectUntrustedHost(\n request: Request,\n allowedHosts: string[]\n): Response | null {\n const hostname = hostnameOf(request);\n const isAllowedHost =\n hostname !== null &&\n (isLoopbackHostname(hostname) || allowedHosts.includes(hostname));\n if (!isAllowedHost) {\n return errorResponse(\n \"Reflet devtools only answers on localhost. Add other dev hostnames to allowedHosts or REFLET_DEVTOOLS_HOSTS.\",\n 403\n );\n }\n return null;\n}\n\nexport function rejectUntrustedCaller(\n request: Request,\n allowedHosts: string[]\n): Response | null {\n if (request.headers.get(DEVTOOLS_REQUEST_HEADER) !== \"1\") {\n return errorResponse(\n `Reflet devtools requests must send the ${DEVTOOLS_REQUEST_HEADER} header.`,\n 403\n );\n }\n\n const fetchSite = request.headers.get(\"sec-fetch-site\");\n const hostname = hostnameOf(request);\n // Browsers omit Sec-Fetch-Site only outside secure contexts: a plain-HTTP allowed host, never loopback.\n const mayOmitFetchSite =\n hostname !== null &&\n allowedHosts.includes(hostname) &&\n !isLoopbackHostname(hostname);\n const isTrustedSite =\n fetchSite === null\n ? mayOmitFetchSite\n : TRUSTED_FETCH_SITES.includes(fetchSite);\n if (!isTrustedSite) {\n return errorResponse(\n \"Reflet devtools only answers requests from the app's own origin.\",\n 403\n );\n }\n\n return null;\n}\n","import { isLoopbackHostname } from \"../request-guard\";\n\n/** Mirrors the backend redirect allowlist, which stays the authority; this only decides whether Connect is offered. */\nexport function isConnectableHost(hostname: string): boolean {\n return isLoopbackHostname(hostname) || hostname.endsWith(\".test\");\n}\n","import { createHash, randomUUID } from \"node:crypto\";\nimport { mkdir, readFile, rename, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { z } from \"zod\";\n\nconst storedConnectionSchema = z.object({\n apiUrl: z.url(),\n organizationName: z.string(),\n token: z.string().startsWith(\"fb_dev_\"),\n});\nexport type StoredConnection = z.infer<typeof storedConnectionSchema>;\n\nconst connectionsDirectory = () => join(homedir(), \".reflet\", \"devtools\");\n\nfunction connectionFile(root: string, apiUrl: string) {\n const key = createHash(\"sha256\")\n .update(JSON.stringify([root, apiUrl]))\n .digest(\"hex\");\n return join(connectionsDirectory(), `${key}.json`);\n}\n\nexport async function readConnection(\n root: string,\n apiUrl: string\n): Promise<StoredConnection | null> {\n try {\n const connection = storedConnectionSchema.parse(\n JSON.parse(await readFile(connectionFile(root, apiUrl), \"utf8\"))\n );\n return connection.apiUrl === apiUrl ? connection : null;\n } catch (error) {\n if (error instanceof Error && \"code\" in error && error.code === \"ENOENT\") {\n return null;\n }\n throw error;\n }\n}\n\nexport async function saveConnection(\n root: string,\n connection: StoredConnection\n): Promise<void> {\n await mkdir(connectionsDirectory(), { mode: 0o700, recursive: true });\n const file = connectionFile(root, connection.apiUrl);\n const temporaryFile = `${file}.${randomUUID()}.tmp`;\n try {\n await writeFile(temporaryFile, `${JSON.stringify(connection)}\\n`, {\n flag: \"wx\",\n mode: 0o600,\n });\n await rename(temporaryFile, file);\n } finally {\n await rm(temporaryFile, { force: true });\n }\n}\n\nexport async function removeConnection(\n root: string,\n apiUrl: string,\n rejectedToken?: string\n): Promise<StoredConnection | null> {\n const removed = await readConnection(root, apiUrl);\n if (!removed || (rejectedToken && removed.token !== rejectedToken)) {\n return null;\n }\n await rm(connectionFile(root, apiUrl), { force: true });\n return removed;\n}\n","import type { BoardAccess } from \"../../protocol\";\nimport type { ResolvedDevtoolsOptions } from \"../options\";\nimport { isConnectableHost } from \"./connectable-host\";\nimport { readConnection } from \"./connection-store\";\n\nexport interface BoardCredential {\n isStored: boolean;\n token: string;\n}\n\nexport async function boardCredential(\n settings: ResolvedDevtoolsOptions\n): Promise<BoardCredential | null> {\n if (settings.secretKey) {\n return { isStored: false, token: settings.secretKey };\n }\n const connection = await readConnection(settings.root, settings.apiUrl);\n return connection ? { isStored: true, token: connection.token } : null;\n}\n\nexport async function boardAccess(\n request: Request,\n settings: ResolvedDevtoolsOptions\n): Promise<BoardAccess> {\n if (settings.secretKey) {\n return { kind: \"secretKey\" };\n }\n const connection = await readConnection(settings.root, settings.apiUrl);\n if (connection) {\n return { kind: \"connected\", organizationName: connection.organizationName };\n }\n return {\n canConnect: isConnectableHost(new URL(request.url).hostname),\n kind: \"disconnected\",\n };\n}\n","const HTML_ESCAPES: Record<string, string> = {\n \"'\": \"'\",\n '\"': \""\",\n \"&\": \"&\",\n \"<\": \"<\",\n \">\": \">\",\n};\nconst HTML_SPECIAL_CHARACTERS = /[&<>\"']/g;\n\nconst escapeHtml = (text: string): string =>\n text.replace(\n HTML_SPECIAL_CHARACTERS,\n (character) => HTML_ESCAPES[character] ?? character\n );\n\nexport function htmlPage(\n title: string,\n message: string,\n status: number\n): Response {\n const safeTitle = escapeHtml(title);\n const body = `<!doctype html>\n<html lang=\"en\">\n<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\"><title>${safeTitle} · Reflet devtools</title></head>\n<body style=\"margin:0;min-height:100vh;display:flex;align-items:center;justify-content:center;font-family:system-ui,sans-serif;background:#fafafa;color:#18181b\">\n<main style=\"max-width:28rem;padding:1.5rem\">\n<h1 style=\"font-size:1.25rem;margin:0 0 .5rem\">${safeTitle}</h1>\n<p style=\"margin:0;line-height:1.5;color:#52525b\">${escapeHtml(message)}</p>\n</main>\n</body>\n</html>\n`;\n return new Response(body, {\n headers: {\n \"cache-control\": \"no-store\",\n \"content-security-policy\":\n \"default-src 'none'; style-src 'unsafe-inline'\",\n \"content-type\": \"text/html; charset=utf-8\",\n \"referrer-policy\": \"no-referrer\",\n \"x-content-type-options\": \"nosniff\",\n },\n status,\n });\n}\n","import { createHash, randomBytes } from \"node:crypto\";\n\ninterface ConnectBinding {\n apiUrl: string;\n redirectUri: string;\n root: string;\n}\n\ninterface PendingConnect {\n binding: ConnectBinding;\n codeVerifier: string;\n startedAt: number;\n}\n\nconst PENDING_CONNECT_TTL_MS = 10 * 60_000;\nconst MAX_PENDING_CONNECTS = 10;\ndeclare global {\n // Preserve pending connects across dev server module reloads.\n var refletDevtoolsPendingConnects: Map<string, PendingConnect> | undefined;\n}\n\nfunction pendingConnects(): Map<string, PendingConnect> {\n globalThis.refletDevtoolsPendingConnects ??= new Map();\n return globalThis.refletDevtoolsPendingConnects;\n}\n\nexport function beginConnect(binding: ConnectBinding): {\n codeChallenge: string;\n codeVerifier: string;\n state: string;\n} {\n const state = randomBytes(32).toString(\"base64url\");\n const codeVerifier = randomBytes(32).toString(\"base64url\");\n const codeChallenge = createHash(\"sha256\")\n .update(codeVerifier)\n .digest(\"base64url\");\n\n const pending = pendingConnects();\n while (pending.size >= MAX_PENDING_CONNECTS) {\n const oldestState = pending.keys().next().value;\n if (oldestState === undefined) {\n break;\n }\n pending.delete(oldestState);\n }\n pending.set(state, { binding, codeVerifier, startedAt: Date.now() });\n\n return { codeChallenge, codeVerifier, state };\n}\n\nexport function takeConnect(\n state: string,\n binding: ConnectBinding\n): { codeVerifier: string } | null {\n const pending = pendingConnects();\n const connect = pending.get(state);\n if (!connect) {\n return null;\n }\n if (Date.now() - connect.startedAt > PENDING_CONNECT_TTL_MS) {\n pending.delete(state);\n return null;\n }\n const matchesServer =\n connect.binding.root === binding.root &&\n connect.binding.apiUrl === binding.apiUrl &&\n connect.binding.redirectUri === binding.redirectUri;\n if (!matchesServer) {\n return null;\n }\n pending.delete(state);\n return { codeVerifier: connect.codeVerifier };\n}\n","import { z } from \"zod\";\nimport {\n type ConnectStartResponse,\n DEVTOOLS_ENDPOINTS,\n DEVTOOLS_ROUTE_BASE,\n type DisconnectResponse,\n} from \"../../protocol\";\nimport { errorResponse, jsonResponse } from \"../json-response\";\nimport type { ResolvedDevtoolsOptions } from \"../options\";\nimport { isConnectableHost } from \"./connectable-host\";\nimport { removeConnection, saveConnection } from \"./connection-store\";\nimport { htmlPage } from \"./html-page\";\nimport { beginConnect, takeConnect } from \"./pending-connects\";\n\nconst publicKeySchema = z.object({\n publicKey: z.string().startsWith(\"fb_pub_\").max(200),\n});\nconst tokenExchangeSchema = z.object({\n organizationName: z.string(),\n token: z.string().startsWith(\"fb_dev_\"),\n});\nconst upstreamErrorSchema = z.object({ error: z.string() });\n\nconst redirectUriFor = (request: Request): string =>\n `${new URL(request.url).origin}${DEVTOOLS_ROUTE_BASE}${DEVTOOLS_ENDPOINTS.connectCallback}`;\n\nasync function readPublicKey(request: Request): Promise<string | null> {\n const parsed = publicKeySchema.safeParse(\n await request.json().catch(() => null)\n );\n return parsed.success ? parsed.data.publicKey : null;\n}\n\nasync function readJson(response: Response): Promise<unknown> {\n try {\n return await response.json();\n } catch {\n return null;\n }\n}\n\nexport async function startConnect(\n request: Request,\n settings: ResolvedDevtoolsOptions\n): Promise<Response> {\n const publicKey = await readPublicKey(request);\n if (!publicKey) {\n return errorResponse(\n \"Pass the widget's fb_pub_ public key to connect.\",\n 400\n );\n }\n if (settings.secretKey) {\n return errorResponse(\n \"REFLET_SECRET_KEY is set, so this dev server already reaches your board.\",\n 409\n );\n }\n if (!isConnectableHost(new URL(request.url).hostname)) {\n return errorResponse(\n \"Connecting from the browser works on localhost, *.localhost and *.test. Set REFLET_SECRET_KEY instead.\",\n 403\n );\n }\n\n const { codeChallenge, state } = beginConnect({\n apiUrl: settings.apiUrl,\n redirectUri: redirectUriFor(request),\n root: settings.root,\n });\n const authorizeUrl = new URL(\"/auth/devtools\", settings.appUrl);\n authorizeUrl.searchParams.set(\"public_key\", publicKey);\n authorizeUrl.searchParams.set(\"redirect_uri\", redirectUriFor(request));\n authorizeUrl.searchParams.set(\"state\", state);\n authorizeUrl.searchParams.set(\"code_challenge\", codeChallenge);\n return jsonResponse({\n authorizeUrl: authorizeUrl.toString(),\n } satisfies ConnectStartResponse);\n}\n\nexport async function finishConnect(\n request: Request,\n settings: ResolvedDevtoolsOptions\n): Promise<Response> {\n const { searchParams } = new URL(request.url);\n const code = searchParams.get(\"code\");\n const state = searchParams.get(\"state\");\n const pending =\n code && state\n ? takeConnect(state, {\n apiUrl: settings.apiUrl,\n redirectUri: redirectUriFor(request),\n root: settings.root,\n })\n : null;\n if (!(code && pending)) {\n return htmlPage(\n \"Link expired\",\n \"This connect link expired or was already used. Start again from the Board tab.\",\n 400\n );\n }\n\n let upstream: Response;\n try {\n upstream = await fetch(`${settings.apiUrl}/api/v1/devtools/token`, {\n body: JSON.stringify({\n code,\n codeVerifier: pending.codeVerifier,\n redirectUri: redirectUriFor(request),\n }),\n headers: {\n Accept: \"application/json\",\n \"Content-Type\": \"application/json\",\n },\n method: \"POST\",\n signal: AbortSignal.timeout(10_000),\n });\n } catch {\n return htmlPage(\n \"Connection failed\",\n `Could not reach Reflet at ${settings.apiUrl}.`,\n 502\n );\n }\n\n const payload = await readJson(upstream);\n if (!upstream.ok) {\n return htmlPage(\n \"Connection refused\",\n upstreamErrorSchema.safeParse(payload).data?.error ??\n \"Reflet refused this connect code.\",\n 400\n );\n }\n const exchange = tokenExchangeSchema.safeParse(payload);\n if (!exchange.success) {\n return htmlPage(\n \"Connection failed\",\n \"Reflet answered with an unexpected response.\",\n 502\n );\n }\n\n await saveConnection(settings.root, {\n apiUrl: settings.apiUrl,\n organizationName: exchange.data.organizationName,\n token: exchange.data.token,\n });\n return htmlPage(\n \"Connected\",\n `Connected to ${exchange.data.organizationName}. Go back to your app: the Board tab is ready.`,\n 200\n );\n}\n\nasync function revokeUpstream(apiUrl: string, token: string): Promise<boolean> {\n try {\n const response = await fetch(`${apiUrl}/api/v1/devtools/revoke`, {\n headers: { Authorization: `Bearer ${token}` },\n method: \"POST\",\n signal: AbortSignal.timeout(10_000),\n });\n return response.ok;\n } catch {\n return false;\n }\n}\n\nexport async function disconnect(\n settings: ResolvedDevtoolsOptions\n): Promise<Response> {\n const removed = await removeConnection(settings.root, settings.apiUrl);\n const revoked = removed\n ? await revokeUpstream(removed.apiUrl, removed.token)\n : false;\n return jsonResponse({ revoked } satisfies DisconnectResponse);\n}\n","import { resolve } from \"node:path\";\nimport { DEFAULT_API_URL } from \"../../client\";\nimport { EDITORS, type EditorId } from \"../protocol\";\n\nexport interface DevtoolsServerOptions {\n /** Dev hostnames besides localhost, e.g. `app.test`. Falls back to REFLET_DEVTOOLS_HOSTS, comma-separated. */\n allowedHosts?: string[];\n /** Reflet API origin. Falls back to REFLET_API_URL, then the hosted API. */\n apiUrl?: string;\n /** Reflet web app origin for Connect. Falls back to REFLET_APP_URL, then https://www.reflet.app. */\n appUrl?: string;\n /** Editor that \"open in editor\" links target. Falls back to REFLET_EDITOR. */\n editor?: EditorId;\n /** App directory source paths resolve against. Defaults to the working directory. */\n root?: string;\n /** Falls back to REFLET_SECRET_KEY. Never sent to the browser. */\n secretKey?: string;\n}\n\nexport type DevtoolsEnv = Readonly<Record<string, string | undefined>>;\n\nexport interface ResolvedDevtoolsOptions {\n allowedHosts: string[];\n apiUrl: string;\n appUrl: string;\n editor: EditorId;\n root: string;\n secretKey: string | null;\n}\n\nconst DEFAULT_APP_URL = \"https://www.reflet.app\";\nconst DEFAULT_EDITOR: EditorId = \"vscode\";\nconst TRAILING_SLASHES = /\\/+$/;\n\nfunction isEditorId(value: string | undefined): value is EditorId {\n return EDITORS.some((editor) => editor === value);\n}\n\nfunction presentValue(value: string | undefined): string | undefined {\n const trimmed = value?.trim();\n return trimmed ? trimmed : undefined;\n}\n\nfunction resolveEditor(\n optionEditor: string | undefined,\n envEditor: string | undefined\n): EditorId {\n if (isEditorId(optionEditor)) {\n return optionEditor;\n }\n const normalizedEnvEditor = presentValue(envEditor)?.toLowerCase();\n return isEditorId(normalizedEnvEditor) ? normalizedEnvEditor : DEFAULT_EDITOR;\n}\n\nexport function resolveDevtoolsOptions(\n options: DevtoolsServerOptions,\n env: DevtoolsEnv\n): ResolvedDevtoolsOptions {\n const apiUrl =\n presentValue(options.apiUrl) ??\n presentValue(env.REFLET_API_URL) ??\n DEFAULT_API_URL;\n const appUrl =\n presentValue(options.appUrl) ??\n presentValue(env.REFLET_APP_URL) ??\n DEFAULT_APP_URL;\n\n return {\n allowedHosts: (\n options.allowedHosts ??\n presentValue(env.REFLET_DEVTOOLS_HOSTS)?.split(\",\") ??\n []\n )\n .map((host) => host.trim().toLowerCase())\n .filter(Boolean),\n apiUrl: apiUrl.replace(TRAILING_SLASHES, \"\"),\n appUrl: appUrl.replace(TRAILING_SLASHES, \"\"),\n editor: resolveEditor(options.editor, env.REFLET_EDITOR),\n root: resolve(presentValue(options.root) ?? process.cwd()),\n secretKey:\n presentValue(options.secretKey) ??\n presentValue(env.REFLET_SECRET_KEY) ??\n null,\n };\n}\n","import { PROXIED_API_PATHS } from \"../protocol\";\nimport { errorResponse, JSON_RESPONSE_HEADERS } from \"./json-response\";\n\ntype ProxiedApiPath = (typeof PROXIED_API_PATHS)[number];\n\nconst CREATE_FEEDBACK_PATH: ProxiedApiPath = \"/api/v1/feedback/create\";\nconst MISSING_BOARD_ACCESS_ERROR =\n \"Connect to Reflet from the devtools Board tab, or set REFLET_SECRET_KEY in the dev server environment.\";\nconst BODYLESS_STATUSES = [204, 205, 304];\n\nexport interface RefletProxyTarget {\n apiUrl: string;\n token: string | null;\n}\n\ntype ForwardedBody = { body: string | undefined } | { error: string };\n\nfunction isProxiedApiPath(path: string): path is ProxiedApiPath {\n return PROXIED_API_PATHS.some((proxiedPath) => proxiedPath === path);\n}\n\nfunction isJsonObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nasync function readForwardedBody(\n request: Request,\n apiPath: ProxiedApiPath\n): Promise<ForwardedBody> {\n if (request.method !== \"POST\") {\n return { body: undefined };\n }\n const text = await request.text();\n if (apiPath !== CREATE_FEEDBACK_PATH) {\n return { body: text || undefined };\n }\n\n let payload: unknown;\n try {\n payload = JSON.parse(text);\n } catch {\n return { error: \"Feedback must be a JSON object.\" };\n }\n if (!isJsonObject(payload)) {\n return { error: \"Feedback must be a JSON object.\" };\n }\n return { body: JSON.stringify({ ...payload, internal: true }) };\n}\n\n/** Forwards an allowlisted Reflet API call with the board token; devtools notes are always internal. */\nexport async function proxyToReflet(\n request: Request,\n apiPath: string,\n target: RefletProxyTarget\n): Promise<Response> {\n if (!isProxiedApiPath(apiPath)) {\n return errorResponse(\n `Reflet devtools does not forward ${apiPath || \"/\"}.`,\n 404\n );\n }\n if (!target.token) {\n return errorResponse(MISSING_BOARD_ACCESS_ERROR, 503);\n }\n if (request.method !== \"GET\" && request.method !== \"POST\") {\n return errorResponse(`${request.method} is not supported here.`, 405);\n }\n\n const forwarded = await readForwardedBody(request, apiPath);\n if (\"error\" in forwarded) {\n return errorResponse(forwarded.error, 400);\n }\n\n const { search } = new URL(request.url);\n let upstream: Response;\n try {\n upstream = await fetch(`${target.apiUrl}${apiPath}${search}`, {\n body: forwarded.body,\n headers: {\n Accept: \"application/json\",\n Authorization: `Bearer ${target.token}`,\n \"Content-Type\": \"application/json\",\n },\n method: request.method,\n signal: AbortSignal.timeout(15_000),\n });\n } catch {\n return errorResponse(`Could not reach Reflet at ${target.apiUrl}.`, 502);\n }\n\n return new Response(\n BODYLESS_STATUSES.includes(upstream.status) ? null : upstream.body,\n { headers: JSON_RESPONSE_HEADERS, status: upstream.status }\n );\n}\n","import { type ExecFileException, execFile } from \"node:child_process\";\nimport { join } from \"node:path\";\nimport type { CodeMatch, CodeSearchResult } from \"../../protocol\";\nimport { type DevtoolsOutcome, failure } from \"../json-response\";\n\nconst MIN_QUERY_LENGTH = 2;\nconst MAX_QUERY_LENGTH = 200;\nconst MAX_MATCHES = 20;\nconst PREVIEW_LENGTH = 160;\nconst PREVIEW_LEAD = 40;\nconst SEARCH_TIMEOUT_MS = 4000;\nconst MAX_OUTPUT_BYTES = 1_048_576;\nconst NO_MATCHES_EXIT_CODE = 1;\nconst NOT_A_REPOSITORY_EXIT_CODE = 128;\nconst SEARCHED_FILES = [\n \"*.tsx\",\n \"*.jsx\",\n \"*.ts\",\n \"*.js\",\n \"*.vue\",\n \"*.svelte\",\n \"*.astro\",\n \"*.mdx\",\n];\nconst LINE_BREAK = /[\\r\\n]/;\n\ninterface GitGrepRun {\n error: ExecFileException | null;\n stdout: string;\n}\n\nfunction runGitGrep(workspaceRoot: string, query: string): Promise<GitGrepRun> {\n const args = [\n \"grep\",\n \"-n\",\n \"-z\",\n \"-I\",\n \"-F\",\n \"--no-color\",\n \"--untracked\",\n \"-e\",\n query,\n \"--\",\n ...SEARCHED_FILES,\n ];\n return new Promise((resolveRun) => {\n execFile(\n \"git\",\n args,\n {\n cwd: workspaceRoot,\n encoding: \"utf8\",\n maxBuffer: MAX_OUTPUT_BYTES,\n timeout: SEARCH_TIMEOUT_MS,\n },\n (error, stdout) => resolveRun({ error, stdout })\n );\n });\n}\n\nfunction previewLine(content: string, query: string): string {\n const text = content.trim();\n if (text.length <= PREVIEW_LENGTH) {\n return text;\n }\n const matchIndex = text.indexOf(query);\n const start = Math.max(\n 0,\n Math.min(matchIndex - PREVIEW_LEAD, text.length - PREVIEW_LENGTH)\n );\n const end = start + PREVIEW_LENGTH;\n const head = start > 0 ? \"…\" : \"\";\n const tail = end < text.length ? \"…\" : \"\";\n return `${head}${text.slice(start, end)}${tail}`;\n}\n\nfunction parseMatches(\n stdout: string,\n workspaceRoot: string,\n query: string\n): CodeMatch[] {\n const matches: CodeMatch[] = [];\n for (const record of stdout.split(\"\\n\")) {\n const [path, lineText, content] = record.split(\"\\0\");\n const line = Number(lineText);\n const isComplete =\n path !== undefined && content !== undefined && Number.isInteger(line);\n if (isComplete && !path.split(\"/\").includes(\"node_modules\")) {\n matches.push({\n absolutePath: join(workspaceRoot, path),\n line,\n path,\n preview: previewLine(content, query),\n });\n if (matches.length === MAX_MATCHES) {\n break;\n }\n }\n }\n return matches;\n}\n\nfunction describeGitFailure(error: ExecFileException): DevtoolsOutcome<never> {\n if (error.code === \"ENOENT\") {\n return failure(\"Code search needs git installed on the dev server.\", 503);\n }\n if (error.code === NOT_A_REPOSITORY_EXIT_CODE) {\n return failure(\n \"Code search needs the app to live in a git repository.\",\n 503\n );\n }\n if (error.killed) {\n return failure(\"Code search timed out.\", 504);\n }\n return failure(`Code search failed: ${error.message}`, 500);\n}\n\nexport async function searchCode(\n workspaceRoot: string,\n rawQuery: string\n): Promise<DevtoolsOutcome<CodeSearchResult>> {\n const query = rawQuery.trim();\n if (query.length < MIN_QUERY_LENGTH || query.length > MAX_QUERY_LENGTH) {\n return failure(\n `Search for ${MIN_QUERY_LENGTH} to ${MAX_QUERY_LENGTH} characters.`,\n 400\n );\n }\n if (LINE_BREAK.test(query)) {\n return failure(\"Search for a single line of text.\", 400);\n }\n\n const { error, stdout } = await runGitGrep(workspaceRoot, query);\n const matches = parseMatches(stdout, workspaceRoot, query);\n const hasNoMatches = error?.code === NO_MATCHES_EXIT_CODE;\n if (!error || hasNoMatches || matches.length > 0) {\n return { ok: true, value: { matches } };\n }\n return describeGitFailure(error);\n}\n","import { existsSync, realpathSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\n\nexport interface ProjectRoots {\n /** The app directory, where the dev server runs. */\n root: string;\n /** Nearest ancestor of the app directory holding `.git`, else the app directory. */\n workspaceRoot: string;\n}\n\nexport function resolveProjectRoots(appRoot: string): ProjectRoots {\n const resolvedRoot = resolve(appRoot);\n const root = existsSync(resolvedRoot)\n ? realpathSync(resolvedRoot)\n : resolvedRoot;\n\n for (let directory = root; ; directory = dirname(directory)) {\n if (existsSync(join(directory, \".git\"))) {\n return { root, workspaceRoot: directory };\n }\n if (dirname(directory) === directory) {\n return { root, workspaceRoot: root };\n }\n }\n}\n","import type { LineRange } from \"../../protocol\";\n\nconst FAILED = -1;\nconst MAX_TAG_LOOKBACK = 2;\nconst TAG_NAME_START = /[A-Za-z_$]/;\nconst TAG_NAME_CHAR = /[\\w$.:-]/;\nconst IDENTIFIER_CHAR = /[\\w$]/;\nconst WHITESPACE = /\\s/;\nconst JSX_EXPRESSION_LEAD = /[([{,;=?:&|!>]/;\nconst JSX_KEYWORD_LEADS = [\"return\", \"yield\", \"default\", \"await\"];\n\ninterface OpeningTag {\n end: number;\n name: string;\n selfClosing: boolean;\n}\n\nfunction isTagStart(code: string, index: number): boolean {\n if (code.charAt(index) !== \"<\") {\n return false;\n }\n const next = code.charAt(index + 1);\n return next === \">\" || TAG_NAME_START.test(next);\n}\n\nfunction startsJsxInExpression(code: string, index: number): boolean {\n let cursor = index - 1;\n while (cursor >= 0 && WHITESPACE.test(code.charAt(cursor))) {\n cursor -= 1;\n }\n if (cursor < 0) {\n return true;\n }\n const previous = code.charAt(cursor);\n if (JSX_EXPRESSION_LEAD.test(previous)) {\n return true;\n }\n let wordStart = cursor;\n while (wordStart > 0 && IDENTIFIER_CHAR.test(code.charAt(wordStart - 1))) {\n wordStart -= 1;\n }\n return JSX_KEYWORD_LEADS.includes(code.slice(wordStart, cursor + 1));\n}\n\nfunction skipJsString(code: string, index: number): number {\n const quote = code.charAt(index);\n let cursor = index + 1;\n while (cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \"\\\\\") {\n cursor += 2;\n } else if (char === quote) {\n return cursor + 1;\n } else if (char === \"\\n\") {\n return index + 1;\n } else {\n cursor += 1;\n }\n }\n return index + 1;\n}\n\nfunction skipTemplate(code: string, index: number): number {\n let cursor = index + 1;\n while (cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \"\\\\\") {\n cursor += 2;\n } else if (char === \"`\") {\n return cursor + 1;\n } else if (char === \"$\" && code.charAt(cursor + 1) === \"{\") {\n cursor = skipJsExpression(code, cursor + 1);\n if (cursor === FAILED) {\n return FAILED;\n }\n } else {\n cursor += 1;\n }\n }\n return FAILED;\n}\n\nfunction skipJsToken(code: string, index: number): number {\n const char = code.charAt(index);\n const next = code.charAt(index + 1);\n if (char === '\"' || char === \"'\") {\n return skipJsString(code, index);\n }\n if (char === \"`\") {\n return skipTemplate(code, index);\n }\n if (char === \"/\" && next === \"/\") {\n const lineEnd = code.indexOf(\"\\n\", index);\n return lineEnd === -1 ? code.length : lineEnd;\n }\n if (char === \"/\" && next === \"*\") {\n const commentEnd = code.indexOf(\"*/\", index + 2);\n return commentEnd === -1 ? FAILED : commentEnd + 2;\n }\n if (isTagStart(code, index) && startsJsxInExpression(code, index)) {\n return skipElement(code, index);\n }\n return index + 1;\n}\n\nfunction skipJsExpression(code: string, index: number): number {\n let depth = 0;\n let cursor = index;\n while (cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \"{\" || char === \"}\") {\n depth += char === \"{\" ? 1 : -1;\n cursor += 1;\n if (depth === 0) {\n return cursor;\n }\n } else {\n cursor = skipJsToken(code, cursor);\n if (cursor === FAILED) {\n return FAILED;\n }\n }\n }\n return FAILED;\n}\n\nfunction skipTypeArguments(code: string, index: number): number {\n let depth = 0;\n for (let cursor = index; cursor < code.length; cursor += 1) {\n const char = code.charAt(cursor);\n if (char === \"<\") {\n depth += 1;\n } else if (char === \">\") {\n depth -= 1;\n if (depth === 0) {\n return cursor + 1;\n }\n }\n }\n return FAILED;\n}\n\nfunction skipAttributeToken(code: string, index: number): number {\n const char = code.charAt(index);\n if (char === \"{\") {\n return skipJsExpression(code, index);\n }\n if (char === '\"' || char === \"'\") {\n const closingQuote = code.indexOf(char, index + 1);\n return closingQuote === -1 ? FAILED : closingQuote + 1;\n }\n return index + 1;\n}\n\nfunction readTagName(code: string, index: number): number {\n let cursor = index;\n while (TAG_NAME_CHAR.test(code.charAt(cursor))) {\n cursor += 1;\n }\n return cursor;\n}\n\nfunction readOpeningTag(code: string, index: number): OpeningTag | null {\n const nameEnd = readTagName(code, index + 1);\n const name = code.slice(index + 1, nameEnd);\n let cursor =\n code.charAt(nameEnd) === \"<\" ? skipTypeArguments(code, nameEnd) : nameEnd;\n\n while (cursor !== FAILED && cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \">\") {\n return { end: cursor + 1, name, selfClosing: false };\n }\n if (char === \"/\" && code.charAt(cursor + 1) === \">\") {\n return { end: cursor + 2, name, selfClosing: true };\n }\n cursor = skipAttributeToken(code, cursor);\n }\n return null;\n}\n\nfunction readClosingTagEnd(code: string, index: number, name: string): number {\n let cursor = index + 2;\n while (WHITESPACE.test(code.charAt(cursor))) {\n cursor += 1;\n }\n const nameEnd = readTagName(code, cursor);\n if (code.slice(cursor, nameEnd) !== name) {\n return FAILED;\n }\n cursor = nameEnd;\n while (WHITESPACE.test(code.charAt(cursor))) {\n cursor += 1;\n }\n return code.charAt(cursor) === \">\" ? cursor + 1 : FAILED;\n}\n\nfunction skipChildren(code: string, index: number, name: string): number {\n let cursor = index;\n while (cursor !== FAILED && cursor < code.length) {\n const char = code.charAt(cursor);\n if (char === \"<\" && code.charAt(cursor + 1) === \"/\") {\n return readClosingTagEnd(code, cursor, name);\n }\n if (char === \"{\") {\n cursor = skipJsExpression(code, cursor);\n } else if (isTagStart(code, cursor)) {\n cursor = skipElement(code, cursor);\n } else {\n cursor += 1;\n }\n }\n return FAILED;\n}\n\nfunction skipElement(code: string, index: number): number {\n const tag = readOpeningTag(code, index);\n if (!tag) {\n return FAILED;\n }\n return tag.selfClosing ? tag.end : skipChildren(code, tag.end, tag.name);\n}\n\nfunction lineOffset(code: string, line: number): number {\n if (!Number.isInteger(line) || line < 1) {\n return FAILED;\n }\n let offset = 0;\n for (let current = 1; current < line; current += 1) {\n const newline = code.indexOf(\"\\n\", offset);\n if (newline === -1) {\n return FAILED;\n }\n offset = newline + 1;\n }\n return offset;\n}\n\nfunction findTagStart(\n code: string,\n lineStart: number,\n lineEnd: number,\n column: number\n): number {\n const origin = Math.min(lineStart + Math.max(column, 0), lineEnd);\n for (let back = 0; back <= MAX_TAG_LOOKBACK; back += 1) {\n const candidate = origin - back;\n if (candidate >= lineStart && isTagStart(code, candidate)) {\n return candidate;\n }\n }\n for (let candidate = origin + 1; candidate < lineEnd; candidate += 1) {\n if (isTagStart(code, candidate)) {\n return candidate;\n }\n }\n return FAILED;\n}\n\nfunction countNewlines(code: string, from: number, to: number): number {\n let count = 0;\n let newline = code.indexOf(\"\\n\", from);\n while (newline !== -1 && newline < to) {\n count += 1;\n newline = code.indexOf(\"\\n\", newline + 1);\n }\n return count;\n}\n\n/** Lines spanned by the JSX element at a 1-based line and 0-based column. */\nexport function jsxElementLines(\n code: string,\n line: number,\n column: number\n): LineRange | null {\n const lineStart = lineOffset(code, line);\n if (lineStart === FAILED) {\n return null;\n }\n const newline = code.indexOf(\"\\n\", lineStart);\n const lineEnd = newline === -1 ? code.length : newline;\n const tagStart = findTagStart(code, lineStart, lineEnd, column);\n if (tagStart === FAILED) {\n return null;\n }\n const elementEnd = skipElement(code, tagStart);\n if (elementEnd === FAILED) {\n return null;\n }\n return {\n end: line + countNewlines(code, tagStart, elementEnd - 1),\n start: line,\n };\n}\n","import { isAbsolute, relative, sep } from \"node:path\";\n\n/** Forward-slash path from the workspace root, or null when `realPath` escapes it (including another Windows drive). */\nexport function workspaceRelativePath(\n realPath: string,\n workspaceRoot: string\n): string | null {\n const relativePath = relative(workspaceRoot, realPath);\n const escapes =\n relativePath === \"\" ||\n relativePath === \"..\" ||\n relativePath.startsWith(`..${sep}`) ||\n isAbsolute(relativePath);\n return escapes ? null : relativePath.split(sep).join(\"/\");\n}\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport { SourceMap } from \"node:module\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { type DevtoolsOutcome, failure } from \"../json-response\";\nimport type { SourceRequest } from \"./source-file\";\nimport { workspaceRelativePath } from \"./workspace-path\";\n\nconst SERVER_FRAME_PREFIX = /^(?:about|rsc):\\/\\/React\\/Server\\//;\nconst QUERY_OR_HASH = /[?#].*$/;\nconst SOURCE_MAPPING_URL = /\\/\\/# sourceMappingURL=(\\S+)\\s*$/;\nconst MAX_MAP_BYTES = 50 * 1_048_576;\n\nconst mapCache = new Map<string, { map: SourceMap; mtimeMs: number }>();\n\nexport function isServerFrame(fileName: string): boolean {\n return SERVER_FRAME_PREFIX.test(fileName);\n}\n\nasync function mapPathFor(chunkPath: string): Promise<string> {\n const code = await readFile(chunkPath, \"utf8\");\n const declared = SOURCE_MAPPING_URL.exec(code)?.[1];\n return declared\n ? join(dirname(chunkPath), decodeURIComponent(declared))\n : `${chunkPath}.map`;\n}\n\nasync function loadMap(mapPath: string): Promise<SourceMap> {\n const { mtimeMs, size } = await stat(mapPath);\n if (size > MAX_MAP_BYTES) {\n throw new Error(\"source map too large\");\n }\n const cached = mapCache.get(mapPath);\n if (cached?.mtimeMs === mtimeMs) {\n return cached.map;\n }\n const map = new SourceMap(JSON.parse(await readFile(mapPath, \"utf8\")));\n mapCache.set(mapPath, { map, mtimeMs });\n return map;\n}\n\n/**\n * Server Components stamp their elements with frames into the dev server's\n * own chunks (`about://React/Server/file:///…/.next/…`); the browser cannot\n * fetch those maps, so they are resolved here from disk.\n */\nexport async function mapServerFrame(\n request: SourceRequest,\n workspaceRoot: string\n): Promise<DevtoolsOutcome<SourceRequest>> {\n const unreadable = failure<SourceRequest>(\n \"This element comes from a Server Component whose source map could not be read.\",\n 404\n );\n if (request.line === null) {\n return unreadable;\n }\n try {\n const chunkUrl = request.fileName\n .replace(SERVER_FRAME_PREFIX, \"\")\n .replace(QUERY_OR_HASH, \"\");\n const chunkPath = await realpath(fileURLToPath(chunkUrl));\n if (workspaceRelativePath(chunkPath, workspaceRoot) === null) {\n return failure<SourceRequest>(\n \"Reflet devtools only reads files inside your repository.\",\n 403\n );\n }\n const map = await loadMap(await mapPathFor(chunkPath));\n const origin = map.findOrigin(request.line, (request.column ?? 0) + 1);\n if (!(\"fileName\" in origin)) {\n return unreadable;\n }\n return {\n ok: true,\n value: {\n column: origin.columnNumber - 1,\n fileName: origin.fileName,\n line: origin.lineNumber,\n },\n };\n } catch {\n return unreadable;\n }\n}\n","import { readFile, realpath, stat } from \"node:fs/promises\";\nimport { extname, isAbsolute, join } from \"node:path\";\nimport type { SourceFile } from \"../../protocol\";\nimport { type DevtoolsOutcome, failure } from \"../json-response\";\nimport { jsxElementLines } from \"./jsx-range\";\nimport type { ProjectRoots } from \"./project-roots\";\nimport { isServerFrame, mapServerFrame } from \"./server-frame\";\nimport { workspaceRelativePath } from \"./workspace-path\";\n\nconst MAX_SOURCE_BYTES = 1_048_576;\nconst MAX_FILE_NAME_LENGTH = 2048;\nconst MAX_NORMALIZE_PASSES = 8;\nconst SOURCE_EXTENSIONS = [\n \".astro\",\n \".cjs\",\n \".js\",\n \".jsx\",\n \".mdx\",\n \".mjs\",\n \".svelte\",\n \".ts\",\n \".tsx\",\n \".vue\",\n];\nconst EXTENSION_REFUSAL = `Reflet devtools only reads source files (${SOURCE_EXTENSIONS.join(\", \")}).`;\nconst OUTSIDE_WORKSPACE_REFUSAL =\n \"Reflet devtools only reads files inside your repository.\";\nconst NODE_MODULES_REFUSAL =\n \"Reflet devtools does not read files inside node_modules.\";\nconst QUERY_OR_HASH = /[?#].*$/;\nconst TURBOPACK_MODULE_SUFFIX = /(?: \\[[\\w-]+\\])+(?: \\([\\w-]+\\))*$/;\nconst URL_PREFIXES = [/^file:\\/\\//, /^https?:\\/\\/[^/]*/];\nconst SLASH_BEFORE_DRIVE = /^\\/(?=[a-z]:[\\\\/])/i;\nconst BUNDLER_PREFIXES = [\n /^rsc:\\/\\/React\\/[^/]+\\//,\n /^webpack-internal:\\/{2,}/,\n /^webpack:\\/\\/[^/]*\\//,\n /^turbopack:\\/{2,}/,\n /^\\[project\\]\\//,\n /^\\(app-pages-browser\\)\\//,\n /^\\([\\w-]+\\)\\/(?=\\.\\/)/,\n /^\\/@fs(?=\\/)/,\n /^\\.\\//,\n];\n\ninterface LocatedFile {\n realPath: string;\n relativePath: string;\n size: number;\n}\n\ntype CandidateCheck =\n | ({ kind: \"found\" } & LocatedFile)\n | { kind: \"missing\" }\n | { kind: \"refused\"; reason: string };\n\nexport interface SourceRequest {\n column: number | null;\n fileName: string;\n line: number | null;\n}\n\nfunction decodePath(path: string): string {\n try {\n return decodeURIComponent(path);\n } catch {\n return path;\n }\n}\n\nfunction stripFirstPrefix(fileName: string, prefixes: RegExp[]): string {\n for (const prefix of prefixes) {\n if (prefix.test(fileName)) {\n return fileName.replace(prefix, \"\");\n }\n }\n return fileName;\n}\n\n/** Turns a file name from a React debug stack into a filesystem path. */\nexport function normalizeSourceFileName(rawFileName: string): string {\n let fileName = rawFileName\n .trim()\n .replace(QUERY_OR_HASH, \"\")\n .replace(TURBOPACK_MODULE_SUFFIX, \"\");\n let isUrlEncoded = false;\n\n for (let pass = 0; pass < MAX_NORMALIZE_PASSES; pass += 1) {\n const withoutUrl = stripFirstPrefix(fileName, URL_PREFIXES);\n isUrlEncoded ||= withoutUrl !== fileName;\n const stripped = stripFirstPrefix(withoutUrl, BUNDLER_PREFIXES);\n if (stripped === fileName) {\n break;\n }\n fileName = stripped;\n }\n\n const path = isUrlEncoded ? decodePath(fileName) : fileName;\n return path.replace(SLASH_BEFORE_DRIVE, \"\");\n}\n\nfunction candidatePaths(fileName: string, roots: ProjectRoots): string[] {\n const candidates = [\n join(roots.root, fileName),\n join(roots.workspaceRoot, fileName),\n ];\n if (isAbsolute(fileName)) {\n candidates.unshift(fileName);\n }\n return [...new Set(candidates)];\n}\n\nfunction isSourceExtension(path: string): boolean {\n return SOURCE_EXTENSIONS.includes(extname(path).toLowerCase());\n}\n\nasync function checkCandidate(\n candidate: string,\n workspaceRoot: string\n): Promise<CandidateCheck> {\n let realPath: string;\n let size: number;\n try {\n realPath = await realpath(candidate);\n const stats = await stat(realPath);\n if (!stats.isFile()) {\n return { kind: \"missing\" };\n }\n size = stats.size;\n } catch {\n return { kind: \"missing\" };\n }\n\n const relativePath = workspaceRelativePath(realPath, workspaceRoot);\n if (relativePath === null) {\n return { kind: \"refused\", reason: OUTSIDE_WORKSPACE_REFUSAL };\n }\n if (relativePath.split(\"/\").includes(\"node_modules\")) {\n return { kind: \"refused\", reason: NODE_MODULES_REFUSAL };\n }\n if (!isSourceExtension(realPath)) {\n return { kind: \"refused\", reason: EXTENSION_REFUSAL };\n }\n return { kind: \"found\", realPath, relativePath, size };\n}\n\nasync function locateSourceFile(\n fileName: string,\n roots: ProjectRoots\n): Promise<DevtoolsOutcome<LocatedFile>> {\n let refusal: string | null = null;\n for (const candidate of candidatePaths(fileName, roots)) {\n const check = await checkCandidate(candidate, roots.workspaceRoot);\n if (check.kind === \"found\") {\n return { ok: true, value: check };\n }\n if (check.kind === \"refused\") {\n refusal ??= check.reason;\n }\n }\n if (refusal) {\n return failure(refusal, 403);\n }\n return failure(`Could not find ${fileName} in ${roots.workspaceRoot}.`, 404);\n}\n\n/** Server-map columns can point past the line; the element then starts at its first tag. */\nfunction columnWithinLine(code: string, line: number, column: number | null) {\n const text = code.split(\"\\n\")[line - 1] ?? \"\";\n return column !== null && column < text.length ? column : null;\n}\n\nexport async function readSourceFile(\n frame: SourceRequest,\n roots: ProjectRoots\n): Promise<DevtoolsOutcome<SourceFile>> {\n if (\n frame.fileName.length > MAX_FILE_NAME_LENGTH ||\n frame.fileName.includes(\"\\0\")\n ) {\n return failure(\"That source file name is not a valid path.\", 400);\n }\n const mapped = isServerFrame(frame.fileName)\n ? await mapServerFrame(frame, roots.workspaceRoot)\n : { ok: true as const, value: frame };\n if (!mapped.ok) {\n return mapped;\n }\n const request = mapped.value;\n const fileName = normalizeSourceFileName(request.fileName);\n if (!fileName) {\n return failure(\"A source file name is required.\", 400);\n }\n if (!isSourceExtension(fileName)) {\n return failure(EXTENSION_REFUSAL, 403);\n }\n\n const located = await locateSourceFile(fileName, roots);\n if (!located.ok) {\n return located;\n }\n const { realPath, relativePath, size } = located.value;\n if (size > MAX_SOURCE_BYTES) {\n return failure(\n `${relativePath} is larger than 1 MB, too big to preview.`,\n 413\n );\n }\n\n const code = await readFile(realPath, \"utf8\");\n const column =\n request.line === null\n ? request.column\n : columnWithinLine(code, request.line, request.column);\n const elementLines =\n request.line === null\n ? null\n : jsxElementLines(code, request.line, column ?? 0);\n\n return {\n ok: true,\n value: {\n absolutePath: realPath,\n code,\n column,\n elementLines,\n line: request.line,\n path: relativePath,\n },\n };\n}\n","import {\n DEVTOOLS_ENDPOINTS,\n DEVTOOLS_ROUTE_BASE,\n DEVTOOLS_STATUS_MARKER,\n type DevtoolsStatus,\n} from \"../protocol\";\nimport { boardAccess, boardCredential } from \"./connect/board-credential\";\nimport {\n disconnect,\n finishConnect,\n startConnect,\n} from \"./connect/connect-routes\";\nimport { removeConnection } from \"./connect/connection-store\";\nimport {\n type DevtoolsOutcome,\n errorResponse,\n jsonResponse,\n} from \"./json-response\";\nimport {\n type DevtoolsEnv,\n type DevtoolsServerOptions,\n type ResolvedDevtoolsOptions,\n resolveDevtoolsOptions,\n} from \"./options\";\nimport { proxyToReflet } from \"./reflet-proxy\";\nimport { rejectUntrustedCaller, rejectUntrustedHost } from \"./request-guard\";\nimport { searchCode } from \"./source/code-search\";\nimport { type ProjectRoots, resolveProjectRoots } from \"./source/project-roots\";\nimport { readSourceFile } from \"./source/source-file\";\n\nexport type DevtoolsHandler = (request: Request) => Promise<Response>;\n\nconst TRAILING_SLASHES = /\\/+$/;\n\nconst ENDPOINT_METHODS: Record<string, \"GET\" | \"POST\"> = {\n [DEVTOOLS_ENDPOINTS.connectCallback]: \"GET\",\n [DEVTOOLS_ENDPOINTS.connectStart]: \"POST\",\n [DEVTOOLS_ENDPOINTS.disconnect]: \"POST\",\n [DEVTOOLS_ENDPOINTS.search]: \"GET\",\n [DEVTOOLS_ENDPOINTS.source]: \"GET\",\n [DEVTOOLS_ENDPOINTS.status]: \"GET\",\n};\n\nfunction outcomeResponse<T>(outcome: DevtoolsOutcome<T>): Response {\n return outcome.ok\n ? jsonResponse(outcome.value)\n : errorResponse(outcome.error, outcome.status);\n}\n\nfunction routeSubPath(pathname: string): string | null {\n const baseIndex = pathname.indexOf(DEVTOOLS_ROUTE_BASE);\n if (baseIndex === -1) {\n return null;\n }\n return pathname\n .slice(baseIndex + DEVTOOLS_ROUTE_BASE.length)\n .replace(TRAILING_SLASHES, \"\");\n}\n\nfunction readInteger(value: string | null, minimum: number): number | null {\n if (value === null || value === \"\") {\n return null;\n }\n const parsed = Number(value);\n return Number.isInteger(parsed) && parsed >= minimum ? parsed : null;\n}\n\nasync function proxyWithBoardCredential(\n request: Request,\n apiPath: string,\n settings: ResolvedDevtoolsOptions\n): Promise<Response> {\n const credential = await boardCredential(settings);\n const response = await proxyToReflet(request, apiPath, {\n apiUrl: settings.apiUrl,\n token: credential?.token ?? null,\n });\n if (credential?.isStored && response.status === 401) {\n await removeConnection(settings.root, settings.apiUrl, credential.token);\n }\n return response;\n}\n\nasync function routeRequest(\n request: Request,\n subPath: string | null,\n settings: ResolvedDevtoolsOptions,\n projectRoots: () => ProjectRoots\n): Promise<Response> {\n const url = new URL(request.url);\n\n if (subPath?.startsWith(`${DEVTOOLS_ENDPOINTS.proxy}/`)) {\n const apiPath = subPath.slice(DEVTOOLS_ENDPOINTS.proxy.length);\n return await proxyWithBoardCredential(request, apiPath, settings);\n }\n\n const requiredMethod = subPath ? ENDPOINT_METHODS[subPath] : undefined;\n if (requiredMethod && request.method !== requiredMethod) {\n return errorResponse(\n `${subPath} only answers ${requiredMethod} requests.`,\n 405\n );\n }\n\n switch (subPath) {\n case DEVTOOLS_ENDPOINTS.status:\n return jsonResponse({\n board: await boardAccess(request, settings),\n editor: settings.editor,\n marker: DEVTOOLS_STATUS_MARKER,\n } satisfies DevtoolsStatus);\n case DEVTOOLS_ENDPOINTS.connectStart:\n return await startConnect(request, settings);\n case DEVTOOLS_ENDPOINTS.connectCallback:\n return await finishConnect(request, settings);\n case DEVTOOLS_ENDPOINTS.disconnect:\n return await disconnect(settings);\n case DEVTOOLS_ENDPOINTS.source:\n return outcomeResponse(\n await readSourceFile(\n {\n column: readInteger(url.searchParams.get(\"column\"), 0),\n fileName: url.searchParams.get(\"file\") ?? \"\",\n line: readInteger(url.searchParams.get(\"line\"), 1),\n },\n projectRoots()\n )\n );\n case DEVTOOLS_ENDPOINTS.search:\n return outcomeResponse(\n await searchCode(\n projectRoots().workspaceRoot,\n url.searchParams.get(\"q\") ?? \"\"\n )\n );\n default:\n return errorResponse(\n `No Reflet devtools endpoint at ${url.pathname}.`,\n 404\n );\n }\n}\n\nexport function createDevtoolsHandler(\n options: DevtoolsServerOptions = {},\n env: DevtoolsEnv = process.env\n): DevtoolsHandler {\n const settings = resolveDevtoolsOptions(options, env);\n let roots: ProjectRoots | null = null;\n const projectRoots = (): ProjectRoots => {\n roots ??= resolveProjectRoots(settings.root);\n return roots;\n };\n\n return async (request) => {\n const hostRejection = rejectUntrustedHost(request, settings.allowedHosts);\n if (hostRejection) {\n return hostRejection;\n }\n const subPath = routeSubPath(new URL(request.url).pathname);\n const isConnectCallback =\n request.method === \"GET\" &&\n subPath === DEVTOOLS_ENDPOINTS.connectCallback;\n const callerRejection = isConnectCallback\n ? null\n : rejectUntrustedCaller(request, settings.allowedHosts);\n if (callerRejection) {\n return callerRejection;\n }\n try {\n return await routeRequest(request, subPath, settings, projectRoots);\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error);\n return errorResponse(`Reflet devtools route failed: ${reason}`, 500);\n }\n };\n}\n"],"mappings":"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"}
|