ng-openapi 0.1.8 → 0.1.9-pr-18-feature-schema-validation-dbff16c.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 (4) hide show
  1. package/cli.cjs +141 -54
  2. package/index.d.ts +11 -2
  3. package/index.js +163 -54
  4. package/package.json +1 -1
package/cli.cjs CHANGED
@@ -115,6 +115,7 @@ __name(escapeString, "escapeString");
115
115
  // ../shared/src/utils/functions/collect-used-types.ts
116
116
  function collectUsedTypes(operations) {
117
117
  const usedTypes = /* @__PURE__ */ new Set();
118
+ usedTypes.add("RequestOptions");
118
119
  operations.forEach((operation) => {
119
120
  operation.parameters?.forEach((param) => {
120
121
  collectTypesFromSchema(param.schema || param, usedTypes);
@@ -387,6 +388,34 @@ function getResponseType(response, config) {
387
388
  }
388
389
  __name(getResponseType, "getResponseType");
389
390
 
391
+ // ../shared/src/utils/functions/get-request-body-type.ts
392
+ function getRequestBodyType(requestBody, config) {
393
+ const content = requestBody.content || {};
394
+ const jsonContent = content["application/json"];
395
+ if (jsonContent?.schema) {
396
+ return getTypeScriptType(jsonContent.schema, config, jsonContent.schema.nullable);
397
+ }
398
+ return "any";
399
+ }
400
+ __name(getRequestBodyType, "getRequestBodyType");
401
+
402
+ // ../shared/src/utils/functions/is-data-type-interface.ts
403
+ function isDataTypeInterface(type) {
404
+ const invalidTypes = [
405
+ "any",
406
+ "File",
407
+ "string",
408
+ "number",
409
+ "boolean",
410
+ "object",
411
+ "unknown",
412
+ "[]",
413
+ "Array"
414
+ ];
415
+ return !invalidTypes.some((invalidType) => type.includes(invalidType));
416
+ }
417
+ __name(isDataTypeInterface, "isDataTypeInterface");
418
+
390
419
  // ../shared/src/config/constants.ts
391
420
  var disableLinting = `/* @ts-nocheck */
392
421
  /* eslint-disable */
@@ -629,6 +658,7 @@ var TypeGenerator = class _TypeGenerator {
629
658
  Object.entries(definitions).forEach(([name, definition]) => {
630
659
  this.generateInterface(name, definition);
631
660
  });
661
+ this.generateSdkTypes();
632
662
  this.sourceFile.formatText();
633
663
  this.sourceFile.saveSync();
634
664
  } catch (error) {
@@ -885,6 +915,74 @@ var TypeGenerator = class _TypeGenerator {
885
915
  escapeString(str) {
886
916
  return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
887
917
  }
918
+ generateSdkTypes() {
919
+ this.sourceFile.addImportDeclarations([
920
+ {
921
+ namedImports: [
922
+ "HttpContext",
923
+ "HttpHeaders"
924
+ ],
925
+ moduleSpecifier: "@angular/common/http"
926
+ }
927
+ ]);
928
+ const { response } = this.config.options.validation ?? {};
929
+ const typeParameters = [
930
+ "TResponseType extends 'arraybuffer' | 'blob' | 'json' | 'text'"
931
+ ];
932
+ const properties = [
933
+ {
934
+ name: "headers",
935
+ type: "HttpHeaders",
936
+ hasQuestionToken: true
937
+ },
938
+ {
939
+ name: "reportProgress",
940
+ type: "boolean",
941
+ hasQuestionToken: true
942
+ },
943
+ {
944
+ name: "responseType",
945
+ type: "TResponseType",
946
+ hasQuestionToken: true
947
+ },
948
+ {
949
+ name: "withCredentials",
950
+ type: "boolean",
951
+ hasQuestionToken: true
952
+ },
953
+ {
954
+ name: "context",
955
+ type: "HttpContext",
956
+ hasQuestionToken: true
957
+ }
958
+ ];
959
+ if (response) {
960
+ properties.push({
961
+ name: "parse",
962
+ type: "(response: unknown) => TReturnType",
963
+ hasQuestionToken: true
964
+ });
965
+ typeParameters.push("TReturnType");
966
+ this.sourceFile.addInterface({
967
+ name: "RequestOptions",
968
+ isExported: true,
969
+ typeParameters,
970
+ properties,
971
+ docs: [
972
+ "Request Options for Angular HttpClient requests without request parsing"
973
+ ]
974
+ });
975
+ }
976
+ this.sourceFile.addInterface({
977
+ name: "RequestOptions",
978
+ isExported: true,
979
+ typeParameters,
980
+ properties,
981
+ docs: [
982
+ "Request Options for Angular HttpClient requests"
983
+ ]
984
+ });
985
+ }
888
986
  };
889
987
 
890
988
  // src/lib/generators/utility/token.generator.ts
@@ -1705,14 +1803,6 @@ var ServiceMethodBodyGenerator = class {
1705
1803
  ];
1706
1804
  return bodyParts.filter(Boolean).join("\n");
1707
1805
  }
1708
- getRequestBodyType(requestBody) {
1709
- const content = requestBody.content || {};
1710
- const jsonContent = content["application/json"];
1711
- if (jsonContent?.schema) {
1712
- return getTypeScriptType(jsonContent.schema, this.config, jsonContent.schema.nullable);
1713
- }
1714
- return "any";
1715
- }
1716
1806
  isMultipartFormData(operation) {
1717
1807
  return !!operation.requestBody?.content?.["multipart/form-data"];
1718
1808
  }
@@ -1830,8 +1920,8 @@ const requestOptions: any = {
1830
1920
  if (context.isMultipart) {
1831
1921
  bodyParam = "formData";
1832
1922
  } else if (operation.requestBody?.content?.["application/json"]) {
1833
- const bodyType = this.getRequestBodyType(operation.requestBody);
1834
- const isInterface = this.isDataTypeInterface(bodyType);
1923
+ const bodyType = getRequestBodyType(operation.requestBody, this.config);
1924
+ const isInterface = isDataTypeInterface(bodyType);
1835
1925
  bodyParam = isInterface ? camelCase(bodyType) : "requestBody";
1836
1926
  }
1837
1927
  }
@@ -1840,12 +1930,13 @@ const requestOptions: any = {
1840
1930
  "put",
1841
1931
  "patch"
1842
1932
  ];
1933
+ const parseResponse = this.config.options.validation?.response ? `.pipe(map(response => options?.parse?.(response) ?? response))` : "";
1843
1934
  if (methodsWithBody.includes(httpMethod)) {
1844
1935
  return `
1845
- return this.httpClient.${httpMethod}(url, ${bodyParam || "null"}, requestOptions);`;
1936
+ return this.httpClient.${httpMethod}(url, ${bodyParam || "null"}, requestOptions)${parseResponse};`;
1846
1937
  } else {
1847
1938
  return `
1848
- return this.httpClient.${httpMethod}(url, requestOptions);`;
1939
+ return this.httpClient.${httpMethod}(url, requestOptions)${parseResponse};`;
1849
1940
  }
1850
1941
  }
1851
1942
  determineResponseType(operation) {
@@ -1863,20 +1954,6 @@ return this.httpClient.${httpMethod}(url, requestOptions);`;
1863
1954
  }
1864
1955
  return "json";
1865
1956
  }
1866
- isDataTypeInterface(type) {
1867
- const invalidTypes = [
1868
- "any",
1869
- "File",
1870
- "string",
1871
- "number",
1872
- "boolean",
1873
- "object",
1874
- "unknown",
1875
- "[]",
1876
- "Array"
1877
- ];
1878
- return !invalidTypes.some((invalidType) => type.includes(invalidType));
1879
- }
1880
1957
  };
1881
1958
 
1882
1959
  // src/lib/generators/service/service-method/service-method-params.generator.ts
@@ -1890,7 +1967,7 @@ var ServiceMethodParamsGenerator = class {
1890
1967
  }
1891
1968
  generateMethodParameters(operation) {
1892
1969
  const params = this.generateApiParameters(operation);
1893
- const optionsParam = this.addOptionsParameter();
1970
+ const optionsParam = this.addOptionsParameter(params);
1894
1971
  const combined = [
1895
1972
  ...params,
1896
1973
  ...optionsParam
@@ -1926,7 +2003,7 @@ var ServiceMethodParamsGenerator = class {
1926
2003
  }
1927
2004
  if (operation.requestBody && operation.requestBody?.content?.["application/json"]) {
1928
2005
  const bodyType = this.getRequestBodyType(operation.requestBody);
1929
- const isInterface = this.isDataTypeInterface(bodyType);
2006
+ const isInterface = isDataTypeInterface(bodyType);
1930
2007
  params.push({
1931
2008
  name: isInterface ? camelCase(bodyType) : "requestBody",
1932
2009
  type: bodyType,
@@ -1943,7 +2020,7 @@ var ServiceMethodParamsGenerator = class {
1943
2020
  });
1944
2021
  return params.sort((a, b) => Number(a.hasQuestionToken) - Number(b.hasQuestionToken));
1945
2022
  }
1946
- addOptionsParameter() {
2023
+ addOptionsParameter(params) {
1947
2024
  return [
1948
2025
  {
1949
2026
  name: "observe",
@@ -1952,24 +2029,21 @@ var ServiceMethodParamsGenerator = class {
1952
2029
  },
1953
2030
  {
1954
2031
  name: "options",
1955
- type: `{ headers?: HttpHeaders; params?: HttpParams; reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; context?: HttpContext; }`,
2032
+ type: this.getHttpRequestOptionsParameter(params),
1956
2033
  hasQuestionToken: true
1957
2034
  }
1958
2035
  ];
1959
2036
  }
1960
- isDataTypeInterface(type) {
1961
- const invalidTypes = [
1962
- "any",
1963
- "File",
1964
- "string",
1965
- "number",
1966
- "boolean",
1967
- "object",
1968
- "unknown",
1969
- "[]",
1970
- "Array"
1971
- ];
1972
- return !invalidTypes.some((invalidType) => type.includes(invalidType));
2037
+ getHttpRequestOptionsParameter(params) {
2038
+ const { response } = this.config.options.validation ?? {};
2039
+ const additionalTypeParameters = [];
2040
+ if (response) {
2041
+ additionalTypeParameters.push("any");
2042
+ }
2043
+ if (additionalTypeParameters.length === 0) {
2044
+ return `RequestOptions<'arraybuffer' | 'blob' | 'json' | 'text'>`;
2045
+ }
2046
+ return `RequestOptions<'arraybuffer' | 'blob' | 'json' | 'text', ${additionalTypeParameters.join(", ")}>`;
1973
2047
  }
1974
2048
  getRequestBodyType(requestBody) {
1975
2049
  const content = requestBody.content || {};
@@ -1988,6 +2062,7 @@ var ServiceMethodOverloadsGenerator = class {
1988
2062
  }
1989
2063
  config;
1990
2064
  paramsGenerator;
2065
+ responseDataType = "any";
1991
2066
  constructor(config) {
1992
2067
  this.config = config;
1993
2068
  this.paramsGenerator = new ServiceMethodParamsGenerator(config);
@@ -2009,9 +2084,9 @@ var ServiceMethodOverloadsGenerator = class {
2009
2084
  return overloads;
2010
2085
  }
2011
2086
  generateMethodOverload(operation, observe, responseType) {
2012
- const responseDataType = this.generateOverloadResponseType(operation);
2087
+ this.responseDataType = this.generateOverloadResponseType(operation);
2013
2088
  const params = this.generateOverloadParameters(operation, observe, responseType);
2014
- const returnType = this.generateOverloadReturnType(responseDataType, observe);
2089
+ const returnType = this.generateOverloadReturnType(observe);
2015
2090
  return {
2016
2091
  parameters: params,
2017
2092
  returnType
@@ -2019,7 +2094,7 @@ var ServiceMethodOverloadsGenerator = class {
2019
2094
  }
2020
2095
  generateOverloadParameters(operation, observe, responseType) {
2021
2096
  const params = this.paramsGenerator.generateApiParameters(operation);
2022
- const optionsParam = this.addOverloadOptionsParameter(observe, responseType);
2097
+ const optionsParam = this.addOverloadOptionsParameter(params, observe, responseType);
2023
2098
  const combined = [
2024
2099
  ...params,
2025
2100
  ...optionsParam
@@ -2034,7 +2109,7 @@ var ServiceMethodOverloadsGenerator = class {
2034
2109
  }
2035
2110
  return uniqueParams;
2036
2111
  }
2037
- addOverloadOptionsParameter(observe, responseType) {
2112
+ addOverloadOptionsParameter(params, observe, responseType) {
2038
2113
  return [
2039
2114
  {
2040
2115
  name: "observe",
@@ -2043,7 +2118,7 @@ var ServiceMethodOverloadsGenerator = class {
2043
2118
  },
2044
2119
  {
2045
2120
  name: "options",
2046
- type: `{ headers?: HttpHeaders; reportProgress?: boolean; responseType?: '${responseType}'; withCredentials?: boolean; context?: HttpContext; }`,
2121
+ type: this.getHttpRequestOptionsParameter(params, responseType),
2047
2122
  hasQuestionToken: true
2048
2123
  }
2049
2124
  ];
@@ -2055,18 +2130,29 @@ var ServiceMethodOverloadsGenerator = class {
2055
2130
  }
2056
2131
  return getResponseType(response, this.config);
2057
2132
  }
2058
- generateOverloadReturnType(responseType, observe) {
2133
+ generateOverloadReturnType(observe) {
2059
2134
  switch (observe) {
2060
2135
  case "body":
2061
- return `Observable<${responseType}>`;
2136
+ return `Observable<${this.responseDataType}>`;
2062
2137
  case "response":
2063
- return `Observable<HttpResponse<${responseType}>>`;
2138
+ return `Observable<HttpResponse<${this.responseDataType}>>`;
2064
2139
  case "events":
2065
- return `Observable<HttpEvent<${responseType}>>`;
2140
+ return `Observable<HttpEvent<${this.responseDataType}>>`;
2066
2141
  default:
2067
2142
  throw new Error(`Unsupported observe type: ${observe}`);
2068
2143
  }
2069
2144
  }
2145
+ getHttpRequestOptionsParameter(params, responseType) {
2146
+ const { response } = this.config.options.validation ?? {};
2147
+ const additionalTypeParameters = [];
2148
+ if (response) {
2149
+ additionalTypeParameters.push(this.responseDataType);
2150
+ }
2151
+ if (additionalTypeParameters.length === 0) {
2152
+ return `RequestOptions<'${responseType}'>`;
2153
+ }
2154
+ return `RequestOptions<'${responseType}', ${additionalTypeParameters.join(", ")}>`;
2155
+ }
2070
2156
  determineResponseTypeForOperation(operation) {
2071
2157
  const successResponses = [
2072
2158
  "200",
@@ -2231,7 +2317,8 @@ var ServiceGenerator = class _ServiceGenerator {
2231
2317
  },
2232
2318
  {
2233
2319
  namedImports: [
2234
- "Observable"
2320
+ "Observable",
2321
+ "map"
2235
2322
  ],
2236
2323
  moduleSpecifier: "rxjs"
2237
2324
  },
@@ -2439,7 +2526,7 @@ async function generateFromConfig(config) {
2439
2526
  __name(generateFromConfig, "generateFromConfig");
2440
2527
 
2441
2528
  // package.json
2442
- var version = "0.1.7";
2529
+ var version = "0.1.8";
2443
2530
 
2444
2531
  // src/lib/cli.ts
2445
2532
  var program = new import_commander.Command();
package/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { Project, ScriptTarget, ModuleKind, MethodDeclaration, FunctionDeclaration } from 'ts-morph';
1
+ import { Project, ScriptTarget, ModuleKind, MethodDeclaration, FunctionDeclaration, OptionalKind, ParameterDeclarationStructure } from 'ts-morph';
2
2
  import { HttpInterceptor } from '@angular/common/http';
3
3
  import { Info, ExternalDocs, Path, ParameterType, XML, BodyParameter, QueryParameter, Security, Tag } from 'swagger-schema-official';
4
4
 
@@ -202,6 +202,9 @@ interface GeneratorConfig {
202
202
  options: {
203
203
  dateType: "string" | "Date";
204
204
  enumStyle: "enum" | "union";
205
+ validation?: {
206
+ response?: boolean;
207
+ };
205
208
  generateServices?: boolean;
206
209
  generateEnumBasedOnDescription?: boolean;
207
210
  customHeaders?: Record<string, string>;
@@ -261,6 +264,12 @@ declare function isPrimitiveType(schema: any): boolean;
261
264
  declare function inferResponseTypeFromContentType(contentType: string): "json" | "blob" | "arraybuffer" | "text";
262
265
  declare function getResponseType(response: SwaggerResponse, config: GeneratorConfig): string;
263
266
 
267
+ declare function getRequestBodyType(requestBody: RequestBody, config: GeneratorConfig): string;
268
+
269
+ declare function isDataTypeInterface(type: string): boolean;
270
+
271
+ declare function generateParseRequestTypeParams(params: OptionalKind<ParameterDeclarationStructure>[]): string;
272
+
264
273
  declare const TYPE_GENERATOR_HEADER_COMMENT: string;
265
274
  declare const SERVICE_INDEX_GENERATOR_HEADER_COMMENT: string;
266
275
  declare const SERVICE_GENERATOR_HEADER_COMMENT: (controllerName: string) => string;
@@ -278,4 +287,4 @@ declare function validateInput(inputPath: string): void;
278
287
  */
279
288
  declare function generateFromConfig(config: GeneratorConfig): Promise<void>;
280
289
 
281
- export { BASE_INTERCEPTOR_HEADER_COMMENT, type EnumValueObject, type GeneratorConfig, type GetMethodGenerationContext, HTTP_RESOURCE_GENERATOR_HEADER_COMMENT, type IPluginGenerator, type IPluginGeneratorClass, type IPluginGeneratorConstructor, MAIN_INDEX_GENERATOR_HEADER_COMMENT, type MethodGenerationContext, type NgOpenapiClientConfig, PROVIDER_GENERATOR_HEADER_COMMENT, type Parameter, type PathInfo, type RequestBody, SERVICE_GENERATOR_HEADER_COMMENT, SERVICE_INDEX_GENERATOR_HEADER_COMMENT, type SwaggerDefinition, SwaggerParser, type SwaggerResponse, type SwaggerSpec, TYPE_GENERATOR_HEADER_COMMENT, type TypeSchema, camelCase, collectUsedTypes, escapeString, extractPaths, generateFromConfig, getBasePathTokenName, getClientContextTokenName, getResponseType, getResponseTypeFromResponse, getTypeScriptType, hasDuplicateFunctionNames, inferResponseTypeFromContentType, isPrimitiveType, kebabCase, nullableType, pascalCase, type placeHolder, validateInput };
290
+ export { BASE_INTERCEPTOR_HEADER_COMMENT, type EnumValueObject, type GeneratorConfig, type GetMethodGenerationContext, HTTP_RESOURCE_GENERATOR_HEADER_COMMENT, type IPluginGenerator, type IPluginGeneratorClass, type IPluginGeneratorConstructor, MAIN_INDEX_GENERATOR_HEADER_COMMENT, type MethodGenerationContext, type NgOpenapiClientConfig, PROVIDER_GENERATOR_HEADER_COMMENT, type Parameter, type PathInfo, type RequestBody, SERVICE_GENERATOR_HEADER_COMMENT, SERVICE_INDEX_GENERATOR_HEADER_COMMENT, type SwaggerDefinition, SwaggerParser, type SwaggerResponse, type SwaggerSpec, TYPE_GENERATOR_HEADER_COMMENT, type TypeSchema, camelCase, collectUsedTypes, escapeString, extractPaths, generateFromConfig, generateParseRequestTypeParams, getBasePathTokenName, getClientContextTokenName, getRequestBodyType, getResponseType, getResponseTypeFromResponse, getTypeScriptType, hasDuplicateFunctionNames, inferResponseTypeFromContentType, isDataTypeInterface, isPrimitiveType, kebabCase, nullableType, pascalCase, type placeHolder, validateInput };
package/index.js CHANGED
@@ -86,13 +86,16 @@ __export(index_exports, {
86
86
  escapeString: () => escapeString,
87
87
  extractPaths: () => extractPaths,
88
88
  generateFromConfig: () => generateFromConfig,
89
+ generateParseRequestTypeParams: () => generateParseRequestTypeParams,
89
90
  getBasePathTokenName: () => getBasePathTokenName,
90
91
  getClientContextTokenName: () => getClientContextTokenName,
92
+ getRequestBodyType: () => getRequestBodyType,
91
93
  getResponseType: () => getResponseType,
92
94
  getResponseTypeFromResponse: () => getResponseTypeFromResponse,
93
95
  getTypeScriptType: () => getTypeScriptType,
94
96
  hasDuplicateFunctionNames: () => hasDuplicateFunctionNames,
95
97
  inferResponseTypeFromContentType: () => inferResponseTypeFromContentType,
98
+ isDataTypeInterface: () => isDataTypeInterface,
96
99
  isPrimitiveType: () => isPrimitiveType,
97
100
  kebabCase: () => kebabCase,
98
101
  nullableType: () => nullableType,
@@ -191,6 +194,7 @@ __name(escapeString, "escapeString");
191
194
  // ../shared/src/utils/functions/collect-used-types.ts
192
195
  function collectUsedTypes(operations) {
193
196
  const usedTypes = /* @__PURE__ */ new Set();
197
+ usedTypes.add("RequestOptions");
194
198
  operations.forEach((operation) => {
195
199
  var _a;
196
200
  (_a = operation.parameters) == null ? void 0 : _a.forEach((param) => {
@@ -465,6 +469,47 @@ function getResponseType(response, config) {
465
469
  }
466
470
  __name(getResponseType, "getResponseType");
467
471
 
472
+ // ../shared/src/utils/functions/get-request-body-type.ts
473
+ function getRequestBodyType(requestBody, config) {
474
+ const content = requestBody.content || {};
475
+ const jsonContent = content["application/json"];
476
+ if (jsonContent == null ? void 0 : jsonContent.schema) {
477
+ return getTypeScriptType(jsonContent.schema, config, jsonContent.schema.nullable);
478
+ }
479
+ return "any";
480
+ }
481
+ __name(getRequestBodyType, "getRequestBodyType");
482
+
483
+ // ../shared/src/utils/functions/is-data-type-interface.ts
484
+ function isDataTypeInterface(type) {
485
+ const invalidTypes = [
486
+ "any",
487
+ "File",
488
+ "string",
489
+ "number",
490
+ "boolean",
491
+ "object",
492
+ "unknown",
493
+ "[]",
494
+ "Array"
495
+ ];
496
+ return !invalidTypes.some((invalidType) => type.includes(invalidType));
497
+ }
498
+ __name(isDataTypeInterface, "isDataTypeInterface");
499
+
500
+ // ../shared/src/utils/functions/generate-parse-request-type-params.ts
501
+ function generateParseRequestTypeParams(params) {
502
+ const bodyParam = params.find((param) => {
503
+ return typeof param.type === "string" && isDataTypeInterface(param.type);
504
+ });
505
+ if (bodyParam) {
506
+ const optional = bodyParam.hasQuestionToken ? " | undefined" : "";
507
+ return `${bodyParam.type}${optional}`;
508
+ }
509
+ return "";
510
+ }
511
+ __name(generateParseRequestTypeParams, "generateParseRequestTypeParams");
512
+
468
513
  // ../shared/src/config/constants.ts
469
514
  var disableLinting = `/* @ts-nocheck */
470
515
  /* eslint-disable */
@@ -717,6 +762,7 @@ var _TypeGenerator = class _TypeGenerator {
717
762
  Object.entries(definitions).forEach(([name, definition]) => {
718
763
  this.generateInterface(name, definition);
719
764
  });
765
+ this.generateSdkTypes();
720
766
  this.sourceFile.formatText();
721
767
  this.sourceFile.saveSync();
722
768
  } catch (error) {
@@ -976,6 +1022,75 @@ var _TypeGenerator = class _TypeGenerator {
976
1022
  escapeString(str) {
977
1023
  return str.replace(/\\/g, "\\\\").replace(/'/g, "\\'");
978
1024
  }
1025
+ generateSdkTypes() {
1026
+ var _a;
1027
+ this.sourceFile.addImportDeclarations([
1028
+ {
1029
+ namedImports: [
1030
+ "HttpContext",
1031
+ "HttpHeaders"
1032
+ ],
1033
+ moduleSpecifier: "@angular/common/http"
1034
+ }
1035
+ ]);
1036
+ const { response } = (_a = this.config.options.validation) != null ? _a : {};
1037
+ const typeParameters = [
1038
+ "TResponseType extends 'arraybuffer' | 'blob' | 'json' | 'text'"
1039
+ ];
1040
+ const properties = [
1041
+ {
1042
+ name: "headers",
1043
+ type: "HttpHeaders",
1044
+ hasQuestionToken: true
1045
+ },
1046
+ {
1047
+ name: "reportProgress",
1048
+ type: "boolean",
1049
+ hasQuestionToken: true
1050
+ },
1051
+ {
1052
+ name: "responseType",
1053
+ type: "TResponseType",
1054
+ hasQuestionToken: true
1055
+ },
1056
+ {
1057
+ name: "withCredentials",
1058
+ type: "boolean",
1059
+ hasQuestionToken: true
1060
+ },
1061
+ {
1062
+ name: "context",
1063
+ type: "HttpContext",
1064
+ hasQuestionToken: true
1065
+ }
1066
+ ];
1067
+ if (response) {
1068
+ properties.push({
1069
+ name: "parse",
1070
+ type: "(response: unknown) => TReturnType",
1071
+ hasQuestionToken: true
1072
+ });
1073
+ typeParameters.push("TReturnType");
1074
+ this.sourceFile.addInterface({
1075
+ name: "RequestOptions",
1076
+ isExported: true,
1077
+ typeParameters,
1078
+ properties,
1079
+ docs: [
1080
+ "Request Options for Angular HttpClient requests without request parsing"
1081
+ ]
1082
+ });
1083
+ }
1084
+ this.sourceFile.addInterface({
1085
+ name: "RequestOptions",
1086
+ isExported: true,
1087
+ typeParameters,
1088
+ properties,
1089
+ docs: [
1090
+ "Request Options for Angular HttpClient requests"
1091
+ ]
1092
+ });
1093
+ }
979
1094
  };
980
1095
  __name(_TypeGenerator, "TypeGenerator");
981
1096
  var TypeGenerator = _TypeGenerator;
@@ -1792,14 +1907,6 @@ var _ServiceMethodBodyGenerator = class _ServiceMethodBodyGenerator {
1792
1907
  ];
1793
1908
  return bodyParts.filter(Boolean).join("\n");
1794
1909
  }
1795
- getRequestBodyType(requestBody) {
1796
- const content = requestBody.content || {};
1797
- const jsonContent = content["application/json"];
1798
- if (jsonContent == null ? void 0 : jsonContent.schema) {
1799
- return getTypeScriptType(jsonContent.schema, this.config, jsonContent.schema.nullable);
1800
- }
1801
- return "any";
1802
- }
1803
1910
  isMultipartFormData(operation) {
1804
1911
  var _a, _b;
1805
1912
  return !!((_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b["multipart/form-data"]);
@@ -1915,15 +2022,15 @@ const requestOptions: any = {
1915
2022
  };`;
1916
2023
  }
1917
2024
  generateHttpRequest(operation, context) {
1918
- var _a, _b;
2025
+ var _a, _b, _c;
1919
2026
  const httpMethod = operation.method.toLowerCase();
1920
2027
  let bodyParam = "";
1921
2028
  if (context.hasBody) {
1922
2029
  if (context.isMultipart) {
1923
2030
  bodyParam = "formData";
1924
2031
  } else if ((_b = (_a = operation.requestBody) == null ? void 0 : _a.content) == null ? void 0 : _b["application/json"]) {
1925
- const bodyType = this.getRequestBodyType(operation.requestBody);
1926
- const isInterface = this.isDataTypeInterface(bodyType);
2032
+ const bodyType = getRequestBodyType(operation.requestBody, this.config);
2033
+ const isInterface = isDataTypeInterface(bodyType);
1927
2034
  bodyParam = isInterface ? camelCase(bodyType) : "requestBody";
1928
2035
  }
1929
2036
  }
@@ -1932,12 +2039,13 @@ const requestOptions: any = {
1932
2039
  "put",
1933
2040
  "patch"
1934
2041
  ];
2042
+ const parseResponse = ((_c = this.config.options.validation) == null ? void 0 : _c.response) ? `.pipe(map(response => options?.parse?.(response) ?? response))` : "";
1935
2043
  if (methodsWithBody.includes(httpMethod)) {
1936
2044
  return `
1937
- return this.httpClient.${httpMethod}(url, ${bodyParam || "null"}, requestOptions);`;
2045
+ return this.httpClient.${httpMethod}(url, ${bodyParam || "null"}, requestOptions)${parseResponse};`;
1938
2046
  } else {
1939
2047
  return `
1940
- return this.httpClient.${httpMethod}(url, requestOptions);`;
2048
+ return this.httpClient.${httpMethod}(url, requestOptions)${parseResponse};`;
1941
2049
  }
1942
2050
  }
1943
2051
  determineResponseType(operation) {
@@ -1956,20 +2064,6 @@ return this.httpClient.${httpMethod}(url, requestOptions);`;
1956
2064
  }
1957
2065
  return "json";
1958
2066
  }
1959
- isDataTypeInterface(type) {
1960
- const invalidTypes = [
1961
- "any",
1962
- "File",
1963
- "string",
1964
- "number",
1965
- "boolean",
1966
- "object",
1967
- "unknown",
1968
- "[]",
1969
- "Array"
1970
- ];
1971
- return !invalidTypes.some((invalidType) => type.includes(invalidType));
1972
- }
1973
2067
  };
1974
2068
  __name(_ServiceMethodBodyGenerator, "ServiceMethodBodyGenerator");
1975
2069
  var ServiceMethodBodyGenerator = _ServiceMethodBodyGenerator;
@@ -1982,7 +2076,7 @@ var _ServiceMethodParamsGenerator = class _ServiceMethodParamsGenerator {
1982
2076
  }
1983
2077
  generateMethodParameters(operation) {
1984
2078
  const params = this.generateApiParameters(operation);
1985
- const optionsParam = this.addOptionsParameter();
2079
+ const optionsParam = this.addOptionsParameter(params);
1986
2080
  const combined = [
1987
2081
  ...params,
1988
2082
  ...optionsParam
@@ -2019,7 +2113,7 @@ var _ServiceMethodParamsGenerator = class _ServiceMethodParamsGenerator {
2019
2113
  }
2020
2114
  if (operation.requestBody && ((_i = (_h = operation.requestBody) == null ? void 0 : _h.content) == null ? void 0 : _i["application/json"])) {
2021
2115
  const bodyType = this.getRequestBodyType(operation.requestBody);
2022
- const isInterface = this.isDataTypeInterface(bodyType);
2116
+ const isInterface = isDataTypeInterface(bodyType);
2023
2117
  params.push({
2024
2118
  name: isInterface ? camelCase(bodyType) : "requestBody",
2025
2119
  type: bodyType,
@@ -2036,7 +2130,7 @@ var _ServiceMethodParamsGenerator = class _ServiceMethodParamsGenerator {
2036
2130
  });
2037
2131
  return params.sort((a, b) => Number(a.hasQuestionToken) - Number(b.hasQuestionToken));
2038
2132
  }
2039
- addOptionsParameter() {
2133
+ addOptionsParameter(params) {
2040
2134
  return [
2041
2135
  {
2042
2136
  name: "observe",
@@ -2045,24 +2139,22 @@ var _ServiceMethodParamsGenerator = class _ServiceMethodParamsGenerator {
2045
2139
  },
2046
2140
  {
2047
2141
  name: "options",
2048
- type: `{ headers?: HttpHeaders; params?: HttpParams; reportProgress?: boolean; responseType?: 'arraybuffer' | 'blob' | 'json' | 'text'; withCredentials?: boolean; context?: HttpContext; }`,
2142
+ type: this.getHttpRequestOptionsParameter(params),
2049
2143
  hasQuestionToken: true
2050
2144
  }
2051
2145
  ];
2052
2146
  }
2053
- isDataTypeInterface(type) {
2054
- const invalidTypes = [
2055
- "any",
2056
- "File",
2057
- "string",
2058
- "number",
2059
- "boolean",
2060
- "object",
2061
- "unknown",
2062
- "[]",
2063
- "Array"
2064
- ];
2065
- return !invalidTypes.some((invalidType) => type.includes(invalidType));
2147
+ getHttpRequestOptionsParameter(params) {
2148
+ var _a;
2149
+ const { response } = (_a = this.config.options.validation) != null ? _a : {};
2150
+ const additionalTypeParameters = [];
2151
+ if (response) {
2152
+ additionalTypeParameters.push("any");
2153
+ }
2154
+ if (additionalTypeParameters.length === 0) {
2155
+ return `RequestOptions<'arraybuffer' | 'blob' | 'json' | 'text'>`;
2156
+ }
2157
+ return `RequestOptions<'arraybuffer' | 'blob' | 'json' | 'text', ${additionalTypeParameters.join(", ")}>`;
2066
2158
  }
2067
2159
  getRequestBodyType(requestBody) {
2068
2160
  const content = requestBody.content || {};
@@ -2081,6 +2173,7 @@ var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2081
2173
  constructor(config) {
2082
2174
  __publicField(this, "config");
2083
2175
  __publicField(this, "paramsGenerator");
2176
+ __publicField(this, "responseDataType", "any");
2084
2177
  this.config = config;
2085
2178
  this.paramsGenerator = new ServiceMethodParamsGenerator(config);
2086
2179
  }
@@ -2101,9 +2194,9 @@ var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2101
2194
  return overloads;
2102
2195
  }
2103
2196
  generateMethodOverload(operation, observe, responseType) {
2104
- const responseDataType = this.generateOverloadResponseType(operation);
2197
+ this.responseDataType = this.generateOverloadResponseType(operation);
2105
2198
  const params = this.generateOverloadParameters(operation, observe, responseType);
2106
- const returnType = this.generateOverloadReturnType(responseDataType, observe);
2199
+ const returnType = this.generateOverloadReturnType(observe);
2107
2200
  return {
2108
2201
  parameters: params,
2109
2202
  returnType
@@ -2111,7 +2204,7 @@ var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2111
2204
  }
2112
2205
  generateOverloadParameters(operation, observe, responseType) {
2113
2206
  const params = this.paramsGenerator.generateApiParameters(operation);
2114
- const optionsParam = this.addOverloadOptionsParameter(observe, responseType);
2207
+ const optionsParam = this.addOverloadOptionsParameter(params, observe, responseType);
2115
2208
  const combined = [
2116
2209
  ...params,
2117
2210
  ...optionsParam
@@ -2126,7 +2219,7 @@ var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2126
2219
  }
2127
2220
  return uniqueParams;
2128
2221
  }
2129
- addOverloadOptionsParameter(observe, responseType) {
2222
+ addOverloadOptionsParameter(params, observe, responseType) {
2130
2223
  return [
2131
2224
  {
2132
2225
  name: "observe",
@@ -2135,7 +2228,7 @@ var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2135
2228
  },
2136
2229
  {
2137
2230
  name: "options",
2138
- type: `{ headers?: HttpHeaders; reportProgress?: boolean; responseType?: '${responseType}'; withCredentials?: boolean; context?: HttpContext; }`,
2231
+ type: this.getHttpRequestOptionsParameter(params, responseType),
2139
2232
  hasQuestionToken: true
2140
2233
  }
2141
2234
  ];
@@ -2148,18 +2241,30 @@ var _ServiceMethodOverloadsGenerator = class _ServiceMethodOverloadsGenerator {
2148
2241
  }
2149
2242
  return getResponseType(response, this.config);
2150
2243
  }
2151
- generateOverloadReturnType(responseType, observe) {
2244
+ generateOverloadReturnType(observe) {
2152
2245
  switch (observe) {
2153
2246
  case "body":
2154
- return `Observable<${responseType}>`;
2247
+ return `Observable<${this.responseDataType}>`;
2155
2248
  case "response":
2156
- return `Observable<HttpResponse<${responseType}>>`;
2249
+ return `Observable<HttpResponse<${this.responseDataType}>>`;
2157
2250
  case "events":
2158
- return `Observable<HttpEvent<${responseType}>>`;
2251
+ return `Observable<HttpEvent<${this.responseDataType}>>`;
2159
2252
  default:
2160
2253
  throw new Error(`Unsupported observe type: ${observe}`);
2161
2254
  }
2162
2255
  }
2256
+ getHttpRequestOptionsParameter(params, responseType) {
2257
+ var _a;
2258
+ const { response } = (_a = this.config.options.validation) != null ? _a : {};
2259
+ const additionalTypeParameters = [];
2260
+ if (response) {
2261
+ additionalTypeParameters.push(this.responseDataType);
2262
+ }
2263
+ if (additionalTypeParameters.length === 0) {
2264
+ return `RequestOptions<'${responseType}'>`;
2265
+ }
2266
+ return `RequestOptions<'${responseType}', ${additionalTypeParameters.join(", ")}>`;
2267
+ }
2163
2268
  determineResponseTypeForOperation(operation) {
2164
2269
  var _a;
2165
2270
  const successResponses = [
@@ -2325,7 +2430,8 @@ var _ServiceGenerator = class _ServiceGenerator {
2325
2430
  },
2326
2431
  {
2327
2432
  namedImports: [
2328
- "Observable"
2433
+ "Observable",
2434
+ "map"
2329
2435
  ],
2330
2436
  moduleSpecifier: "rxjs"
2331
2437
  },
@@ -2549,13 +2655,16 @@ __name(generateFromConfig, "generateFromConfig");
2549
2655
  escapeString,
2550
2656
  extractPaths,
2551
2657
  generateFromConfig,
2658
+ generateParseRequestTypeParams,
2552
2659
  getBasePathTokenName,
2553
2660
  getClientContextTokenName,
2661
+ getRequestBodyType,
2554
2662
  getResponseType,
2555
2663
  getResponseTypeFromResponse,
2556
2664
  getTypeScriptType,
2557
2665
  hasDuplicateFunctionNames,
2558
2666
  inferResponseTypeFromContentType,
2667
+ isDataTypeInterface,
2559
2668
  isPrimitiveType,
2560
2669
  kebabCase,
2561
2670
  nullableType,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ng-openapi",
3
- "version": "0.1.8",
3
+ "version": "0.1.9-pr-18-feature-schema-validation-dbff16c.0",
4
4
  "description": "Generate Angular services and TypeScript types from OpenAPI/Swagger specifications",
5
5
  "keywords": [
6
6
  "ng-openapi",