@@ -4,6 +4,36 @@ import { createRef } from "../lib/utils.js";
44import type { ParameterObject , ReferenceObject , TransformNodeOptions } from "../types.js" ;
55import transformParameterObject from "./parameter-object.js" ;
66
7+ // Regex to match path parameters in URL
8+ const PATH_PARAM_RE = / \{ ( [ ^ } ] + ) \} / g;
9+
10+ /**
11+ * Create a synthetic path parameter object from a parameter name
12+ */
13+ function createPathParameter ( paramName : string ) : ParameterObject {
14+ return {
15+ name : paramName ,
16+ in : "path" ,
17+ required : true ,
18+ schema : { type : "string" } ,
19+ } ;
20+ }
21+
22+ /**
23+ * Extract path parameters from a URL
24+ */
25+ function extractPathParamsFromUrl ( path : string ) : ParameterObject [ ] {
26+ const params : ParameterObject [ ] = [ ] ;
27+ const matches = path . match ( PATH_PARAM_RE ) ;
28+ if ( matches ) {
29+ for ( const match of matches ) {
30+ const paramName = match . slice ( 1 , - 1 ) ;
31+ params . push ( createPathParameter ( paramName ) ) ;
32+ }
33+ }
34+ return params ;
35+ }
36+
737/**
838 * Synthetic type. Array of (ParameterObject | ReferenceObject)s found in OperationObject and PathItemObject.
939 */
@@ -13,14 +43,36 @@ export function transformParametersArray(
1343) : ts . TypeElement [ ] {
1444 const type : ts . TypeElement [ ] = [ ] ;
1545
46+ // Create a working copy of parameters array
47+ const workingParameters = [ ...parametersArray ] ;
48+
49+ // Generate path parameters if enabled
50+ if ( options . ctx . generatePathParams && options . path ) {
51+ const pathString = Array . isArray ( options . path ) ? options . path [ 0 ] : options . path ;
52+ if ( typeof pathString === "string" ) {
53+ const pathParams = extractPathParamsFromUrl ( pathString ) ;
54+ // Only add path parameters that aren't already defined
55+ for ( const param of pathParams ) {
56+ const exists = workingParameters . some ( ( p ) => {
57+ const resolved = "$ref" in p ? options . ctx . resolve < ParameterObject > ( p . $ref ) : p ;
58+ return resolved ?. in === "path" && resolved ?. name === param . name ;
59+ } ) ;
60+ if ( ! exists ) {
61+ workingParameters . push ( param ) ;
62+ }
63+ }
64+ }
65+ }
66+
1667 // parameters
1768 const paramType : ts . TypeElement [ ] = [ ] ;
1869 for ( const paramIn of [ "query" , "header" , "path" , "cookie" ] as ParameterObject [ "in" ] [ ] ) {
1970 const paramLocType : ts . TypeElement [ ] = [ ] ;
20- let operationParameters = parametersArray . map ( ( param ) => ( {
71+ let operationParameters = workingParameters . map ( ( param ) => ( {
2172 original : param ,
2273 resolved : "$ref" in param ? options . ctx . resolve < ParameterObject > ( param . $ref ) : param ,
2374 } ) ) ;
75+
2476 // this is the only array type in the spec, so we have to one-off sort here
2577 if ( options . ctx . alphabetize ) {
2678 operationParameters . sort ( ( a , b ) => ( a . resolved ?. name ?? "" ) . localeCompare ( b . resolved ?. name ?? "" ) ) ;
0 commit comments