From 1765fa070489d3928c8f539a710685bc416197c0 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Mon, 11 May 2026 20:07:27 +0530 Subject: [PATCH 1/4] fix: issues in api request viewer: --- .../SnippetViewer/ExecuteApiRequestViewer.tsx | 146 ++++++++++++++---- 1 file changed, 115 insertions(+), 31 deletions(-) diff --git a/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx b/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx index 8354f8352d..1072af2e2d 100644 --- a/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx +++ b/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx @@ -268,8 +268,32 @@ ${parts.join('\n')} return code; } + case SupportedLanguage.CURL: { + let url = `$FGA_API_URL${path}`; + if (pathParams) { + for (const [k, v] of Object.entries(pathParams)) { + url = url.split(`{${k}}`).join(v); + } + } + if (queryParams && Object.keys(queryParams).length > 0) { + const qs = Object.entries(queryParams) + .map(([k, v]) => `${k}=${v}`) + .join('&'); + url += `?${qs}`; + } + let code = `curl -X ${method} '${url}' \\\n`; + code += ` -H 'Content-Type: application/json' \\\n`; + code += ` -H 'Authorization: Bearer $FGA_BEARER_TOKEN'`; + if (body) { + code += ` \\\n -d '${JSON.stringify(body, null, 2)}'`; + } + if (responseExample) { + code += `\n\n# Response: ${responseExample}`; + } + return code; + } + case SupportedLanguage.CLI: - case SupportedLanguage.CURL: case SupportedLanguage.RPC: case SupportedLanguage.PLAYGROUND: return `# API Executor is only available through the SDKs`; @@ -285,6 +309,7 @@ export function ExecuteApiRequestViewer(opts: ExecuteApiRequestViewerOpts): JSX. SupportedLanguage.DOTNET_SDK, SupportedLanguage.PYTHON_SDK, SupportedLanguage.JAVA_SDK, + SupportedLanguage.CURL, ]; const allowedLanguages = getFilteredAllowedLangs(opts.allowedLanguages, defaultLangs); return defaultOperationsViewer(allowedLanguages, opts, executeApiRequestViewer); @@ -294,20 +319,16 @@ export function ExecuteApiRequestViewer(opts: ExecuteApiRequestViewerOpts): JSX. // 2. ExecuteApiRequestStreamingViewer – configurable streaming request // --------------------------------------------------------------------------- -interface ExecuteApiRequestStreamingViewerOpts extends ExecuteApiRequestViewerOpts { - /** Field name to extract from each streamed result, e.g. "object". */ - responseField?: string; -} +interface ExecuteApiRequestStreamingViewerOpts extends ExecuteApiRequestViewerOpts {} function executeApiRequestStreamingViewer(lang: SupportedLanguage, opts: ExecuteApiRequestStreamingViewerOpts): string { - const { operationName, path, pathParams, body, responseField } = opts; - const field = responseField || 'object'; + const { operationName, method, path, pathParams, body, queryParams } = opts; switch (lang) { case SupportedLanguage.JS_SDK: { const parts: string[] = []; parts.push(` operationName: "${operationName}",`); - parts.push(` method: "POST",`); + parts.push(` method: "${method}",`); parts.push(` path: "${path}",`); if (pathParams && Object.keys(pathParams).length > 0) { const entries = Object.entries(pathParams) @@ -315,47 +336,71 @@ function executeApiRequestStreamingViewer(lang: SupportedLanguage, opts: Execute .join(', '); parts.push(` pathParams: { ${entries} },`); } - parts.push(` body: ${jsValue(body, 4)},`); + if (body) { + parts.push(` body: ${jsValue(body, 4)},`); + } + if (queryParams && Object.keys(queryParams).length > 0) { + const entries = Object.entries(queryParams) + .map(([k, v]) => `${k}: "${v}"`) + .join(', '); + parts.push(` queryParams: { ${entries} },`); + } return `for await (const chunk of fgaClient.executeStreamedApiRequest({ ${parts.join('\n')} })) { - if (chunk.result) { - console.log(chunk.result.${field}); - } + console.log(chunk); }`; } case SupportedLanguage.GO_SDK: { - let code = `requestBody := ${goValue(body, 8)}\n\n`; + let code = ''; + if (body) { + code += `requestBody := ${goValue(body, 8)}\n\n`; + } code += `request := openfga.NewAPIExecutorRequestBuilder(\n`; - code += ` "${operationName}", http.MethodPost, "${path}",\n)`; + code += ` "${operationName}", ${goMethod(method)}, "${path}",\n)`; if (pathParams) { for (const [k, v] of Object.entries(pathParams)) { code += `.\n WithPathParameter("${k}", "${v}")`; } } - code += `.\n WithBody(requestBody).\n Build()\n\n`; + if (queryParams) { + for (const [k, v] of Object.entries(queryParams)) { + code += `.\n WithQueryParameter("${k}", "${v}")`; + } + } + if (body) { + code += `.\n WithBody(requestBody)`; + } + code += `.\n Build()\n\n`; code += `channel, err := executor.ExecuteStreaming(ctx, request, openfga.DefaultStreamBufferSize)\n`; code += `if err != nil {\n log.Fatalf("Streaming request failed: %v", err)\n}\ndefer channel.Close()\n\n`; code += `for {\n select {\n case result, ok := <-channel.Results:\n if !ok {\n return\n }\n`; - code += ` var obj map[string]interface{}\n json.Unmarshal(result, &obj)\n`; - code += ` fmt.Println(obj["${field}"])\n`; + code += ` fmt.Println(string(result))\n`; code += ` case err := <-channel.Errors:\n if err != nil {\n log.Fatalf("Stream error: %v", err)\n }\n }\n}`; return code; } case SupportedLanguage.DOTNET_SDK: { let code = `var request = RequestBuilder\n`; - code += ` .Create(HttpMethod.Post, configuration.ApiUrl, "${path}")`; + code += ` .Create(${csharpMethod(method)}, configuration.ApiUrl, "${path}")`; if (pathParams) { for (const [k, v] of Object.entries(pathParams)) { code += `\n .WithPathParameter("${k}", "${v}")`; } } - code += `\n .WithBody(${csharpValue(body, 8)});\n\n`; - code += `await foreach (var item in executor.ExecuteStreamingAsync(\n`; + if (queryParams) { + for (const [k, v] of Object.entries(queryParams)) { + code += `\n .WithQueryParameter("${k}", "${v}")`; + } + } + if (body) { + code += `\n .WithBody(${csharpValue(body, 8)})`; + } + code += `;\n\n`; + code += `await foreach (var item in executor.ExecuteStreamingAsync>(\n`; code += ` request, "${operationName}"))\n{\n`; - code += ` Console.WriteLine(item.${field.charAt(0).toUpperCase() + field.slice(1)});`; + code += ` Console.WriteLine(item);`; code += `\n}`; return code; } @@ -363,7 +408,7 @@ ${parts.join('\n')} case SupportedLanguage.PYTHON_SDK: { const parts: string[] = []; parts.push(` operation_name="${operationName}",`); - parts.push(` method="POST",`); + parts.push(` method="${method}",`); parts.push(` path="${path}",`); if (pathParams && Object.keys(pathParams).length > 0) { const entries = Object.entries(pathParams) @@ -371,36 +416,74 @@ ${parts.join('\n')} .join(', '); parts.push(` path_params={${entries}},`); } - parts.push(` body=${pyValue(body, 8)},`); + if (body) { + parts.push(` body=${pyValue(body, 8)},`); + } + if (queryParams && Object.keys(queryParams).length > 0) { + const entries = Object.entries(queryParams) + .map(([k, v]) => `"${k}": "${v}"`) + .join(', '); + parts.push(` query_params={${entries}},`); + } return `async for chunk in fga_client.execute_streamed_api_request( ${parts.join('\n')} ): - if "result" in chunk: - print(chunk["result"]["${field}"])`; + print(chunk)`; } case SupportedLanguage.JAVA_SDK: { let code = ''; - code += `Map requestBody = ${javaValue(body, 8)};\n\n`; + if (body) { + code += `Map requestBody = ${javaValue(body, 8)};\n\n`; + } code += `var request = ApiExecutorRequestBuilder.builder(\n`; - code += ` HttpMethod.POST, "${path}"\n)`; + code += ` ${javaMethod(method)}, "${path}"\n)`; if (pathParams) { for (const [k, v] of Object.entries(pathParams)) { code += `\n .pathParam("${k}", "${v}")`; } } - code += `\n .body(requestBody)\n .build();\n\n`; - code += `fgaClient.streamingApiExecutor(StreamedListObjectsResponse.class)\n`; + if (queryParams) { + for (const [k, v] of Object.entries(queryParams)) { + code += `\n .queryParam("${k}", "${v}")`; + } + } + if (body) { + code += `\n .body(requestBody)`; + } + code += `\n .build();\n\n`; + code += `fgaClient.streamingApiExecutor(Map.class)\n`; code += ` .stream(\n`; code += ` request,\n`; - code += ` response -> System.out.println(response.get${field.charAt(0).toUpperCase() + field.slice(1)}()),\n`; + code += ` response -> System.out.println(response),\n`; code += ` error -> System.err.println("Stream error: " + error.getMessage())\n`; code += ` )\n .get();`; return code; } + case SupportedLanguage.CURL: { + let url = `$FGA_API_URL${path}`; + if (pathParams) { + for (const [k, v] of Object.entries(pathParams)) { + url = url.split(`{${k}}`).join(v); + } + } + if (queryParams && Object.keys(queryParams).length > 0) { + const qs = Object.entries(queryParams) + .map(([k, v]) => `${k}=${v}`) + .join('&'); + url += `?${qs}`; + } + let code = `curl -X ${method} '${url}' \\\n`; + code += ` -H 'Content-Type: application/json' \\\n`; + code += ` -H 'Authorization: Bearer $FGA_BEARER_TOKEN'`; + if (body) { + code += ` \\\n -d '${JSON.stringify(body, null, 2)}'`; + } + return code; + } + case SupportedLanguage.CLI: - case SupportedLanguage.CURL: case SupportedLanguage.RPC: case SupportedLanguage.PLAYGROUND: return `# API Executor streaming is only available through the SDKs`; @@ -416,6 +499,7 @@ export function ExecuteApiRequestStreamingViewer(opts: ExecuteApiRequestStreamin SupportedLanguage.DOTNET_SDK, SupportedLanguage.PYTHON_SDK, SupportedLanguage.JAVA_SDK, + SupportedLanguage.CURL, ]; const allowedLanguages = getFilteredAllowedLangs(opts.allowedLanguages, defaultLangs); return defaultOperationsViewer( From c84a1e4bd62ede9b0cc854ef154375f0d2653129 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Mon, 11 May 2026 21:01:07 +0530 Subject: [PATCH 2/4] fix: lint --- src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx b/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx index 1072af2e2d..03246fba96 100644 --- a/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx +++ b/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx @@ -319,6 +319,7 @@ export function ExecuteApiRequestViewer(opts: ExecuteApiRequestViewerOpts): JSX. // 2. ExecuteApiRequestStreamingViewer – configurable streaming request // --------------------------------------------------------------------------- +// eslint-disable-next-line @typescript-eslint/no-empty-object-type interface ExecuteApiRequestStreamingViewerOpts extends ExecuteApiRequestViewerOpts {} function executeApiRequestStreamingViewer(lang: SupportedLanguage, opts: ExecuteApiRequestStreamingViewerOpts): string { From d0aefbaff3e34ad538b9417e414ea92f0ac0a210 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Mon, 11 May 2026 21:11:53 +0530 Subject: [PATCH 3/4] fix: some more issues --- .../SnippetViewer/ExecuteApiRequestViewer.tsx | 90 ++++++++++--------- 1 file changed, 49 insertions(+), 41 deletions(-) diff --git a/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx b/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx index 03246fba96..03e558b0e9 100644 --- a/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx +++ b/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx @@ -103,7 +103,44 @@ function csharpMethod(method: string): string { } function javaMethod(method: string): string { - return `HttpMethod.${method.toUpperCase()}`; + const map: Record = { + GET: 'HttpMethod.GET', + POST: 'HttpMethod.POST', + PUT: 'HttpMethod.PUT', + DELETE: 'HttpMethod.DELETE', + PATCH: 'HttpMethod.PATCH', + }; + return map[method.toUpperCase()] || `HttpMethod.valueOf("${method.toUpperCase()}")`; +} + +function buildCurlSnippet(opts: { + method: string; + path: string; + pathParams?: Record; + queryParams?: Record; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + body?: Record; +}): string { + const { method, path, pathParams, queryParams, body } = opts; + let url = `$FGA_API_URL${path}`; + if (pathParams) { + for (const [k, v] of Object.entries(pathParams)) { + url = url.split(`{${k}}`).join(v); + } + } + if (queryParams && Object.keys(queryParams).length > 0) { + const qs = Object.entries(queryParams) + .map(([k, v]) => `${k}=${v}`) + .join('&'); + url += `?${qs}`; + } + let code = `curl -X ${method} '${url}' \\\n`; + code += ` -H 'Content-Type: application/json' \\\n`; + code += ` -H 'Authorization: Bearer $FGA_API_TOKEN'`; + if (body) { + code += ` \\\n -d '${JSON.stringify(body, null, 2)}'`; + } + return code; } // --------------------------------------------------------------------------- @@ -269,24 +306,7 @@ ${parts.join('\n')} } case SupportedLanguage.CURL: { - let url = `$FGA_API_URL${path}`; - if (pathParams) { - for (const [k, v] of Object.entries(pathParams)) { - url = url.split(`{${k}}`).join(v); - } - } - if (queryParams && Object.keys(queryParams).length > 0) { - const qs = Object.entries(queryParams) - .map(([k, v]) => `${k}=${v}`) - .join('&'); - url += `?${qs}`; - } - let code = `curl -X ${method} '${url}' \\\n`; - code += ` -H 'Content-Type: application/json' \\\n`; - code += ` -H 'Authorization: Bearer $FGA_BEARER_TOKEN'`; - if (body) { - code += ` \\\n -d '${JSON.stringify(body, null, 2)}'`; - } + let code = buildCurlSnippet({ method, path, pathParams, queryParams, body }); if (responseExample) { code += `\n\n# Response: ${responseExample}`; } @@ -346,9 +366,15 @@ function executeApiRequestStreamingViewer(lang: SupportedLanguage, opts: Execute .join(', '); parts.push(` queryParams: { ${entries} },`); } - return `for await (const chunk of fgaClient.executeStreamedApiRequest({ + return `import { parseNDJSONStream } from '@openfga/sdk'; + +const streamResp = await fgaClient.executeStreamedApiRequest({ ${parts.join('\n')} -})) { +}); + +const source = streamResp.$response?.data ?? streamResp; + +for await (const chunk of parseNDJSONStream(source)) { console.log(chunk); }`; } @@ -401,7 +427,7 @@ ${parts.join('\n')} code += `;\n\n`; code += `await foreach (var item in executor.ExecuteStreamingAsync>(\n`; code += ` request, "${operationName}"))\n{\n`; - code += ` Console.WriteLine(item);`; + code += ` Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(item));`; code += `\n}`; return code; } @@ -463,25 +489,7 @@ ${parts.join('\n')} } case SupportedLanguage.CURL: { - let url = `$FGA_API_URL${path}`; - if (pathParams) { - for (const [k, v] of Object.entries(pathParams)) { - url = url.split(`{${k}}`).join(v); - } - } - if (queryParams && Object.keys(queryParams).length > 0) { - const qs = Object.entries(queryParams) - .map(([k, v]) => `${k}=${v}`) - .join('&'); - url += `?${qs}`; - } - let code = `curl -X ${method} '${url}' \\\n`; - code += ` -H 'Content-Type: application/json' \\\n`; - code += ` -H 'Authorization: Bearer $FGA_BEARER_TOKEN'`; - if (body) { - code += ` \\\n -d '${JSON.stringify(body, null, 2)}'`; - } - return code; + return buildCurlSnippet({ method, path, pathParams, queryParams, body }); } case SupportedLanguage.CLI: From 0d028d2edb596c92a790edcb2d9ef41e9af993c2 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Mon, 11 May 2026 21:17:27 +0530 Subject: [PATCH 4/4] fix: bool --- .../Docs/SnippetViewer/ExecuteApiRequestViewer.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx b/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx index 03e558b0e9..fd435d3e15 100644 --- a/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx +++ b/src/components/Docs/SnippetViewer/ExecuteApiRequestViewer.tsx @@ -120,8 +120,9 @@ function buildCurlSnippet(opts: { queryParams?: Record; // eslint-disable-next-line @typescript-eslint/no-explicit-any body?: Record; + streaming?: boolean; }): string { - const { method, path, pathParams, queryParams, body } = opts; + const { method, path, pathParams, queryParams, body, streaming } = opts; let url = `$FGA_API_URL${path}`; if (pathParams) { for (const [k, v] of Object.entries(pathParams)) { @@ -134,7 +135,7 @@ function buildCurlSnippet(opts: { .join('&'); url += `?${qs}`; } - let code = `curl -X ${method} '${url}' \\\n`; + let code = streaming ? `curl -N -X ${method} '${url}' \\\n` : `curl -X ${method} '${url}' \\\n`; code += ` -H 'Content-Type: application/json' \\\n`; code += ` -H 'Authorization: Bearer $FGA_API_TOKEN'`; if (body) { @@ -489,7 +490,7 @@ ${parts.join('\n')} } case SupportedLanguage.CURL: { - return buildCurlSnippet({ method, path, pathParams, queryParams, body }); + return buildCurlSnippet({ method, path, pathParams, queryParams, body, streaming: true }); } case SupportedLanguage.CLI: