@redocly/cli 2.47.0 → 2.49.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.
Files changed (133) hide show
  1. package/lib/chunks/{QRD3XQNU.js → 2U54VUOE.js} +1 -1
  2. package/lib/chunks/3JJEI7CJ.js +456 -0
  3. package/lib/chunks/4I2OVMBJ.js +11 -0
  4. package/lib/chunks/{REBHK2JR.js → 4JDAOKRJ.js} +1 -1
  5. package/lib/chunks/5JIGUBC3.js +7 -0
  6. package/lib/chunks/{QVV2EKMT.js → 5SAFIITS.js} +1 -1
  7. package/lib/chunks/6KCIFTIG.js +57 -0
  8. package/lib/chunks/{5NR4DJW4.js → 6VSHPQXO.js} +1 -1
  9. package/lib/chunks/{W2NJCZOS.js → 74WJ7S7J.js} +1 -1
  10. package/lib/chunks/{QL4V2A4A.js → 7R5PBTLG.js} +1 -1
  11. package/lib/chunks/BT3ELZVX.js +42 -0
  12. package/lib/chunks/C5TR4MMN.js +19 -0
  13. package/lib/chunks/CCR5RYCX.js +20 -0
  14. package/lib/chunks/DCN3GSUA.js +7 -0
  15. package/lib/chunks/{TEQA5OM7.js → E5I67ZCZ.js} +1 -1
  16. package/lib/chunks/FUMCRNTK.js +78 -0
  17. package/lib/chunks/GNMJA2V2.js +16 -0
  18. package/lib/chunks/GRJG3TOI.js +14 -0
  19. package/lib/chunks/HA22GUKQ.js +7 -0
  20. package/lib/chunks/HJ36YGCI.js +184 -0
  21. package/lib/chunks/HJYFWIVE.js +9 -0
  22. package/lib/chunks/HL5FOKC4.js +16 -0
  23. package/lib/chunks/{SL6AH3N2.js → JBNPGEIJ.js} +1 -1
  24. package/lib/chunks/KHEMMNFU.js +26 -0
  25. package/lib/chunks/{SN2EC2ZR.js → KK2STV73.js} +1 -1
  26. package/lib/chunks/KK77ANZH.js +7 -0
  27. package/lib/chunks/L3TZNNJJ.js +13 -0
  28. package/lib/chunks/M6KLAAY4.js +7 -0
  29. package/lib/chunks/MHITBEGC.js +90 -0
  30. package/lib/chunks/NB54XRRU.js +10 -0
  31. package/lib/chunks/NSIQWNYL.js +7 -0
  32. package/lib/chunks/{YQW463Z7.js → NTPLYWAB.js} +1 -1
  33. package/lib/chunks/{5PXRDPHV.js → NUNOXB7Z.js} +1 -1
  34. package/lib/chunks/NWMTC4AN.js +7 -0
  35. package/lib/chunks/NYLAOZPO.js +22 -0
  36. package/lib/chunks/O4R6BSAS.js +20 -0
  37. package/lib/chunks/OKITK6EF.js +30 -0
  38. package/lib/chunks/OUCZOBEX.js +22 -0
  39. package/lib/chunks/PFYPTG4G.js +7 -0
  40. package/lib/chunks/QZH7EL26.js +7 -0
  41. package/lib/chunks/R4XFBOJU.js +9 -0
  42. package/lib/chunks/REFX2EKS.js +13 -0
  43. package/lib/chunks/{S4MX7JPH.js → RXOEH2LN.js} +1 -1
  44. package/lib/chunks/SGBB4RNM.js +11 -0
  45. package/lib/chunks/SQVG3CEM.js +8 -0
  46. package/lib/chunks/{RIFZSMUA.js → T5EPIBMA.js} +1 -1
  47. package/lib/chunks/TLQZAJQU.js +18 -0
  48. package/lib/chunks/TSB6PODJ.js +13 -0
  49. package/lib/chunks/TSRK76GA.js +19 -0
  50. package/lib/chunks/{34J2ZJDK.js → U2H2LXZE.js} +1 -1
  51. package/lib/chunks/UKSQ7B5H.js +2268 -0
  52. package/lib/chunks/UMQN5HTL.js +42 -0
  53. package/lib/chunks/V2LJ4UGM.js +7 -0
  54. package/lib/chunks/VBPP2WUF.js +7 -0
  55. package/lib/chunks/WPGKH5NI.js +177 -0
  56. package/lib/chunks/WXVC3KOI.js +67 -0
  57. package/lib/chunks/{KEUH3PST.js → YI34NB7D.js} +1 -1
  58. package/lib/chunks/YOJGIGE3.js +7 -0
  59. package/lib/chunks/{TO2KJ36N.js → YP5GHFYE.js} +1 -1
  60. package/lib/chunks/YXXYE4G2.js +7 -0
  61. package/lib/chunks/ZBL4IVEW.js +11 -0
  62. package/lib/chunks/ZMCRMR2V.js +5400 -0
  63. package/lib/chunks/ZOUQBK53.js +14 -0
  64. package/lib/chunks/ZXKOHMC6.js +177 -0
  65. package/lib/eject-assets/AGENTS.md +137 -0
  66. package/lib/eject-assets/generators/cli/docs.ts +224 -0
  67. package/lib/eject-assets/generators/cli/engine-source.ts +21 -0
  68. package/lib/eject-assets/generators/cli/index.ts +90 -0
  69. package/lib/eject-assets/generators/cli/render.ts +348 -0
  70. package/lib/eject-assets/generators/go/client.ts +57 -0
  71. package/lib/eject-assets/generators/go/descriptor.ts +41 -0
  72. package/lib/eject-assets/generators/go/index.ts +336 -0
  73. package/lib/eject-assets/generators/go/models.ts +179 -0
  74. package/lib/eject-assets/generators/go/naming.ts +49 -0
  75. package/lib/eject-assets/generators/go/operations.ts +296 -0
  76. package/lib/eject-assets/generators/go/pagination.ts +194 -0
  77. package/lib/eject-assets/generators/go/types.ts +60 -0
  78. package/lib/eject-assets/generators/mock/faker.ts +214 -0
  79. package/lib/eject-assets/generators/mock/index.ts +35 -0
  80. package/lib/eject-assets/generators/mock/render.ts +282 -0
  81. package/lib/eject-assets/generators/mock/sample.ts +316 -0
  82. package/lib/eject-assets/generators/mock/values.ts +63 -0
  83. package/lib/eject-assets/generators/php/client.ts +63 -0
  84. package/lib/eject-assets/generators/php/descriptor.ts +58 -0
  85. package/lib/eject-assets/generators/php/index.ts +237 -0
  86. package/lib/eject-assets/generators/php/models.ts +275 -0
  87. package/lib/eject-assets/generators/php/naming.ts +51 -0
  88. package/lib/eject-assets/generators/php/operations.ts +232 -0
  89. package/lib/eject-assets/generators/php/pagination.ts +133 -0
  90. package/lib/eject-assets/generators/php/types.ts +148 -0
  91. package/lib/eject-assets/generators/python/client.ts +123 -0
  92. package/lib/eject-assets/generators/python/descriptor.ts +52 -0
  93. package/lib/eject-assets/generators/python/index.ts +251 -0
  94. package/lib/eject-assets/generators/python/models.ts +242 -0
  95. package/lib/eject-assets/generators/python/naming.ts +46 -0
  96. package/lib/eject-assets/generators/python/operations.ts +147 -0
  97. package/lib/eject-assets/generators/python/pagination.ts +128 -0
  98. package/lib/eject-assets/generators/python/types.ts +54 -0
  99. package/lib/eject-assets/generators/swr/index.ts +37 -0
  100. package/lib/eject-assets/generators/swr/render.ts +78 -0
  101. package/lib/eject-assets/generators/tanstack-query/index.ts +48 -0
  102. package/lib/eject-assets/generators/tanstack-query/render.ts +346 -0
  103. package/lib/eject-assets/generators/transformers/index.ts +46 -0
  104. package/lib/eject-assets/generators/transformers/render.ts +506 -0
  105. package/lib/eject-assets/generators/typescript/banner.ts +35 -0
  106. package/lib/eject-assets/generators/typescript/client.ts +254 -0
  107. package/lib/eject-assets/generators/typescript/descriptor.ts +137 -0
  108. package/lib/eject-assets/generators/typescript/index.ts +101 -0
  109. package/lib/eject-assets/generators/typescript/inline-runtime.ts +135 -0
  110. package/lib/eject-assets/generators/typescript/operation-signature.ts +62 -0
  111. package/lib/eject-assets/generators/typescript/operation-types.ts +17 -0
  112. package/lib/eject-assets/generators/typescript/operations.ts +524 -0
  113. package/lib/eject-assets/generators/typescript/response-headers.ts +74 -0
  114. package/lib/eject-assets/generators/typescript/type-guards.ts +159 -0
  115. package/lib/eject-assets/generators/typescript/types.ts +172 -0
  116. package/lib/eject-assets/generators/zod/index.ts +32 -0
  117. package/lib/eject-assets/generators/zod/schemas.ts +456 -0
  118. package/lib/eject-assets/skills/cli-generator/SKILL.md +121 -0
  119. package/lib/eject-assets/skills/client-generators/SKILL.md +142 -0
  120. package/lib/eject-assets/skills/go-generator/SKILL.md +96 -0
  121. package/lib/eject-assets/skills/mock-generator/SKILL.md +50 -0
  122. package/lib/eject-assets/skills/php-generator/SKILL.md +112 -0
  123. package/lib/eject-assets/skills/python-generator/SKILL.md +110 -0
  124. package/lib/eject-assets/skills/swr-generator/SKILL.md +50 -0
  125. package/lib/eject-assets/skills/tanstack-query-generator/SKILL.md +55 -0
  126. package/lib/eject-assets/skills/transformers-generator/SKILL.md +47 -0
  127. package/lib/eject-assets/skills/typescript-generator/SKILL.md +95 -0
  128. package/lib/eject-assets/skills/zod-generator/SKILL.md +54 -0
  129. package/lib/index.js +271 -193
  130. package/package.json +1 -1
  131. package/lib/chunks/B6HS7CVY.js +0 -184
  132. package/lib/chunks/PIJLRHNN.js +0 -8
  133. package/lib/chunks/Y5HLCNL5.js +0 -2542
@@ -0,0 +1,296 @@
1
+ // Ejected from @redocly/client-generator@0.4.1 — 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.1 — 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.1 — 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
+ }