Skip to content

Commit f0ab031

Browse files
mikewuuseambot
andauthored
fix: render batch resource responses (#987)
* mape resource sample for batch * ci: Generate docs * render batch * update response * include docs * run gen * fix missing samples * fix again * fix again * ci: Generate docs * fix missing ** * fix types * ci: Generate docs * fix unknown type * ci: Generate docs --------- Co-authored-by: Seam Bot <[email protected]>
1 parent 04ee7d1 commit f0ab031

File tree

10 files changed

+1516
-18
lines changed

10 files changed

+1516
-18
lines changed

codegen/layouts/api-endpoint.hbs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -79,7 +79,8 @@ None
7979
8080
{% hint style="success" %}
8181
Returns:
82-
**{{#if response.resourceType}}{{#if (eq response.responseType "resource_list")}}Array of [{{response.escapedResourceType}}s]({{#if response.responsePath}}{{response.responsePath}}{{else}}./{{/if}}){{else}}[{{response.escapedResourceType}}]({{#if response.responsePath}}{{response.responsePath}}{{else}}./{{/if}}){{/if}}{{else}}void{{/if}}**
82+
{{#if response.batchResources}}batch response{{#each response.batchResources}}
83+
- `{{this.batchKey}}`: Array of [{{this.escapedResourceType}}s]({{#if this.responsePath}}{{this.responsePath}}{{else}}./{{/if}}){{/each}}{{else}}**{{#if response.resourceType}}{{#if (eq response.responseType "resource_list")}}Array of [{{response.escapedResourceType}}s]({{#if response.responsePath}}{{response.responsePath}}{{else}}./{{/if}}){{else}}[{{response.escapedResourceType}}]({{#if response.responsePath}}{{response.responsePath}}{{else}}./{{/if}}){{/if}}{{else}}void{{/if}}{{/if}}**
8384
8485
{% endhint %}
8586

codegen/lib/layout/api-endpoint.ts

Lines changed: 146 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ export interface ApiEndpointLayoutContext {
5353
responseKey: string | null
5454
responseType: string | null
5555
responsePath: string | null
56+
batchResources: Array<{
57+
batchKey: string
58+
resourceType: string
59+
escapedResourceType: string
60+
responsePath: string | null
61+
}> | null
5662
actionAttempt?: Omit<ApiRouteResource, 'events'>
5763
}
5864
resourceSamples: ResourceSampleContext[]
@@ -156,6 +162,7 @@ export function setEndpointLayoutContext(
156162
responseKey: null,
157163
responseType: null,
158164
responsePath: null,
165+
batchResources: null,
159166
}
160167

161168
if (endpoint.response.responseType !== 'void') {
@@ -177,6 +184,35 @@ export function setEndpointLayoutContext(
177184
file.response.responseKey = responseKey
178185
file.response.responseType = responseType
179186
file.response.responsePath = responsePath
187+
188+
// Handle batch resource types
189+
if (
190+
'batchResourceTypes' in endpoint.response &&
191+
endpoint.response.batchResourceTypes != null
192+
) {
193+
file.response.batchResources = endpoint.response.batchResourceTypes.map(
194+
(batchResource) => {
195+
const batchResourceDef = resources.find(
196+
(r) => r.resourceType === batchResource.resourceType,
197+
)
198+
let batchResponsePath = null
199+
if (batchResourceDef != null) {
200+
batchResponsePath = path
201+
.relative(endpoint.path, batchResourceDef.routePath)
202+
.replace('..', '.')
203+
}
204+
return {
205+
batchKey: batchResource.batchKey,
206+
resourceType: batchResource.resourceType,
207+
responsePath: batchResponsePath,
208+
escapedResourceType: batchResource.resourceType.replaceAll(
209+
'_',
210+
'\\_',
211+
),
212+
}
213+
},
214+
)
215+
}
180216
}
181217

182218
if (
@@ -318,8 +354,65 @@ const getResourceSamples = (
318354
)
319355
}
320356

321-
if (resource == null) return []
357+
// Manually build sample for batch resources by fetching each resource's sample
358+
// and then combining them in a batch with the correct batch keys.
359+
if (
360+
response.responseType === 'resource' &&
361+
response.batchResourceTypes != null
362+
) {
363+
const batchResourceSamples = getBatchResourceSamples(
364+
response,
365+
resources,
366+
endpoint,
367+
pathMetadata,
368+
)
369+
370+
const batchResourceSamplesString = JSON.stringify(
371+
batchResourceSamples,
372+
null,
373+
2,
374+
)
375+
return [
376+
{
377+
title: 'JSON',
378+
description: '',
379+
resource_type: 'batch',
380+
resource: {
381+
seam_cli: {
382+
title: 'JSON',
383+
resource_data: batchResourceSamplesString,
384+
resource_data_syntax: 'json' as const,
385+
},
386+
},
387+
properties: batchResourceSamples,
388+
},
389+
]
390+
}
391+
392+
if (resource == null) {
393+
return []
394+
}
395+
396+
const sample = getResourceSample(resource, endpoint, pathMetadata)
397+
398+
if (sample == null) {
399+
return []
400+
}
322401

402+
return [
403+
{
404+
...sample,
405+
title: 'JSON',
406+
description: '',
407+
},
408+
]
409+
}
410+
411+
function getResourceSample(
412+
resource: Resource | ActionAttempt,
413+
endpoint: Endpoint,
414+
pathMetadata: PathMetadata,
415+
): ResourceSample | null {
323416
const endpointMetadata = pathMetadata[resource.routePath]
324417
const endpointSample = resource.resourceSamples.filter(
325418
resourceSampleFilter({
@@ -339,13 +432,57 @@ const getResourceSamples = (
339432

340433
const sample = parentSample ?? endpointSample
341434

342-
if (sample == null) return []
435+
if (sample == null) {
436+
return null
437+
}
343438

344-
return [
345-
{
346-
...sample,
347-
title: 'JSON',
348-
description: '',
349-
},
350-
]
439+
return {
440+
...sample,
441+
title: 'JSON',
442+
description: '',
443+
}
444+
}
445+
446+
function getBatchResourceSamples(
447+
response: Extract<Endpoint['response'], { responseType: 'resource' }>,
448+
resources: Resource[],
449+
endpoint: Endpoint,
450+
pathMetadata: PathMetadata,
451+
): Record<string, Array<any>> {
452+
// 'any' is inevitable here since the data is being parsed from a string
453+
// and every sample data is different.
454+
const batchResourceSamples: Record<string, Array<any>> = {}
455+
456+
if (response.batchResourceTypes == null) {
457+
return batchResourceSamples
458+
}
459+
460+
for (const batchResourceType of response.batchResourceTypes) {
461+
const batchResource = resources.find(
462+
(r) => r.resourceType === batchResourceType.resourceType,
463+
)
464+
465+
if (batchResource == null) {
466+
continue
467+
}
468+
469+
const sample = getResourceSample(batchResource, endpoint, pathMetadata)
470+
if (sample == null) {
471+
continue
472+
}
473+
474+
// Get the seam_cli resource data (sample object) for this batch resource
475+
const jsonSample = Object.entries(sample.resource).find(
476+
([k]) => (k as SdkName) === 'seam_cli',
477+
)?.[1]
478+
479+
if (jsonSample != null) {
480+
// Parse the resource_data to get the actual object
481+
const resourceData = JSON.parse(jsonSample.resource_data)
482+
// Wrap in array since batch responses contain arrays
483+
batchResourceSamples[batchResourceType.batchKey] = [resourceData]
484+
}
485+
}
486+
487+
return batchResourceSamples
351488
}

0 commit comments

Comments
 (0)