From 4f1b5ebf92f54b182dc81442d6462cc05a6d6707 Mon Sep 17 00:00:00 2001 From: Daniel Jonathan Date: Mon, 3 Nov 2025 14:18:23 -0500 Subject: [PATCH 1/7] docs: add StreamedListObjects documentation Add documentation for the StreamedListObjects API to the List Objects guide. Changes: - Add Streamed List Objects section explaining streaming differences - Include Node.js and Python SDK examples - Add note about SDK availability - Add related link to StreamedListObjects API reference Related: - openfga/js-sdk#280 - openfga/sdk-generator#654 - openfga/sdk-generator#76 --- .../getting-started/perform-list-objects.mdx | 50 +++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/docs/content/getting-started/perform-list-objects.mdx b/docs/content/getting-started/perform-list-objects.mdx index 5e3f919011..4fdab9f799 100644 --- a/docs/content/getting-started/perform-list-objects.mdx +++ b/docs/content/getting-started/perform-list-objects.mdx @@ -182,6 +182,51 @@ The result `document:otherdoc` and `document:planning` are the document objects The performance characteristics of the ListObjects endpoint vary drastically depending on the model complexity, number of tuples, and the relations it needs to evaluate. Relations with 'and' or 'but not' are more expensive to evaluate than relations with 'or'. ::: +## Streamed List Objects + +The Streamed ListObjects API is similar to the ListObjects API, with two key differences: + +1. **Streaming Response**: Instead of collecting all objects before returning a response, it streams them to the client as they are collected. +2. **No Result Limit**: The number of results returned is only limited by the execution timeout specified in the flag `OPENFGA_LIST_OBJECTS_DEADLINE`, not by a fixed limit. + +:::info Node.js & Python Only +The streaming functionality is currently available in the **Node.js SDK** and **Python SDK**. Other SDKs return results using the standard ListObjects endpoint. +::: + +### Using Streamed List Objects + + + + +```javascript +const objects = []; +for await (const response of fgaClient.streamedListObjects( + { user: "user:anne", relation: "reader", type: "document" } +)) { + objects.push(response.object); +} +// objects = ["document:otherdoc", "document:planning"] +``` + + + + +```python +objects = [] +async for response in fga_client.streamed_list_objects( + ClientListObjectsRequest( + user="user:anne", + relation="reader", + type="document" + ) +): + objects.append(response.object) +# objects = ["document:otherdoc", "document:planning"] +``` + + + + ## Related Sections From ebcd40a48ab6107b79fd42193d8a5b706fbecbb7 Mon Sep 17 00:00:00 2001 From: Daniel Jonathan Date: Wed, 5 Nov 2025 15:33:49 -0500 Subject: [PATCH 2/7] docs: add .NET SDK example for StreamedListObjects - Add .NET SDK code sample in Streamed List Objects section - Update info notice to include .NET SDK support - Show IAsyncEnumerable pattern for streaming objects --- .../getting-started/perform-list-objects.mdx | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/docs/content/getting-started/perform-list-objects.mdx b/docs/content/getting-started/perform-list-objects.mdx index 4fdab9f799..907de642b1 100644 --- a/docs/content/getting-started/perform-list-objects.mdx +++ b/docs/content/getting-started/perform-list-objects.mdx @@ -189,8 +189,8 @@ The Streamed ListObjects API is similar to the ListObjects API, with two key dif 1. **Streaming Response**: Instead of collecting all objects before returning a response, it streams them to the client as they are collected. 2. **No Result Limit**: The number of results returned is only limited by the execution timeout specified in the flag `OPENFGA_LIST_OBJECTS_DEADLINE`, not by a fixed limit. -:::info Node.js & Python Only -The streaming functionality is currently available in the **Node.js SDK** and **Python SDK**. Other SDKs return results using the standard ListObjects endpoint. +:::info +The streaming functionality is currently available in the **Node.js SDK**, **Python SDK**, and **.NET SDK**. Other SDKs return results using the standard ListObjects endpoint. ::: ### Using Streamed List Objects @@ -208,6 +208,22 @@ for await (const response of fgaClient.streamedListObjects( // objects = ["document:otherdoc", "document:planning"] ``` + + + +```dotnet +var objects = new List(); +await foreach (var response in fgaClient.StreamedListObjects( + new ClientListObjectsRequest { + User = "user:anne", + Relation = "reader", + Type = "document" + })) { + objects.Add(response.Object); +} +// objects = ["document:otherdoc", "document:planning"] +``` + From 10c0d0c55290b23d156d189ed9be38d1686682d7 Mon Sep 17 00:00:00 2001 From: Daniel Jonathan Date: Wed, 5 Nov 2025 15:51:22 -0500 Subject: [PATCH 3/7] docs: add .NET SDK support for StreamedListObjects - Create StreamedListObjectsRequestViewer component - Add .NET SDK code example for streaming objects - Update info notice to include .NET SDK support - Export new viewer component in index.ts --- .../getting-started/perform-list-objects.mdx | 60 +++----------- .../StreamedListObjectsRequestViewer.tsx | 80 +++++++++++++++++++ src/components/Docs/SnippetViewer/index.ts | 1 + 3 files changed, 94 insertions(+), 47 deletions(-) create mode 100644 src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx diff --git a/docs/content/getting-started/perform-list-objects.mdx b/docs/content/getting-started/perform-list-objects.mdx index 907de642b1..74aed87d7a 100644 --- a/docs/content/getting-started/perform-list-objects.mdx +++ b/docs/content/getting-started/perform-list-objects.mdx @@ -9,6 +9,7 @@ import { SupportedLanguage, languageLabelMap, ListObjectsRequestViewer, + StreamedListObjectsRequestViewer, DocumentationNotice, ProductConcept, ProductName, @@ -195,53 +196,18 @@ The streaming functionality is currently available in the **Node.js SDK**, **Pyt ### Using Streamed List Objects - - - -```javascript -const objects = []; -for await (const response of fgaClient.streamedListObjects( - { user: "user:anne", relation: "reader", type: "document" } -)) { - objects.push(response.object); -} -// objects = ["document:otherdoc", "document:planning"] -``` - - - - -```dotnet -var objects = new List(); -await foreach (var response in fgaClient.StreamedListObjects( - new ClientListObjectsRequest { - User = "user:anne", - Relation = "reader", - Type = "document" - })) { - objects.Add(response.Object); -} -// objects = ["document:otherdoc", "document:planning"] -``` - - - - -```python -objects = [] -async for response in fga_client.streamed_list_objects( - ClientListObjectsRequest( - user="user:anne", - relation="reader", - type="document" - ) -): - objects.append(response.object) -# objects = ["document:otherdoc", "document:planning"] -``` - - - + ## Related Sections diff --git a/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx b/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx new file mode 100644 index 0000000000..4ec6304f44 --- /dev/null +++ b/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx @@ -0,0 +1,80 @@ +import { getFilteredAllowedLangs, SupportedLanguage } from './SupportedLanguage'; +import { defaultOperationsViewer } from './DefaultTabbedViewer'; +import assertNever from 'assert-never/index'; + +interface StreamedListObjectsRequestViewerOpts { + user: string; + relation: string; + objectType: string; + expectedResults: string[]; + skipSetup?: boolean; + allowedLanguages?: SupportedLanguage[]; +} + +function streamedListObjectsRequestViewer( + lang: SupportedLanguage, + opts: StreamedListObjectsRequestViewerOpts, +): string { + const { user, relation, objectType, expectedResults } = opts; + + switch (lang) { + case SupportedLanguage.PLAYGROUND: + return `# Note: Streamed List Objects is not currently supported on the playground`; + case SupportedLanguage.CLI: + return `# Note: Streamed List Objects is not currently supported in the CLI`; + case SupportedLanguage.CURL: + return `# Note: Streamed List Objects requires handling NDJSON streams +# For curl examples, see the API documentation`; + case SupportedLanguage.JS_SDK: + return `const objects = []; +for await (const response of fgaClient.streamedListObjects( + { user: "${user}", relation: "${relation}", type: "${objectType}" } +)) { + objects.push(response.object); +} +// objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`; + case SupportedLanguage.DOTNET_SDK: + return `var objects = new List(); +await foreach (var response in fgaClient.StreamedListObjects( + new ClientListObjectsRequest { + User = "${user}", + Relation = "${relation}", + Type = "${objectType}" + })) { + objects.Add(response.Object); +} +// objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`; + case SupportedLanguage.PYTHON_SDK: + return `objects = [] +async for response in fga_client.streamed_list_objects( + ClientListObjectsRequest( + user="${user}", + relation="${relation}", + type="${objectType}" + ) +): + objects.append(response.object) +# objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`; + case SupportedLanguage.GO_SDK: + return `# Note: Streamed List Objects is not yet available in the Go SDK`; + case SupportedLanguage.JAVA_SDK: + return `# Note: Streamed List Objects is not yet available in the Java SDK`; + case SupportedLanguage.RPC: + return `# Note: Use CURL or SDK for streaming examples`; + default: + return assertNever(lang); + } +} + +export function StreamedListObjectsRequestViewer( + opts: StreamedListObjectsRequestViewerOpts, +): JSX.Element { + const defaultLangs = [ + SupportedLanguage.JS_SDK, + SupportedLanguage.DOTNET_SDK, + SupportedLanguage.PYTHON_SDK, + ]; + const allowedLanguages = getFilteredAllowedLangs(opts.allowedLanguages, defaultLangs); + return defaultOperationsViewer(allowedLanguages, opts, streamedListObjectsRequestViewer); +} + diff --git a/src/components/Docs/SnippetViewer/index.ts b/src/components/Docs/SnippetViewer/index.ts index 4f50acffa3..19efebe2d1 100644 --- a/src/components/Docs/SnippetViewer/index.ts +++ b/src/components/Docs/SnippetViewer/index.ts @@ -8,5 +8,6 @@ export * from './ReadChangesRequestViewer'; export * from './ReadRequestViewer'; export { SdkSetupHeader } from './SdkSetup'; export { SupportedLanguage, languageLabelMap } from './SupportedLanguage'; +export * from './StreamedListObjectsRequestViewer'; export * from './WriteRequestViewer'; export * from './WriteAuthzModelViewer'; From edac1800d6e04548ccc55e8a6b754a0b00a87708 Mon Sep 17 00:00:00 2001 From: Daniel Jonathan Date: Tue, 18 Nov 2025 12:39:35 -0600 Subject: [PATCH 4/7] Update src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx Co-authored-by: Raghd Hamzeh --- .../StreamedListObjectsRequestViewer.tsx | 33 +++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx b/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx index 4ec6304f44..5c70faea4f 100644 --- a/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx +++ b/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx @@ -23,8 +23,37 @@ function streamedListObjectsRequestViewer( case SupportedLanguage.CLI: return `# Note: Streamed List Objects is not currently supported in the CLI`; case SupportedLanguage.CURL: - return `# Note: Streamed List Objects requires handling NDJSON streams -# For curl examples, see the API documentation`; + return `curl -X POST $FGA_API_URL/stores/$FGA_STORE_ID/streamed-list-objects \\ + -H "Authorization: Bearer $FGA_API_TOKEN" \\ # Not needed if service does not require authorization + -H "content-type: application/json" \\ + -d '{ + "authorization_model_id": "${modelId}", + "type": "${objectType}", + "relation": "${relation}", + "user":"${user}"${ + contextualTuples + ? `, + "contextual_tuples": { + "tuple_keys": [${contextualTuples + .map( + (tuple) => ` + {"object": "${tuple.object}", "relation": "${tuple.relation}", "user": "${tuple.user}"}`, + ) + .join(',')} + ] + }` + : '' + }${ + context + ? `, + "context":${JSON.stringify(context)}` + : '' + } + }' + + +# Response: +${expectedResults.map((r) => `{"result":{"object":"${r}"}}`).join('\n')}` case SupportedLanguage.JS_SDK: return `const objects = []; for await (const response of fgaClient.streamedListObjects( From f7055dd0ff82298ad792a53a9bce82e7ec645fa1 Mon Sep 17 00:00:00 2001 From: Daniel Jonathan Date: Tue, 18 Nov 2025 12:40:07 -0600 Subject: [PATCH 5/7] Update docs/content/getting-started/perform-list-objects.mdx Co-authored-by: Raghd Hamzeh --- docs/content/getting-started/perform-list-objects.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/getting-started/perform-list-objects.mdx b/docs/content/getting-started/perform-list-objects.mdx index 74aed87d7a..f563e0ace1 100644 --- a/docs/content/getting-started/perform-list-objects.mdx +++ b/docs/content/getting-started/perform-list-objects.mdx @@ -191,7 +191,7 @@ The Streamed ListObjects API is similar to the ListObjects API, with two key dif 2. **No Result Limit**: The number of results returned is only limited by the execution timeout specified in the flag `OPENFGA_LIST_OBJECTS_DEADLINE`, not by a fixed limit. :::info -The streaming functionality is currently available in the **Node.js SDK**, **Python SDK**, and **.NET SDK**. Other SDKs return results using the standard ListObjects endpoint. +The streaming functionality is currently available in the **Node.js SDK**, **Python SDK**, and **.NET SDK**. ::: ### Using Streamed List Objects From e65cc41fb59bc353c93bef28bf47b5b6b8a388ac Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Thu, 5 Feb 2026 18:57:55 +0530 Subject: [PATCH 6/7] feat: add go and java examples in docs --- .../getting-started/perform-list-objects.mdx | 7 +-- .../StreamedListObjectsRequestViewer.tsx | 49 ++++++++++--------- 2 files changed, 27 insertions(+), 29 deletions(-) diff --git a/docs/content/getting-started/perform-list-objects.mdx b/docs/content/getting-started/perform-list-objects.mdx index f563e0ace1..d8ab5a5197 100644 --- a/docs/content/getting-started/perform-list-objects.mdx +++ b/docs/content/getting-started/perform-list-objects.mdx @@ -191,7 +191,7 @@ The Streamed ListObjects API is similar to the ListObjects API, with two key dif 2. **No Result Limit**: The number of results returned is only limited by the execution timeout specified in the flag `OPENFGA_LIST_OBJECTS_DEADLINE`, not by a fixed limit. :::info -The streaming functionality is currently available in the **Node.js SDK**, **Python SDK**, and **.NET SDK**. +The streaming functionality is currently available in the **Node.js SDK**, **Go SDK**, **.NET SDK**, **Python SDK**, and **Java SDK**. ::: ### Using Streamed List Objects @@ -202,11 +202,6 @@ The streaming functionality is currently available in the **Node.js SDK**, **Pyt objectType="document" expectedResults={['document:otherdoc', 'document:planning']} skipSetup={true} - allowedLanguages={[ - SupportedLanguage.JS_SDK, - SupportedLanguage.DOTNET_SDK, - SupportedLanguage.PYTHON_SDK, - ]} /> ## Related Sections diff --git a/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx b/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx index 5c70faea4f..82bff87b2d 100644 --- a/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx +++ b/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx @@ -27,33 +27,14 @@ function streamedListObjectsRequestViewer( -H "Authorization: Bearer $FGA_API_TOKEN" \\ # Not needed if service does not require authorization -H "content-type: application/json" \\ -d '{ - "authorization_model_id": "${modelId}", "type": "${objectType}", "relation": "${relation}", - "user":"${user}"${ - contextualTuples - ? `, - "contextual_tuples": { - "tuple_keys": [${contextualTuples - .map( - (tuple) => ` - {"object": "${tuple.object}", "relation": "${tuple.relation}", "user": "${tuple.user}"}`, - ) - .join(',')} - ] - }` - : '' - }${ - context - ? `, - "context":${JSON.stringify(context)}` - : '' - } + "user":"${user}" }' # Response: -${expectedResults.map((r) => `{"result":{"object":"${r}"}}`).join('\n')}` +${expectedResults.map((r) => `{"result":{"object":"${r}"}}`).join('\n')}`; case SupportedLanguage.JS_SDK: return `const objects = []; for await (const response of fgaClient.streamedListObjects( @@ -85,9 +66,29 @@ async for response in fga_client.streamed_list_objects( objects.append(response.object) # objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`; case SupportedLanguage.GO_SDK: - return `# Note: Streamed List Objects is not yet available in the Go SDK`; + return `objects := []string{} +err := fgaClient.StreamedListObjects(context.Background()). + Body(client.ClientListObjectsRequest{ + User: "${user}", + Relation: "${relation}", + Type: "${objectType}", + }). + Execute(func(response *client.ClientStreamedListObjectsResponse) error { + objects = append(objects, response.Object) + return nil + }) +// objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`; case SupportedLanguage.JAVA_SDK: - return `# Note: Streamed List Objects is not yet available in the Java SDK`; + return `var objects = new ArrayList(); +var request = new ClientListObjectsRequest() + .user("${user}") + .relation("${relation}") + .type("${objectType}"); + +fgaClient.streamedListObjects(request, new ClientStreamedListObjectsOptions(), response -> { + objects.add(response.getObject()); +}).get(); +// objects = [${expectedResults.map((r) => `"${r}"`).join(', ')}]`; case SupportedLanguage.RPC: return `# Note: Use CURL or SDK for streaming examples`; default: @@ -100,8 +101,10 @@ export function StreamedListObjectsRequestViewer( ): JSX.Element { const defaultLangs = [ SupportedLanguage.JS_SDK, + SupportedLanguage.GO_SDK, SupportedLanguage.DOTNET_SDK, SupportedLanguage.PYTHON_SDK, + SupportedLanguage.JAVA_SDK, ]; const allowedLanguages = getFilteredAllowedLangs(opts.allowedLanguages, defaultLangs); return defaultOperationsViewer(allowedLanguages, opts, streamedListObjectsRequestViewer); From 1da1b2aaf7428a70237e40285359852646840053 Mon Sep 17 00:00:00 2001 From: Anurag Bandyopadhyay Date: Thu, 5 Feb 2026 19:03:10 +0530 Subject: [PATCH 7/7] fix: prettier fix --- .../SnippetViewer/StreamedListObjectsRequestViewer.tsx | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx b/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx index 82bff87b2d..fda566737e 100644 --- a/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx +++ b/src/components/Docs/SnippetViewer/StreamedListObjectsRequestViewer.tsx @@ -11,10 +11,7 @@ interface StreamedListObjectsRequestViewerOpts { allowedLanguages?: SupportedLanguage[]; } -function streamedListObjectsRequestViewer( - lang: SupportedLanguage, - opts: StreamedListObjectsRequestViewerOpts, -): string { +function streamedListObjectsRequestViewer(lang: SupportedLanguage, opts: StreamedListObjectsRequestViewerOpts): string { const { user, relation, objectType, expectedResults } = opts; switch (lang) { @@ -96,9 +93,7 @@ fgaClient.streamedListObjects(request, new ClientStreamedListObjectsOptions(), r } } -export function StreamedListObjectsRequestViewer( - opts: StreamedListObjectsRequestViewerOpts, -): JSX.Element { +export function StreamedListObjectsRequestViewer(opts: StreamedListObjectsRequestViewerOpts): JSX.Element { const defaultLangs = [ SupportedLanguage.JS_SDK, SupportedLanguage.GO_SDK, @@ -109,4 +104,3 @@ export function StreamedListObjectsRequestViewer( const allowedLanguages = getFilteredAllowedLangs(opts.allowedLanguages, defaultLangs); return defaultOperationsViewer(allowedLanguages, opts, streamedListObjectsRequestViewer); } -