1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
// This file is auto-generated by @hey-api/openapi-ts
type Slot = "body" | "headers" | "path" | "query"
export type Field =
| {
in: Exclude<Slot, "body">
/**
* Field name. This is the name we want the user to see and use.
*/
key: string
/**
* Field mapped name. This is the name we want to use in the request.
* If omitted, we use the same value as `key`.
*/
map?: string
}
| {
in: Extract<Slot, "body">
/**
* Key isn't required for bodies.
*/
key?: string
map?: string
}
export interface Fields {
allowExtra?: Partial<Record<Slot, boolean>>
args?: ReadonlyArray<Field>
}
export type FieldsConfig = ReadonlyArray<Field | Fields>
const extraPrefixesMap: Record<string, Slot> = {
$body_: "body",
$headers_: "headers",
$path_: "path",
$query_: "query",
}
const extraPrefixes = Object.entries(extraPrefixesMap)
type KeyMap = Map<
string,
{
in: Slot
map?: string
}
>
const buildKeyMap = (fields: FieldsConfig, map?: KeyMap): KeyMap => {
if (!map) {
map = new Map()
}
for (const config of fields) {
if ("in" in config) {
if (config.key) {
map.set(config.key, {
in: config.in,
map: config.map,
})
}
} else if (config.args) {
buildKeyMap(config.args, map)
}
}
return map
}
interface Params {
body: unknown
headers: Record<string, unknown>
path: Record<string, unknown>
query: Record<string, unknown>
}
const stripEmptySlots = (params: Params) => {
for (const [slot, value] of Object.entries(params)) {
if (value && typeof value === "object" && !Object.keys(value).length) {
delete params[slot as Slot]
}
}
}
export const buildClientParams = (args: ReadonlyArray<unknown>, fields: FieldsConfig) => {
const params: Params = {
body: {},
headers: {},
path: {},
query: {},
}
const map = buildKeyMap(fields)
let config: FieldsConfig[number] | undefined
for (const [index, arg] of args.entries()) {
if (fields[index]) {
config = fields[index]
}
if (!config) {
continue
}
if ("in" in config) {
if (config.key) {
const field = map.get(config.key)!
const name = field.map || config.key
;(params[field.in] as Record<string, unknown>)[name] = arg
} else {
params.body = arg
}
} else {
for (const [key, value] of Object.entries(arg ?? {})) {
const field = map.get(key)
if (field) {
const name = field.map || key
;(params[field.in] as Record<string, unknown>)[name] = value
} else {
const extra = extraPrefixes.find(([prefix]) => key.startsWith(prefix))
if (extra) {
const [prefix, slot] = extra
;(params[slot] as Record<string, unknown>)[key.slice(prefix.length)] = value
} else {
for (const [slot, allowed] of Object.entries(config.allowExtra ?? {})) {
if (allowed) {
;(params[slot as Slot] as Record<string, unknown>)[key] = value
break
}
}
}
}
}
}
}
stripEmptySlots(params)
return params
}
|