@redocly/cli 2.47.0 → 2.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/chunks/{TEQA5OM7.js → 2GJPOM5H.js} +1 -1
- package/lib/chunks/{W2NJCZOS.js → 3CR6IHZV.js} +1 -1
- package/lib/chunks/3JJEI7CJ.js +456 -0
- package/lib/chunks/{QRD3XQNU.js → 3M6ARSHY.js} +1 -1
- package/lib/chunks/3X52NOC5.js +7 -0
- package/lib/chunks/46OWEERC.js +19 -0
- package/lib/chunks/4IA3ZTGK.js +20 -0
- package/lib/chunks/{TO2KJ36N.js → 5E3L4HJN.js} +1 -1
- package/lib/chunks/5EG7SNNU.js +177 -0
- package/lib/chunks/5L3FH5WQ.js +16 -0
- package/lib/chunks/5L5WOOWA.js +7 -0
- package/lib/chunks/5ZEWVWOC.js +14 -0
- package/lib/chunks/6O3ZHZZ2.js +7 -0
- package/lib/chunks/{KEUH3PST.js → AJZAID3R.js} +1 -1
- package/lib/chunks/BD5JG7YZ.js +7 -0
- package/lib/chunks/{B6HS7CVY.js → BEOYUN4L.js} +48 -48
- package/lib/chunks/CF5YCHNA.js +7 -0
- package/lib/chunks/D27SC2KR.js +90 -0
- package/lib/chunks/{SN2EC2ZR.js → DYAVWTVD.js} +1 -1
- package/lib/chunks/E35Q6YJN.js +7 -0
- package/lib/chunks/EB2V4VMP.js +7 -0
- package/lib/chunks/{QVV2EKMT.js → FL3CA53Z.js} +1 -1
- package/lib/chunks/FVBSRIWC.js +18 -0
- package/lib/chunks/G2XR6TRU.js +67 -0
- package/lib/chunks/G3YJARF7.js +57 -0
- package/lib/chunks/GA6WYGKY.js +7 -0
- package/lib/chunks/GBRES7WG.js +5400 -0
- package/lib/chunks/GHPAE4DZ.js +20 -0
- package/lib/chunks/{SL6AH3N2.js → GJRJZYC4.js} +1 -1
- package/lib/chunks/{REBHK2JR.js → GOJNDGZT.js} +1 -1
- package/lib/chunks/HJYFWIVE.js +9 -0
- package/lib/chunks/HLZCPNF7.js +16 -0
- package/lib/chunks/KIQI3UBS.js +177 -0
- package/lib/chunks/KNPQJVYA.js +14 -0
- package/lib/chunks/L3TZNNJJ.js +13 -0
- package/lib/chunks/{34J2ZJDK.js → LUC2DWUK.js} +1 -1
- package/lib/chunks/MBHFDTYI.js +78 -0
- package/lib/chunks/NB54XRRU.js +10 -0
- package/lib/chunks/NSIQWNYL.js +7 -0
- package/lib/chunks/NWMTC4AN.js +7 -0
- package/lib/chunks/PFYPTG4G.js +7 -0
- package/lib/chunks/{5NR4DJW4.js → PVM7EVWV.js} +1 -1
- package/lib/chunks/Q5FNL2RM.js +22 -0
- package/lib/chunks/QW5MTOU2.js +22 -0
- package/lib/chunks/REFX2EKS.js +13 -0
- package/lib/chunks/S4GQKQ5G.js +7 -0
- package/lib/chunks/SGBB4RNM.js +11 -0
- package/lib/chunks/{YQW463Z7.js → SPPRUUK3.js} +1 -1
- package/lib/chunks/SQVG3CEM.js +8 -0
- package/lib/chunks/TSB6PODJ.js +13 -0
- package/lib/chunks/U2A6GEAN.js +42 -0
- package/lib/chunks/UDBINQ2S.js +42 -0
- package/lib/chunks/UKSQ7B5H.js +2268 -0
- package/lib/chunks/{QL4V2A4A.js → V3JMSQFP.js} +1 -1
- package/lib/chunks/VWSPU27A.js +30 -0
- package/lib/chunks/W62VKXGM.js +26 -0
- package/lib/chunks/WIZYCYZG.js +7 -0
- package/lib/chunks/XDK4JK3V.js +9 -0
- package/lib/chunks/{5PXRDPHV.js → YJGI7CZ2.js} +1 -1
- package/lib/chunks/YQS3OX36.js +11 -0
- package/lib/chunks/{S4MX7JPH.js → Z2AXUXMK.js} +1 -1
- package/lib/chunks/ZBL4IVEW.js +11 -0
- package/lib/chunks/ZGMTMVBB.js +19 -0
- package/lib/chunks/{RIFZSMUA.js → ZVUMPMHU.js} +1 -1
- package/lib/eject-assets/AGENTS.md +137 -0
- package/lib/eject-assets/generators/cli/docs.ts +224 -0
- package/lib/eject-assets/generators/cli/engine-source.ts +21 -0
- package/lib/eject-assets/generators/cli/index.ts +90 -0
- package/lib/eject-assets/generators/cli/render.ts +348 -0
- package/lib/eject-assets/generators/go/client.ts +57 -0
- package/lib/eject-assets/generators/go/descriptor.ts +41 -0
- package/lib/eject-assets/generators/go/index.ts +336 -0
- package/lib/eject-assets/generators/go/models.ts +179 -0
- package/lib/eject-assets/generators/go/naming.ts +49 -0
- package/lib/eject-assets/generators/go/operations.ts +296 -0
- package/lib/eject-assets/generators/go/pagination.ts +194 -0
- package/lib/eject-assets/generators/go/types.ts +60 -0
- package/lib/eject-assets/generators/mock/faker.ts +214 -0
- package/lib/eject-assets/generators/mock/index.ts +35 -0
- package/lib/eject-assets/generators/mock/render.ts +282 -0
- package/lib/eject-assets/generators/mock/sample.ts +316 -0
- package/lib/eject-assets/generators/mock/values.ts +63 -0
- package/lib/eject-assets/generators/php/client.ts +63 -0
- package/lib/eject-assets/generators/php/descriptor.ts +58 -0
- package/lib/eject-assets/generators/php/index.ts +237 -0
- package/lib/eject-assets/generators/php/models.ts +275 -0
- package/lib/eject-assets/generators/php/naming.ts +51 -0
- package/lib/eject-assets/generators/php/operations.ts +232 -0
- package/lib/eject-assets/generators/php/pagination.ts +133 -0
- package/lib/eject-assets/generators/php/types.ts +148 -0
- package/lib/eject-assets/generators/python/client.ts +123 -0
- package/lib/eject-assets/generators/python/descriptor.ts +52 -0
- package/lib/eject-assets/generators/python/index.ts +251 -0
- package/lib/eject-assets/generators/python/models.ts +242 -0
- package/lib/eject-assets/generators/python/naming.ts +46 -0
- package/lib/eject-assets/generators/python/operations.ts +147 -0
- package/lib/eject-assets/generators/python/pagination.ts +128 -0
- package/lib/eject-assets/generators/python/types.ts +54 -0
- package/lib/eject-assets/generators/swr/index.ts +37 -0
- package/lib/eject-assets/generators/swr/render.ts +78 -0
- package/lib/eject-assets/generators/tanstack-query/index.ts +48 -0
- package/lib/eject-assets/generators/tanstack-query/render.ts +346 -0
- package/lib/eject-assets/generators/transformers/index.ts +46 -0
- package/lib/eject-assets/generators/transformers/render.ts +506 -0
- package/lib/eject-assets/generators/typescript/banner.ts +35 -0
- package/lib/eject-assets/generators/typescript/client.ts +254 -0
- package/lib/eject-assets/generators/typescript/descriptor.ts +137 -0
- package/lib/eject-assets/generators/typescript/index.ts +101 -0
- package/lib/eject-assets/generators/typescript/inline-runtime.ts +135 -0
- package/lib/eject-assets/generators/typescript/operation-signature.ts +62 -0
- package/lib/eject-assets/generators/typescript/operation-types.ts +17 -0
- package/lib/eject-assets/generators/typescript/operations.ts +524 -0
- package/lib/eject-assets/generators/typescript/response-headers.ts +74 -0
- package/lib/eject-assets/generators/typescript/type-guards.ts +159 -0
- package/lib/eject-assets/generators/typescript/types.ts +172 -0
- package/lib/eject-assets/generators/zod/index.ts +32 -0
- package/lib/eject-assets/generators/zod/schemas.ts +456 -0
- package/lib/eject-assets/skills/cli-generator/SKILL.md +121 -0
- package/lib/eject-assets/skills/client-generators/SKILL.md +142 -0
- package/lib/eject-assets/skills/go-generator/SKILL.md +96 -0
- package/lib/eject-assets/skills/mock-generator/SKILL.md +50 -0
- package/lib/eject-assets/skills/php-generator/SKILL.md +112 -0
- package/lib/eject-assets/skills/python-generator/SKILL.md +110 -0
- package/lib/eject-assets/skills/swr-generator/SKILL.md +50 -0
- package/lib/eject-assets/skills/tanstack-query-generator/SKILL.md +55 -0
- package/lib/eject-assets/skills/transformers-generator/SKILL.md +47 -0
- package/lib/eject-assets/skills/typescript-generator/SKILL.md +95 -0
- package/lib/eject-assets/skills/zod-generator/SKILL.md +54 -0
- package/lib/index.js +272 -193
- package/package.json +1 -1
- package/lib/chunks/PIJLRHNN.js +0 -8
- package/lib/chunks/Y5HLCNL5.js +0 -2542
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
// Ejected from @redocly/client-generator@0.4.0 — the built-in "go" generator.
|
|
2
|
+
// This file is yours: edit freely; the generated client stays machine-owned and is
|
|
3
|
+
// rebuilt by `redocly generate-client`. Newer generator versions merge in with
|
|
4
|
+
// `redocly eject-generator go --update`.
|
|
5
|
+
// The `operations` stage: one typed request method per operation, plus the
|
|
6
|
+
// argument and envelope-header planning it shares with the pagination wrappers.
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
type ApiModel,
|
|
10
|
+
type DateType,
|
|
11
|
+
headerCoerceType,
|
|
12
|
+
isMultipartBody,
|
|
13
|
+
jsonSuccessSchema,
|
|
14
|
+
type OperationModel,
|
|
15
|
+
type ParamModel,
|
|
16
|
+
sseResponse,
|
|
17
|
+
uniqueIdentifiers,
|
|
18
|
+
} from '@redocly/client-generator';
|
|
19
|
+
import { exported, type GoPrinter } from '@redocly/client-generator/printers/go';
|
|
20
|
+
|
|
21
|
+
import { GO, naming } from './naming.ts';
|
|
22
|
+
import { goType } from './types.ts';
|
|
23
|
+
|
|
24
|
+
/** A query-value expression formatted to string for url.Values. */
|
|
25
|
+
export function goQueryFormat(expr: string, type: string): string {
|
|
26
|
+
if (type === 'string') return expr;
|
|
27
|
+
// Dates serialize in their wire layout, not Go's default String(). A dereferenced
|
|
28
|
+
// pointer needs parentheses: `*p.Format(…)` would deref Format's result.
|
|
29
|
+
const receiver = expr.startsWith('*') ? `(${expr})` : expr;
|
|
30
|
+
if (type === 'time.Time') return `${receiver}.Format(time.RFC3339)`;
|
|
31
|
+
if (type === 'Date') return `${receiver}.Format("2006-01-02")`;
|
|
32
|
+
if (type === 'int64') return `strconv.FormatInt(${expr}, 10)`;
|
|
33
|
+
if (type === 'float64') return `strconv.FormatFloat(${expr}, 'f', -1, 64)`;
|
|
34
|
+
if (type === 'bool') return `strconv.FormatBool(${expr})`;
|
|
35
|
+
return `fmt.Sprint(${expr})`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* The argument names a method declares beside its path parameters: the receiver, the
|
|
40
|
+
* context, the request body, and the query struct.
|
|
41
|
+
*/
|
|
42
|
+
const METHOD_ARG_SLOTS = ['c', 'ctx', 'body', 'params', 'out', 'op'];
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Path parameters as Go arguments, uniquely named. A parameter named after one of the
|
|
46
|
+
* method's own arguments (or a name a description reuses across locations) moves aside as
|
|
47
|
+
* `id2` — Go rejects a duplicate parameter, and the wire name is untouched either way.
|
|
48
|
+
*/
|
|
49
|
+
export function pathArguments(
|
|
50
|
+
op: OperationModel,
|
|
51
|
+
dateType: DateType
|
|
52
|
+
): Array<{ param: ParamModel; go: string; type: string }> {
|
|
53
|
+
const names = uniqueIdentifiers(
|
|
54
|
+
op.pathParams.map((param) => param.name),
|
|
55
|
+
{ style: 'camel', reserved: GO, taken: METHOD_ARG_SLOTS }
|
|
56
|
+
);
|
|
57
|
+
return op.pathParams.map((param, index) => ({
|
|
58
|
+
param,
|
|
59
|
+
go: names[index],
|
|
60
|
+
type: goType(param.schema, dateType),
|
|
61
|
+
}));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/** Declared response headers planned for the `<Op>Headers` struct: field, wire name, coerce helper. */
|
|
65
|
+
function envelopeHeaderPlan(
|
|
66
|
+
op: OperationModel,
|
|
67
|
+
model: ApiModel
|
|
68
|
+
): Array<{ field: string; name: string; goType: string; helper: string }> {
|
|
69
|
+
const used = new Set<string>();
|
|
70
|
+
return (op.successResponseHeaders ?? []).map((header) => {
|
|
71
|
+
const base = exported(header.name);
|
|
72
|
+
let field = base;
|
|
73
|
+
let suffix = 2;
|
|
74
|
+
while (used.has(field)) field = `${base}${suffix++}`;
|
|
75
|
+
used.add(field);
|
|
76
|
+
const coerce = headerCoerceType(header.schema, model);
|
|
77
|
+
const mapping = {
|
|
78
|
+
integer: { goType: '*int64', helper: 'headerInt64' },
|
|
79
|
+
number: { goType: '*float64', helper: 'headerFloat64' },
|
|
80
|
+
boolean: { goType: '*bool', helper: 'headerBool' },
|
|
81
|
+
string: { goType: '*string', helper: 'headerString' },
|
|
82
|
+
}[coerce];
|
|
83
|
+
return { field, name: header.name, ...mapping };
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function writeGoMethod(
|
|
88
|
+
printer: GoPrinter,
|
|
89
|
+
op: OperationModel,
|
|
90
|
+
ident: string,
|
|
91
|
+
dateType: DateType,
|
|
92
|
+
model?: ApiModel,
|
|
93
|
+
envelope = false
|
|
94
|
+
): void {
|
|
95
|
+
const pathArgs = pathArguments(op, dateType);
|
|
96
|
+
const hasParams = op.queryParams.length > 0;
|
|
97
|
+
const success = jsonSuccessSchema(op);
|
|
98
|
+
const returnType = success === undefined ? undefined : goType(success, dateType);
|
|
99
|
+
const headerPlan = envelope ? envelopeHeaderPlan(op, model!) : [];
|
|
100
|
+
if (envelope) {
|
|
101
|
+
printer.line(
|
|
102
|
+
`// ${ident}Headers carries the declared response headers of ${ident}WithHeaders (nil when absent or unparsable).`
|
|
103
|
+
);
|
|
104
|
+
printer.block(
|
|
105
|
+
`type ${ident}Headers struct {`,
|
|
106
|
+
() => {
|
|
107
|
+
for (const planned of headerPlan) printer.line(`${planned.field} ${planned.goType}`);
|
|
108
|
+
},
|
|
109
|
+
'}'
|
|
110
|
+
);
|
|
111
|
+
printer.blank();
|
|
112
|
+
}
|
|
113
|
+
const args = [
|
|
114
|
+
'ctx context.Context',
|
|
115
|
+
...pathArgs.map(({ go, type }) => `${go} ${type}`),
|
|
116
|
+
...(op.requestBody ? [`body ${goType(op.requestBody.schema, dateType)}`] : []),
|
|
117
|
+
...(hasParams ? [`params *${ident}Params`] : []),
|
|
118
|
+
];
|
|
119
|
+
const sse = sseResponse(op);
|
|
120
|
+
const returns = envelope
|
|
121
|
+
? returnType === undefined
|
|
122
|
+
? `(${ident}Headers, error)`
|
|
123
|
+
: `(${returnType}, ${ident}Headers, error)`
|
|
124
|
+
: sse !== undefined
|
|
125
|
+
? 'func(yield func(ServerSentEvent, error) bool)'
|
|
126
|
+
: returnType === undefined
|
|
127
|
+
? 'error'
|
|
128
|
+
: `(${returnType}, error)`;
|
|
129
|
+
const fail = (errExpr: string) =>
|
|
130
|
+
envelope
|
|
131
|
+
? returnType === undefined
|
|
132
|
+
? `return headers, ${errExpr}`
|
|
133
|
+
: `return out, headers, ${errExpr}`
|
|
134
|
+
: returnType === undefined
|
|
135
|
+
? `return ${errExpr}`
|
|
136
|
+
: `return out, ${errExpr}`;
|
|
137
|
+
const funcName = envelope ? `${ident}WithHeaders` : ident;
|
|
138
|
+
printer.doc(
|
|
139
|
+
funcName,
|
|
140
|
+
envelope ? `Like ${ident}, also returning the declared response headers.` : op.summary
|
|
141
|
+
);
|
|
142
|
+
printer.block(
|
|
143
|
+
`func (c *Client) ${funcName}(${args.join(', ')}) ${returns} {`,
|
|
144
|
+
() => {
|
|
145
|
+
if (sse === undefined && returnType !== undefined) printer.line(`var out ${returnType}`);
|
|
146
|
+
if (envelope) printer.line(`var headers ${ident}Headers`);
|
|
147
|
+
printer.line(`op := operations[${naming.string(op.specName ?? op.name)}]`);
|
|
148
|
+
printer.line('authHeaders, query := resolveAuth(op.Security, c.config.Auth)');
|
|
149
|
+
if (hasParams) {
|
|
150
|
+
printer.block(
|
|
151
|
+
'if params != nil {',
|
|
152
|
+
() => {
|
|
153
|
+
for (const param of op.queryParams) {
|
|
154
|
+
const field = exported(param.name);
|
|
155
|
+
printer.block(
|
|
156
|
+
`if params.${field} != nil {`,
|
|
157
|
+
() => {
|
|
158
|
+
// An array repeats the key per element (OpenAPI `form` + `explode`, the
|
|
159
|
+
// default — and what the TS runtime sends). `fmt.Sprint` of a slice
|
|
160
|
+
// would put `[a b]` on the wire as one value.
|
|
161
|
+
if (param.schema.kind === 'array') {
|
|
162
|
+
const elementType = goType(param.schema.items, dateType);
|
|
163
|
+
printer.block(
|
|
164
|
+
`for _, item := range *params.${field} {`,
|
|
165
|
+
() => {
|
|
166
|
+
printer.line(
|
|
167
|
+
`query.Add(${naming.string(param.name)}, ${goQueryFormat('item', elementType)})`
|
|
168
|
+
);
|
|
169
|
+
},
|
|
170
|
+
'}'
|
|
171
|
+
);
|
|
172
|
+
} else {
|
|
173
|
+
printer.line(
|
|
174
|
+
`query.Set(${naming.string(param.name)}, ${goQueryFormat(`*params.${field}`, goType(param.schema, dateType))})`
|
|
175
|
+
);
|
|
176
|
+
}
|
|
177
|
+
},
|
|
178
|
+
'}'
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
},
|
|
182
|
+
'}'
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
const pathDict = pathArgs
|
|
186
|
+
.map(({ param, go, type }) => `${naming.string(param.name)}: ${goQueryFormat(go, type)}`)
|
|
187
|
+
.join(', ');
|
|
188
|
+
printer.line(
|
|
189
|
+
`requestURL := buildURL(c.config.ServerURL, op.Path, map[string]string{${pathDict}})`
|
|
190
|
+
);
|
|
191
|
+
if (sse !== undefined) {
|
|
192
|
+
printer.block(
|
|
193
|
+
'open := func(extraHeaders map[string]string) (*http.Response, error) {',
|
|
194
|
+
() => {
|
|
195
|
+
printer.line('merged := map[string]string{}');
|
|
196
|
+
printer.block(
|
|
197
|
+
'for key, value := range authHeaders {',
|
|
198
|
+
() => {
|
|
199
|
+
printer.line('merged[key] = value');
|
|
200
|
+
},
|
|
201
|
+
'}'
|
|
202
|
+
);
|
|
203
|
+
printer.block(
|
|
204
|
+
'for key, value := range extraHeaders {',
|
|
205
|
+
() => {
|
|
206
|
+
printer.line('merged[key] = value');
|
|
207
|
+
},
|
|
208
|
+
'}'
|
|
209
|
+
);
|
|
210
|
+
printer.line(
|
|
211
|
+
'return send(ctx, &c.config, requestSpec{OperationID: op.ID, Method: op.Method, URL: requestURL, Headers: merged, Query: query})'
|
|
212
|
+
);
|
|
213
|
+
},
|
|
214
|
+
'}'
|
|
215
|
+
);
|
|
216
|
+
printer.line(
|
|
217
|
+
`return iterSSE(open, ${sse.schema !== undefined && sse.schema.kind !== 'unknown'})`
|
|
218
|
+
);
|
|
219
|
+
return;
|
|
220
|
+
}
|
|
221
|
+
const specFields = [
|
|
222
|
+
'OperationID: op.ID',
|
|
223
|
+
'Method: op.Method',
|
|
224
|
+
'URL: requestURL',
|
|
225
|
+
'Headers: authHeaders',
|
|
226
|
+
'Query: query',
|
|
227
|
+
];
|
|
228
|
+
if (op.requestBody && isMultipartBody(op)) {
|
|
229
|
+
printer.line('contentType, reader, err := toMultipart(body)');
|
|
230
|
+
printer.block(
|
|
231
|
+
'if err != nil {',
|
|
232
|
+
() => {
|
|
233
|
+
printer.line(fail('err'));
|
|
234
|
+
},
|
|
235
|
+
'}'
|
|
236
|
+
);
|
|
237
|
+
specFields.push('Body: reader');
|
|
238
|
+
specFields.push('ContentType: contentType');
|
|
239
|
+
} else if (op.requestBody) {
|
|
240
|
+
printer.line('payload, err := json.Marshal(body)');
|
|
241
|
+
printer.block(
|
|
242
|
+
'if err != nil {',
|
|
243
|
+
() => {
|
|
244
|
+
printer.line(fail('err'));
|
|
245
|
+
},
|
|
246
|
+
'}'
|
|
247
|
+
);
|
|
248
|
+
specFields.push('Body: bytes.NewReader(payload)');
|
|
249
|
+
specFields.push(`ContentType: ${naming.string(op.requestBody.contentType)}`);
|
|
250
|
+
}
|
|
251
|
+
printer.line(`resp, err := send(ctx, &c.config, requestSpec{${specFields.join(', ')}})`);
|
|
252
|
+
printer.block(
|
|
253
|
+
'if err != nil {',
|
|
254
|
+
() => {
|
|
255
|
+
printer.line(fail('err'));
|
|
256
|
+
},
|
|
257
|
+
'}'
|
|
258
|
+
);
|
|
259
|
+
printer.block(
|
|
260
|
+
'if resp.StatusCode >= 400 {',
|
|
261
|
+
() => {
|
|
262
|
+
printer.line(fail('apiErrorFrom(resp, requestURL)'));
|
|
263
|
+
},
|
|
264
|
+
'}'
|
|
265
|
+
);
|
|
266
|
+
if (envelope) {
|
|
267
|
+
printer.block(
|
|
268
|
+
`if err := decodeJSON(resp, ${returnType === undefined ? 'nil' : '&out'}); err != nil {`,
|
|
269
|
+
() => {
|
|
270
|
+
printer.line(fail('err'));
|
|
271
|
+
},
|
|
272
|
+
'}'
|
|
273
|
+
);
|
|
274
|
+
for (const planned of headerPlan) {
|
|
275
|
+
printer.line(
|
|
276
|
+
`headers.${planned.field} = ${planned.helper}(resp.Header, ${naming.string(planned.name)})`
|
|
277
|
+
);
|
|
278
|
+
}
|
|
279
|
+
printer.line(returnType === undefined ? 'return headers, nil' : 'return out, headers, nil');
|
|
280
|
+
} else if (returnType === undefined) {
|
|
281
|
+
printer.line('return decodeJSON(resp, nil)');
|
|
282
|
+
} else {
|
|
283
|
+
printer.block(
|
|
284
|
+
'if err := decodeJSON(resp, &out); err != nil {',
|
|
285
|
+
() => {
|
|
286
|
+
printer.line('return out, err');
|
|
287
|
+
},
|
|
288
|
+
'}'
|
|
289
|
+
);
|
|
290
|
+
printer.line('return out, nil');
|
|
291
|
+
}
|
|
292
|
+
},
|
|
293
|
+
'}'
|
|
294
|
+
);
|
|
295
|
+
printer.blank();
|
|
296
|
+
}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// Ejected from @redocly/client-generator@0.4.0 — the built-in "go" generator.
|
|
2
|
+
// This file is yours: edit freely; the generated client stays machine-owned and is
|
|
3
|
+
// rebuilt by `redocly generate-client`. Newer generator versions merge in with
|
|
4
|
+
// `redocly eject-generator go --update`.
|
|
5
|
+
// The `pagination` stage: the `<Op>Pages` / `<Op>Items` yield-func iterators.
|
|
6
|
+
|
|
7
|
+
import { type DateType, type OperationModel } from '@redocly/client-generator';
|
|
8
|
+
import { exported, type GoPrinter } from '@redocly/client-generator/printers/go';
|
|
9
|
+
|
|
10
|
+
import { naming } from './naming.ts';
|
|
11
|
+
import { goQueryFormat, pathArguments } from './operations.ts';
|
|
12
|
+
import { goType } from './types.ts';
|
|
13
|
+
|
|
14
|
+
/** `<Op>Pages` / `<Op>Items` iterators over the runtime's `iterPages`, hydrated via `reencode`. */
|
|
15
|
+
export function writeGoPaginationWrappers(
|
|
16
|
+
printer: GoPrinter,
|
|
17
|
+
op: OperationModel,
|
|
18
|
+
ident: string,
|
|
19
|
+
dateType: DateType,
|
|
20
|
+
pageType: string,
|
|
21
|
+
itemType: string
|
|
22
|
+
): void {
|
|
23
|
+
const pathArgs = pathArguments(op, dateType);
|
|
24
|
+
const hasParams = op.queryParams.length > 0;
|
|
25
|
+
const args = [
|
|
26
|
+
'ctx context.Context',
|
|
27
|
+
...pathArgs.map(({ go, type }) => `${go} ${type}`),
|
|
28
|
+
...(hasParams ? [`params *${ident}Params`] : []),
|
|
29
|
+
].join(', ');
|
|
30
|
+
|
|
31
|
+
const writeCallClosure = () => {
|
|
32
|
+
printer.line(`op := operations[${naming.string(op.specName ?? op.name)}]`);
|
|
33
|
+
printer.line('base := url.Values{}');
|
|
34
|
+
if (hasParams) {
|
|
35
|
+
printer.block(
|
|
36
|
+
'if params != nil {',
|
|
37
|
+
() => {
|
|
38
|
+
for (const param of op.queryParams) {
|
|
39
|
+
const field = exported(param.name);
|
|
40
|
+
printer.block(
|
|
41
|
+
`if params.${field} != nil {`,
|
|
42
|
+
() => {
|
|
43
|
+
printer.line(
|
|
44
|
+
`base.Set(${naming.string(param.name)}, ${goQueryFormat(`*params.${field}`, goType(param.schema, dateType))})`
|
|
45
|
+
);
|
|
46
|
+
},
|
|
47
|
+
'}'
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
},
|
|
51
|
+
'}'
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
printer.block(
|
|
55
|
+
'call := func(pageParams url.Values) (any, *http.Response, error) {',
|
|
56
|
+
() => {
|
|
57
|
+
printer.line('authHeaders, query := resolveAuth(op.Security, c.config.Auth)');
|
|
58
|
+
printer.block(
|
|
59
|
+
'for key, values := range pageParams {',
|
|
60
|
+
() => {
|
|
61
|
+
printer.block(
|
|
62
|
+
'for _, value := range values {',
|
|
63
|
+
() => {
|
|
64
|
+
printer.line('query.Set(key, value)');
|
|
65
|
+
},
|
|
66
|
+
'}'
|
|
67
|
+
);
|
|
68
|
+
},
|
|
69
|
+
'}'
|
|
70
|
+
);
|
|
71
|
+
const pathDict = pathArgs
|
|
72
|
+
.map(({ param, go, type }) => `${naming.string(param.name)}: ${goQueryFormat(go, type)}`)
|
|
73
|
+
.join(', ');
|
|
74
|
+
printer.line(
|
|
75
|
+
`requestURL := buildURL(c.config.ServerURL, op.Path, map[string]string{${pathDict}})`
|
|
76
|
+
);
|
|
77
|
+
printer.line(
|
|
78
|
+
'resp, err := send(ctx, &c.config, requestSpec{OperationID: op.ID, Method: op.Method, URL: requestURL, Headers: authHeaders, Query: query})'
|
|
79
|
+
);
|
|
80
|
+
printer.block(
|
|
81
|
+
'if err != nil {',
|
|
82
|
+
() => {
|
|
83
|
+
printer.line('return nil, nil, err');
|
|
84
|
+
},
|
|
85
|
+
'}'
|
|
86
|
+
);
|
|
87
|
+
printer.block(
|
|
88
|
+
'if resp.StatusCode >= 400 {',
|
|
89
|
+
() => {
|
|
90
|
+
printer.line('return nil, resp, apiErrorFrom(resp, requestURL)');
|
|
91
|
+
},
|
|
92
|
+
'}'
|
|
93
|
+
);
|
|
94
|
+
printer.line('var raw any');
|
|
95
|
+
printer.block(
|
|
96
|
+
'if err := decodeJSON(resp, &raw); err != nil {',
|
|
97
|
+
() => {
|
|
98
|
+
printer.line('return nil, resp, err');
|
|
99
|
+
},
|
|
100
|
+
'}'
|
|
101
|
+
);
|
|
102
|
+
printer.line('return raw, resp, nil');
|
|
103
|
+
},
|
|
104
|
+
'}'
|
|
105
|
+
);
|
|
106
|
+
printer.line('pages := iterPages(call, *op.Pagination, base)');
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
printer.line(
|
|
110
|
+
`// ${ident}Pages iterates ${ident} response pages; use with \`for page, err := range\`.`
|
|
111
|
+
);
|
|
112
|
+
printer.block(
|
|
113
|
+
`func (c *Client) ${ident}Pages(${args}) func(yield func(${pageType}, error) bool) {`,
|
|
114
|
+
() => {
|
|
115
|
+
writeCallClosure();
|
|
116
|
+
printer.block(
|
|
117
|
+
`return func(yield func(${pageType}, error) bool) {`,
|
|
118
|
+
() => {
|
|
119
|
+
printer.block(
|
|
120
|
+
'pages(func(raw any, err error) bool {',
|
|
121
|
+
() => {
|
|
122
|
+
printer.line(`var page ${pageType}`);
|
|
123
|
+
printer.block(
|
|
124
|
+
'if err == nil {',
|
|
125
|
+
() => {
|
|
126
|
+
printer.line('err = reencode(raw, &page)');
|
|
127
|
+
},
|
|
128
|
+
'}'
|
|
129
|
+
);
|
|
130
|
+
printer.line('return yield(page, err)');
|
|
131
|
+
},
|
|
132
|
+
'})'
|
|
133
|
+
);
|
|
134
|
+
},
|
|
135
|
+
'}'
|
|
136
|
+
);
|
|
137
|
+
},
|
|
138
|
+
'}'
|
|
139
|
+
);
|
|
140
|
+
printer.blank();
|
|
141
|
+
|
|
142
|
+
printer.line(`// ${ident}Items iterates the items of every ${ident} page.`);
|
|
143
|
+
printer.block(
|
|
144
|
+
`func (c *Client) ${ident}Items(${args}) func(yield func(${itemType}, error) bool) {`,
|
|
145
|
+
() => {
|
|
146
|
+
writeCallClosure();
|
|
147
|
+
printer.block(
|
|
148
|
+
`return func(yield func(${itemType}, error) bool) {`,
|
|
149
|
+
() => {
|
|
150
|
+
printer.block(
|
|
151
|
+
'pages(func(raw any, err error) bool {',
|
|
152
|
+
() => {
|
|
153
|
+
printer.block(
|
|
154
|
+
'if err != nil {',
|
|
155
|
+
() => {
|
|
156
|
+
printer.line(`var zero ${itemType}`);
|
|
157
|
+
printer.line('return yield(zero, err)');
|
|
158
|
+
},
|
|
159
|
+
'}'
|
|
160
|
+
);
|
|
161
|
+
printer.line('pageItems, _ := resolvePointer(raw, op.Pagination.Items).([]any)');
|
|
162
|
+
printer.block(
|
|
163
|
+
'for _, item := range pageItems {',
|
|
164
|
+
() => {
|
|
165
|
+
printer.line(`var typed ${itemType}`);
|
|
166
|
+
printer.block(
|
|
167
|
+
'if err := reencode(item, &typed); err != nil {',
|
|
168
|
+
() => {
|
|
169
|
+
printer.line('return yield(typed, err)');
|
|
170
|
+
},
|
|
171
|
+
'}'
|
|
172
|
+
);
|
|
173
|
+
printer.block(
|
|
174
|
+
'if !yield(typed, nil) {',
|
|
175
|
+
() => {
|
|
176
|
+
printer.line('return false');
|
|
177
|
+
},
|
|
178
|
+
'}'
|
|
179
|
+
);
|
|
180
|
+
},
|
|
181
|
+
'}'
|
|
182
|
+
);
|
|
183
|
+
printer.line('return true');
|
|
184
|
+
},
|
|
185
|
+
'})'
|
|
186
|
+
);
|
|
187
|
+
},
|
|
188
|
+
'}'
|
|
189
|
+
);
|
|
190
|
+
},
|
|
191
|
+
'}'
|
|
192
|
+
);
|
|
193
|
+
printer.blank();
|
|
194
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Ejected from @redocly/client-generator@0.4.0 — the built-in "go" generator.
|
|
2
|
+
// This file is yours: edit freely; the generated client stays machine-owned and is
|
|
3
|
+
// rebuilt by `redocly generate-client`. Newer generator versions merge in with
|
|
4
|
+
// `redocly eject-generator go --update`.
|
|
5
|
+
// The `types` stage: the Go type annotation for a schema.
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
type DateType,
|
|
9
|
+
isNullable,
|
|
10
|
+
type SchemaModel,
|
|
11
|
+
unwrapNullable,
|
|
12
|
+
} from '@redocly/client-generator';
|
|
13
|
+
import { exported } from '@redocly/client-generator/printers/go';
|
|
14
|
+
|
|
15
|
+
/** The Go type for a schema; `required=false` optionals become pointers at the field site. */
|
|
16
|
+
export function goType(schema: SchemaModel, dateType: DateType = 'string'): string {
|
|
17
|
+
if (isNullable(schema)) {
|
|
18
|
+
const inner = goType(unwrapNullable(schema), dateType);
|
|
19
|
+
return inner.startsWith('*') || inner === 'any' ? inner : `*${inner}`;
|
|
20
|
+
}
|
|
21
|
+
switch (schema.kind) {
|
|
22
|
+
case 'scalar':
|
|
23
|
+
// Under `dateType: Date`, a date-time is a time.Time (encoding/json handles
|
|
24
|
+
// RFC 3339 natively) and a bare date is the runtime's `Date` wrapper.
|
|
25
|
+
if (dateType === 'Date' && schema.scalar === 'string') {
|
|
26
|
+
if (schema.metadata?.format === 'date-time') return 'time.Time';
|
|
27
|
+
if (schema.metadata?.format === 'date') return 'Date';
|
|
28
|
+
}
|
|
29
|
+
return { string: 'string', integer: 'int64', number: 'float64', boolean: 'bool' }[
|
|
30
|
+
schema.scalar
|
|
31
|
+
];
|
|
32
|
+
case 'array':
|
|
33
|
+
return `[]${goType(schema.items, dateType)}`;
|
|
34
|
+
case 'record':
|
|
35
|
+
return `map[string]${goType(schema.value, dateType)}`;
|
|
36
|
+
case 'ref':
|
|
37
|
+
return exported(schema.name);
|
|
38
|
+
case 'literal':
|
|
39
|
+
return typeof schema.value === 'string'
|
|
40
|
+
? 'string'
|
|
41
|
+
: typeof schema.value === 'boolean'
|
|
42
|
+
? 'bool'
|
|
43
|
+
: 'float64';
|
|
44
|
+
case 'enum':
|
|
45
|
+
// Anonymous (inline) enums keep the wire scalar; only NAMED enums get types.
|
|
46
|
+
return { string: 'string', integer: 'int64', number: 'float64', boolean: 'bool' }[
|
|
47
|
+
schema.scalar
|
|
48
|
+
];
|
|
49
|
+
case 'omit':
|
|
50
|
+
// Go has no Omit; the base struct is the honest annotation (readOnly
|
|
51
|
+
// fields are server-managed and simply omitted from requests).
|
|
52
|
+
return exported(schema.base);
|
|
53
|
+
case 'union':
|
|
54
|
+
case 'null':
|
|
55
|
+
case 'object':
|
|
56
|
+
case 'intersection':
|
|
57
|
+
case 'unknown':
|
|
58
|
+
return 'any';
|
|
59
|
+
}
|
|
60
|
+
}
|