@@ -92,3 +92,104 @@ export function isIMeldingOmVedtak(data: unknown): data is IMeldingOmVedtak {
92
92
93
93
return hasValidHtml && hasValidUtvidedeBeskrivelser ;
94
94
}
95
+
96
+ /**
97
+ * Represents a primitive value type that can be parsed from a URL parameter
98
+ */
99
+ type PrimitiveValue = string | number | boolean ;
100
+
101
+ /**
102
+ * Represents possible parsed values from URL parameters
103
+ */
104
+ type ParsedValue = PrimitiveValue | PrimitiveValue [ ] ;
105
+
106
+ /**
107
+ * Converts URLSearchParams to a typed query object based on OpenAPI path schema
108
+ * @param searchParams - The URLSearchParams object or URLSearchParams-like object to parse
109
+ * @returns A typed query object with correctly parsed values
110
+ */
111
+ export function parseSearchParamsToOpenApiQuery < T extends Record < string , unknown > | undefined > (
112
+ searchParams : URLSearchParams | Record < string , string > | string ,
113
+ ) : T {
114
+ // Ensure we're working with a proper URLSearchParams object
115
+ const params = ensureURLSearchParams ( searchParams ) ;
116
+ const result : Record < string , ParsedValue > = { } ;
117
+
118
+ // Use forEach which is more reliably available than entries()
119
+ params . forEach ( ( value , key ) => {
120
+ // Skip empty values
121
+ if ( value === "" ) return ;
122
+
123
+ // Check if the key already exists in the result (for array parameters)
124
+ if ( key in result ) {
125
+ // If the existing value is already an array, push to it
126
+ if ( Array . isArray ( result [ key ] ) ) {
127
+ ( result [ key ] as PrimitiveValue [ ] ) . push ( parseValue ( value ) ) ;
128
+ } else {
129
+ // Convert existing value to an array and add the new value
130
+ result [ key ] = [ result [ key ] as PrimitiveValue , parseValue ( value ) ] ;
131
+ }
132
+ } else {
133
+ // Get all values for this key to check if it should be an array
134
+ const allValues = params . getAll ( key ) ;
135
+
136
+ if ( allValues . length > 1 ) {
137
+ // If multiple values exist, create an array
138
+ result [ key ] = allValues . map ( parseValue ) ;
139
+ } else {
140
+ // Otherwise, set as a single value
141
+ result [ key ] = parseValue ( value ) ;
142
+ }
143
+ }
144
+ } ) ;
145
+
146
+ return result as T ;
147
+ }
148
+
149
+ /**
150
+ * Helper function to ensure we're working with a URLSearchParams object
151
+ * @param input - The input to convert to URLSearchParams
152
+ * @returns A URLSearchParams object
153
+ */
154
+ function ensureURLSearchParams (
155
+ input : URLSearchParams | Record < string , string > | string ,
156
+ ) : URLSearchParams {
157
+ if ( input instanceof URLSearchParams ) {
158
+ return input ;
159
+ }
160
+
161
+ if ( typeof input === "string" ) {
162
+ return new URLSearchParams ( input ) ;
163
+ }
164
+
165
+ // Handle plain objects by creating a new URLSearchParams
166
+ if ( typeof input === "object" ) {
167
+ const params = new URLSearchParams ( ) ;
168
+ Object . entries ( input ) . forEach ( ( [ key , value ] ) => {
169
+ params . append ( key , value ) ;
170
+ } ) ;
171
+ return params ;
172
+ }
173
+
174
+ // Default fallback
175
+ return new URLSearchParams ( ) ;
176
+ }
177
+
178
+ /**
179
+ * Helper function to parse string values to appropriate types
180
+ * @param value - The string value to parse
181
+ * @returns The parsed value with the correct type
182
+ */
183
+ function parseValue ( value : string ) : PrimitiveValue {
184
+ // Parse boolean values
185
+ if ( value . toLowerCase ( ) === "true" ) return true ;
186
+ if ( value . toLowerCase ( ) === "false" ) return false ;
187
+
188
+ // Parse numeric values
189
+ if ( ! isNaN ( Number ( value ) ) && value . trim ( ) !== "" ) {
190
+ return Number ( value ) ;
191
+ }
192
+
193
+ // Keep strings as is
194
+ return value ;
195
+ }
0 commit comments