fork of hey-api/openapi-ts because I need some additional things
at main 4.2 kB view raw
1interface SerializeOptions<T> 2 extends SerializePrimitiveOptions, 3 SerializerOptions<T> {} 4 5interface SerializePrimitiveOptions { 6 allowReserved?: boolean; 7 name: string; 8} 9 10export interface SerializerOptions<T> { 11 /** 12 * @default true 13 */ 14 explode: boolean; 15 style: T; 16} 17 18export type ArrayStyle = 'form' | 'spaceDelimited' | 'pipeDelimited'; 19export type ArraySeparatorStyle = ArrayStyle | MatrixStyle; 20type MatrixStyle = 'label' | 'matrix' | 'simple'; 21export type ObjectStyle = 'form' | 'deepObject'; 22type ObjectSeparatorStyle = ObjectStyle | MatrixStyle; 23 24interface SerializePrimitiveParam extends SerializePrimitiveOptions { 25 value: string; 26} 27 28export const separatorArrayExplode = (style: ArraySeparatorStyle) => { 29 switch (style) { 30 case 'label': 31 return '.'; 32 case 'matrix': 33 return ';'; 34 case 'simple': 35 return ','; 36 default: 37 return '&'; 38 } 39}; 40 41export const separatorArrayNoExplode = (style: ArraySeparatorStyle) => { 42 switch (style) { 43 case 'form': 44 return ','; 45 case 'pipeDelimited': 46 return '|'; 47 case 'spaceDelimited': 48 return '%20'; 49 default: 50 return ','; 51 } 52}; 53 54export const separatorObjectExplode = (style: ObjectSeparatorStyle) => { 55 switch (style) { 56 case 'label': 57 return '.'; 58 case 'matrix': 59 return ';'; 60 case 'simple': 61 return ','; 62 default: 63 return '&'; 64 } 65}; 66 67export const serializeArrayParam = ({ 68 allowReserved, 69 explode, 70 name, 71 style, 72 value, 73}: SerializeOptions<ArraySeparatorStyle> & { 74 value: unknown[]; 75}) => { 76 if (!explode) { 77 const joinedValues = ( 78 allowReserved ? value : value.map((v) => encodeURIComponent(v as string)) 79 ).join(separatorArrayNoExplode(style)); 80 switch (style) { 81 case 'label': 82 return `.${joinedValues}`; 83 case 'matrix': 84 return `;${name}=${joinedValues}`; 85 case 'simple': 86 return joinedValues; 87 default: 88 return `${name}=${joinedValues}`; 89 } 90 } 91 92 const separator = separatorArrayExplode(style); 93 const joinedValues = value 94 .map((v) => { 95 if (style === 'label' || style === 'simple') { 96 return allowReserved ? v : encodeURIComponent(v as string); 97 } 98 99 return serializePrimitiveParam({ 100 allowReserved, 101 name, 102 value: v as string, 103 }); 104 }) 105 .join(separator); 106 return style === 'label' || style === 'matrix' 107 ? separator + joinedValues 108 : joinedValues; 109}; 110 111export const serializePrimitiveParam = ({ 112 allowReserved, 113 name, 114 value, 115}: SerializePrimitiveParam) => { 116 if (value === undefined || value === null) { 117 return ''; 118 } 119 120 if (typeof value === 'object') { 121 throw new Error( 122 'Deeply-nested arrays/objects aren’t supported. Provide your own `querySerializer()` to handle these.', 123 ); 124 } 125 126 return `${name}=${allowReserved ? value : encodeURIComponent(value)}`; 127}; 128 129export const serializeObjectParam = ({ 130 allowReserved, 131 explode, 132 name, 133 style, 134 value, 135 valueOnly, 136}: SerializeOptions<ObjectSeparatorStyle> & { 137 value: Record<string, unknown> | Date; 138 valueOnly?: boolean; 139}) => { 140 if (value instanceof Date) { 141 return valueOnly ? value.toISOString() : `${name}=${value.toISOString()}`; 142 } 143 144 if (style !== 'deepObject' && !explode) { 145 let values: string[] = []; 146 Object.entries(value).forEach(([key, v]) => { 147 values = [ 148 ...values, 149 key, 150 allowReserved ? (v as string) : encodeURIComponent(v as string), 151 ]; 152 }); 153 const joinedValues = values.join(','); 154 switch (style) { 155 case 'form': 156 return `${name}=${joinedValues}`; 157 case 'label': 158 return `.${joinedValues}`; 159 case 'matrix': 160 return `;${name}=${joinedValues}`; 161 default: 162 return joinedValues; 163 } 164 } 165 166 const separator = separatorObjectExplode(style); 167 const joinedValues = Object.entries(value) 168 .map(([key, v]) => 169 serializePrimitiveParam({ 170 allowReserved, 171 name: style === 'deepObject' ? `${name}[${key}]` : key, 172 value: v as string, 173 }), 174 ) 175 .join(separator); 176 return style === 'label' || style === 'matrix' 177 ? separator + joinedValues 178 : joinedValues; 179};