@alxia/react-router 0.17.0 → 0.19.0
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/README.md +45 -1
- package/dist/chunks/index-3jfeew2y.js.map +1 -1
- package/dist/chunks/index-6jf7zpxz.js.map +1 -1
- package/dist/chunks/index-9xv2a8et.js.map +1 -1
- package/dist/chunks/{index-c3k47yw7.js → index-a45b1582.js} +7 -6
- package/dist/chunks/{index-c3k47yw7.js.map → index-a45b1582.js.map} +3 -3
- package/dist/chunks/index-kfekhvgr.js.map +1 -1
- package/dist/chunks/index-mscfme4r.js +12 -0
- package/dist/chunks/index-mscfme4r.js.map +10 -0
- package/dist/cli/index.js.map +1 -1
- package/dist/entry/index.js.map +1 -1
- package/dist/errors/cross-site.d.ts +8 -0
- package/dist/errors/cross-site.d.ts.map +1 -0
- package/dist/errors/index.js +1 -1
- package/dist/errors/index.js.map +1 -1
- package/dist/errors/same-site.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/pwa/index.js.map +1 -1
- package/dist/pwa/worker/index.js.map +1 -1
- package/dist/session/index.js +1 -1
- package/dist/session/index.js.map +1 -1
- package/dist/session/react/index.js +17 -6
- package/dist/session/react/index.js.map +3 -3
- package/dist/session/react/use-link-param.d.ts +12 -2
- package/dist/session/react/use-link-param.d.ts.map +1 -1
- package/dist/subscription/documents.d.ts +3 -0
- package/dist/subscription/documents.d.ts.map +1 -0
- package/dist/subscription/index.d.ts +7 -0
- package/dist/subscription/index.d.ts.map +1 -0
- package/dist/subscription/index.js +360 -0
- package/dist/subscription/index.js.map +14 -0
- package/dist/subscription/proxy.d.ts +40 -0
- package/dist/subscription/proxy.d.ts.map +1 -0
- package/dist/subscription/read.d.ts +17 -0
- package/dist/subscription/read.d.ts.map +1 -0
- package/dist/subscription/refusal.d.ts +11 -0
- package/dist/subscription/refusal.d.ts.map +1 -0
- package/dist/subscription/relay.d.ts +16 -0
- package/dist/subscription/relay.d.ts.map +1 -0
- package/dist/vite/index.js.map +1 -1
- package/docs/README.md +2 -1
- package/docs/guide/session.md +18 -1
- package/docs/guide/subscriptions.md +126 -0
- package/docs/roadmap.md +10 -2
- package/docs/troubleshooting.md +109 -0
- package/package.json +9 -3
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/subscription/documents.ts", "../src/subscription/refusal.ts", "../src/subscription/read.ts", "../src/subscription/relay.ts", "../src/subscription/proxy.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"/**\n * Checks, when the proxy is created, that each document the server holds\n * defines `subscription <key>` and nothing else. The documents are the app's\n * own text, never a client's, so a plain scan is enough to catch a mistake (a\n * mutation listed, a name that does not match its key); it is not a parser and\n * guards nothing against hostile input.\n */\nfunction stripped(document: string): string {\n\treturn document\n\t\t.replace(/\"\"\"[\\s\\S]*?\"\"\"/g, ' ')\n\t\t.replace(/\"(?:\\\\.|[^\"\\\\\\n])*\"/g, ' ')\n\t\t.replace(/#[^\\n\\r]*/g, ' ');\n}\n\n/** The top-level definitions of `document`: `[keyword, name]`, `{` for a shorthand query. */\nfunction definitions(document: string): Array<[string, string | undefined]> {\n\tconst found: Array<[string, string | undefined]> = [];\n\tlet depth = 0;\n\tlet open: string | undefined;\n\tlet skipping = false;\n\tfor (const m of stripped(document).matchAll(/[{}()]|[A-Za-z_]\\w*/g)) {\n\t\tconst t = m[0];\n\t\tif (t === '(') depth++;\n\t\telse if (t === ')') depth--;\n\t\telse if (t === '{') {\n\t\t\tif (depth === 0 && !skipping) {\n\t\t\t\tif (open !== undefined) {\n\t\t\t\t\tfound.push([open, undefined]);\n\t\t\t\t\topen = undefined;\n\t\t\t\t} else found.push(['{', undefined]);\n\t\t\t}\n\t\t\tif (depth === 0) skipping = false;\n\t\t\tdepth++;\n\t\t} else if (t === '}') depth--;\n\t\telse if (depth === 0) {\n\t\t\tif (open !== undefined && !skipping) {\n\t\t\t\tfound.push([open, t]);\n\t\t\t\topen = undefined;\n\t\t\t\tskipping = true;\n\t\t\t} else if (t === 'fragment') skipping = true;\n\t\t\telse if (t === 'query' || t === 'mutation' || t === 'subscription')\n\t\t\t\topen = t;\n\t\t}\n\t}\n\treturn found;\n}\n\n/** Throws a worded `TypeError` for a document that is not exactly `subscription <name>`. */\nexport function checkDocuments(allow: Readonly<Record<string, string>>): void {\n\tfor (const [name, document] of Object.entries(allow)) {\n\t\tconst operations = definitions(document).filter(\n\t\t\t([kind]) => kind !== 'fragment',\n\t\t);\n\t\tconst ok =\n\t\t\toperations.length === 1 &&\n\t\t\toperations[0]?.[0] === 'subscription' &&\n\t\t\toperations[0]?.[1] === name;\n\t\tif (!ok)\n\t\t\tthrow new TypeError(\n\t\t\t\t`createSubscriptionProxy(): allow[${JSON.stringify(name)}] must define exactly one operation, \\`subscription ${name}\\`; its document defines ${\n\t\t\t\t\toperations.length === 0\n\t\t\t\t\t\t? 'none'\n\t\t\t\t\t\t: operations.map(([k, n]) => `${k}${n ? ` ${n}` : ''}`).join(', ')\n\t\t\t\t}. Fragments are allowed.`,\n\t\t\t);\n\t}\n}\n",
|
|
6
|
+
"/** An answer the proxy gives itself, as GraphQL-shaped JSON a client can read. */\nexport class Refusal extends Error {\n\tconstructor(\n\t\treadonly status: number,\n\t\tmessage: string,\n\t\treadonly code: string,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'Refusal';\n\t}\n}\n\nexport function problem(\n\tstatus: number,\n\tmessage: string,\n\tcode: string,\n\textra: Record<string, unknown> = {},\n\theaders: HeadersInit = {},\n): Response {\n\treturn new Response(\n\t\tJSON.stringify({\n\t\t\terrors: [{ message, extensions: { code, ...extra } }],\n\t\t\t...extra,\n\t\t}),\n\t\t{\n\t\t\tstatus,\n\t\t\theaders: {\n\t\t\t\t'content-type': 'application/json',\n\t\t\t\t'cache-control': 'no-store',\n\t\t\t\t...headers,\n\t\t\t},\n\t\t},\n\t);\n}\n\nexport const refusalResponse = (refusal: Refusal): Response =>\n\tproblem(refusal.status, refusal.message, refusal.code);\n\nfunction retryAfterOf(upstream: Response, body: unknown): number | undefined {\n\tconst header = Number(upstream.headers.get('retry-after'));\n\tif (Number.isFinite(header) && header > 0) return Math.ceil(header);\n\tconst seconds = (value: unknown): number | undefined =>\n\t\ttypeof value === 'number' && Number.isFinite(value) && value > 0\n\t\t\t? Math.ceil(value)\n\t\t\t: undefined;\n\tif (typeof body !== 'object' || body === null) return undefined;\n\tconst top = body as { retryAfter?: unknown; errors?: unknown };\n\tconst first = Array.isArray(top.errors)\n\t\t? (top.errors[0] as { extensions?: { retryAfter?: unknown } } | undefined)\n\t\t: undefined;\n\treturn seconds(top.retryAfter) ?? seconds(first?.extensions?.retryAfter);\n}\n\n/** What a non-2xx upstream answer becomes: a 429 with `retryAfter`, a 502 for a 5xx, any other 4xx as it came. */\nexport async function refusedUpstream(upstream: Response): Promise<Response> {\n\tconst text = await upstream.text().catch(() => '');\n\tif (upstream.status === 429) {\n\t\tlet body: unknown;\n\t\ttry {\n\t\t\tbody = JSON.parse(text);\n\t\t} catch {}\n\t\tconst retryAfter = retryAfterOf(upstream, body);\n\t\treturn problem(\n\t\t\t429,\n\t\t\t'Too many requests.',\n\t\t\t'RATE_LIMITED',\n\t\t\tretryAfter === undefined ? {} : { retryAfter },\n\t\t\tretryAfter === undefined ? {} : { 'retry-after': String(retryAfter) },\n\t\t);\n\t}\n\tif (upstream.status >= 500)\n\t\treturn problem(502, 'The API is unavailable.', 'UPSTREAM_ERROR');\n\treturn new Response(text, {\n\t\tstatus: upstream.status,\n\t\theaders: {\n\t\t\t'content-type':\n\t\t\t\tupstream.headers.get('content-type') ?? 'application/json',\n\t\t\t'cache-control': 'no-store',\n\t\t},\n\t});\n}\n",
|
|
7
|
+
"import { Refusal } from './refusal';\n\n/** The most a body, a query string or the variables may weigh, in bytes. */\nexport const LIMITS = {\n\tbody: 64 * 1024,\n\tqueryString: 16 * 1024,\n\tvariables: 16 * 1024,\n} as const;\n\nexport interface Asked {\n\treadonly operationName: string;\n\treadonly variables?: Record<string, unknown>;\n}\n\nconst TOO_LARGE = () =>\n\tnew Refusal(400, 'The request is too large.', 'BAD_REQUEST');\nconst NOT_JSON = () =>\n\tnew Refusal(400, 'The request is not valid JSON.', 'BAD_REQUEST');\n\nfunction record(value: unknown): Record<string, unknown> | undefined {\n\treturn typeof value === 'object' && value !== null && !Array.isArray(value)\n\t\t? (value as Record<string, unknown>)\n\t\t: undefined;\n}\n\n/** The body as text, refused past `limit` bytes: `content-length` first, then a cap on what is read. */\nasync function textOf(request: Request, limit: number): Promise<string> {\n\tconst declared = Number(request.headers.get('content-length'));\n\tif (Number.isFinite(declared) && declared > limit) throw TOO_LARGE();\n\tif (request.body === null) return '';\n\tconst reader = request.body.getReader();\n\tconst chunks: Uint8Array[] = [];\n\tlet size = 0;\n\tfor (;;) {\n\t\tconst { done, value } = await reader.read();\n\t\tif (done) break;\n\t\tsize += value.byteLength;\n\t\tif (size > limit) {\n\t\t\tvoid reader.cancel().catch(() => {});\n\t\t\tthrow TOO_LARGE();\n\t\t}\n\t\tchunks.push(value);\n\t}\n\treturn new TextDecoder().decode(Buffer.concat(chunks));\n}\n\nfunction parse(text: string): unknown {\n\ttry {\n\t\treturn JSON.parse(text);\n\t} catch {\n\t\tthrow NOT_JSON();\n\t}\n}\n\n/**\n * What a client asks for: an `operationName` and its `variables`, from a\n * GET's search params or a POST's JSON body. Any `query` or `extensions` it\n * sends (graphql-sse always sends a `query`) is ignored.\n */\nexport async function readAsked(request: Request): Promise<Asked> {\n\tlet raw: Record<string, unknown> | undefined;\n\tif (request.method === 'GET') {\n\t\tconst url = new URL(request.url);\n\t\tif (url.search.length > LIMITS.queryString) throw TOO_LARGE();\n\t\tconst variables = url.searchParams.get('variables');\n\t\traw = {\n\t\t\toperationName: url.searchParams.get('operationName') ?? undefined,\n\t\t\tvariables: variables ? parse(variables) : undefined,\n\t\t};\n\t} else {\n\t\tconst type = (request.headers.get('content-type') ?? '')\n\t\t\t.split(';')[0]\n\t\t\t?.trim()\n\t\t\t.toLowerCase();\n\t\tif (type !== 'application/json')\n\t\t\tthrow new Refusal(\n\t\t\t\t415,\n\t\t\t\t'Send the request as application/json.',\n\t\t\t\t'UNSUPPORTED_MEDIA_TYPE',\n\t\t\t);\n\t\traw = record(parse(await textOf(request, LIMITS.body)));\n\t\tif (raw === undefined)\n\t\t\tthrow new Refusal(\n\t\t\t\t400,\n\t\t\t\t'The request must be a JSON object.',\n\t\t\t\t'BAD_REQUEST',\n\t\t\t);\n\t}\n\tconst { operationName, variables } = raw;\n\tif (operationName === undefined)\n\t\tthrow new Refusal(400, 'Send an \"operationName\".', 'BAD_REQUEST');\n\tif (typeof operationName !== 'string')\n\t\tthrow new Refusal(400, '\"operationName\" must be a string.', 'BAD_REQUEST');\n\tif (variables !== undefined) {\n\t\tif (record(variables) === undefined)\n\t\t\tthrow new Refusal(400, '\"variables\" must be an object.', 'BAD_REQUEST');\n\t\tif (JSON.stringify(variables).length > LIMITS.variables) throw TOO_LARGE();\n\t}\n\treturn {\n\t\toperationName,\n\t\t...(variables === undefined\n\t\t\t? {}\n\t\t\t: { variables: variables as Record<string, unknown> }),\n\t};\n}\n",
|
|
8
|
+
"/** The most one event may weigh before the stream is cut, in characters. */\nexport const MAX_EVENT = 1024 * 1024;\n\nconst encoder = new TextEncoder();\nconst decoder = new TextDecoder();\n\nexport const SSE_HEADERS = {\n\t'content-type': 'text/event-stream; charset=utf-8',\n\t'cache-control': 'no-store, no-transform',\n\t'x-accel-buffering': 'no',\n};\n\nconst FAILED =\n\t'event: next\\ndata: {\"errors\":[{\"message\":\"The API stream failed.\",\"extensions\":{\"code\":\"UPSTREAM_ERROR\"}}]}\\n\\nevent: complete\\ndata:\\n\\n';\n\n/**\n * Relays whole events (a heartbeat never lands inside one) until the upstream\n * ends or the client leaves. The stream is pulled: upstream is read only when\n * the client has taken what was queued, so a slow client holds the upstream\n * back instead of growing a buffer, and a heartbeat is skipped while one is\n * waiting.\n */\nexport function relay(\n\tupstream: Response,\n\tabort: AbortController,\n\theartbeatMs: number,\n): Response {\n\tconst reader = (upstream.body as ReadableStream<Uint8Array>).getReader();\n\tlet timer: ReturnType<typeof setInterval> | undefined;\n\tlet buffer = '';\n\tconst stop = (): void => {\n\t\tif (timer !== undefined) clearInterval(timer);\n\t\ttimer = undefined;\n\t};\n\tconst stream = new ReadableStream<Uint8Array>(\n\t\t{\n\t\t\tstart(controller) {\n\t\t\t\tif (heartbeatMs > 0)\n\t\t\t\t\ttimer = setInterval(() => {\n\t\t\t\t\t\tif ((controller.desiredSize ?? 0) > 0)\n\t\t\t\t\t\t\tcontroller.enqueue(encoder.encode(':\\n\\n'));\n\t\t\t\t\t}, heartbeatMs);\n\t\t\t},\n\t\t\tasync pull(controller) {\n\t\t\t\ttry {\n\t\t\t\t\tfor (;;) {\n\t\t\t\t\t\tconst { done, value } = await reader.read();\n\t\t\t\t\t\tif (done) {\n\t\t\t\t\t\t\tstop();\n\t\t\t\t\t\t\tif (buffer.trim() !== '')\n\t\t\t\t\t\t\t\tcontroller.enqueue(encoder.encode(`${buffer}\\n\\n`));\n\t\t\t\t\t\t\tcontroller.close();\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbuffer += decoder\n\t\t\t\t\t\t\t.decode(value, { stream: true })\n\t\t\t\t\t\t\t.replace(/\\r\\n?/g, '\\n');\n\t\t\t\t\t\tconst cut = buffer.lastIndexOf('\\n\\n');\n\t\t\t\t\t\tif (cut !== -1) {\n\t\t\t\t\t\t\tcontroller.enqueue(encoder.encode(buffer.slice(0, cut + 2)));\n\t\t\t\t\t\t\tbuffer = buffer.slice(cut + 2);\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif (buffer.length > MAX_EVENT) throw new Error('event too large');\n\t\t\t\t\t}\n\t\t\t\t} catch {\n\t\t\t\t\tstop();\n\t\t\t\t\tif (abort.signal.aborted) return;\n\t\t\t\t\tabort.abort();\n\t\t\t\t\tcontroller.enqueue(encoder.encode(FAILED));\n\t\t\t\t\tcontroller.close();\n\t\t\t\t}\n\t\t\t},\n\t\t\tcancel() {\n\t\t\t\tstop();\n\t\t\t\tabort.abort();\n\t\t\t\tvoid reader.cancel().catch(() => {});\n\t\t\t},\n\t\t},\n\t\t{ highWaterMark: 1 },\n\t);\n\treturn new Response(stream, { status: 200, headers: SSE_HEADERS });\n}\n",
|
|
9
|
+
"import { isCrossSite } from '../errors/cross-site';\nimport { checkDocuments } from './documents';\nimport { readAsked } from './read';\nimport { problem, Refusal, refusalResponse, refusedUpstream } from './refusal';\nimport { relay } from './relay';\n\ntype HeaderValues = Record<string, string | null | undefined> | Headers;\n\nexport interface SubscriptionProxyOptions {\n\t/** The API's GraphQL endpoint, which serves subscriptions over SSE. */\n\treadonly endpoint: string | URL;\n\t/**\n\t * The operations the browser may start: each name with the document the\n\t * proxy sends upstream for it. The client names an operation and sends\n\t * variables; its own `query` and `extensions` are ignored, so nothing it\n\t * writes reaches the API. A name that is not a key is a 403.\n\t */\n\treadonly allow: Readonly<Record<string, string>>;\n\t/** The session's token, from the request: `(request) => cookies.token(request)`. Empty is a 401. */\n\treadonly getToken: (\n\t\trequest: Request,\n\t) => string | null | undefined | Promise<string | null | undefined>;\n\t/** Extra upstream headers (client name, proxy secret, `X-Forwarded-For`, `Accept-Language`), fixed or built per request. A `null` or `undefined` value is left out. */\n\treadonly headers?:\n\t\t| HeaderValues\n\t\t| ((request: Request) => HeaderValues | Promise<HeaderValues>);\n\t/** The app's own origin for the cross-site check, as `jsonActions` takes it; the request's own by default. */\n\treadonly origin?: string | (() => string | undefined);\n\t/** A comment line sent this often so a proxy or Bun's `idleTimeout` keeps the stream open. 15000 by default; `0` turns it off. */\n\treadonly heartbeatMs?: number;\n\t/** The `fetch` used upstream. The global one by default. */\n\treadonly fetch?: (request: Request) => Promise<Response>;\n}\n\nexport interface SubscriptionProxy {\n\t/** A GET: graphql-sse's distinct connections mode, the operation in the search params. */\n\tloader(args: { request: Request }): Promise<Response>;\n\t/** A POST: the operation in a JSON body. */\n\taction(args: { request: Request }): Promise<Response>;\n}\n\ninterface Config {\n\treadonly endpoint: URL;\n\treadonly documents: ReadonlyMap<string, string>;\n\treadonly options: SubscriptionProxyOptions;\n\treadonly origin: () => string | undefined;\n\treadonly heartbeatMs: number;\n\treadonly upstreamFetch: (request: Request) => Promise<Response>;\n}\n\nconst UNSAFE = /[\\r\\n\\0]/;\n\nasync function upstreamHeaders(\n\tconfig: Config,\n\trequest: Request,\n\ttoken: string,\n): Promise<Headers> {\n\tconst { headers } = config.options;\n\tconst extra =\n\t\ttypeof headers === 'function' ? await headers(request) : headers;\n\tconst out = new Headers();\n\tfor (const [name, value] of extra instanceof Headers\n\t\t? extra.entries()\n\t\t: Object.entries(extra ?? {}))\n\t\tif (value !== null && value !== undefined) out.set(name, value);\n\tout.set('content-type', 'application/json');\n\tout.set('accept', 'text/event-stream');\n\tout.set('authorization', `Bearer ${token}`);\n\treturn out;\n}\n\nasync function handle(config: Config, request: Request): Promise<Response> {\n\tif (isCrossSite(request, config.origin()))\n\t\treturn problem(403, 'Cross-site request refused.', 'FORBIDDEN');\n\tconst token = await config.options.getToken(request);\n\tif (!token || UNSAFE.test(token))\n\t\treturn problem(401, 'Sign in to continue.', 'UNAUTHENTICATED');\n\n\tlet asked: Awaited<ReturnType<typeof readAsked>>;\n\ttry {\n\t\tasked = await readAsked(request);\n\t} catch (error) {\n\t\tif (error instanceof Refusal) return refusalResponse(error);\n\t\treturn problem(400, 'The request body could not be read.', 'BAD_REQUEST');\n\t}\n\tconst query = config.documents.get(asked.operationName);\n\tif (query === undefined)\n\t\treturn problem(403, 'This operation is not allowed.', 'FORBIDDEN');\n\n\tlet headers: Headers;\n\ttry {\n\t\theaders = await upstreamHeaders(config, request, token);\n\t} catch {\n\t\treturn problem(\n\t\t\t500,\n\t\t\t\"The proxy's upstream headers are not valid (a name or a value no header can hold).\",\n\t\t\t'PROXY_MISCONFIGURED',\n\t\t);\n\t}\n\n\tconst abort = new AbortController();\n\tif (request.signal.aborted) abort.abort();\n\telse\n\t\trequest.signal.addEventListener('abort', () => abort.abort(), {\n\t\t\tonce: true,\n\t\t});\n\tlet upstream: Response;\n\ttry {\n\t\tupstream = await config.upstreamFetch(\n\t\t\tnew Request(config.endpoint, {\n\t\t\t\tmethod: 'POST',\n\t\t\t\theaders,\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tquery,\n\t\t\t\t\toperationName: asked.operationName,\n\t\t\t\t\t...(asked.variables === undefined\n\t\t\t\t\t\t? {}\n\t\t\t\t\t\t: { variables: asked.variables }),\n\t\t\t\t}),\n\t\t\t\tsignal: abort.signal,\n\t\t\t}),\n\t\t);\n\t} catch {\n\t\treturn problem(502, 'The API is unreachable.', 'UPSTREAM_ERROR');\n\t}\n\tconst streaming =\n\t\tupstream.ok &&\n\t\tupstream.body !== null &&\n\t\t(upstream.headers.get('content-type') ?? '').startsWith(\n\t\t\t'text/event-stream',\n\t\t);\n\tif (streaming) return relay(upstream, abort, config.heartbeatMs);\n\tif (upstream.ok) {\n\t\tabort.abort();\n\t\treturn problem(\n\t\t\t502,\n\t\t\t'The API did not answer with an event stream.',\n\t\t\t'UPSTREAM_ERROR',\n\t\t);\n\t}\n\tconst refused = await refusedUpstream(upstream);\n\tabort.abort();\n\treturn refused;\n}\n\nfunction only(\n\tmethod: string,\n\trun: (request: Request) => Promise<Response>,\n): (args: { request: Request }) => Promise<Response> {\n\treturn async ({ request }) =>\n\t\trequest.method === method\n\t\t\t? run(request)\n\t\t\t: problem(\n\t\t\t\t\t405,\n\t\t\t\t\t`Use ${method}.`,\n\t\t\t\t\t'METHOD_NOT_ALLOWED',\n\t\t\t\t\t{},\n\t\t\t\t\t{ allow: method },\n\t\t\t\t);\n}\n\n/**\n * A resource route that exposes GraphQL subscriptions to the browser without\n * giving it the API's token or a way to write its own document. See the\n * subscription guide.\n */\nexport function createSubscriptionProxy(\n\toptions: SubscriptionProxyOptions,\n): SubscriptionProxy {\n\tcheckDocuments(options.allow);\n\tconst config: Config = {\n\t\tendpoint: new URL(options.endpoint),\n\t\tdocuments: new Map(Object.entries(options.allow)),\n\t\toptions,\n\t\torigin: () =>\n\t\t\ttypeof options.origin === 'function' ? options.origin() : options.origin,\n\t\theartbeatMs: options.heartbeatMs ?? 15000,\n\t\tupstreamFetch: options.fetch ?? ((request) => fetch(request)),\n\t};\n\treturn {\n\t\tloader: only('GET', (request) => handle(config, request)),\n\t\taction: only('POST', (request) => handle(config, request)),\n\t};\n}\n"
|
|
10
|
+
],
|
|
11
|
+
"mappings": "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",
|
|
12
|
+
"debugId": "943D148BD34D8EDC64756E2164756E21",
|
|
13
|
+
"names": []
|
|
14
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
type HeaderValues = Record<string, string | null | undefined> | Headers;
|
|
2
|
+
export interface SubscriptionProxyOptions {
|
|
3
|
+
/** The API's GraphQL endpoint, which serves subscriptions over SSE. */
|
|
4
|
+
readonly endpoint: string | URL;
|
|
5
|
+
/**
|
|
6
|
+
* The operations the browser may start: each name with the document the
|
|
7
|
+
* proxy sends upstream for it. The client names an operation and sends
|
|
8
|
+
* variables; its own `query` and `extensions` are ignored, so nothing it
|
|
9
|
+
* writes reaches the API. A name that is not a key is a 403.
|
|
10
|
+
*/
|
|
11
|
+
readonly allow: Readonly<Record<string, string>>;
|
|
12
|
+
/** The session's token, from the request: `(request) => cookies.token(request)`. Empty is a 401. */
|
|
13
|
+
readonly getToken: (request: Request) => string | null | undefined | Promise<string | null | undefined>;
|
|
14
|
+
/** Extra upstream headers (client name, proxy secret, `X-Forwarded-For`, `Accept-Language`), fixed or built per request. A `null` or `undefined` value is left out. */
|
|
15
|
+
readonly headers?: HeaderValues | ((request: Request) => HeaderValues | Promise<HeaderValues>);
|
|
16
|
+
/** The app's own origin for the cross-site check, as `jsonActions` takes it; the request's own by default. */
|
|
17
|
+
readonly origin?: string | (() => string | undefined);
|
|
18
|
+
/** A comment line sent this often so a proxy or Bun's `idleTimeout` keeps the stream open. 15000 by default; `0` turns it off. */
|
|
19
|
+
readonly heartbeatMs?: number;
|
|
20
|
+
/** The `fetch` used upstream. The global one by default. */
|
|
21
|
+
readonly fetch?: (request: Request) => Promise<Response>;
|
|
22
|
+
}
|
|
23
|
+
export interface SubscriptionProxy {
|
|
24
|
+
/** A GET: graphql-sse's distinct connections mode, the operation in the search params. */
|
|
25
|
+
loader(args: {
|
|
26
|
+
request: Request;
|
|
27
|
+
}): Promise<Response>;
|
|
28
|
+
/** A POST: the operation in a JSON body. */
|
|
29
|
+
action(args: {
|
|
30
|
+
request: Request;
|
|
31
|
+
}): Promise<Response>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A resource route that exposes GraphQL subscriptions to the browser without
|
|
35
|
+
* giving it the API's token or a way to write its own document. See the
|
|
36
|
+
* subscription guide.
|
|
37
|
+
*/
|
|
38
|
+
export declare function createSubscriptionProxy(options: SubscriptionProxyOptions): SubscriptionProxy;
|
|
39
|
+
export {};
|
|
40
|
+
//# sourceMappingURL=proxy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/subscription/proxy.ts"],"names":[],"mappings":"AAMA,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,GAAG,OAAO,CAAC;AAExE,MAAM,WAAW,wBAAwB;IACxC,uEAAuE;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,GAAG,CAAC;IAChC;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;IACjD,oGAAoG;IACpG,QAAQ,CAAC,QAAQ,EAAE,CAClB,OAAO,EAAE,OAAO,KACZ,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAC;IACpE,uKAAuK;IACvK,QAAQ,CAAC,OAAO,CAAC,EACd,YAAY,GACZ,CAAC,CAAC,OAAO,EAAE,OAAO,KAAK,YAAY,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC;IAChE,8GAA8G;IAC9G,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,SAAS,CAAC,CAAC;IACtD,kIAAkI;IAClI,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;IAC9B,4DAA4D;IAC5D,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACzD;AAED,MAAM,WAAW,iBAAiB;IACjC,0FAA0F;IAC1F,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;IACtD,4CAA4C;IAC5C,MAAM,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,OAAO,CAAA;KAAE,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC;CACtD;AA0HD;;;;GAIG;AACH,wBAAgB,uBAAuB,CACtC,OAAO,EAAE,wBAAwB,GAC/B,iBAAiB,CAenB"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/** The most a body, a query string or the variables may weigh, in bytes. */
|
|
2
|
+
export declare const LIMITS: {
|
|
3
|
+
readonly body: number;
|
|
4
|
+
readonly queryString: number;
|
|
5
|
+
readonly variables: number;
|
|
6
|
+
};
|
|
7
|
+
export interface Asked {
|
|
8
|
+
readonly operationName: string;
|
|
9
|
+
readonly variables?: Record<string, unknown>;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* What a client asks for: an `operationName` and its `variables`, from a
|
|
13
|
+
* GET's search params or a POST's JSON body. Any `query` or `extensions` it
|
|
14
|
+
* sends (graphql-sse always sends a `query`) is ignored.
|
|
15
|
+
*/
|
|
16
|
+
export declare function readAsked(request: Request): Promise<Asked>;
|
|
17
|
+
//# sourceMappingURL=read.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/subscription/read.ts"],"names":[],"mappings":"AAEA,4EAA4E;AAC5E,eAAO,MAAM,MAAM;;;;CAIT,CAAC;AAEX,MAAM,WAAW,KAAK;IACrB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C;AA0CD;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,CA6ChE"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** An answer the proxy gives itself, as GraphQL-shaped JSON a client can read. */
|
|
2
|
+
export declare class Refusal extends Error {
|
|
3
|
+
readonly status: number;
|
|
4
|
+
readonly code: string;
|
|
5
|
+
constructor(status: number, message: string, code: string);
|
|
6
|
+
}
|
|
7
|
+
export declare function problem(status: number, message: string, code: string, extra?: Record<string, unknown>, headers?: HeadersInit): Response;
|
|
8
|
+
export declare const refusalResponse: (refusal: Refusal) => Response;
|
|
9
|
+
/** What a non-2xx upstream answer becomes: a 429 with `retryAfter`, a 502 for a 5xx, any other 4xx as it came. */
|
|
10
|
+
export declare function refusedUpstream(upstream: Response): Promise<Response>;
|
|
11
|
+
//# sourceMappingURL=refusal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"refusal.d.ts","sourceRoot":"","sources":["../../src/subscription/refusal.ts"],"names":[],"mappings":"AAAA,kFAAkF;AAClF,qBAAa,OAAQ,SAAQ,KAAK;IAEhC,QAAQ,CAAC,MAAM,EAAE,MAAM;IAEvB,QAAQ,CAAC,IAAI,EAAE,MAAM;gBAFZ,MAAM,EAAE,MAAM,EACvB,OAAO,EAAE,MAAM,EACN,IAAI,EAAE,MAAM;CAKtB;AAED,wBAAgB,OAAO,CACtB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,EACnC,OAAO,GAAE,WAAgB,GACvB,QAAQ,CAeV;AAED,eAAO,MAAM,eAAe,GAAI,SAAS,OAAO,KAAG,QACI,CAAC;AAiBxD,kHAAkH;AAClH,wBAAsB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,CA0B3E"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/** The most one event may weigh before the stream is cut, in characters. */
|
|
2
|
+
export declare const MAX_EVENT: number;
|
|
3
|
+
export declare const SSE_HEADERS: {
|
|
4
|
+
'content-type': string;
|
|
5
|
+
'cache-control': string;
|
|
6
|
+
'x-accel-buffering': string;
|
|
7
|
+
};
|
|
8
|
+
/**
|
|
9
|
+
* Relays whole events (a heartbeat never lands inside one) until the upstream
|
|
10
|
+
* ends or the client leaves. The stream is pulled: upstream is read only when
|
|
11
|
+
* the client has taken what was queued, so a slow client holds the upstream
|
|
12
|
+
* back instead of growing a buffer, and a heartbeat is skipped while one is
|
|
13
|
+
* waiting.
|
|
14
|
+
*/
|
|
15
|
+
export declare function relay(upstream: Response, abort: AbortController, heartbeatMs: number): Response;
|
|
16
|
+
//# sourceMappingURL=relay.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay.d.ts","sourceRoot":"","sources":["../../src/subscription/relay.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,eAAO,MAAM,SAAS,QAAc,CAAC;AAKrC,eAAO,MAAM,WAAW;;;;CAIvB,CAAC;AAKF;;;;;;GAMG;AACH,wBAAgB,KAAK,CACpB,QAAQ,EAAE,QAAQ,EAClB,KAAK,EAAE,eAAe,EACtB,WAAW,EAAE,MAAM,GACjB,QAAQ,CAwDV"}
|
package/dist/vite/index.js.map
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
"import { NAME } from './entry';\n\n/**\n * Refuses, with what to do, a dev or preview server running on Node. The\n * React Router CLI's `#!/usr/bin/env node` runs it on Node whenever a node\n * is installed, even from `bun run dev`, and alxia's server then fails on\n * its first request with `ReferenceError: Bun is not defined`.\n */\nexport function requireBun(\n\tcommand: string,\n\thint = `bun --bun ${command}`,\n\tonBun = (globalThis as { Bun?: unknown }).Bun !== undefined,\n\treason = \"and alxia's server runs on Bun\",\n): void {\n\tif (onBun) return;\n\tthrow new Error(\n\t\t`${NAME}: ${command} is running on Node, ${reason}. Add a bunfig.toml beside package.json with \"[run]\" and \"bun = true\", so bun run starts it on Bun, or run it as ${hint}.`,\n\t);\n}\n",
|
|
15
15
|
"/**\n * The service worker, built by `alxia()` once React Router has built the\n * client: `app/service-worker.ts` is the opt-in, as `app/server.ts` is.\n */\nimport { existsSync } from 'node:fs';\nimport { basename, isAbsolute, join, resolve } from 'node:path';\nimport type { ResolvedConfig } from 'vite';\nimport { type BuildWorkerOptions, buildWorker } from '../pwa/build';\nimport { contextOf } from './config';\nimport { NAME } from './entry';\nimport type { AlxiaOptions } from './index';\nimport { requireBun } from './runtime';\n\n/** `buildWorker()`'s options but where: the plugin knows the root, the client build and, by default, the file. */\nexport type AlxiaWorkerOptions = Omit<\n\tBuildWorkerOptions,\n\t'root' | 'client' | 'file'\n> & { readonly file?: string };\n\n/**\n * The worker's source, absolute, or `undefined` when there is none to\n * build: `worker: false`, or no `app/service-worker.ts` and no named file.\n * Throws when a named file does not exist.\n */\nexport function workerFile(\n\toption: AlxiaOptions['worker'],\n\tconfig: ResolvedConfig,\n): string | undefined {\n\tif (option === false) return undefined;\n\tconst named = typeof option === 'string' ? option : option?.file;\n\tif (named !== undefined) {\n\t\tconst file = isAbsolute(named) ? named : resolve(config.root, named);\n\t\tif (!existsSync(file)) {\n\t\t\tthrow new Error(\n\t\t\t\t`${NAME}: the worker ${named} does not exist. Create it, or leave worker out to build app/service-worker.ts when it exists.`,\n\t\t\t);\n\t\t}\n\t\treturn file;\n\t}\n\tconst file = join(contextOf(config).appDirectory, 'service-worker.ts');\n\treturn existsSync(file) ? file : undefined;\n}\n\nconst MB = (bytes: number) => (bytes / 1024 / 1024).toFixed(2);\nconst KB = (bytes: number) => (bytes / 1024).toFixed(1);\n\n/** Builds the worker into `build/client`, if the app has one. */\nexport async function buildAppWorker(\n\tconfig: ResolvedConfig,\n\toption: AlxiaOptions['worker'],\n): Promise<void> {\n\tconst file = workerFile(option, config);\n\tif (file === undefined) return;\n\trequireBun(\n\t\t'react-router build with a service worker',\n\t\t'bun --bun react-router build',\n\t\tundefined,\n\t\t'and the worker is bundled by Bun.build',\n\t);\n\tconst rest = typeof option === 'object' ? option : {};\n\tconst built = await buildWorker({\n\t\t...rest,\n\t\tfile,\n\t\troot: config.root,\n\t\tclient: join(contextOf(config).buildDirectory, 'client'),\n\t}).catch((error: unknown) => {\n\t\tthrow new Error(`${NAME}: ${(error as Error).message}`, { cause: error });\n\t});\n\tconfig.logger.info(\n\t\t`✓ ${basename(built.file)}: ${built.precache.length} files precached (${MB(built.precacheBytes)} MB), worker ${KB(built.bytes)} kB`,\n\t);\n}\n"
|
|
16
16
|
],
|
|
17
|
-
"mappings": "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",
|
|
17
|
+
"mappings": "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",
|
|
18
18
|
"debugId": "7F0E7AC67885D01F64756E2164756E21",
|
|
19
19
|
"names": []
|
|
20
20
|
}
|
package/docs/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
The [package README](../README.md) is the short version. This folder is
|
|
4
4
|
the long one: the setup, the Vite plugin and its default server, the build for Bun,
|
|
5
5
|
customising the server, the typed context, the client's files, making the app
|
|
6
|
-
installable and usable offline, wording an API's refusals, and what to do with each message.
|
|
6
|
+
installable and usable offline, wording an API's refusals, the BFF session, a GraphQL subscription relayed to the browser (`/subscription`), and what to do with each message.
|
|
7
7
|
|
|
8
8
|
| Page | Read it when |
|
|
9
9
|
| --- | --- |
|
|
@@ -20,6 +20,7 @@ installable and usable offline, wording an API's refusals, and what to do with e
|
|
|
20
20
|
| [Installable and offline](guide/pwa.md) | making the app installable and usable offline: the subpaths of `@alxia/react-router/pwa`, the service worker (`startWorker`, `/pwa/worker`), its build by `alxia()` or `buildWorker` (`/pwa/build`), its contract and cache names, which requests the worker caches and which responses it stores, the precache list read from a build, or clearing the caches at sign-out |
|
|
21
21
|
| [An API's refusals](guide/errors.md) | wording a GraphQL API's refusals for the pages: recognising an `ApiError`, the request id, the page a request is for, the catalogue store, the form checks in the API's words, the provider, and the loaders, the error page and the actions that answer with it, the JSON actions with their CSRF check and fetcher hook, calling the API from a loader (`apiCallFailure`), and keeping the catalogue fresh (`@alxia/react-router/errors`) |
|
|
22
22
|
| [A BFF session](guide/session.md) | redirecting after sign-in to a page of the site and nowhere else, the sign-in pages' paths, the session's cookies, the sign-in flow (where an answer lands, a refused code, the viewer, sign-out; `@alxia/react-router/session`), the pages a mail's link opens (a magic link, a password reset: `authLinks`), the page's hooks (sign-out, a mail link's parameter, a one-code field; `@alxia/react-router/session/react`), and the step-up's state and the props it gives the UI (`@alxia/react-router/session/model`) |
|
|
23
|
+
| [Subscriptions for a BFF](guide/subscriptions.md) | showing a GraphQL subscription in the browser without giving it the API's token or a way to write a document: a resource route with a map of operation names to the server's documents, the same-site check, the bearer from the session, extra upstream headers, a heartbeat, abort propagation, size limits and a 429 passed through with `retryAfter` (`@alxia/react-router/subscription`) |
|
|
23
24
|
| [Troubleshooting](troubleshooting.md) | something went wrong and you have the message, or a page streams, hydrates or reads its context unlike you expected |
|
|
24
25
|
| [Roadmap](roadmap.md) | wondering what is coming, and what is not planned |
|
|
25
26
|
|
package/docs/guide/session.md
CHANGED
|
@@ -992,7 +992,7 @@ const { signOut } = useSignOut({
|
|
|
992
992
|
### `useLinkParam`
|
|
993
993
|
|
|
994
994
|
Reads the query parameter a mail's link carries, once: the first render's value
|
|
995
|
-
is kept for the page's life. With `drop: true` the parameter is then removed
|
|
995
|
+
is kept for the page's life (unless `live: true`, below). With `drop: true` the parameter is then removed
|
|
996
996
|
from the address bar (`history.replaceState`, keeping the history state and the
|
|
997
997
|
hash), so a token is not left in the history, a bookmark or a screenshot. It is
|
|
998
998
|
`null` when the parameter is absent or empty.
|
|
@@ -1017,6 +1017,23 @@ The router's own location is not updated by `replaceState`: a loader or
|
|
|
1017
1017
|
`useSearchParams` elsewhere still sees the token until the next navigation.
|
|
1018
1018
|
Read it with the hook once, and pass it down.
|
|
1019
1019
|
|
|
1020
|
+
#### `live: true`: a parameter set after the page mounted
|
|
1021
|
+
|
|
1022
|
+
By default the value is read once. A route that stays mounted while an action
|
|
1023
|
+
redirects back to it with a new parameter (`/settings` to
|
|
1024
|
+
`/settings?state=linked`) never sees it. `live: true` follows the URL: the
|
|
1025
|
+
value is the parameter of the current location, and each new location is read
|
|
1026
|
+
again.
|
|
1027
|
+
|
|
1028
|
+
```tsx
|
|
1029
|
+
const state = useLinkParam('state', { live: true }); // 'linked' | 'invalid' | null
|
|
1030
|
+
```
|
|
1031
|
+
|
|
1032
|
+
With `drop: true` too, the value is kept after the address bar loses the
|
|
1033
|
+
parameter, until a location carries a new one: a navigation that has no such
|
|
1034
|
+
parameter does not clear it, since the drop removed it. Without `drop` the
|
|
1035
|
+
value is exactly the current location's parameter, `null` when it is gone.
|
|
1036
|
+
|
|
1020
1037
|
### `useCodeField` and `useOnRefusal`
|
|
1021
1038
|
|
|
1022
1039
|
A form that asks for one code (an authenticator app's, a recovery code) and
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
# Subscriptions for a BFF
|
|
2
|
+
|
|
3
|
+
This page is for a React Router app that is the backend of its own pages (a
|
|
4
|
+
BFF) and wants to show a GraphQL subscription in the browser: a room's
|
|
5
|
+
events, a chat, a live counter. The browser must not hold the API's token and
|
|
6
|
+
must not be able to send the API a document of its own, so the app exposes
|
|
7
|
+
**one resource route** that checks the user's session, looks the operation up
|
|
8
|
+
in a list the server holds, and relays the API's server-sent events.
|
|
9
|
+
|
|
10
|
+
`@alxia/react-router/subscription` is that route. It imports nothing (web APIs only), so it adds no peer.
|
|
11
|
+
|
|
12
|
+
## Expose a subscription
|
|
13
|
+
|
|
14
|
+
`allow` maps each operation name to the **document the server sends for it**.
|
|
15
|
+
Build the map from your codegen's documents, so the text is the one your
|
|
16
|
+
client was generated from:
|
|
17
|
+
|
|
18
|
+
```ts
|
|
19
|
+
// app/routes/events.ts: a resource route, served at /events
|
|
20
|
+
import { createSubscriptionProxy } from '@alxia/react-router/subscription';
|
|
21
|
+
import { print } from 'graphql';
|
|
22
|
+
import { ChatMessagesDocument, RoomEventsDocument } from '../generated/graphql';
|
|
23
|
+
import { cookies } from '../session.server';
|
|
24
|
+
|
|
25
|
+
const events = createSubscriptionProxy({
|
|
26
|
+
endpoint: 'https://api.example.com/graphql',
|
|
27
|
+
allow: {
|
|
28
|
+
RoomEvents: print(RoomEventsDocument), // a TypedDocumentNode
|
|
29
|
+
ChatMessages: print(ChatMessagesDocument),
|
|
30
|
+
// or the document string codegen exports, or a literal
|
|
31
|
+
},
|
|
32
|
+
getToken: (request) => cookies.token(request),
|
|
33
|
+
headers: (request) => ({
|
|
34
|
+
'x-client-name': 'my-bff',
|
|
35
|
+
'x-proxy-secret': process.env.PROXY_SECRET,
|
|
36
|
+
'x-forwarded-for': request.headers.get('x-forwarded-for'),
|
|
37
|
+
'accept-language': request.headers.get('accept-language'),
|
|
38
|
+
}),
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
export const loader = events.loader; // GET: operationName and variables in the query string
|
|
42
|
+
export const action = events.action; // POST: the same in a JSON body
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// app/routes.ts
|
|
47
|
+
import { route, type RouteConfig } from '@react-router/dev/routes';
|
|
48
|
+
|
|
49
|
+
export default [route('events', 'routes/events.ts')] satisfies RouteConfig;
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
The browser talks to `/events` with a client that speaks GraphQL over SSE in
|
|
53
|
+
its distinct connections mode, such as `graphql-sse`. It names the operation
|
|
54
|
+
and sends its variables; the `query` it sends, as `graphql-sse` always does,
|
|
55
|
+
is **ignored**:
|
|
56
|
+
|
|
57
|
+
```ts
|
|
58
|
+
import { createClient } from 'graphql-sse';
|
|
59
|
+
|
|
60
|
+
const client = createClient({ url: '/events', singleConnection: false });
|
|
61
|
+
|
|
62
|
+
const dispose = client.subscribe(
|
|
63
|
+
{
|
|
64
|
+
query: 'subscription RoomEvents($id: ID!) { roomEvents(id: $id) { id kind } }',
|
|
65
|
+
operationName: 'RoomEvents',
|
|
66
|
+
variables: { id: roomId },
|
|
67
|
+
},
|
|
68
|
+
{ next: show, error: report, complete: () => {} },
|
|
69
|
+
);
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
`graphql-sse` sends a POST by default and a GET for `method: 'GET'`; both
|
|
73
|
+
work, each through the matching export.
|
|
74
|
+
|
|
75
|
+
## What the proxy does
|
|
76
|
+
|
|
77
|
+
| Step | Rule |
|
|
78
|
+
| --- | --- |
|
|
79
|
+
| Same site | Both methods run the rule of `jsonActions`: an `Origin` that is not the app's own, or a `Sec-Fetch-Site` other than `same-origin` or `none`, is a **403** (`origin` sets the app's origin; the request's own by default). It reads headers only. A POST must be `application/json`, else **415**. |
|
|
80
|
+
| Session | `getToken(request)` gives the token, read on the server from the HttpOnly cookie. Empty, `null`, `undefined` or a token holding a line break is a **401**; nothing goes upstream. |
|
|
81
|
+
| Request | The client's `operationName` and `variables` are read. A body that cannot be read (the client left) is a **400**; a body past 64 KiB (`Content-Length` first, then the bytes read), a query string past 16 KiB or `variables` past 16 KiB is a **400**, as is malformed input. Its `query` and `extensions` are ignored. |
|
|
82
|
+
| Allow-list | Each document of `allow` must define `subscription <key>` and no other operation (fragments are fine), or `createSubscriptionProxy` throws a `TypeError` when it is created. `operationName` must be a key of `allow`, else **403**. The proxy sends **its own document** for it, with the client's variables: no document, fragment, extension or persisted id of the client's reaches the API. |
|
|
83
|
+
| Upstream request | A `POST` to `endpoint` with `Accept: text/event-stream`, `Authorization: Bearer <token>` and your `headers`. The browser's own headers and cookies are never forwarded. A header name or value no header can hold (a line break) is a worded **500**. |
|
|
84
|
+
| Relay | Whole events are relayed in order, as the client takes them: a slow client holds the upstream back instead of growing a buffer, and a heartbeat is skipped while one is waiting. A heartbeat comment (`:`) goes out every `heartbeatMs` (15000 by default, `0` turns it off), never inside an event. An event of more than 1 MiB with no end cuts the stream with an `UPSTREAM_ERROR`. |
|
|
85
|
+
| End | The upstream's `complete`, or the end of its stream, closes the client's stream. A stream that breaks sends a `next` with an `UPSTREAM_ERROR` and a `complete`. |
|
|
86
|
+
| Abort | When the browser closes the request, the upstream request is aborted: no subscription is left running. A request that is already aborted never starts one. |
|
|
87
|
+
| Rate limit | An upstream **429** is passed through with `Retry-After` and `retryAfter` in the body (`{ "retryAfter": 12, "errors": [{ "extensions": { "code": "RATE_LIMITED", "retryAfter": 12 } }] }`), read from the upstream's header or body. The proxy never retries. |
|
|
88
|
+
| Other failures | An upstream 5xx, an unreachable API or an answer that is not an event stream is a **502** (`UPSTREAM_ERROR`); an upstream 4xx such as a 401 passes through. |
|
|
89
|
+
|
|
90
|
+
The stream is answered with `Content-Type: text/event-stream`,
|
|
91
|
+
`Cache-Control: no-store, no-transform` and `X-Accel-Buffering: no`, so no
|
|
92
|
+
adapter or reverse proxy needs to buffer it.
|
|
93
|
+
|
|
94
|
+
## Options
|
|
95
|
+
|
|
96
|
+
| Option | |
|
|
97
|
+
| --- | --- |
|
|
98
|
+
| `endpoint` | the API's GraphQL URL (required) |
|
|
99
|
+
| `allow` | operation name to the document sent upstream (required); each document must define `subscription <name>`, that operation alone, checked when the proxy is created |
|
|
100
|
+
| `getToken(request)` | the session's token, sync or async (required) |
|
|
101
|
+
| `headers` | a record, `Headers`, or `(request) => record`; a `null` or `undefined` value is left out |
|
|
102
|
+
| `origin` | the app's origin for the same-site check, a string or a getter; the request's own by default |
|
|
103
|
+
| `heartbeatMs` | 15000 |
|
|
104
|
+
| `fetch` | the `fetch` used upstream (the global one); useful in specs |
|
|
105
|
+
|
|
106
|
+
## Keep the stream alive
|
|
107
|
+
|
|
108
|
+
Bun closes an idle connection after `idleTimeout` seconds (10 by default).
|
|
109
|
+
The heartbeat covers it as long as `heartbeatMs` is shorter, and so is a proxy's
|
|
110
|
+
read timeout. Behind nginx, keep `proxy_buffering off` for the route (the
|
|
111
|
+
`X-Accel-Buffering: no` header does it per response).
|
|
112
|
+
|
|
113
|
+
## Cross-site requests
|
|
114
|
+
|
|
115
|
+
Both methods refuse a request from another site (the rule above), and the
|
|
116
|
+
session cookie should stay `SameSite=Lax` (`sessionCookies` does it). The
|
|
117
|
+
allow-list is what the browser may start; because the documents are the
|
|
118
|
+
server's, it cannot start anything else, a mutation included. The route does
|
|
119
|
+
not stop a signed-in user from starting an allowed subscription as often as
|
|
120
|
+
they like: rate-limit it (`@alxia/rate-limit`) if the API does not.
|
|
121
|
+
|
|
122
|
+
## Testing
|
|
123
|
+
|
|
124
|
+
Give the proxy a fake API through `fetch`, or start a `Bun.serve` that
|
|
125
|
+
answers with an event stream, and call `events.action({ request })`; the
|
|
126
|
+
answer is a plain `Response`.
|
package/docs/roadmap.md
CHANGED
|
@@ -8,12 +8,20 @@ number on it. Every release, with each change it made, is in
|
|
|
8
8
|
## Now
|
|
9
9
|
|
|
10
10
|
- **`@alxia/react-router/session/react`: the page's hooks around the session
|
|
11
|
-
flows.** `useSignOut`, `useLinkParam` (a mail link's parameter, read once and
|
|
12
|
-
|
|
11
|
+
flows.** `useSignOut`, `useLinkParam` (a mail link's parameter, read once and optionally dropped
|
|
12
|
+
from the address bar, or with `live: true` following the URL) and `useCodeField` /
|
|
13
13
|
`useOnRefusal` (a one-code field that clears and refocuses on each refusal),
|
|
14
14
|
so an app stops carrying its own copies. See the
|
|
15
15
|
[session guide](guide/session.md#the-pages-hooks).
|
|
16
16
|
|
|
17
|
+
- **`@alxia/react-router/subscription`: GraphQL subscriptions for the
|
|
18
|
+
browser of a BFF.** `createSubscriptionProxy` gives a resource route's
|
|
19
|
+
`loader` and `action` that relay a subscription over SSE: the server holds
|
|
20
|
+
each allowed document, the bearer comes from the session, the route refuses
|
|
21
|
+
cross-site requests, keeps the stream alive with a heartbeat, aborts the
|
|
22
|
+
upstream with the client and passes a 429 on with `retryAfter`. See the
|
|
23
|
+
[subscriptions guide](guide/subscriptions.md).
|
|
24
|
+
|
|
17
25
|
## Next
|
|
18
26
|
|
|
19
27
|
Nothing planned.
|
package/docs/troubleshooting.md
CHANGED
|
@@ -2714,3 +2714,112 @@ import { TOKEN_PAGE_HEADERS } from '@alxia/react-router/session';
|
|
|
2714
2714
|
|
|
2715
2715
|
export const headers = () => TOKEN_PAGE_HEADERS;
|
|
2716
2716
|
```
|
|
2717
|
+
|
|
2718
|
+
### A subscription answers 401
|
|
2719
|
+
|
|
2720
|
+
`{"errors":[{"message":"Sign in to continue.","extensions":{"code":"UNAUTHENTICATED"}}]}`
|
|
2721
|
+
|
|
2722
|
+
**Why:** `getToken(request)` returned `null`, `undefined`, `''` or a token with a
|
|
2723
|
+
line break: the browser sent no session cookie (signed out, expired, or a
|
|
2724
|
+
cross-site request with a `SameSite=Lax` cookie), or `getToken` reads another
|
|
2725
|
+
cookie than the one the sign-in wrote.
|
|
2726
|
+
|
|
2727
|
+
**Fix:** return the token the loaders use, and send the cookie with the request
|
|
2728
|
+
(`credentials: 'include'` for a cross-origin client):
|
|
2729
|
+
|
|
2730
|
+
```ts
|
|
2731
|
+
getToken: (request) => cookies.token(request),
|
|
2732
|
+
```
|
|
2733
|
+
|
|
2734
|
+
### A subscription answers 403 `This operation is not allowed.`
|
|
2735
|
+
|
|
2736
|
+
**Why:** `operationName` is not a key of `allow`. The proxy runs only the
|
|
2737
|
+
documents the server holds; a `query` the client sends is ignored.
|
|
2738
|
+
|
|
2739
|
+
**Fix:** list the name with its document, and send that name:
|
|
2740
|
+
|
|
2741
|
+
```ts
|
|
2742
|
+
createSubscriptionProxy({ endpoint, allow: { RoomEvents: document }, getToken });
|
|
2743
|
+
```
|
|
2744
|
+
|
|
2745
|
+
### A subscription answers 403 `Cross-site request refused.`
|
|
2746
|
+
|
|
2747
|
+
**Why:** the request's `Origin` is not the app's own, or its `Sec-Fetch-Site` is
|
|
2748
|
+
`cross-site`, or `same-site` (another subdomain of the same site: only `same-origin` and `none` pass). Behind a TLS-terminating proxy
|
|
2749
|
+
the request's own origin can read `http://`.
|
|
2750
|
+
|
|
2751
|
+
**Fix:** call the route from the app's own pages, or give the proxy the public
|
|
2752
|
+
origin:
|
|
2753
|
+
|
|
2754
|
+
```ts
|
|
2755
|
+
createSubscriptionProxy({ endpoint, allow, getToken, origin: 'https://app.example.com' });
|
|
2756
|
+
```
|
|
2757
|
+
|
|
2758
|
+
### A subscription answers 415 `Send the request as application/json.`
|
|
2759
|
+
|
|
2760
|
+
**Why:** a POST with another `Content-Type`, or none.
|
|
2761
|
+
|
|
2762
|
+
**Fix:** send `Content-Type: application/json` (`graphql-sse` does), or use GET.
|
|
2763
|
+
|
|
2764
|
+
### A subscription answers 400 `The request is too large.`
|
|
2765
|
+
|
|
2766
|
+
**Why:** the body is over 64 KiB, the query string over 16 KiB, or `variables`
|
|
2767
|
+
over 16 KiB.
|
|
2768
|
+
|
|
2769
|
+
**Fix:** send less in `variables`; a document does not belong in the request,
|
|
2770
|
+
the server holds it.
|
|
2771
|
+
|
|
2772
|
+
### A subscription answers 400 `The request is not valid JSON.`
|
|
2773
|
+
|
|
2774
|
+
**Why:** the POST body, or the `variables` parameter of a GET, is not JSON.
|
|
2775
|
+
|
|
2776
|
+
**Fix:** send `JSON.stringify({ operationName, variables })`, and `variables`
|
|
2777
|
+
JSON-encoded in a GET.
|
|
2778
|
+
|
|
2779
|
+
### A subscription answers 400 `The request must be a JSON object.`, `Send an "operationName".`, `"operationName" must be a string.` or `"variables" must be an object.`
|
|
2780
|
+
|
|
2781
|
+
**Why:** the body is an array or a scalar, `operationName` is missing or not a
|
|
2782
|
+
string, or `variables` is not an object.
|
|
2783
|
+
|
|
2784
|
+
**Fix:** send `{ "operationName": "RoomEvents", "variables": { … } }`.
|
|
2785
|
+
|
|
2786
|
+
### A subscription answers 500 `The proxy's upstream headers are not valid …`
|
|
2787
|
+
|
|
2788
|
+
**Why:** a value of `headers` (a forwarded `Accept-Language`, a secret from the
|
|
2789
|
+
environment) holds a line break, or a name is not a header name.
|
|
2790
|
+
|
|
2791
|
+
**Fix:** trim or validate the value before it goes in `headers`.
|
|
2792
|
+
|
|
2793
|
+
### A subscription answers 429 with `retryAfter`
|
|
2794
|
+
|
|
2795
|
+
The API's rate limit answered. The proxy passes it on and never retries.
|
|
2796
|
+
|
|
2797
|
+
**Fix:** have the client wait `Retry-After` seconds (also `retryAfter` in the
|
|
2798
|
+
body) before it subscribes again.
|
|
2799
|
+
|
|
2800
|
+
### A subscription answers 502
|
|
2801
|
+
|
|
2802
|
+
**Why:** the API is unreachable, answered 5xx, or answered something that is
|
|
2803
|
+
not `text/event-stream` (a proxy in front of it, or a wrong `endpoint`).
|
|
2804
|
+
|
|
2805
|
+
**Fix:** post the document to the `endpoint` by hand with the same headers; it
|
|
2806
|
+
must answer with `Content-Type: text/event-stream`.
|
|
2807
|
+
|
|
2808
|
+
### The stream ends with `The API stream failed.`
|
|
2809
|
+
|
|
2810
|
+
**Why:** the upstream stream broke, or sent an event of more than 1 MiB with
|
|
2811
|
+
no blank line ending it.
|
|
2812
|
+
|
|
2813
|
+
**Fix:** read the API's logs; a subscription's events are small and end with a
|
|
2814
|
+
blank line.
|
|
2815
|
+
|
|
2816
|
+
### Events arrive in bursts, or the stream closes after a few seconds
|
|
2817
|
+
|
|
2818
|
+
**Why:** a proxy or CDN between the app and the browser buffers the response,
|
|
2819
|
+
or closes an idle connection (Bun's `idleTimeout`, a load balancer's timeout)
|
|
2820
|
+
because `heartbeatMs` is longer than it.
|
|
2821
|
+
|
|
2822
|
+
**Fix:** keep `heartbeatMs` shorter than the shortest idle timeout on the
|
|
2823
|
+
path, turn response buffering off for the route (nginx `proxy_buffering off`;
|
|
2824
|
+
the route already sends `X-Accel-Buffering: no`), and do not compress the
|
|
2825
|
+
route's responses.
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alxia/react-router",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "alxia as the server of a React Router framework app: server rendering behind the app's hooks, loaders reading its typed context, the client's assets served; the code with no UI an installable app shares (`/pwa`), its hooks (`/pwa/react`), `noCache` for the worker's script (`/pwa/server`), the service worker on Workbox (`/pwa/worker`) and its build (`/pwa/build`), an API's refusals worded for the page (`/errors`), the BFF session: cookies, sign-in, step-up and mail links (`/session`), its page hooks (`/session/react`) and what it shares with the page (`/session/model`), the page's CSP nonce and inline boot scripts (`/document`) and a streaming `entry.server` (`/entry`)",
|
|
3
|
+
"version": "0.19.0",
|
|
4
|
+
"description": "alxia as the server of a React Router framework app: server rendering behind the app's hooks, loaders reading its typed context, the client's assets served; the code with no UI an installable app shares (`/pwa`), its hooks (`/pwa/react`), `noCache` for the worker's script (`/pwa/server`), the service worker on Workbox (`/pwa/worker`) and its build (`/pwa/build`), an API's refusals worded for the page (`/errors`), the BFF session: cookies, sign-in, step-up and mail links (`/session`), its page hooks (`/session/react`) and what it shares with the page (`/session/model`), a GraphQL subscription relayed to the browser over SSE (`/subscription`), the page's CSP nonce and inline boot scripts (`/document`) and a streaming `entry.server` (`/entry`)",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./dist/index.js",
|
|
@@ -82,6 +82,11 @@
|
|
|
82
82
|
"import": "./dist/session/model/index.js",
|
|
83
83
|
"default": "./dist/session/model/index.js"
|
|
84
84
|
},
|
|
85
|
+
"./subscription": {
|
|
86
|
+
"types": "./dist/subscription/index.d.ts",
|
|
87
|
+
"import": "./dist/subscription/index.js",
|
|
88
|
+
"default": "./dist/subscription/index.js"
|
|
89
|
+
},
|
|
85
90
|
"./package.json": "./package.json"
|
|
86
91
|
},
|
|
87
92
|
"repository": {
|
|
@@ -109,6 +114,7 @@
|
|
|
109
114
|
"src/session/model/index.ts",
|
|
110
115
|
"src/session/index.ts",
|
|
111
116
|
"src/session/react/index.ts",
|
|
117
|
+
"src/subscription/index.ts",
|
|
112
118
|
"src/document/index.ts",
|
|
113
119
|
"src/entry/index.ts",
|
|
114
120
|
"src/pwa/worker/index.ts",
|
|
@@ -123,7 +129,7 @@
|
|
|
123
129
|
"@nxgt/graphql-client": "^0.4.0",
|
|
124
130
|
"@nxgt/janus": "^0.29.0",
|
|
125
131
|
"@react-router/dev": "^8.5.0",
|
|
126
|
-
"@types/bun": "^1.4.
|
|
132
|
+
"@types/bun": "^1.4.4",
|
|
127
133
|
"@types/react": "^19.3.0",
|
|
128
134
|
"@types/react-dom": "^19.3.0",
|
|
129
135
|
"graphql": "^17.0.2",
|