@redocly/cli 2.71.2 → 2.72.1

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 (159) hide show
  1. package/README.md +1 -1
  2. package/THIRD_PARTY_NOTICES +29 -7
  3. package/lib/chunks/{EHJ3FMW6.js → 2AW4F6ZZ.js} +1 -1
  4. package/lib/chunks/{3EQNI6CT.js → 2MF3MKAD.js} +1 -1
  5. package/lib/chunks/{UYZXI3NO.js → 2X2KHSF3.js} +1 -1
  6. package/lib/chunks/{YF4FMOTE.js → 3FA5W77S.js} +1 -1
  7. package/lib/chunks/{VPTYPV6P.js → 3FVHXIZN.js} +1 -1
  8. package/lib/chunks/{P5T6BIKW.js → 3N53VPSU.js} +1 -1
  9. package/lib/chunks/{KLGUZBJO.js → 3N73A66H.js} +1 -1
  10. package/lib/chunks/{JO76DPXR.js → 3WOXO2JS.js} +1 -1
  11. package/lib/chunks/{ORWIUECT.js → 4A5R4H5W.js} +1 -1
  12. package/lib/chunks/{NXREEI2S.js → 4LTPQZBP.js} +1 -1
  13. package/lib/chunks/{L325HIGK.js → 4QC7OVHI.js} +1 -1
  14. package/lib/chunks/{FDKY4PGX.js → 542GVIYM.js} +1 -1
  15. package/lib/chunks/5JF6EUWW.js +9 -0
  16. package/lib/chunks/{6X42UQ3O.js → 5MZU5MHZ.js} +1 -1
  17. package/lib/chunks/{DZT5NLUB.js → 5UPBGRBZ.js} +1 -1
  18. package/lib/chunks/{WO6IIVA3.js → 6LZX65VY.js} +8 -8
  19. package/lib/chunks/{NEWT5A6S.js → 6RTITFQA.js} +1 -1
  20. package/lib/chunks/{IQLQH23V.js → 6Y6B2SKE.js} +1 -1
  21. package/lib/chunks/765BYRQR.js +7 -0
  22. package/lib/chunks/{2TG3DP4I.js → 7NZS5HXU.js} +1 -1
  23. package/lib/chunks/{5CR6AOLY.js → A65OW7M7.js} +3 -3
  24. package/lib/chunks/ARUYNQHA.js +7 -0
  25. package/lib/chunks/BJ6Z66KZ.js +7 -0
  26. package/lib/chunks/{T77BOGYV.js → BWGBTYNU.js} +1 -1
  27. package/lib/chunks/{DM4EUYBB.js → BZTZIEWS.js} +2 -2
  28. package/lib/chunks/{4S6LRPCX.js → CBFNHKDJ.js} +1 -1
  29. package/lib/chunks/{OFIQ2EST.js → CYCPHJNX.js} +33 -33
  30. package/lib/chunks/DSBDKSRR.js +53 -0
  31. package/lib/chunks/E2CEKR6N.js +22 -0
  32. package/lib/chunks/{HRZLSSOF.js → EMWHLZB6.js} +1 -1
  33. package/lib/chunks/{DWXDCKZ7.js → ENIFTFYK.js} +1 -1
  34. package/lib/chunks/{BIS2ZFGS.js → ETJMQLWJ.js} +1 -1
  35. package/lib/chunks/{ADACRYTN.js → EU5WR2O3.js} +1 -1
  36. package/lib/chunks/{FAFMGLT6.js → FLQQ3VRQ.js} +1 -1
  37. package/lib/chunks/{BPJTNQBC.js → FZZACVYL.js} +1 -1
  38. package/lib/chunks/{N4GCIKY4.js → G7A4OE2M.js} +1 -1
  39. package/lib/chunks/{HP7UD4BA.js → GCAL2PYM.js} +1 -1
  40. package/lib/chunks/{MJ2NI6MR.js → GGHLD27S.js} +1 -1
  41. package/lib/chunks/{U4MI7HDM.js → GMPHU6KM.js} +1 -1
  42. package/lib/chunks/{HTFKP5HH.js → GWBLS542.js} +1 -1
  43. package/lib/chunks/{U2F3JOT2.js → GXILNSWK.js} +1 -1
  44. package/lib/chunks/{5AVTCY6F.js → HM7M6465.js} +1 -1
  45. package/lib/chunks/{5HPO77VR.js → I2JZXLJ6.js} +2 -2
  46. package/lib/chunks/I3YF3GEY.js +13 -0
  47. package/lib/chunks/{YWRFPTTI.js → IIQW437Z.js} +1 -1
  48. package/lib/chunks/{4H3DPQDW.js → IM4YIUUN.js} +1 -1
  49. package/lib/chunks/{LET2MPMU.js → JDMRVD45.js} +1 -1
  50. package/lib/chunks/{XVS7B4RZ.js → KIFXQTTL.js} +1 -1
  51. package/lib/chunks/{UVKUPD4U.js → L4VSY42B.js} +1 -1
  52. package/lib/chunks/LH3ONQEX.js +17 -0
  53. package/lib/chunks/{SSEMMWPY.js → LUNR7GV4.js} +1 -1
  54. package/lib/chunks/{LY6BDOEF.js → LY5MGNMA.js} +1 -1
  55. package/lib/chunks/{XQEXWC5L.js → MAACTVYP.js} +1 -1
  56. package/lib/chunks/{GFSMOHUE.js → MTKICX4T.js} +1 -1
  57. package/lib/chunks/{ZXOX7NF2.js → NMAWU5S4.js} +1 -1
  58. package/lib/chunks/{I4TK6NG7.js → PJHQKG7X.js} +1 -1
  59. package/lib/chunks/PTBPNZRZ.js +7 -0
  60. package/lib/chunks/{CZX7WE2R.js → PUZ5QSL3.js} +1 -1
  61. package/lib/chunks/{JRVXIEVC.js → PW2XFZOB.js} +1 -1
  62. package/lib/chunks/{TH44RKLO.js → QAT3DPT3.js} +1 -1
  63. package/lib/chunks/{QXXAC25O.js → R67IVFZH.js} +1 -1
  64. package/lib/chunks/RA4FAJM3.js +59 -0
  65. package/lib/chunks/{AZ5LIJEO.js → RF5LL2UZ.js} +1 -1
  66. package/lib/chunks/{JOUEVI3E.js → RQPH22PV.js} +1 -1
  67. package/lib/chunks/S3B562IT.js +7 -0
  68. package/lib/chunks/{3FR3456Q.js → S43EG4DB.js} +1 -1
  69. package/lib/chunks/{CER2D6ZD.js → S7VIXBKD.js} +7 -7
  70. package/lib/chunks/{VJZDR6KS.js → TFPMT2XD.js} +1529 -4
  71. package/lib/chunks/{AXGFQS75.js → U56BQ2BR.js} +2 -2
  72. package/lib/chunks/{KJNBOXDI.js → UOTHMCTM.js} +3 -3
  73. package/lib/chunks/{CR5TYFBN.js → VHZJNDWE.js} +2 -2
  74. package/lib/chunks/{BOTTA3HA.js → VOYPXV3Z.js} +1 -1
  75. package/lib/chunks/{UTEOWLD5.js → VS4MTPCM.js} +1 -1
  76. package/lib/chunks/{QTSECOQB.js → WEPGHS5R.js} +2 -2
  77. package/lib/chunks/{LKNL5LEV.js → WRKMMY3F.js} +1 -1
  78. package/lib/chunks/{7JS7JGWP.js → WTJ3S4D7.js} +1 -1
  79. package/lib/chunks/X22IMAJK.js +199 -0
  80. package/lib/chunks/{W7TN2XCW.js → X3FFOCXC.js} +1 -1
  81. package/lib/chunks/{CRJEY7P3.js → XTI7EXWX.js} +1 -1
  82. package/lib/chunks/{BH4FA7AH.js → YA5KTHFN.js} +1 -1
  83. package/lib/chunks/{Z6GFQV2Y.js → YA6D5EUI.js} +1 -1
  84. package/lib/chunks/{HMYFTLS7.js → ZFET6WME.js} +1 -1
  85. package/lib/chunks/{R32HBYOH.js → ZXB5O6JQ.js} +1 -1
  86. package/lib/eject-assets/AGENTS.md +1 -1
  87. package/lib/eject-assets/generators/cli/docs.ts +1 -1
  88. package/lib/eject-assets/generators/cli/engine-source.ts +1 -1
  89. package/lib/eject-assets/generators/cli/index.ts +2 -2
  90. package/lib/eject-assets/generators/cli/render.ts +1 -1
  91. package/lib/eject-assets/generators/go/client.ts +1 -1
  92. package/lib/eject-assets/generators/go/descriptor.ts +1 -1
  93. package/lib/eject-assets/generators/go/index.ts +2 -2
  94. package/lib/eject-assets/generators/go/models.ts +1 -1
  95. package/lib/eject-assets/generators/go/naming.ts +1 -1
  96. package/lib/eject-assets/generators/go/operations.ts +1 -1
  97. package/lib/eject-assets/generators/go/pagination.ts +1 -1
  98. package/lib/eject-assets/generators/go/types.ts +1 -1
  99. package/lib/eject-assets/generators/java/client.ts +66 -0
  100. package/lib/eject-assets/generators/java/descriptor.ts +72 -0
  101. package/lib/eject-assets/generators/java/index.ts +245 -0
  102. package/lib/eject-assets/generators/java/models.ts +362 -0
  103. package/lib/eject-assets/generators/java/naming.ts +135 -0
  104. package/lib/eject-assets/generators/java/operations.ts +300 -0
  105. package/lib/eject-assets/generators/java/pagination.ts +94 -0
  106. package/lib/eject-assets/generators/java/types.ts +103 -0
  107. package/lib/eject-assets/generators/mock/faker.ts +1 -1
  108. package/lib/eject-assets/generators/mock/index.ts +2 -2
  109. package/lib/eject-assets/generators/mock/render.ts +1 -1
  110. package/lib/eject-assets/generators/mock/sample.ts +1 -1
  111. package/lib/eject-assets/generators/mock/values.ts +1 -1
  112. package/lib/eject-assets/generators/php/client.ts +1 -1
  113. package/lib/eject-assets/generators/php/descriptor.ts +1 -1
  114. package/lib/eject-assets/generators/php/index.ts +2 -2
  115. package/lib/eject-assets/generators/php/models.ts +1 -1
  116. package/lib/eject-assets/generators/php/naming.ts +1 -1
  117. package/lib/eject-assets/generators/php/operations.ts +1 -1
  118. package/lib/eject-assets/generators/php/pagination.ts +1 -1
  119. package/lib/eject-assets/generators/php/types.ts +1 -1
  120. package/lib/eject-assets/generators/python/client.ts +1 -1
  121. package/lib/eject-assets/generators/python/descriptor.ts +1 -1
  122. package/lib/eject-assets/generators/python/index.ts +2 -2
  123. package/lib/eject-assets/generators/python/models.ts +1 -1
  124. package/lib/eject-assets/generators/python/naming.ts +1 -1
  125. package/lib/eject-assets/generators/python/operations.ts +1 -1
  126. package/lib/eject-assets/generators/python/pagination.ts +1 -1
  127. package/lib/eject-assets/generators/python/types.ts +1 -1
  128. package/lib/eject-assets/generators/swr/index.ts +2 -2
  129. package/lib/eject-assets/generators/swr/render.ts +1 -1
  130. package/lib/eject-assets/generators/tanstack-query/index.ts +2 -2
  131. package/lib/eject-assets/generators/tanstack-query/render.ts +1 -1
  132. package/lib/eject-assets/generators/transformers/index.ts +2 -2
  133. package/lib/eject-assets/generators/transformers/render.ts +1 -1
  134. package/lib/eject-assets/generators/typescript/banner.ts +1 -1
  135. package/lib/eject-assets/generators/typescript/client.ts +1 -1
  136. package/lib/eject-assets/generators/typescript/descriptor.ts +1 -1
  137. package/lib/eject-assets/generators/typescript/index.ts +2 -2
  138. package/lib/eject-assets/generators/typescript/inline-runtime.ts +1 -1
  139. package/lib/eject-assets/generators/typescript/operation-signature.ts +1 -1
  140. package/lib/eject-assets/generators/typescript/operation-types.ts +1 -1
  141. package/lib/eject-assets/generators/typescript/operations.ts +1 -1
  142. package/lib/eject-assets/generators/typescript/response-headers.ts +1 -1
  143. package/lib/eject-assets/generators/typescript/type-guards.ts +1 -1
  144. package/lib/eject-assets/generators/typescript/types.ts +1 -1
  145. package/lib/eject-assets/generators/zod/index.ts +2 -2
  146. package/lib/eject-assets/generators/zod/schemas.ts +1 -1
  147. package/lib/eject-assets/skills/client-generators/SKILL.md +1 -1
  148. package/lib/eject-assets/skills/java-generator/SKILL.md +161 -0
  149. package/lib/index.js +91 -90
  150. package/lib/skills/redocly-cli/SKILL.md +3 -1
  151. package/package.json +1 -1
  152. package/lib/chunks/2ZEKFWJQ.js +0 -13
  153. package/lib/chunks/3VOQMXIZ.js +0 -7
  154. package/lib/chunks/7GADNOVY.js +0 -9
  155. package/lib/chunks/FRQHCFKP.js +0 -199
  156. package/lib/chunks/J2EPFEBO.js +0 -17
  157. package/lib/chunks/JZATGVUO.js +0 -53
  158. package/lib/chunks/KNMNSDHR.js +0 -7
  159. package/lib/chunks/U5DIFWGH.js +0 -7
@@ -0,0 +1,300 @@
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "java" 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 java --update`.
5
+ // The `operations` stage: one typed request method per operation, the `<Op>Params`
6
+ // class its optional query parameters travel in, and the argument planning and request
7
+ // prologue it shares with the pagination wrappers.
8
+
9
+ import {
10
+ type ApiModel,
11
+ type DateType,
12
+ deref,
13
+ isBinaryContentType,
14
+ isMultipartBody,
15
+ isUntypedMultipartBody,
16
+ jsonSuccessSchema,
17
+ type NeutralPaginationRule,
18
+ type OperationModel,
19
+ sseResponse,
20
+ uniqueIdentifiers,
21
+ unwrapNullable,
22
+ } from '@redocly/client-generator';
23
+ import type { JavaPrinter } from '@redocly/client-generator/printers/java';
24
+
25
+ import { envelopeHeaderSpecs, javaOperationLiteral } from './descriptor.ts';
26
+ import { hydration } from './models.ts';
27
+ import { JAVA, javaString, typeName } from './naming.ts';
28
+ import { javaType } from './types.ts';
29
+
30
+ type MethodArgs = {
31
+ pathArgs: Array<{ java: string; wire: string }>;
32
+ /** The optional query parameters, as fields of the `<Op>Params` class. */
33
+ queryFields: Array<{ java: string; wire: string; type: string; isArray: boolean }>;
34
+ paramsClass: string | undefined;
35
+ signature: string[];
36
+ };
37
+
38
+ /**
39
+ * The argument and local names a request method declares beside its path parameters. A
40
+ * parameter named after one of them takes a suffixed name instead, so each keeps its meaning.
41
+ */
42
+ // prettier-ignore
43
+ const METHOD_ARG_SLOTS = [
44
+ 'body', 'params', 'op', 'auth', 'query', 'url', 'spec', 'payload', 'response', 'data',
45
+ 'headers', 'extraHeaders', 'pageParams', 'call', 'base', 'item', 'page', 'config',
46
+ ];
47
+
48
+ /** Whether the body is `Object` and the runtime sorts out what it got (`multipartBody` / `binaryBody`). */
49
+ function passesThrough(op: OperationModel): boolean {
50
+ return (
51
+ isUntypedMultipartBody(op) ||
52
+ (op.requestBody !== undefined && isBinaryContentType(op.requestBody.contentType))
53
+ );
54
+ }
55
+
56
+ /**
57
+ * The `<Op>Params` class name, when the operation has query parameters. A schema may fold
58
+ * to the same name (`ListOrdersParams` is a plausible schema), and two nested classes cannot
59
+ * share one, so the class moves aside with a suffix.
60
+ */
61
+ export function paramsClassName(
62
+ op: OperationModel,
63
+ ident: string,
64
+ model: ApiModel
65
+ ): string | undefined {
66
+ if (op.queryParams.length === 0) return undefined;
67
+ return uniqueIdentifiers([`${ident}Params`], {
68
+ style: 'pascal',
69
+ reserved: JAVA,
70
+ taken: model.schemas.map((schema) => typeName(schema.name)),
71
+ })[0];
72
+ }
73
+
74
+ export function methodArgs(
75
+ op: OperationModel,
76
+ ident: string,
77
+ model: ApiModel,
78
+ includeBody: boolean,
79
+ dateType: DateType
80
+ ): MethodArgs {
81
+ // Path parameters are arguments, so their names share one namespace with the locals the
82
+ // method declares itself; a repeat moves aside (`body`, `body2`). Query parameters live in
83
+ // their own class, so they only need to be unique among themselves.
84
+ const pathNames = uniqueIdentifiers(
85
+ op.pathParams.map((param) => param.name),
86
+ { style: 'camel', reserved: JAVA, taken: METHOD_ARG_SLOTS }
87
+ );
88
+ const queryNames = uniqueIdentifiers(
89
+ op.queryParams.map((param) => param.name),
90
+ { style: 'camel', reserved: JAVA }
91
+ );
92
+ const pathArgs = op.pathParams.map((param, index) => ({
93
+ java: pathNames[index],
94
+ wire: param.name,
95
+ }));
96
+ const queryFields = op.queryParams.map((param, index) => ({
97
+ java: queryNames[index],
98
+ wire: param.name,
99
+ type: javaType(param.schema, model, dateType),
100
+ // Through a `$ref`: a named list alias repeats the key like an inline array does.
101
+ isArray: deref(unwrapNullable(param.schema), model)?.kind === 'array',
102
+ }));
103
+ const paramsClass = paramsClassName(op, ident, model);
104
+ const signature = [
105
+ ...op.pathParams.map(
106
+ (param, index) => `${javaType(param.schema, model, dateType)} ${pathNames[index]}`
107
+ ),
108
+ ...(includeBody && op.requestBody
109
+ ? [`${passesThrough(op) ? 'Object' : javaType(op.requestBody.schema, model, dateType)} body`]
110
+ : []),
111
+ ...(paramsClass === undefined ? [] : [`${paramsClass} params`]),
112
+ ];
113
+ return { pathArgs, queryFields, paramsClass, signature };
114
+ }
115
+
116
+ /** The `<Op>Params` class: one nullable field per query parameter, with a fluent setter each. */
117
+ export function writeParamsClass(
118
+ printer: JavaPrinter,
119
+ op: OperationModel,
120
+ ident: string,
121
+ model: ApiModel,
122
+ dateType: DateType
123
+ ): void {
124
+ const { queryFields, paramsClass } = methodArgs(op, ident, model, false, dateType);
125
+ if (paramsClass === undefined) return;
126
+ printer.line(`/** The query parameters of ${ident}; an unset field is not sent. */`);
127
+ printer.block(
128
+ `public static final class ${paramsClass} {`,
129
+ () => {
130
+ for (const field of queryFields) printer.line(`public ${field.type} ${field.java};`);
131
+ for (const field of queryFields) {
132
+ printer.blank();
133
+ printer.block(
134
+ `public ${paramsClass} ${field.java}(${field.type} ${field.java}) {`,
135
+ () => {
136
+ printer.line(`this.${field.java} = ${field.java};`);
137
+ printer.line('return this;');
138
+ },
139
+ '}'
140
+ );
141
+ }
142
+ },
143
+ '}'
144
+ );
145
+ printer.blank();
146
+ }
147
+
148
+ /** Add the set query parameters to `target` (a `Map<String, List<String>>`). */
149
+ export function writeQueryParams(printer: JavaPrinter, args: MethodArgs, target: string): void {
150
+ if (args.paramsClass === undefined) return;
151
+ printer.block(
152
+ 'if (params != null) {',
153
+ () => {
154
+ for (const field of args.queryFields) {
155
+ printer.block(
156
+ `if (params.${field.java} != null) {`,
157
+ () => {
158
+ // An array repeats the key per element (OpenAPI `form` + `explode`, the default).
159
+ if (field.isArray) {
160
+ printer.block(
161
+ `for (Object item : params.${field.java}) {`,
162
+ () => {
163
+ printer.line(`addQuery(${target}, ${javaString(field.wire)}, item);`);
164
+ },
165
+ '}'
166
+ );
167
+ } else {
168
+ printer.line(`addQuery(${target}, ${javaString(field.wire)}, params.${field.java});`);
169
+ }
170
+ },
171
+ '}'
172
+ );
173
+ }
174
+ },
175
+ '}'
176
+ );
177
+ }
178
+
179
+ /** The `buildUrl(…)` expression for the operation's path. */
180
+ export function urlExpression(args: MethodArgs): string {
181
+ const pairs = args.pathArgs
182
+ .map(({ java, wire }) => `${javaString(wire)}, textValue(${java})`)
183
+ .join(', ');
184
+ return `buildUrl(config.serverUrl, op.path(), pathParams(${pairs}))`;
185
+ }
186
+
187
+ export function writeJavaMethod(
188
+ printer: JavaPrinter,
189
+ op: OperationModel,
190
+ ident: string,
191
+ model: ApiModel,
192
+ dateType: DateType,
193
+ rule: NeutralPaginationRule | undefined,
194
+ envelope = false
195
+ ): void {
196
+ const args = methodArgs(op, ident, model, true, dateType);
197
+ const sse = sseResponse(op);
198
+ const success = jsonSuccessSchema(op);
199
+ // Non-JSON success bodies (PDFs, images, octet streams) return the raw bytes.
200
+ const rawBody =
201
+ sse === undefined &&
202
+ success === undefined &&
203
+ op.successResponses.some((response) => response.contentType !== '');
204
+ const dataType =
205
+ success !== undefined ? javaType(success, model, dateType) : rawBody ? 'byte[]' : 'void';
206
+ const returnType = envelope
207
+ ? `Envelope<${dataType === 'void' ? 'Void' : dataType}>`
208
+ : sse !== undefined
209
+ ? 'Iterable<ServerSentEvent>'
210
+ : dataType;
211
+ const name = envelope ? `${ident}WithHeaders` : ident;
212
+ printer.doc(
213
+ name,
214
+ envelope
215
+ ? `Like ${ident}, returning an Envelope with the declared response headers.`
216
+ : (op.summary ?? `${op.method.toUpperCase()} ${op.path}`)
217
+ );
218
+ printer.block(
219
+ `public ${returnType} ${name}(${args.signature.join(', ')}) {`,
220
+ () => {
221
+ printer.line(`Operation op = ${javaOperationLiteral(op, model, rule)};`);
222
+ if (sse !== undefined) {
223
+ // Auth resolves inside the opener, so every reconnect asks a token supplier again
224
+ // — a long-lived stream outlives the token it started with.
225
+ const jsonData = sse.schema !== undefined && sse.schema.kind !== 'unknown';
226
+ printer.line('Map<String, List<String>> base = new LinkedHashMap<>();');
227
+ writeQueryParams(printer, args, 'base');
228
+ printer.line(`String url = ${urlExpression(args)};`);
229
+ printer.block(
230
+ 'return iterSse(extraHeaders -> {',
231
+ () => {
232
+ printer.line('ResolvedAuth auth = resolveAuth(op.security(), config.auth);');
233
+ printer.line('Map<String, List<String>> query = cloneQuery(auth.query());');
234
+ printer.line('query.putAll(base);');
235
+ printer.line('Map<String, String> headers = new LinkedHashMap<>(auth.headers());');
236
+ printer.line('headers.putAll(extraHeaders);');
237
+ printer.line(
238
+ 'return send(config, new RequestSpec(op.id(), op.method(), url).headers(headers).query(query));'
239
+ );
240
+ },
241
+ `}, ${jsonData});`
242
+ );
243
+ return;
244
+ }
245
+ printer.line('ResolvedAuth auth = resolveAuth(op.security(), config.auth);');
246
+ printer.line('Map<String, List<String>> query = auth.query();');
247
+ writeQueryParams(printer, args, 'query');
248
+ printer.line(`String url = ${urlExpression(args)};`);
249
+ printer.line(
250
+ 'RequestSpec spec = new RequestSpec(op.id(), op.method(), url).headers(auth.headers()).query(query);'
251
+ );
252
+ if (op.requestBody !== undefined) {
253
+ const contentType = javaString(op.requestBody.contentType);
254
+ const payload = isUntypedMultipartBody(op)
255
+ ? 'multipartBody(body)'
256
+ : passesThrough(op)
257
+ ? `binaryBody(body, ${contentType})`
258
+ : isMultipartBody(op)
259
+ ? 'multipartBody(body)'
260
+ : `jsonBody(body, ${contentType})`;
261
+ printer.line(`Body payload = ${payload};`);
262
+ printer.line('spec.body(payload.body(), payload.contentType());');
263
+ }
264
+ printer.line('HttpResponse<InputStream> response = send(config, spec);');
265
+ printer.block(
266
+ 'if (response.statusCode() >= 400) {',
267
+ () => {
268
+ printer.line('throw apiErrorFrom(response, url);');
269
+ },
270
+ '}'
271
+ );
272
+ const decoded = rawBody
273
+ ? 'readBody(response)'
274
+ : success === undefined
275
+ ? undefined
276
+ : (hydration(success, 'decodeJson(response)', model, dateType) ?? 'decodeJson(response)');
277
+ if (envelope) {
278
+ if (decoded === undefined) {
279
+ printer.line('readBody(response);');
280
+ printer.line(
281
+ `return new Envelope<>(null, readEnvelopeHeaders(response, ${envelopeHeaderSpecs(op, model)}), response.statusCode());`
282
+ );
283
+ } else {
284
+ printer.line(`${dataType} data = ${decoded};`);
285
+ printer.line(
286
+ `return new Envelope<>(data, readEnvelopeHeaders(response, ${envelopeHeaderSpecs(op, model)}), response.statusCode());`
287
+ );
288
+ }
289
+ return;
290
+ }
291
+ if (decoded === undefined) {
292
+ printer.line('readBody(response);');
293
+ return;
294
+ }
295
+ printer.line(`return ${decoded};`);
296
+ },
297
+ '}'
298
+ );
299
+ printer.blank();
300
+ }
@@ -0,0 +1,94 @@
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "java" 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 java --update`.
5
+ // The `pagination` stage: the `<op>Pages()` / `<op>Items()` iterables over the
6
+ // runtime's iterPages.
7
+
8
+ import {
9
+ type ApiModel,
10
+ type DateType,
11
+ jsonSuccessSchema,
12
+ type NeutralPaginationRule,
13
+ type OperationModel,
14
+ paginationItemSchema,
15
+ } from '@redocly/client-generator';
16
+ import type { JavaPrinter } from '@redocly/client-generator/printers/java';
17
+
18
+ import { javaOperationLiteral } from './descriptor.ts';
19
+ import { hydration } from './models.ts';
20
+ import { methodArgs, urlExpression, writeQueryParams } from './operations.ts';
21
+ import { javaType } from './types.ts';
22
+
23
+ /** `<op>Pages()` / `<op>Items()` iterables over the runtime's iterPages, hydrated per element. */
24
+ export function writeJavaPaginationWrappers(
25
+ printer: JavaPrinter,
26
+ op: OperationModel,
27
+ ident: string,
28
+ model: ApiModel,
29
+ dateType: DateType,
30
+ rule: NeutralPaginationRule
31
+ ): void {
32
+ const args = methodArgs(op, ident, model, false, dateType);
33
+ const success = jsonSuccessSchema(op);
34
+ const pageType = success === undefined ? 'Object' : javaType(success, model, dateType);
35
+ const element = paginationItemSchema(success, rule.items, model);
36
+ const itemType = element === undefined ? 'Object' : javaType(element, model, dateType);
37
+ const pageHydration =
38
+ success === undefined ? 'page' : (hydration(success, 'page', model, dateType) ?? 'page');
39
+ const itemHydration =
40
+ element === undefined ? 'item' : (hydration(element, 'item', model, dateType, 1) ?? 'item');
41
+
42
+ const writeCall = () => {
43
+ printer.line(`Operation op = ${javaOperationLiteral(op, model, rule)};`);
44
+ printer.line('Map<String, List<String>> base = new LinkedHashMap<>();');
45
+ writeQueryParams(printer, args, 'base');
46
+ printer.block(
47
+ 'PageCall call = pageParams -> {',
48
+ () => {
49
+ printer.line('ResolvedAuth auth = resolveAuth(op.security(), config.auth);');
50
+ printer.line('Map<String, List<String>> query = cloneQuery(auth.query());');
51
+ printer.line('query.putAll(pageParams);');
52
+ printer.line(`String url = ${urlExpression(args)};`);
53
+ printer.line(
54
+ 'HttpResponse<InputStream> response = send(config, new RequestSpec(op.id(), op.method(), url).headers(auth.headers()).query(query));'
55
+ );
56
+ printer.block(
57
+ 'if (response.statusCode() >= 400) {',
58
+ () => {
59
+ printer.line('throw apiErrorFrom(response, url);');
60
+ },
61
+ '}'
62
+ );
63
+ printer.line('return new PageResult(decodeJson(response), response);');
64
+ },
65
+ '};'
66
+ );
67
+ };
68
+
69
+ printer.line(`/** ${ident} response pages, following the pagination rule automatically. */`);
70
+ printer.block(
71
+ `public Iterable<${pageType}> ${ident}Pages(${args.signature.join(', ')}) {`,
72
+ () => {
73
+ writeCall();
74
+ printer.line(
75
+ `return mapIterable(iterPages(call, op.pagination(), base), page -> ${pageHydration});`
76
+ );
77
+ },
78
+ '}'
79
+ );
80
+ printer.blank();
81
+
82
+ printer.line(`/** The items of every ${ident} page. */`);
83
+ printer.block(
84
+ `public Iterable<${itemType}> ${ident}Items(${args.signature.join(', ')}) {`,
85
+ () => {
86
+ writeCall();
87
+ printer.line(
88
+ `return mapIterable(flattenItems(iterPages(call, op.pagination(), base), op.pagination().items()), item -> ${itemHydration});`
89
+ );
90
+ },
91
+ '}'
92
+ );
93
+ printer.blank();
94
+ }
@@ -0,0 +1,103 @@
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "java" 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 java --update`.
5
+ // The `types` stage: the Java type for a schema, and what a named schema renders as.
6
+
7
+ import {
8
+ type ApiModel,
9
+ type DateType,
10
+ deref,
11
+ discriminatorCases,
12
+ enumValues,
13
+ flattenAllOf,
14
+ type SchemaModel,
15
+ unwrapNullable,
16
+ } from '@redocly/client-generator';
17
+
18
+ import { typeName } from './naming.ts';
19
+
20
+ /**
21
+ * What a named schema renders as: a record, a wire-backed enum, a sealed union interface
22
+ * (every mapping target is a record, so the interface can seal over them), or nothing.
23
+ */
24
+ export function classify(name: string, model: ApiModel): 'record' | 'enum' | 'union' | 'other' {
25
+ const named = model.schemas.find((candidate) => candidate.name === name);
26
+ if (named === undefined) return 'other';
27
+ const schema = named.schema;
28
+ const asEnum = enumValues(schema);
29
+ if (asEnum !== undefined && (asEnum.scalar === 'string' || asEnum.scalar === 'integer')) {
30
+ return 'enum';
31
+ }
32
+ if (
33
+ (schema.kind === 'object' || schema.kind === 'intersection') &&
34
+ flattenAllOf(schema, model) !== undefined
35
+ ) {
36
+ return 'record';
37
+ }
38
+ const cases = discriminatorCases(schema, model);
39
+ if (
40
+ cases !== undefined &&
41
+ cases.cases.length > 0 &&
42
+ cases.cases.every((entry) => classify(entry.schemaName, model) === 'record')
43
+ ) {
44
+ return 'union';
45
+ }
46
+ return 'other';
47
+ }
48
+
49
+ const SCALARS = { string: 'String', integer: 'Long', number: 'Double', boolean: 'Boolean' };
50
+
51
+ /** `date` or `date-time` — the two formats `dateType: Date` turns into java.time objects. */
52
+ export function isDateFormat(schema: SchemaModel): boolean {
53
+ const format = schema.metadata?.format;
54
+ return format === 'date' || format === 'date-time';
55
+ }
56
+
57
+ /**
58
+ * The Java type for a schema. Every type is a reference type (`Long`, not `long`), so an
59
+ * optional or nullable value is simply `null`; untyped shapes widen to `Object`.
60
+ */
61
+ export function javaType(
62
+ schema: SchemaModel,
63
+ model: ApiModel,
64
+ dateType: DateType = 'string'
65
+ ): string {
66
+ const bare = unwrapNullable(schema);
67
+ switch (bare.kind) {
68
+ case 'scalar':
69
+ if (dateType === 'Date' && bare.scalar === 'string') {
70
+ if (bare.metadata?.format === 'date-time') return 'OffsetDateTime';
71
+ if (bare.metadata?.format === 'date') return 'LocalDate';
72
+ }
73
+ return SCALARS[bare.scalar];
74
+ case 'array':
75
+ return `List<${javaType(bare.items, model, dateType)}>`;
76
+ case 'record':
77
+ return `Map<String, ${javaType(bare.value, model, dateType)}>`;
78
+ case 'ref': {
79
+ const kind = classify(bare.name, model);
80
+ if (kind !== 'other') return typeName(bare.name);
81
+ const target = deref(bare, model);
82
+ return target === undefined ? 'Object' : javaType(target, model, dateType);
83
+ }
84
+ case 'enum':
85
+ // Anonymous (inline) enums keep the wire scalar; only NAMED enums get types.
86
+ return SCALARS[bare.scalar];
87
+ case 'literal':
88
+ return typeof bare.value === 'string'
89
+ ? 'String'
90
+ : typeof bare.value === 'boolean'
91
+ ? 'Boolean'
92
+ : 'Double';
93
+ case 'omit':
94
+ // Java has no Omit; the base type is the honest annotation.
95
+ return javaType({ kind: 'ref', name: bare.base }, model, dateType);
96
+ case 'union':
97
+ case 'null':
98
+ case 'object':
99
+ case 'intersection':
100
+ case 'unknown':
101
+ return 'Object';
102
+ }
103
+ }
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "mock" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "mock" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator mock --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "mock" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "mock" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator mock --update`.
@@ -32,5 +32,5 @@ export default {
32
32
  name: 'mock',
33
33
  run: mockGenerator,
34
34
  requires: ["typescript"],
35
- requiresGenerator: '^0.7.13',
35
+ requiresGenerator: '^0.8.1',
36
36
  };
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "mock" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "mock" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator mock --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "mock" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "mock" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator mock --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "mock" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "mock" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator mock --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "php" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "php" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator php --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "php" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "php" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator php --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "php" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "php" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator php --update`.
@@ -234,5 +234,5 @@ export default {
234
234
  "argsStyle": "inputs follow the target language's own idiom",
235
235
  "importExt": "the generated file has no relative imports"
236
236
  },
237
- requiresGenerator: '^0.7.13',
237
+ requiresGenerator: '^0.8.1',
238
238
  };
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "php" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "php" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator php --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "php" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "php" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator php --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "php" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "php" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator php --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "php" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "php" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator php --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "php" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "php" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator php --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "python" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "python" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator python --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "python" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "python" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator python --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "python" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "python" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator python --update`.
@@ -247,5 +247,5 @@ export default {
247
247
  "argsStyle": "inputs follow the target language's own idiom",
248
248
  "importExt": "the generated file has no relative imports"
249
249
  },
250
- requiresGenerator: '^0.7.13',
250
+ requiresGenerator: '^0.8.1',
251
251
  };
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "python" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "python" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator python --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "python" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "python" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator python --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "python" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "python" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator python --update`.
@@ -1,4 +1,4 @@
1
- // Ejected from @redocly/client-generator@0.7.13 — the built-in "python" generator.
1
+ // Ejected from @redocly/client-generator@0.8.1 — the built-in "python" generator.
2
2
  // This file is yours: edit freely; the generated client stays machine-owned and is
3
3
  // rebuilt by `redocly generate-client`. Newer generator versions merge in with
4
4
  // `redocly eject-generator python --update`.