@orval/angular 8.2.0 → 8.4.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/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { generateFormDataAndUrlEncodedFunction, generateMutatorConfig, generateMutatorRequestOptions, generateOptions, generateVerbImports, getDefaultContentType, isBoolean, pascal, sanitize, toObjectString } from "@orval/core";
1
+ import { generateFormDataAndUrlEncodedFunction, generateMutatorConfig, generateMutatorRequestOptions, generateOptions, generateVerbImports, getAngularFilteredParamsCallExpression, getAngularFilteredParamsHelperBody, getDefaultContentType, isBoolean, pascal, sanitize, toObjectString } from "@orval/core";
2
2
 
3
3
  //#region src/index.ts
4
4
  const ANGULAR_DEPENDENCIES = [
@@ -8,7 +8,10 @@ const ANGULAR_DEPENDENCIES = [
8
8
  name: "HttpClient",
9
9
  values: true
10
10
  },
11
- { name: "HttpHeaders" },
11
+ {
12
+ name: "HttpHeaders",
13
+ values: true
14
+ },
12
15
  { name: "HttpParams" },
13
16
  { name: "HttpContext" },
14
17
  {
@@ -35,24 +38,21 @@ const ANGULAR_DEPENDENCIES = [
35
38
  values: true
36
39
  }],
37
40
  dependency: "rxjs"
38
- },
39
- {
40
- exports: [{ name: "DeepNonNullable" }],
41
- dependency: "@orval/core"
42
41
  }
43
42
  ];
44
- const returnTypesToWrite = /* @__PURE__ */ new Map();
45
- const getAngularDependencies = () => ANGULAR_DEPENDENCIES;
43
+ const getAngularDependencies = () => [...ANGULAR_DEPENDENCIES];
46
44
  const generateAngularTitle = (title) => {
47
45
  return `${pascal(sanitize(title))}Service`;
48
46
  };
49
- const generateAngularHeader = ({ title, isRequestOptions, isMutator, isGlobalMutator, provideIn }) => `
47
+ const createAngularHeader = () => ({ title, isRequestOptions, isMutator, isGlobalMutator, provideIn, verbOptions, tag }) => {
48
+ const hasQueryParams = (tag ? Object.values(verbOptions).filter((v) => v.tags.includes(tag)) : Object.values(verbOptions)).some((v) => v.queryParams);
49
+ return `
50
50
  ${isRequestOptions && !isGlobalMutator ? `interface HttpClientOptions {
51
51
  headers?: HttpHeaders | Record<string, string | string[]>;
52
52
  context?: HttpContext;
53
53
  params?:
54
54
  | HttpParams
55
- | Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>>;
55
+ | Record<string, string | number | boolean | Array<string | number | boolean>>;
56
56
  reportProgress?: boolean;
57
57
  withCredentials?: boolean;
58
58
  credentials?: RequestCredentials;
@@ -63,9 +63,11 @@ ${isRequestOptions && !isGlobalMutator ? `interface HttpClientOptions {
63
63
  redirect?: RequestRedirect;
64
64
  referrer?: string;
65
65
  integrity?: string;
66
+ referrerPolicy?: ReferrerPolicy;
66
67
  transferCache?: {includeHeaders?: string[]} | boolean;
67
- timeout?: number;
68
- }` : ""}
68
+ }
69
+
70
+ ${hasQueryParams ? getAngularFilteredParamsHelperBody() : ""}` : ""}
69
71
 
70
72
  ${isRequestOptions && isMutator ? `// eslint-disable-next-line
71
73
  type ThirdParameter<T extends (...args: any) => any> = T extends (
@@ -80,12 +82,16 @@ ${isRequestOptions && isMutator ? `// eslint-disable-next-line
80
82
  export class ${title} {
81
83
  private readonly http = inject(HttpClient);
82
84
  `;
83
- const generateAngularFooter = ({ operationNames }) => {
85
+ };
86
+ const generateAngularHeader = (params) => createAngularHeader()(params);
87
+ const standaloneFooterReturnTypesToWrite = /* @__PURE__ */ new Map();
88
+ const createAngularFooter = (returnTypesToWrite) => ({ operationNames }) => {
84
89
  let footer = "};\n\n";
85
90
  for (const operationName of operationNames) if (returnTypesToWrite.has(operationName)) footer += returnTypesToWrite.get(operationName) + "\n";
86
91
  return footer;
87
92
  };
88
- const generateImplementation = ({ headers, queryParams, operationName, response, mutator, body, props, verb, override, formData, formUrlEncoded, paramsSerializer }, { route, context }) => {
93
+ const generateAngularFooter = (params) => createAngularFooter(standaloneFooterReturnTypesToWrite)(params);
94
+ const generateImplementation = (returnTypesToWrite, { headers, queryParams, operationName, response, mutator, body, props, verb, override, formData, formUrlEncoded, paramsSerializer }, { route, context }) => {
89
95
  const isRequestOptions = override.requestOptions !== false;
90
96
  const isFormData = !override.formData.disabled;
91
97
  const isFormUrlEncoded = override.formUrlEncoded !== false;
@@ -110,7 +116,8 @@ const generateImplementation = ({ headers, queryParams, operationName, response,
110
116
  isFormData,
111
117
  isFormUrlEncoded,
112
118
  hasSignal: false,
113
- isExactOptionalPropertyTypes
119
+ isExactOptionalPropertyTypes,
120
+ isAngular: true
114
121
  });
115
122
  const requestOptions = isRequestOptions ? generateMutatorRequestOptions(override.requestOptions, mutator.hasThirdArg) : "";
116
123
  return ` ${operationName}<TData = ${dataType}>(\n ${mutator.bodyTypeName && body.definition ? toObjectString(props, "implementation").replace(new RegExp(String.raw`(\w*):\s?${body.definition}`), `$1: ${mutator.bodyTypeName}<${body.definition}>`) : toObjectString(props, "implementation")}\n ${isRequestOptions && mutator.hasThirdArg ? `options?: ThirdParameter<typeof ${mutator.name}>` : ""}) {${bodyForm}
@@ -121,7 +128,7 @@ const generateImplementation = ({ headers, queryParams, operationName, response,
121
128
  }
122
129
  `;
123
130
  }
124
- const options = generateOptions({
131
+ const optionsBase = {
125
132
  route,
126
133
  body,
127
134
  headers,
@@ -136,13 +143,42 @@ const generateImplementation = ({ headers, queryParams, operationName, response,
136
143
  isAngular: true,
137
144
  isExactOptionalPropertyTypes,
138
145
  hasSignal: false
139
- });
146
+ };
140
147
  const propsDefinition = toObjectString(props, "definition");
141
148
  const successTypes = response.types.success;
142
149
  const uniqueContentTypes = [...new Set(successTypes.map((t) => t.contentType).filter(Boolean))];
143
150
  const hasMultipleContentTypes = uniqueContentTypes.length > 1;
144
- const defaultContentType = hasMultipleContentTypes ? getDefaultContentType(uniqueContentTypes) : uniqueContentTypes[0] ?? "application/json";
145
- const defaultReturnType = (hasMultipleContentTypes ? successTypes.find((t) => t.contentType === defaultContentType) : void 0)?.value ?? dataType;
151
+ const needsObserveBranching = isRequestOptions && !hasMultipleContentTypes;
152
+ const angularParamsRef = needsObserveBranching && queryParams ? "filteredParams" : void 0;
153
+ let paramsDeclaration = "";
154
+ if (angularParamsRef && queryParams) {
155
+ const callExpr = getAngularFilteredParamsCallExpression("{...params, ...options?.params}", queryParams.requiredNullableKeys ?? []);
156
+ paramsDeclaration = paramsSerializer ? `const ${angularParamsRef} = ${paramsSerializer.name}(${callExpr});\n\n ` : `const ${angularParamsRef} = ${callExpr};\n\n `;
157
+ }
158
+ const options = generateOptions({
159
+ ...optionsBase,
160
+ ...angularParamsRef ? { angularParamsRef } : {}
161
+ });
162
+ const defaultContentType = hasMultipleContentTypes ? uniqueContentTypes.includes("text/plain") ? "text/plain" : getDefaultContentType(uniqueContentTypes) : uniqueContentTypes[0] ?? "application/json";
163
+ const getContentTypeReturnType = (contentType, value) => {
164
+ if (!contentType) return value;
165
+ if (contentType.includes("json") || contentType.includes("+json")) return value;
166
+ if (contentType.startsWith("text/") || contentType.includes("xml")) return "string";
167
+ return "Blob";
168
+ };
169
+ const jsonSuccessValues = [...new Set(successTypes.filter(({ contentType }) => !!contentType && (contentType.includes("json") || contentType.includes("+json"))).map(({ value }) => value))];
170
+ const jsonReturnType = jsonSuccessValues.length > 0 ? jsonSuccessValues.join(" | ") : "unknown";
171
+ const multiImplementationReturnType = `Observable<${jsonReturnType} | string | Blob>`;
172
+ const withObserveMode = (generatedOptions, observeMode) => {
173
+ const spreadPattern = "...(options as Omit<NonNullable<typeof options>, 'observe'>),";
174
+ if (generatedOptions.includes(spreadPattern)) return generatedOptions.replace(spreadPattern, `${spreadPattern}\n observe: '${observeMode}',`);
175
+ return generatedOptions.replace("(options as Omit<NonNullable<typeof options>, 'observe'>)", `{ ...(options as Omit<NonNullable<typeof options>, 'observe'>), observe: '${observeMode}' }`);
176
+ };
177
+ const observeOptions = needsObserveBranching ? {
178
+ body: withObserveMode(options, "body"),
179
+ events: withObserveMode(options, "events"),
180
+ response: withObserveMode(options, "response")
181
+ } : void 0;
146
182
  const isModelType = dataType !== "Blob" && dataType !== "string";
147
183
  let functionName = operationName;
148
184
  if (isModelType && !hasMultipleContentTypes) functionName += `<TData = ${dataType}>`;
@@ -151,23 +187,26 @@ const generateImplementation = ({ headers, queryParams, operationName, response,
151
187
  const requiredProps = props.filter((p) => p.required && !p.default);
152
188
  const optionalProps = props.filter((p) => !p.required || p.default);
153
189
  contentTypeOverloads = successTypes.filter((t) => t.contentType).map(({ contentType, value }) => {
190
+ const returnType = getContentTypeReturnType(contentType, value);
154
191
  return `${operationName}(${[
155
192
  requiredProps.map((p) => p.definition).join(",\n "),
156
193
  `accept: '${contentType}'`,
157
194
  optionalProps.map((p) => p.definition).join(",\n ")
158
- ].filter(Boolean).join(",\n ")}, options?: HttpClientOptions): Observable<${value}>;`;
195
+ ].filter(Boolean).join(",\n ")}, options?: HttpClientOptions): Observable<${returnType}>;`;
159
196
  }).join("\n ");
160
197
  const allParams = [
161
198
  requiredProps.map((p) => p.definition).join(",\n "),
162
199
  "accept?: string",
163
200
  optionalProps.map((p) => p.definition).join(",\n ")
164
201
  ].filter(Boolean).join(",\n ");
165
- contentTypeOverloads += `\n ${operationName}(${allParams}, options?: HttpClientOptions): Observable<${defaultReturnType}>;`;
202
+ contentTypeOverloads += `\n ${operationName}(${allParams}, options?: HttpClientOptions): ${multiImplementationReturnType};`;
166
203
  }
167
204
  const observeOverloads = isRequestOptions && !hasMultipleContentTypes ? `${functionName}(${propsDefinition} options?: HttpClientOptions & { observe?: 'body' }): Observable<${isModelType ? "TData" : dataType}>;
168
205
  ${functionName}(${propsDefinition} options?: HttpClientOptions & { observe: 'events' }): Observable<HttpEvent<${isModelType ? "TData" : dataType}>>;
169
206
  ${functionName}(${propsDefinition} options?: HttpClientOptions & { observe: 'response' }): Observable<AngularHttpResponse<${isModelType ? "TData" : dataType}>>;` : "";
170
207
  const overloads = contentTypeOverloads || observeOverloads;
208
+ const observableDataType = isModelType ? "TData" : dataType;
209
+ const singleImplementationReturnType = isRequestOptions ? `Observable<${observableDataType} | HttpEvent<${observableDataType}> | AngularHttpResponse<${observableDataType}>>` : `Observable<${observableDataType}>`;
171
210
  if (hasMultipleContentTypes) {
172
211
  const requiredProps = props.filter((p) => p.required && !p.default);
173
212
  const optionalProps = props.filter((p) => !p.required || p.default);
@@ -181,51 +220,71 @@ const generateImplementation = ({ headers, queryParams, operationName, response,
181
220
  optionalPart
182
221
  ].filter(Boolean).join(",\n ")},
183
222
  ${isRequestOptions ? "options?: HttpClientOptions" : ""}
184
- ): Observable<any> {${bodyForm}
223
+ ): ${multiImplementationReturnType} {${bodyForm}
224
+ const headers = options?.headers instanceof HttpHeaders
225
+ ? options.headers.set('Accept', accept)
226
+ : { ...(options?.headers ?? {}), Accept: accept };
227
+
185
228
  if (accept.includes('json') || accept.includes('+json')) {
186
- return this.http.${verb}<any>(\`${route}\`, {
229
+ return this.http.${verb}<${jsonReturnType}>(\`${route}\`, {
187
230
  ...options,
188
231
  responseType: 'json',
189
- headers: { Accept: accept, ...options?.headers },
232
+ headers,
190
233
  });
191
234
  } else if (accept.startsWith('text/') || accept.includes('xml')) {
192
235
  return this.http.${verb}(\`${route}\`, {
193
236
  ...options,
194
237
  responseType: 'text',
195
- headers: { Accept: accept, ...options?.headers },
196
- }) as any;
238
+ headers,
239
+ }) as Observable<string>;
197
240
  } else {
198
241
  return this.http.${verb}(\`${route}\`, {
199
242
  ...options,
200
243
  responseType: 'blob',
201
- headers: { Accept: accept, ...options?.headers },
202
- }) as any;
244
+ headers,
245
+ }) as Observable<Blob>;
203
246
  }
204
247
  }
205
248
  `;
206
249
  }
250
+ const observeImplementation = isRequestOptions ? `${paramsDeclaration}if (options?.observe === 'events') {
251
+ return this.http.${verb}${isModelType ? "<TData>" : ""}(${observeOptions?.events ?? options});
252
+ }
253
+
254
+ if (options?.observe === 'response') {
255
+ return this.http.${verb}${isModelType ? "<TData>" : ""}(${observeOptions?.response ?? options});
256
+ }
257
+
258
+ return this.http.${verb}${isModelType ? "<TData>" : ""}(${observeOptions?.body ?? options});` : `return this.http.${verb}${isModelType ? "<TData>" : ""}(${options});`;
207
259
  return ` ${overloads}
208
260
  ${functionName}(
209
- ${toObjectString(props, "implementation")} ${isRequestOptions ? `options?: HttpClientOptions & { observe?: any }` : ""}): Observable<any> {${bodyForm}
210
- return this.http.${verb}${isModelType ? "<TData>" : ""}(${options});
261
+ ${toObjectString(props, "implementation")} ${isRequestOptions ? `options?: HttpClientOptions & { observe?: 'body' | 'events' | 'response' }` : ""}): ${singleImplementationReturnType} {${bodyForm}
262
+ ${observeImplementation}
211
263
  }
212
264
  `;
213
265
  };
214
- const generateAngular = (verbOptions, options) => {
266
+ const createAngularClient = (returnTypesToWrite) => (verbOptions, options, _outputClient, _output) => {
215
267
  const imports = generateVerbImports(verbOptions);
216
268
  return {
217
- implementation: generateImplementation(verbOptions, options),
269
+ implementation: generateImplementation(returnTypesToWrite, verbOptions, options),
218
270
  imports
219
271
  };
220
272
  };
221
- const angularClientBuilder = {
222
- client: generateAngular,
223
- header: generateAngularHeader,
224
- dependencies: getAngularDependencies,
225
- footer: generateAngularFooter,
226
- title: generateAngularTitle
273
+ const standaloneReturnTypesToWrite = /* @__PURE__ */ new Map();
274
+ const generateAngular = (verbOptions, options, outputClient, output) => createAngularClient(standaloneReturnTypesToWrite)(verbOptions, options, outputClient, output);
275
+ const createAngularClientBuilder = () => {
276
+ const returnTypesToWrite = /* @__PURE__ */ new Map();
277
+ return {
278
+ client: createAngularClient(returnTypesToWrite),
279
+ header: createAngularHeader(),
280
+ dependencies: getAngularDependencies,
281
+ footer: createAngularFooter(returnTypesToWrite),
282
+ title: generateAngularTitle
283
+ };
284
+ };
285
+ const builder = () => {
286
+ return () => createAngularClientBuilder();
227
287
  };
228
- const builder = () => () => angularClientBuilder;
229
288
  var src_default = builder;
230
289
 
231
290
  //#endregion
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["ANGULAR_DEPENDENCIES: GeneratorDependency[]","getAngularDependencies: ClientDependenciesBuilder","generateAngularTitle: ClientTitleBuilder","generateAngularHeader: ClientHeaderBuilder","generateAngularFooter: ClientFooterBuilder","generateAngular: ClientBuilder","angularClientBuilder: ClientGeneratorsBuilder"],"sources":["../src/index.ts"],"sourcesContent":["import {\n type ClientBuilder,\n type ClientDependenciesBuilder,\n type ClientFooterBuilder,\n type ClientGeneratorsBuilder,\n type ClientHeaderBuilder,\n type ClientTitleBuilder,\n generateFormDataAndUrlEncodedFunction,\n generateMutatorConfig,\n generateMutatorRequestOptions,\n generateOptions,\n generateVerbImports,\n type GeneratorDependency,\n type GeneratorOptions,\n type GeneratorVerbOptions,\n getDefaultContentType,\n isBoolean,\n pascal,\n sanitize,\n toObjectString,\n} from '@orval/core';\n\nconst ANGULAR_DEPENDENCIES: GeneratorDependency[] = [\n {\n exports: [\n { name: 'HttpClient', values: true },\n { name: 'HttpHeaders' },\n { name: 'HttpParams' },\n { name: 'HttpContext' },\n { name: 'HttpResponse', alias: 'AngularHttpResponse' }, // alias to prevent naming conflict with msw\n { name: 'HttpEvent' },\n ],\n dependency: '@angular/common/http',\n },\n {\n exports: [\n { name: 'Injectable', values: true },\n { name: 'inject', values: true },\n ],\n dependency: '@angular/core',\n },\n {\n exports: [{ name: 'Observable', values: true }],\n dependency: 'rxjs',\n },\n {\n exports: [{ name: 'DeepNonNullable' }],\n dependency: '@orval/core',\n },\n];\n\nconst returnTypesToWrite = new Map<string, string>();\n\nexport const getAngularDependencies: ClientDependenciesBuilder = () =>\n ANGULAR_DEPENDENCIES;\n\nexport const generateAngularTitle: ClientTitleBuilder = (title) => {\n const sanTitle = sanitize(title);\n return `${pascal(sanTitle)}Service`;\n};\n\nexport const generateAngularHeader: ClientHeaderBuilder = ({\n title,\n isRequestOptions,\n isMutator,\n isGlobalMutator,\n provideIn,\n}) => `\n${\n isRequestOptions && !isGlobalMutator\n ? `interface HttpClientOptions {\n headers?: HttpHeaders | Record<string, string | string[]>;\n context?: HttpContext;\n params?:\n | HttpParams\n | Record<string, string | number | boolean | ReadonlyArray<string | number | boolean>>;\n reportProgress?: boolean;\n withCredentials?: boolean;\n credentials?: RequestCredentials;\n keepalive?: boolean;\n priority?: RequestPriority;\n cache?: RequestCache;\n mode?: RequestMode;\n redirect?: RequestRedirect;\n referrer?: string;\n integrity?: string;\n transferCache?: {includeHeaders?: string[]} | boolean;\n timeout?: number;\n}`\n : ''\n}\n\n${\n isRequestOptions && isMutator\n ? `// eslint-disable-next-line\n type ThirdParameter<T extends (...args: any) => any> = T extends (\n config: any,\n httpClient: any,\n args: infer P,\n) => any\n ? P\n : never;`\n : ''\n}\n\n@Injectable(${\n provideIn\n ? `{ providedIn: '${isBoolean(provideIn) ? 'root' : provideIn}' }`\n : ''\n})\nexport class ${title} {\n private readonly http = inject(HttpClient);\n`;\n\nexport const generateAngularFooter: ClientFooterBuilder = ({\n operationNames,\n}) => {\n let footer = '};\\n\\n';\n\n for (const operationName of operationNames) {\n if (returnTypesToWrite.has(operationName)) {\n // Map.has ensures Map.get will not return undefined, but TS still complains\n // bug https://github.com/microsoft/TypeScript/issues/13086\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n footer += returnTypesToWrite.get(operationName) + '\\n';\n }\n }\n\n return footer;\n};\n\nconst generateImplementation = (\n {\n headers,\n queryParams,\n operationName,\n response,\n mutator,\n body,\n props,\n verb,\n override,\n formData,\n formUrlEncoded,\n paramsSerializer,\n }: GeneratorVerbOptions,\n { route, context }: GeneratorOptions,\n) => {\n const isRequestOptions = override.requestOptions !== false;\n const isFormData = !override.formData.disabled;\n const isFormUrlEncoded = override.formUrlEncoded !== false;\n const isExactOptionalPropertyTypes =\n !!context.output.tsconfig?.compilerOptions?.exactOptionalPropertyTypes;\n const bodyForm = generateFormDataAndUrlEncodedFunction({\n formData,\n formUrlEncoded,\n body,\n isFormData,\n isFormUrlEncoded,\n });\n\n const dataType = response.definition.success || 'unknown';\n\n returnTypesToWrite.set(\n operationName,\n `export type ${pascal(\n operationName,\n )}ClientResult = NonNullable<${dataType}>`,\n );\n\n if (mutator) {\n const mutatorConfig = generateMutatorConfig({\n route,\n body,\n headers,\n queryParams,\n response,\n verb,\n isFormData,\n isFormUrlEncoded,\n hasSignal: false,\n isExactOptionalPropertyTypes,\n });\n\n const requestOptions = isRequestOptions\n ? generateMutatorRequestOptions(\n override.requestOptions,\n mutator.hasThirdArg,\n )\n : '';\n\n const propsImplementation =\n mutator.bodyTypeName && body.definition\n ? toObjectString(props, 'implementation').replace(\n new RegExp(String.raw`(\\w*):\\s?${body.definition}`),\n `$1: ${mutator.bodyTypeName}<${body.definition}>`,\n )\n : toObjectString(props, 'implementation');\n\n return ` ${operationName}<TData = ${dataType}>(\\n ${propsImplementation}\\n ${\n isRequestOptions && mutator.hasThirdArg\n ? `options?: ThirdParameter<typeof ${mutator.name}>`\n : ''\n }) {${bodyForm}\n return ${mutator.name}<TData>(\n ${mutatorConfig},\n this.http,\n ${requestOptions});\n }\n `;\n }\n\n const options = generateOptions({\n route,\n body,\n headers,\n queryParams,\n response,\n verb,\n requestOptions: override.requestOptions,\n isFormData,\n isFormUrlEncoded,\n paramsSerializer,\n paramsSerializerOptions: override.paramsSerializerOptions,\n isAngular: true,\n isExactOptionalPropertyTypes,\n hasSignal: false,\n });\n\n const propsDefinition = toObjectString(props, 'definition');\n\n // Check for multiple content types in success responses\n const successTypes = response.types.success;\n const uniqueContentTypes = [\n ...new Set(successTypes.map((t) => t.contentType).filter(Boolean)),\n ];\n const hasMultipleContentTypes = uniqueContentTypes.length > 1;\n\n // For multiple content types, determine the default\n const defaultContentType = hasMultipleContentTypes\n ? getDefaultContentType(uniqueContentTypes)\n : (uniqueContentTypes[0] ?? 'application/json');\n const defaultType = hasMultipleContentTypes\n ? successTypes.find((t) => t.contentType === defaultContentType)\n : undefined;\n const defaultReturnType = defaultType?.value ?? dataType;\n\n const isModelType = dataType !== 'Blob' && dataType !== 'string';\n let functionName = operationName;\n if (isModelType && !hasMultipleContentTypes) {\n functionName += `<TData = ${dataType}>`;\n }\n\n let contentTypeOverloads = '';\n if (hasMultipleContentTypes && isRequestOptions) {\n const requiredProps = props.filter((p) => p.required && !p.default);\n const optionalProps = props.filter((p) => !p.required || p.default);\n\n contentTypeOverloads = successTypes\n .filter((t) => t.contentType)\n .map(({ contentType, value }) => {\n const requiredPart = requiredProps\n .map((p) => p.definition)\n .join(',\\n ');\n const acceptPart = `accept: '${contentType}'`;\n const optionalPart = optionalProps\n .map((p) => p.definition)\n .join(',\\n ');\n\n const allParams = [requiredPart, acceptPart, optionalPart]\n .filter(Boolean)\n .join(',\\n ');\n return `${operationName}(${allParams}, options?: HttpClientOptions): Observable<${value}>;`;\n })\n .join('\\n ');\n\n const requiredPart = requiredProps.map((p) => p.definition).join(',\\n ');\n const optionalPart = optionalProps.map((p) => p.definition).join(',\\n ');\n const allParams = [requiredPart, 'accept?: string', optionalPart]\n .filter(Boolean)\n .join(',\\n ');\n contentTypeOverloads += `\\n ${operationName}(${allParams}, options?: HttpClientOptions): Observable<${defaultReturnType}>;`;\n }\n\n const observeOverloads =\n isRequestOptions && !hasMultipleContentTypes\n ? `${functionName}(${propsDefinition} options?: HttpClientOptions & { observe?: 'body' }): Observable<${isModelType ? 'TData' : dataType}>;\n ${functionName}(${propsDefinition} options?: HttpClientOptions & { observe: 'events' }): Observable<HttpEvent<${isModelType ? 'TData' : dataType}>>;\n ${functionName}(${propsDefinition} options?: HttpClientOptions & { observe: 'response' }): Observable<AngularHttpResponse<${isModelType ? 'TData' : dataType}>>;`\n : '';\n\n const overloads = contentTypeOverloads || observeOverloads;\n\n if (hasMultipleContentTypes) {\n const requiredProps = props.filter((p) => p.required && !p.default);\n const optionalProps = props.filter((p) => !p.required || p.default);\n\n const requiredPart = requiredProps\n .map((p) => p.implementation)\n .join(',\\n ');\n const optionalPart = optionalProps\n .map((p) => p.implementation)\n .join(',\\n ');\n const allParams = [\n requiredPart,\n `accept: string = '${defaultContentType}'`,\n optionalPart,\n ]\n .filter(Boolean)\n .join(',\\n ');\n\n return ` ${overloads}\n ${operationName}(\n ${allParams},\n ${isRequestOptions ? 'options?: HttpClientOptions' : ''}\n ): Observable<any> {${bodyForm}\n if (accept.includes('json') || accept.includes('+json')) {\n return this.http.${verb}<any>(\\`${route}\\`, {\n ...options,\n responseType: 'json',\n headers: { Accept: accept, ...options?.headers },\n });\n } else if (accept.startsWith('text/') || accept.includes('xml')) {\n return this.http.${verb}(\\`${route}\\`, {\n ...options,\n responseType: 'text',\n headers: { Accept: accept, ...options?.headers },\n }) as any;\n } else {\n return this.http.${verb}(\\`${route}\\`, {\n ...options,\n responseType: 'blob',\n headers: { Accept: accept, ...options?.headers },\n }) as any;\n }\n }\n`;\n }\n\n return ` ${overloads}\n ${functionName}(\n ${toObjectString(props, 'implementation')} ${\n isRequestOptions ? `options?: HttpClientOptions & { observe?: any }` : ''\n }): Observable<any> {${bodyForm}\n return this.http.${verb}${isModelType ? '<TData>' : ''}(${options});\n }\n`;\n};\n\nexport const generateAngular: ClientBuilder = (verbOptions, options) => {\n const imports = generateVerbImports(verbOptions);\n const implementation = generateImplementation(verbOptions, options);\n\n return { implementation, imports };\n};\n\nconst angularClientBuilder: ClientGeneratorsBuilder = {\n client: generateAngular,\n header: generateAngularHeader,\n dependencies: getAngularDependencies,\n footer: generateAngularFooter,\n title: generateAngularTitle,\n};\n\nexport const builder = () => () => angularClientBuilder;\n\nexport default builder;\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["getAngularDependencies: ClientDependenciesBuilder","generateAngularTitle: ClientTitleBuilder","generateAngularHeader: ClientHeaderBuilder","generateAngularFooter: ClientFooterBuilder","generateAngular: ClientBuilder","builder: () => () => ClientGeneratorsBuilder"],"sources":["../src/index.ts"],"sourcesContent":["import {\n type ClientBuilder,\n type ClientDependenciesBuilder,\n type ClientFooterBuilder,\n type ClientGeneratorsBuilder,\n type ClientHeaderBuilder,\n type ClientTitleBuilder,\n generateFormDataAndUrlEncodedFunction,\n generateMutatorConfig,\n generateMutatorRequestOptions,\n generateOptions,\n generateVerbImports,\n type GeneratorDependency,\n type GeneratorOptions,\n type GeneratorVerbOptions,\n getAngularFilteredParamsCallExpression,\n getAngularFilteredParamsHelperBody,\n getDefaultContentType,\n isBoolean,\n pascal,\n sanitize,\n toObjectString,\n} from '@orval/core';\n\nconst ANGULAR_DEPENDENCIES = [\n {\n exports: [\n { name: 'HttpClient', values: true },\n { name: 'HttpHeaders', values: true },\n { name: 'HttpParams' },\n { name: 'HttpContext' },\n { name: 'HttpResponse', alias: 'AngularHttpResponse' }, // alias to prevent naming conflict with msw\n { name: 'HttpEvent' },\n ],\n dependency: '@angular/common/http',\n },\n {\n exports: [\n { name: 'Injectable', values: true },\n { name: 'inject', values: true },\n ],\n dependency: '@angular/core',\n },\n {\n exports: [{ name: 'Observable', values: true }],\n dependency: 'rxjs',\n },\n] as const satisfies readonly GeneratorDependency[];\n\ntype ReturnTypesToWrite = Map<string, string>;\n\nexport const getAngularDependencies: ClientDependenciesBuilder = () => [\n ...ANGULAR_DEPENDENCIES,\n];\n\nexport const generateAngularTitle: ClientTitleBuilder = (title) => {\n const sanTitle = sanitize(title);\n return `${pascal(sanTitle)}Service`;\n};\n\nconst createAngularHeader =\n (): ClientHeaderBuilder =>\n ({\n title,\n isRequestOptions,\n isMutator,\n isGlobalMutator,\n provideIn,\n verbOptions,\n tag,\n }) => {\n const relevantVerbs = tag\n ? Object.values(verbOptions).filter((v) => v.tags.includes(tag as string))\n : Object.values(verbOptions);\n const hasQueryParams = relevantVerbs.some((v) => v.queryParams);\n return `\n${\n isRequestOptions && !isGlobalMutator\n ? `interface HttpClientOptions {\n headers?: HttpHeaders | Record<string, string | string[]>;\n context?: HttpContext;\n params?:\n | HttpParams\n | Record<string, string | number | boolean | Array<string | number | boolean>>;\n reportProgress?: boolean;\n withCredentials?: boolean;\n credentials?: RequestCredentials;\n keepalive?: boolean;\n priority?: RequestPriority;\n cache?: RequestCache;\n mode?: RequestMode;\n redirect?: RequestRedirect;\n referrer?: string;\n integrity?: string;\n referrerPolicy?: ReferrerPolicy;\n transferCache?: {includeHeaders?: string[]} | boolean;\n}\n\n${hasQueryParams ? getAngularFilteredParamsHelperBody() : ''}`\n : ''\n}\n\n${\n isRequestOptions && isMutator\n ? `// eslint-disable-next-line\n type ThirdParameter<T extends (...args: any) => any> = T extends (\n config: any,\n httpClient: any,\n args: infer P,\n) => any\n ? P\n : never;`\n : ''\n}\n\n@Injectable(${provideIn ? `{ providedIn: '${isBoolean(provideIn) ? 'root' : provideIn}' }` : ''})\nexport class ${title} {\n private readonly http = inject(HttpClient);\n`;\n };\n\nexport const generateAngularHeader: ClientHeaderBuilder = (params) =>\n createAngularHeader()(params);\n\nconst standaloneFooterReturnTypesToWrite = new Map<string, string>();\n\nconst createAngularFooter =\n (returnTypesToWrite: ReturnTypesToWrite): ClientFooterBuilder =>\n ({ operationNames }) => {\n let footer = '};\\n\\n';\n\n for (const operationName of operationNames) {\n if (returnTypesToWrite.has(operationName)) {\n // Map.has ensures Map.get will not return undefined, but TS still complains\n // bug https://github.com/microsoft/TypeScript/issues/13086\n // eslint-disable-next-line @typescript-eslint/restrict-plus-operands\n footer += returnTypesToWrite.get(operationName) + '\\n';\n }\n }\n\n return footer;\n };\n\nexport const generateAngularFooter: ClientFooterBuilder = (params) =>\n createAngularFooter(standaloneFooterReturnTypesToWrite)(params);\n\nconst generateImplementation = (\n returnTypesToWrite: ReturnTypesToWrite,\n {\n headers,\n queryParams,\n operationName,\n response,\n mutator,\n body,\n props,\n verb,\n override,\n formData,\n formUrlEncoded,\n paramsSerializer,\n }: GeneratorVerbOptions,\n { route, context }: GeneratorOptions,\n) => {\n const isRequestOptions = override.requestOptions !== false;\n const isFormData = !override.formData.disabled;\n const isFormUrlEncoded = override.formUrlEncoded !== false;\n const isExactOptionalPropertyTypes =\n !!context.output.tsconfig?.compilerOptions?.exactOptionalPropertyTypes;\n const bodyForm = generateFormDataAndUrlEncodedFunction({\n formData,\n formUrlEncoded,\n body,\n isFormData,\n isFormUrlEncoded,\n });\n\n const dataType = response.definition.success || 'unknown';\n\n returnTypesToWrite.set(\n operationName,\n `export type ${pascal(\n operationName,\n )}ClientResult = NonNullable<${dataType}>`,\n );\n\n if (mutator) {\n const mutatorConfig = generateMutatorConfig({\n route,\n body,\n headers,\n queryParams,\n response,\n verb,\n isFormData,\n isFormUrlEncoded,\n hasSignal: false,\n isExactOptionalPropertyTypes,\n isAngular: true,\n });\n\n const requestOptions = isRequestOptions\n ? generateMutatorRequestOptions(\n override.requestOptions,\n mutator.hasThirdArg,\n )\n : '';\n\n const propsImplementation =\n mutator.bodyTypeName && body.definition\n ? toObjectString(props, 'implementation').replace(\n new RegExp(String.raw`(\\w*):\\s?${body.definition}`),\n `$1: ${mutator.bodyTypeName}<${body.definition}>`,\n )\n : toObjectString(props, 'implementation');\n\n return ` ${operationName}<TData = ${dataType}>(\\n ${propsImplementation}\\n ${\n isRequestOptions && mutator.hasThirdArg\n ? `options?: ThirdParameter<typeof ${mutator.name}>`\n : ''\n }) {${bodyForm}\n return ${mutator.name}<TData>(\n ${mutatorConfig},\n this.http,\n ${requestOptions});\n }\n `;\n }\n\n const optionsBase = {\n route,\n body,\n headers,\n queryParams,\n response,\n verb,\n requestOptions: override.requestOptions,\n isFormData,\n isFormUrlEncoded,\n paramsSerializer,\n paramsSerializerOptions: override.paramsSerializerOptions,\n isAngular: true,\n isExactOptionalPropertyTypes,\n hasSignal: false,\n } as const;\n\n const propsDefinition = toObjectString(props, 'definition');\n\n // Check for multiple content types in success responses\n const successTypes = response.types.success;\n const uniqueContentTypes = [\n ...new Set(successTypes.map((t) => t.contentType).filter(Boolean)),\n ];\n const hasMultipleContentTypes = uniqueContentTypes.length > 1;\n\n // When observe branching is active AND there are query params, extract\n // the params computation to a local const to avoid duplicating it in\n // every observe branch.\n const needsObserveBranching = isRequestOptions && !hasMultipleContentTypes;\n const angularParamsRef =\n needsObserveBranching && queryParams ? 'filteredParams' : undefined;\n\n let paramsDeclaration = '';\n if (angularParamsRef && queryParams) {\n const callExpr = getAngularFilteredParamsCallExpression(\n '{...params, ...options?.params}',\n queryParams.requiredNullableKeys ?? [],\n );\n paramsDeclaration = paramsSerializer\n ? `const ${angularParamsRef} = ${paramsSerializer.name}(${callExpr});\\n\\n `\n : `const ${angularParamsRef} = ${callExpr};\\n\\n `;\n }\n\n const options = generateOptions({\n ...optionsBase,\n ...(angularParamsRef ? { angularParamsRef } : {}),\n });\n\n // For multiple content types, determine the default\n const defaultContentType = hasMultipleContentTypes\n ? uniqueContentTypes.includes('text/plain')\n ? 'text/plain'\n : getDefaultContentType(uniqueContentTypes)\n : (uniqueContentTypes[0] ?? 'application/json');\n const getContentTypeReturnType = (\n contentType: string | undefined,\n value: string,\n ): string => {\n if (!contentType) {\n return value;\n }\n\n if (contentType.includes('json') || contentType.includes('+json')) {\n return value;\n }\n\n if (contentType.startsWith('text/') || contentType.includes('xml')) {\n return 'string';\n }\n\n return 'Blob';\n };\n\n const jsonSuccessValues = [\n ...new Set(\n successTypes\n .filter(\n ({ contentType }) =>\n !!contentType &&\n (contentType.includes('json') || contentType.includes('+json')),\n )\n .map(({ value }) => value),\n ),\n ];\n\n const jsonReturnType =\n jsonSuccessValues.length > 0 ? jsonSuccessValues.join(' | ') : 'unknown';\n const multiImplementationReturnType = `Observable<${jsonReturnType} | string | Blob>`;\n\n const withObserveMode = (\n generatedOptions: string,\n observeMode: 'body' | 'events' | 'response',\n ): string => {\n const spreadPattern =\n \"...(options as Omit<NonNullable<typeof options>, 'observe'>),\";\n\n if (generatedOptions.includes(spreadPattern)) {\n return generatedOptions.replace(\n spreadPattern,\n `${spreadPattern}\\n observe: '${observeMode}',`,\n );\n }\n\n return generatedOptions.replace(\n \"(options as Omit<NonNullable<typeof options>, 'observe'>)\",\n `{ ...(options as Omit<NonNullable<typeof options>, 'observe'>), observe: '${observeMode}' }`,\n );\n };\n\n const observeOptions = needsObserveBranching\n ? {\n body: withObserveMode(options, 'body'),\n events: withObserveMode(options, 'events'),\n response: withObserveMode(options, 'response'),\n }\n : undefined;\n\n const isModelType = dataType !== 'Blob' && dataType !== 'string';\n let functionName = operationName;\n if (isModelType && !hasMultipleContentTypes) {\n functionName += `<TData = ${dataType}>`;\n }\n\n let contentTypeOverloads = '';\n if (hasMultipleContentTypes && isRequestOptions) {\n const requiredProps = props.filter((p) => p.required && !p.default);\n const optionalProps = props.filter((p) => !p.required || p.default);\n\n contentTypeOverloads = successTypes\n .filter((t) => t.contentType)\n .map(({ contentType, value }) => {\n const returnType = getContentTypeReturnType(contentType, value);\n const requiredPart = requiredProps\n .map((p) => p.definition)\n .join(',\\n ');\n const acceptPart = `accept: '${contentType}'`;\n const optionalPart = optionalProps\n .map((p) => p.definition)\n .join(',\\n ');\n\n const allParams = [requiredPart, acceptPart, optionalPart]\n .filter(Boolean)\n .join(',\\n ');\n return `${operationName}(${allParams}, options?: HttpClientOptions): Observable<${returnType}>;`;\n })\n .join('\\n ');\n\n const requiredPart = requiredProps.map((p) => p.definition).join(',\\n ');\n const optionalPart = optionalProps.map((p) => p.definition).join(',\\n ');\n const allParams = [requiredPart, 'accept?: string', optionalPart]\n .filter(Boolean)\n .join(',\\n ');\n contentTypeOverloads += `\\n ${operationName}(${allParams}, options?: HttpClientOptions): ${multiImplementationReturnType};`;\n }\n\n const observeOverloads =\n isRequestOptions && !hasMultipleContentTypes\n ? `${functionName}(${propsDefinition} options?: HttpClientOptions & { observe?: 'body' }): Observable<${isModelType ? 'TData' : dataType}>;\n ${functionName}(${propsDefinition} options?: HttpClientOptions & { observe: 'events' }): Observable<HttpEvent<${isModelType ? 'TData' : dataType}>>;\n ${functionName}(${propsDefinition} options?: HttpClientOptions & { observe: 'response' }): Observable<AngularHttpResponse<${isModelType ? 'TData' : dataType}>>;`\n : '';\n\n const overloads = contentTypeOverloads || observeOverloads;\n\n const observableDataType = isModelType ? 'TData' : dataType;\n const singleImplementationReturnType = isRequestOptions\n ? `Observable<${observableDataType} | HttpEvent<${observableDataType}> | AngularHttpResponse<${observableDataType}>>`\n : `Observable<${observableDataType}>`;\n\n if (hasMultipleContentTypes) {\n const requiredProps = props.filter((p) => p.required && !p.default);\n const optionalProps = props.filter((p) => !p.required || p.default);\n\n const requiredPart = requiredProps\n .map((p) => p.implementation)\n .join(',\\n ');\n const optionalPart = optionalProps\n .map((p) => p.implementation)\n .join(',\\n ');\n const allParams = [\n requiredPart,\n `accept: string = '${defaultContentType}'`,\n optionalPart,\n ]\n .filter(Boolean)\n .join(',\\n ');\n\n return ` ${overloads}\n ${operationName}(\n ${allParams},\n ${isRequestOptions ? 'options?: HttpClientOptions' : ''}\n ): ${multiImplementationReturnType} {${bodyForm}\n const headers = options?.headers instanceof HttpHeaders\n ? options.headers.set('Accept', accept)\n : { ...(options?.headers ?? {}), Accept: accept };\n\n if (accept.includes('json') || accept.includes('+json')) {\n return this.http.${verb}<${jsonReturnType}>(\\`${route}\\`, {\n ...options,\n responseType: 'json',\n headers,\n });\n } else if (accept.startsWith('text/') || accept.includes('xml')) {\n return this.http.${verb}(\\`${route}\\`, {\n ...options,\n responseType: 'text',\n headers,\n }) as Observable<string>;\n } else {\n return this.http.${verb}(\\`${route}\\`, {\n ...options,\n responseType: 'blob',\n headers,\n }) as Observable<Blob>;\n }\n }\n`;\n }\n\n const observeImplementation = isRequestOptions\n ? `${paramsDeclaration}if (options?.observe === 'events') {\n return this.http.${verb}${isModelType ? '<TData>' : ''}(${\n observeOptions?.events ?? options\n });\n }\n\n if (options?.observe === 'response') {\n return this.http.${verb}${isModelType ? '<TData>' : ''}(${\n observeOptions?.response ?? options\n });\n }\n\n return this.http.${verb}${isModelType ? '<TData>' : ''}(${\n observeOptions?.body ?? options\n });`\n : `return this.http.${verb}${isModelType ? '<TData>' : ''}(${options});`;\n\n return ` ${overloads}\n ${functionName}(\n ${toObjectString(props, 'implementation')} ${\n isRequestOptions\n ? `options?: HttpClientOptions & { observe?: 'body' | 'events' | 'response' }`\n : ''\n }): ${singleImplementationReturnType} {${bodyForm}\n ${observeImplementation}\n }\n`;\n};\n\nconst createAngularClient =\n (returnTypesToWrite: ReturnTypesToWrite): ClientBuilder =>\n (verbOptions, options, _outputClient, _output) => {\n // Keep signature aligned with ClientBuilder without tripping TS noUnusedParameters\n void _outputClient;\n void _output;\n const imports = generateVerbImports(verbOptions);\n const implementation = generateImplementation(\n returnTypesToWrite,\n verbOptions,\n options,\n );\n\n return { implementation, imports };\n };\n\nconst standaloneReturnTypesToWrite = new Map<string, string>();\n\nexport const generateAngular: ClientBuilder = (\n verbOptions,\n options,\n outputClient,\n output,\n) =>\n createAngularClient(standaloneReturnTypesToWrite)(\n verbOptions,\n options,\n outputClient,\n output,\n );\n\nconst createAngularClientBuilder = (): ClientGeneratorsBuilder => {\n const returnTypesToWrite = new Map<string, string>();\n\n return {\n client: createAngularClient(returnTypesToWrite),\n header: createAngularHeader(),\n dependencies: getAngularDependencies,\n footer: createAngularFooter(returnTypesToWrite),\n title: generateAngularTitle,\n };\n};\n\nexport const builder: () => () => ClientGeneratorsBuilder = () => {\n return () => createAngularClientBuilder();\n};\n\nexport default builder;\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,13 +1,11 @@
1
1
  {
2
2
  "name": "@orval/angular",
3
- "version": "8.2.0",
3
+ "version": "8.4.0",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "exports": {
7
- "import": {
8
- "types": "./dist/index.d.mts",
9
- "import": "./dist/index.mjs"
10
- }
7
+ ".": "./dist/index.mjs",
8
+ "./package.json": "./package.json"
11
9
  },
12
10
  "files": [
13
11
  "dist",
@@ -18,16 +16,21 @@
18
16
  "build": "tsdown --config-loader unrun",
19
17
  "dev": "tsdown --config-loader unrun --watch src",
20
18
  "lint": "eslint .",
19
+ "test": "vitest",
21
20
  "clean": "rimraf .turbo dist",
22
21
  "nuke": "rimraf .turbo dist node_modules"
23
22
  },
24
23
  "dependencies": {
25
- "@orval/core": "8.2.0"
24
+ "@orval/core": "8.4.0"
26
25
  },
27
26
  "devDependencies": {
28
27
  "eslint": "9.39.2",
29
28
  "rimraf": "6.1.2",
30
29
  "tsdown": "0.18.2",
31
- "typescript": "5.9.3"
32
- }
30
+ "typescript": "5.9.3",
31
+ "vitest": "4.0.16"
32
+ },
33
+ "main": "./dist/index.mjs",
34
+ "module": "./dist/index.mjs",
35
+ "types": "./dist/index.d.mts"
33
36
  }