@@ -99,17 +99,13 @@ function matchLegacyOpenApi(input: Record<string, unknown>) {
9999 applyLegacySchemaOverrides ( spec )
100100 normalizeComponentDescriptions ( spec )
101101 addLegacyErrorSchemas ( spec )
102- delete spec . components ?. schemas ?. Unauthorized
103- delete spec . components ?. schemas ?. EffectHttpApiErrorBadRequest
104- delete spec . components ?. schemas ?. EffectHttpApiErrorNotFound
105- delete spec . components ?. schemas ?. effect_HttpApiError_BadRequest
106- delete spec . components ?. schemas ?. effect_HttpApiError_NotFound
107102 delete spec . components ?. securitySchemes
108103
109104 for ( const [ path , item ] of Object . entries ( spec . paths ?? { } ) ) {
110105 for ( const method of [ "get" , "post" , "put" , "delete" , "patch" ] as const ) {
111106 const operation = item [ method ]
112107 if ( ! operation ) continue
108+ const isV2Api = isV2ApiPath ( path )
113109 if ( operation . requestBody ) {
114110 // The legacy OpenAPI surface never marked request bodies as required.
115111 // Keep that SDK surface stable while the HttpApi spec is tightened.
@@ -146,11 +142,14 @@ function matchLegacyOpenApi(input: Record<string, unknown>) {
146142 if ( content . schema ) content . schema = stripOptionalNull ( structuredClone ( content . schema ) )
147143 }
148144 }
149- // Auth is still runtime middleware outside the public OpenAPI metadata, so
150- // the SDK should not expose auth schemes or generated 401 error unions.
151- delete operation . security
152- delete operation . responses ?. [ "401" ]
153- normalizeLegacyErrorResponses ( operation )
145+ if ( ! isV2Api ) {
146+ // Auth is still runtime middleware outside the legacy public OpenAPI
147+ // metadata, so the legacy SDK should not expose auth schemes or
148+ // generated 401 error unions.
149+ delete operation . security
150+ delete operation . responses ?. [ "401" ]
151+ normalizeLegacyErrorResponses ( operation )
152+ }
154153 normalizeLegacyOperation ( operation , path , method )
155154 if ( ( path === "/event" || path === "/global/event" ) && method === "get" ) {
156155 // HttpApi has no first-class SSE response schema, and these handlers are
@@ -171,9 +170,14 @@ function matchLegacyOpenApi(input: Record<string, unknown>) {
171170 for ( const param of operation . parameters ?? [ ] ) normalizeParameter ( param , route )
172171 }
173172 }
173+ deleteUnusedLegacyErrorComponents ( spec )
174174 return input
175175}
176176
177+ function isV2ApiPath ( path : string ) {
178+ return path === "/api" || path . startsWith ( "/api/" )
179+ }
180+
177181function addLegacyErrorSchemas ( spec : OpenApiSpec ) {
178182 if ( ! spec . components ?. schemas ) return
179183 spec . components . schemas . BadRequestError = {
@@ -345,6 +349,26 @@ function normalizeLegacyErrorResponses(operation: OpenApiOperation) {
345349 }
346350}
347351
352+ function deleteUnusedLegacyErrorComponents ( spec : OpenApiSpec ) {
353+ for ( const name of [
354+ "Unauthorized" ,
355+ "EffectHttpApiErrorBadRequest" ,
356+ "EffectHttpApiErrorNotFound" ,
357+ "effect_HttpApiError_BadRequest" ,
358+ "effect_HttpApiError_NotFound" ,
359+ ] ) {
360+ if ( referencesComponent ( spec . paths , name ) ) continue
361+ delete spec . components ?. schemas ?. [ name ]
362+ }
363+ }
364+
365+ function referencesComponent ( input : unknown , name : string ) : boolean {
366+ if ( Array . isArray ( input ) ) return input . some ( ( item ) => referencesComponent ( item , name ) )
367+ if ( ! input || typeof input !== "object" ) return false
368+ if ( ( input as OpenApiSchema ) . $ref === `#/components/schemas/${ name } ` ) return true
369+ return Object . values ( input ) . some ( ( value ) => referencesComponent ( value , name ) )
370+ }
371+
348372function normalizeLegacyOperation ( operation : OpenApiOperation , path : string , method : string ) {
349373 if ( path === "/experimental/console/switch" && method === "post" ) delete operation . responses ?. [ "400" ]
350374 if ( path === "/pty/{ptyID}" && method === "put" ) delete operation . responses ?. [ "404" ]
0 commit comments