@@ -31,7 +31,7 @@ async function main(): Promise<void> {
31
31
] )
32
32
}
33
33
34
- const openapiResponseKeyProp = 'x-fern-sdk-return-value '
34
+ const openapiResponseKeyProp = 'x-response-key '
35
35
36
36
const routePaths = [
37
37
'/access_codes' ,
@@ -124,9 +124,9 @@ interface ClassMeta {
124
124
}
125
125
126
126
const createRoutes = ( ) : Route [ ] => {
127
- const paths = Object . keys ( openapi . paths )
127
+ const allOpenapiPaths = Object . keys ( openapi . paths )
128
128
129
- const unmatchedEndpointPaths = paths
129
+ const unmatchedEndpointPaths = allOpenapiPaths
130
130
. filter (
131
131
( path ) =>
132
132
! routePaths . some ( ( routePath ) => isEndpointUnderRoute ( path , routePath ) ) ,
@@ -141,19 +141,42 @@ const createRoutes = (): Route[] => {
141
141
)
142
142
}
143
143
144
- return routePaths . map ( createRoute )
145
- }
144
+ const routesToGenerate = routePaths . filter (
145
+ ( routePath ) =>
146
+ hasAtLeastOneDocumentedEndpoint ( routePath ) || isNamespaceRoute ( routePath ) ,
147
+ )
146
148
147
- const createRoute = ( routePath : ( typeof routePaths ) [ number ] ) : Route => {
148
- const endpointPaths = Object . keys ( openapi . paths ) . filter ( ( path ) =>
149
- isEndpointUnderRoute ( path , routePath ) ,
149
+ return routesToGenerate . map ( ( routePath ) =>
150
+ createRoute ( routePath , routesToGenerate ) ,
150
151
)
152
+ }
153
+
154
+ const createRoute = (
155
+ routePath : ( typeof routePaths ) [ number ] ,
156
+ documentedRoutePaths : ReadonlyArray < ( typeof routePaths ) [ number ] > ,
157
+ ) : Route => {
158
+ const endpointPaths = Object . entries ( openapi . paths )
159
+ . filter ( ( [ path , pathSchema ] ) => {
160
+ if ( ! isEndpointUnderRoute ( path , routePath ) ) {
161
+ return false
162
+ }
163
+
164
+ return 'post' in pathSchema && ! ( 'x-undocumented' in pathSchema . post )
165
+ } )
166
+ . map ( ( [ path ] ) => path )
151
167
152
168
const namespace = routePath . split ( '/' ) . join ( '_' ) . slice ( 1 )
153
169
170
+ const subresources = ( routePathSubresources [ routePath ] ?? [ ] ) . filter (
171
+ ( subresource ) => {
172
+ const subresourcePath = `${ routePath } /${ subresource } `
173
+ return documentedRoutePaths . some ( ( path ) => path === subresourcePath )
174
+ } ,
175
+ )
176
+
154
177
return {
155
178
namespace,
156
- subresources : routePathSubresources [ routePath ] ?? [ ] ,
179
+ subresources,
157
180
endpoints : endpointPaths . map ( ( endpointPath ) =>
158
181
createEndpoint ( namespace , routePath , endpointPath ) ,
159
182
) ,
@@ -245,6 +268,46 @@ const isEndpointUnderRoute = (
245
268
endpointPath . startsWith ( routePath ) &&
246
269
endpointPath . split ( '/' ) . length - 1 === routePath . split ( '/' ) . length
247
270
271
+ const hasAtLeastOneDocumentedEndpoint = (
272
+ routePath : ( typeof routePaths ) [ number ] ,
273
+ ) : boolean => {
274
+ const endpointsUnderRoute = Object . keys ( openapi . paths ) . filter ( ( path ) =>
275
+ isEndpointUnderRoute ( path , routePath ) ,
276
+ )
277
+
278
+ if ( endpointsUnderRoute . length === 0 ) {
279
+ return false
280
+ }
281
+
282
+ return endpointsUnderRoute . some ( ( path ) => {
283
+ if ( ! isOpenapiPath ( path ) ) return false
284
+
285
+ const pathSchema = openapi . paths [ path ]
286
+ if ( ! ( 'post' in pathSchema ) ) return false
287
+
288
+ return ! ( 'x-undocumented' in pathSchema . post )
289
+ } )
290
+ }
291
+
292
+ /**
293
+ * Determines if a route is a namespace route by checking if it has defined subresources
294
+ * and if any of those subresources have corresponding route paths.
295
+ * (e.g., "/acs" which contains "/acs/users", "/acs/systems", etc.)
296
+ * These routes should be generated even if they don't have direct endpoints themselves.
297
+ */
298
+ function isNamespaceRoute ( routePath : ( typeof routePaths ) [ number ] ) : boolean {
299
+ const subresources = routePathSubresources [ routePath ] ?? [ ]
300
+ if ( subresources . length === 0 ) {
301
+ return false
302
+ }
303
+
304
+ return subresources . some ( ( subresource ) => {
305
+ const subresourcePath =
306
+ `${ routePath } /${ subresource } ` as ( typeof routePaths ) [ number ]
307
+ return routePaths . includes ( subresourcePath )
308
+ } )
309
+ }
310
+
248
311
const renderRoute = ( route : Route , { constructors } : ClassMeta ) : string => `
249
312
/*
250
313
* Automatically generated by generate-routes.ts.
@@ -386,9 +449,7 @@ const renderClassMethodOptions = ({
386
449
resource,
387
450
} : Pick < Endpoint , 'resource' > ) : string => {
388
451
if ( resource === 'action_attempt' ) {
389
- return `options: ${ renderClassMethodOptionsTypeDef ( {
390
- resource,
391
- } ) } = {},`
452
+ return `options: ${ renderClassMethodOptionsTypeDef ( { resource } ) } = {},`
392
453
}
393
454
return ''
394
455
}
0 commit comments