@orval/core 8.3.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,11 +1,12 @@
1
- import { t as __export } from "./chunk-C6wwvPpM.mjs";
1
+ import { t as __export } from "./chunk-1-as6MWF.mjs";
2
+ import { createRequire } from "node:module";
2
3
  import { entries, groupBy, isArray, isBoolean, isBoolean as isBoolean$1, isEmptyish, isFunction, isNullish, isNullish as isNullish$1, isNumber, isString, isString as isString$1, prop, unique, uniqueBy, uniqueWith } from "remeda";
3
4
  import { keyword } from "esutils";
4
5
  import path from "node:path";
5
6
  import { compare } from "compare-versions";
6
7
  import debug from "debug";
7
8
  import { pathToFileURL } from "node:url";
8
- import fs from "node:fs";
9
+ import fs, { existsSync, readFileSync } from "node:fs";
9
10
  import { globby } from "globby";
10
11
  import readline from "node:readline";
11
12
  import chalk from "chalk";
@@ -720,6 +721,47 @@ function joinSafe(...values) {
720
721
  return result;
721
722
  }
722
723
 
724
+ //#endregion
725
+ //#region src/utils/resolve-version.ts
726
+ function resolveInstalledVersion(packageName, fromDir) {
727
+ try {
728
+ const require = createRequire(path.join(fromDir, "noop.js"));
729
+ try {
730
+ return require(`${packageName}/package.json`).version;
731
+ } catch (directError) {
732
+ if (directError instanceof Error && "code" in directError && directError.code === "ERR_PACKAGE_PATH_NOT_EXPORTED") {
733
+ const entryPath = require.resolve(packageName);
734
+ let dir = path.dirname(entryPath);
735
+ while (dir !== path.parse(dir).root) {
736
+ const pkgPath = path.join(dir, "package.json");
737
+ if (existsSync(pkgPath)) {
738
+ const pkgData = JSON.parse(readFileSync(pkgPath, "utf8"));
739
+ if (pkgData.name === packageName) return pkgData.version;
740
+ }
741
+ dir = path.dirname(dir);
742
+ }
743
+ return;
744
+ }
745
+ throw directError;
746
+ }
747
+ } catch {
748
+ return;
749
+ }
750
+ }
751
+ function resolveInstalledVersions(packageJson, fromDir) {
752
+ const resolved = {};
753
+ const allDeps = new Set([
754
+ ...Object.keys(packageJson.dependencies ?? {}),
755
+ ...Object.keys(packageJson.devDependencies ?? {}),
756
+ ...Object.keys(packageJson.peerDependencies ?? {})
757
+ ]);
758
+ for (const pkgName of allDeps) {
759
+ const version = resolveInstalledVersion(pkgName, fromDir);
760
+ if (version) resolved[pkgName] = version;
761
+ }
762
+ return resolved;
763
+ }
764
+
723
765
  //#endregion
724
766
  //#region src/utils/sort.ts
725
767
  const sortByPriority = (arr) => arr.toSorted((a, b) => {
@@ -1437,7 +1479,25 @@ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unkno
1437
1479
  return uniqueBy(responsesOrRequests.filter(([, res]) => Boolean(res)).map(([key, res]) => {
1438
1480
  if (isReference(res)) {
1439
1481
  const { schema: bodySchema, imports: [{ name: name$1, schemaName }] } = resolveRef(res, context);
1440
- const [contentType, mediaType] = Object.entries(bodySchema.content ?? {})[0] ?? [];
1482
+ const firstEntry = Object.entries(bodySchema.content ?? {}).at(0);
1483
+ if (!firstEntry) return [{
1484
+ value: name$1,
1485
+ imports: [{
1486
+ name: name$1,
1487
+ schemaName
1488
+ }],
1489
+ schemas: [],
1490
+ type: "unknown",
1491
+ isEnum: false,
1492
+ isRef: true,
1493
+ hasReadonlyProps: false,
1494
+ originalSchema: void 0,
1495
+ example: void 0,
1496
+ examples: void 0,
1497
+ key,
1498
+ contentType: void 0
1499
+ }];
1500
+ const [contentType, mediaType] = firstEntry;
1441
1501
  const isFormData = formDataContentTypes.has(contentType);
1442
1502
  const isFormUrlEncoded = formUrlEncodedContentTypes.has(contentType);
1443
1503
  if (!isFormData && !isFormUrlEncoded || !mediaType.schema) return [{
@@ -1594,6 +1654,17 @@ function getResReqTypes(responsesOrRequests, name, context, defaultType = "unkno
1594
1654
  }).flat(), uniqueKey);
1595
1655
  }
1596
1656
  /**
1657
+ * Determine the responseType option based on success content types only.
1658
+ * This avoids error-response content types influencing the responseType.
1659
+ */
1660
+ function getSuccessResponseType(response) {
1661
+ const successContentTypes = response.types.success.map((t) => t.contentType).filter(Boolean);
1662
+ if (response.isBlob) return "blob";
1663
+ const hasJsonResponse = successContentTypes.some((contentType) => contentType.includes("json") || contentType.includes("+json"));
1664
+ const hasTextResponse = successContentTypes.some((contentType) => contentType.startsWith("text/") || contentType.includes("xml"));
1665
+ if (!hasJsonResponse && hasTextResponse) return "text";
1666
+ }
1667
+ /**
1597
1668
  * Determine the response type category for a given content type.
1598
1669
  * Used to set the correct responseType option in HTTP clients.
1599
1670
  *
@@ -2677,13 +2748,27 @@ function getProps({ body, queryParams, params, operationName, headers, context }
2677
2748
  ]);
2678
2749
  }
2679
2750
  function getQueryParamDefinition(queryParams, context) {
2680
- let paramType = queryParams?.schema.name;
2681
- if (OutputClient.ANGULAR === context.output.client) paramType = `DeepNonNullable<${paramType}>`;
2751
+ const paramType = queryParams?.schema.name;
2682
2752
  return `params${(queryParams?.isOptional || context.output.allParamsOptional) && !context.output.optionsParamRequired ? "?" : ""}: ${paramType}`;
2683
2753
  }
2684
2754
 
2685
2755
  //#endregion
2686
2756
  //#region src/getters/query-params.ts
2757
+ const isOpenApiSchemaObject = (value) => {
2758
+ if (!value || typeof value !== "object") return false;
2759
+ return !("$ref" in value);
2760
+ };
2761
+ const isSchemaNullable = (schema) => {
2762
+ if (schema.nullable === true) return true;
2763
+ if (schema.type === "null") return true;
2764
+ if (Array.isArray(schema.type) && schema.type.includes("null")) return true;
2765
+ const oneOfVariants = Array.isArray(schema.oneOf) ? schema.oneOf : [];
2766
+ const anyOfVariants = Array.isArray(schema.anyOf) ? schema.anyOf : [];
2767
+ return [...oneOfVariants, ...anyOfVariants].some((variant) => {
2768
+ if (!isOpenApiSchemaObject(variant)) return false;
2769
+ return isSchemaNullable(variant);
2770
+ });
2771
+ };
2687
2772
  function getQueryParamsTypes(queryParams, operationName, context) {
2688
2773
  return queryParams.map(({ parameter, imports: parameterImports }) => {
2689
2774
  const { name, required, schema: schemaParam, content } = parameter;
@@ -2708,6 +2793,8 @@ function getQueryParamsTypes(queryParams, operationName, context) {
2708
2793
  ...schemaForDoc
2709
2794
  }, void 0, context);
2710
2795
  if (parameterImports.length > 0) return {
2796
+ name,
2797
+ required,
2711
2798
  definition: `${doc}${key}${!required || schema.default ? "?" : ""}: ${parameterImports[0].name};`,
2712
2799
  imports: parameterImports,
2713
2800
  schemas: [],
@@ -2717,6 +2804,8 @@ function getQueryParamsTypes(queryParams, operationName, context) {
2717
2804
  const enumName = queryName;
2718
2805
  const enumValue = getEnum(resolvedValue.value, enumName, getEnumNames(resolvedValue.originalSchema), context.output.override.enumGenerationType, getEnumDescriptions(resolvedValue.originalSchema), context.output.override.namingConvention.enum);
2719
2806
  return {
2807
+ name,
2808
+ required,
2720
2809
  definition: `${doc}${key}${!required || schema.default ? "?" : ""}: ${enumName};`,
2721
2810
  imports: [{ name: enumName }],
2722
2811
  schemas: [...resolvedValue.schemas, {
@@ -2728,6 +2817,8 @@ function getQueryParamsTypes(queryParams, operationName, context) {
2728
2817
  };
2729
2818
  }
2730
2819
  return {
2820
+ name,
2821
+ required,
2731
2822
  definition: `${doc}${key}${!required || schema.default ? "?" : ""}: ${resolvedValue.value};`,
2732
2823
  imports: resolvedValue.imports,
2733
2824
  schemas: resolvedValue.schemas,
@@ -2743,6 +2834,7 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
2743
2834
  const name = `${pascal(operationName)}${pascal(suffix)}`;
2744
2835
  const type = types.map(({ definition }) => definition).join("\n");
2745
2836
  const allOptional = queryParams.every(({ parameter }) => !parameter.required);
2837
+ const requiredNullableKeys = types.filter(({ required, originalSchema }) => required && isSchemaNullable(originalSchema)).map(({ name: name$1 }) => name$1);
2746
2838
  return {
2747
2839
  schema: {
2748
2840
  name,
@@ -2750,14 +2842,15 @@ function getQueryParams({ queryParams, operationName, context, suffix = "params"
2750
2842
  imports
2751
2843
  },
2752
2844
  deps: schemas,
2753
- isOptional: allOptional
2845
+ isOptional: allOptional,
2846
+ requiredNullableKeys
2754
2847
  };
2755
2848
  }
2756
2849
 
2757
2850
  //#endregion
2758
2851
  //#region src/getters/response.ts
2759
2852
  function getResponse({ responses, operationName, context, contentType }) {
2760
- const filteredTypes = filterByContentType(getResReqTypes(Object.entries(responses), operationName, context, "void", (type) => `${type.key}-${type.value}`), contentType);
2853
+ const filteredTypes = filterByContentType(getResReqTypes(Object.entries(responses), operationName, context, "void", (type) => `${type.key}-${type.value}-${type.contentType}`), contentType);
2761
2854
  const imports = filteredTypes.flatMap(({ imports: imports$1 }) => imports$1);
2762
2855
  const schemas = filteredTypes.flatMap(({ schemas: schemas$1 }) => schemas$1);
2763
2856
  const contentTypes = [...new Set(filteredTypes.map(({ contentType: contentType$1 }) => contentType$1))];
@@ -2876,7 +2969,7 @@ function generateComponentDefinition(responses = {}, context, suffix) {
2876
2969
  //#region src/generators/imports.ts
2877
2970
  function generateImports({ imports, namingConvention = NamingConvention.CAMEL_CASE }) {
2878
2971
  if (imports.length === 0) return "";
2879
- const grouped = groupBy(uniqueWith(imports, (a, b) => a.name === b.name && a.default === b.default).map((imp) => ({
2972
+ const grouped = groupBy(uniqueWith(imports, (a, b) => a.name === b.name && a.default === b.default && a.alias === b.alias && a.values === b.values && a.isConstant === b.isConstant && a.namespaceImport === b.namespaceImport && a.syntheticDefaultImport === b.syntheticDefaultImport && a.importPath === b.importPath).map((imp) => ({
2880
2973
  ...imp,
2881
2974
  importPath: imp.importPath ?? `./${conventionName(imp.name, namingConvention)}`
2882
2975
  })), (imp) => !imp.default && !imp.namespaceImport && !imp.syntheticDefaultImport && !imp.values && !imp.isConstant ? `aggregate|${imp.importPath}` : `single|${imp.importPath}|${imp.name}|${imp.alias ?? ""}|${String(imp.default)}|${String(imp.namespaceImport)}|${String(imp.syntheticDefaultImport)}|${String(imp.values)}|${String(imp.isConstant)}`);
@@ -2951,7 +3044,7 @@ function addDependency({ implementation, exports, dependency, projectName, isAll
2951
3044
  if (types.length > 0) {
2952
3045
  let uniqueTypes = types;
2953
3046
  if (values.length > 0) {
2954
- uniqueTypes = types.filter((t) => !values.some((v) => v.name === t.name));
3047
+ uniqueTypes = types.filter((t) => !values.some((v) => v.name === t.name && (v.alias ?? "") === (t.alias ?? "")));
2955
3048
  dep += "\n";
2956
3049
  }
2957
3050
  dep += generateDependency({
@@ -2994,7 +3087,17 @@ function generateVerbImports({ response, body, queryParams, props, headers, para
2994
3087
  ...queryParams ? [{ name: queryParams.schema.name }] : [],
2995
3088
  ...headers ? [{ name: headers.schema.name }] : [],
2996
3089
  ...params.flatMap(({ imports }) => imports)
2997
- ];
3090
+ ].flatMap((imp) => {
3091
+ if (imp.name !== "Error" || !imp.values || imp.alias) return [imp];
3092
+ return [{
3093
+ ...imp,
3094
+ values: void 0
3095
+ }, {
3096
+ ...imp,
3097
+ alias: "ErrorSchema",
3098
+ values: true
3099
+ }];
3100
+ });
2998
3101
  }
2999
3102
 
3000
3103
  //#endregion
@@ -3156,46 +3259,143 @@ function removeComments(file) {
3156
3259
 
3157
3260
  //#endregion
3158
3261
  //#region src/generators/options.ts
3262
+ /**
3263
+ * Filters query params for Angular's HttpClient.
3264
+ *
3265
+ * Why: Angular's HttpParams / HttpClient `params` type does not accept `null` or
3266
+ * `undefined` values, and arrays must only contain string/number/boolean.
3267
+ * Orval models often include nullable query params, so we remove nullish values
3268
+ * (including nulls inside arrays) before passing params to HttpClient or a
3269
+ * paramsSerializer to avoid runtime and type issues.
3270
+ *
3271
+ * Returns an inline IIFE expression. For paths that benefit from a shared helper
3272
+ * (e.g. observe-mode branches), prefer getAngularFilteredParamsCallExpression +
3273
+ * getAngularFilteredParamsHelperBody instead.
3274
+ */
3275
+ const getAngularFilteredParamsExpression = (paramsExpression, requiredNullableParamKeys = []) => `(() => {
3276
+ const requiredNullableParamKeys = new Set<string>(${JSON.stringify(requiredNullableParamKeys)});
3277
+ const filteredParams = {} as Record<string, string | number | boolean | null | Array<string | number | boolean>>;
3278
+ for (const [key, value] of Object.entries(${paramsExpression})) {
3279
+ if (Array.isArray(value)) {
3280
+ const filtered = value.filter(
3281
+ (item) =>
3282
+ item != null &&
3283
+ (typeof item === 'string' ||
3284
+ typeof item === 'number' ||
3285
+ typeof item === 'boolean'),
3286
+ ) as Array<string | number | boolean>;
3287
+ if (filtered.length) {
3288
+ filteredParams[key] = filtered;
3289
+ }
3290
+ } else if (value === null && requiredNullableParamKeys.has(key)) {
3291
+ filteredParams[key] = value;
3292
+ } else if (
3293
+ value != null &&
3294
+ (typeof value === 'string' ||
3295
+ typeof value === 'number' ||
3296
+ typeof value === 'boolean')
3297
+ ) {
3298
+ filteredParams[key] = value as string | number | boolean;
3299
+ }
3300
+ }
3301
+ return filteredParams as unknown as Record<string, string | number | boolean | Array<string | number | boolean>>;
3302
+ })()`;
3303
+ /**
3304
+ * Returns the body of a standalone `filterParams` helper function
3305
+ * to be emitted once in the generated file header, replacing the
3306
+ * inline IIFE that was previously duplicated in every method.
3307
+ */
3308
+ const getAngularFilteredParamsHelperBody = () => `function filterParams(
3309
+ params: Record<string, unknown>,
3310
+ requiredNullableKeys: Set<string> = new Set(),
3311
+ ): Record<string, string | number | boolean | Array<string | number | boolean>> {
3312
+ const filteredParams: Record<string, string | number | boolean | null | Array<string | number | boolean>> = {};
3313
+ for (const [key, value] of Object.entries(params)) {
3314
+ if (Array.isArray(value)) {
3315
+ const filtered = value.filter(
3316
+ (item) =>
3317
+ item != null &&
3318
+ (typeof item === 'string' ||
3319
+ typeof item === 'number' ||
3320
+ typeof item === 'boolean'),
3321
+ ) as Array<string | number | boolean>;
3322
+ if (filtered.length) {
3323
+ filteredParams[key] = filtered;
3324
+ }
3325
+ } else if (value === null && requiredNullableKeys.has(key)) {
3326
+ filteredParams[key] = value;
3327
+ } else if (
3328
+ value != null &&
3329
+ (typeof value === 'string' ||
3330
+ typeof value === 'number' ||
3331
+ typeof value === 'boolean')
3332
+ ) {
3333
+ filteredParams[key] = value as string | number | boolean;
3334
+ }
3335
+ }
3336
+ return filteredParams as Record<string, string | number | boolean | Array<string | number | boolean>>;
3337
+ }`;
3338
+ /**
3339
+ * Returns a call expression to the `filterParams` helper function.
3340
+ */
3341
+ const getAngularFilteredParamsCallExpression = (paramsExpression, requiredNullableParamKeys = []) => `filterParams(${paramsExpression}, new Set<string>(${JSON.stringify(requiredNullableParamKeys)}))`;
3159
3342
  function generateBodyOptions(body, isFormData, isFormUrlEncoded) {
3160
3343
  if (isFormData && body.formData) return "\n formData,";
3161
3344
  if (isFormUrlEncoded && body.formUrlEncoded) return "\n formUrlEncoded,";
3162
3345
  if (body.implementation) return `\n ${body.implementation},`;
3163
3346
  return "";
3164
3347
  }
3165
- function generateAxiosOptions({ response, isExactOptionalPropertyTypes, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false, isVue, isAngular, paramsSerializer, paramsSerializerOptions }) {
3348
+ function generateAxiosOptions({ response, isExactOptionalPropertyTypes, angularObserve, angularParamsRef, requiredNullableQueryParamKeys, queryParams, headers, requestOptions, hasSignal, hasSignalParam = false, isVue, isAngular, paramsSerializer, paramsSerializerOptions }) {
3166
3349
  const isRequestOptions = requestOptions !== false;
3167
3350
  const signalVar = hasSignalParam ? "querySignal" : "signal";
3168
3351
  const signalProp = hasSignalParam ? `signal: ${signalVar}` : "signal";
3169
3352
  if (!queryParams && !headers && !response.isBlob && response.definition.success !== "string") {
3170
- if (isRequestOptions) return "options";
3353
+ if (isRequestOptions) return isAngular ? angularObserve ? `{
3354
+ ...(options as Omit<NonNullable<typeof options>, 'observe'>),
3355
+ observe: '${angularObserve}',
3356
+ }` : "(options as Omit<NonNullable<typeof options>, 'observe'>)" : "options";
3171
3357
  if (hasSignal) return isExactOptionalPropertyTypes ? `...(${signalVar} ? { ${signalProp} } : {})` : signalProp;
3172
3358
  return "";
3173
3359
  }
3174
3360
  let value = "";
3175
3361
  if (!isRequestOptions) {
3176
- if (queryParams) value += "\n params,";
3362
+ if (queryParams) if (isAngular) {
3363
+ const iifeExpr = getAngularFilteredParamsExpression("params ?? {}", requiredNullableQueryParamKeys);
3364
+ value += paramsSerializer ? `\n params: ${paramsSerializer.name}(${iifeExpr}),` : `\n params: ${iifeExpr},`;
3365
+ } else value += "\n params,";
3177
3366
  if (headers) value += "\n headers,";
3178
3367
  if (hasSignal) value += isExactOptionalPropertyTypes ? `\n ...(${signalVar} ? { ${signalProp} } : {}),` : `\n ${signalProp},`;
3179
3368
  }
3180
3369
  if (!isObject(requestOptions) || !Object.hasOwn(requestOptions, "responseType")) {
3181
- if (response.isBlob) value += `\n responseType: 'blob',`;
3182
- else if (response.contentTypes.at(0) === "text/plain") value += `\n responseType: 'text',`;
3370
+ const successResponseType = getSuccessResponseType(response);
3371
+ if (successResponseType) value += `\n responseType: '${successResponseType}',`;
3183
3372
  }
3184
3373
  if (isObject(requestOptions)) value += `\n ${stringify(requestOptions)?.slice(1, -1)}`;
3185
3374
  if (isRequestOptions) {
3186
- value += "\n ...options,";
3375
+ value += isAngular ? "\n ...(options as Omit<NonNullable<typeof options>, 'observe'>)," : "\n ...options,";
3376
+ if (isAngular && angularObserve) value += `\n observe: '${angularObserve}',`;
3187
3377
  if (queryParams) if (isVue) value += "\n params: {...unref(params), ...options?.params},";
3188
- else if (isAngular && paramsSerializer) value += `\n params: ${paramsSerializer.name}({...params, ...options?.params}),`;
3378
+ else if (isAngular && angularParamsRef) value += `\n params: ${angularParamsRef},`;
3379
+ else if (isAngular && paramsSerializer) {
3380
+ const callExpr = getAngularFilteredParamsCallExpression("{...params, ...options?.params}", requiredNullableQueryParamKeys);
3381
+ value += `\n params: ${paramsSerializer.name}(${callExpr}),`;
3382
+ } else if (isAngular) value += `\n params: ${getAngularFilteredParamsCallExpression("{...params, ...options?.params}", requiredNullableQueryParamKeys)},`;
3189
3383
  else value += "\n params: {...params, ...options?.params},";
3190
3384
  if (headers) value += "\n headers: {...headers, ...options?.headers},";
3191
3385
  }
3192
- if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) value += paramsSerializer ? `\n paramsSerializer: ${paramsSerializer.name},` : `\n paramsSerializer: (params) => qs.stringify(params, ${JSON.stringify(paramsSerializerOptions?.qs)}),`;
3386
+ if (!isAngular && queryParams && (paramsSerializer || paramsSerializerOptions?.qs)) {
3387
+ const qsOptions = paramsSerializerOptions?.qs;
3388
+ value += paramsSerializer ? `\n paramsSerializer: ${paramsSerializer.name},` : `\n paramsSerializer: (params) => qs.stringify(params, ${JSON.stringify(qsOptions)}),`;
3389
+ }
3193
3390
  return value;
3194
3391
  }
3195
- function generateOptions({ route, body, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions }) {
3392
+ function generateOptions({ route, body, angularObserve, angularParamsRef, headers, queryParams, response, verb, requestOptions, isFormData, isFormUrlEncoded, isAngular, isExactOptionalPropertyTypes, hasSignal, hasSignalParam, isVue, paramsSerializer, paramsSerializerOptions }) {
3196
3393
  const bodyOptions = getIsBodyVerb(verb) ? generateBodyOptions(body, isFormData, isFormUrlEncoded) : "";
3197
3394
  const axiosOptions = generateAxiosOptions({
3198
3395
  response,
3396
+ angularObserve,
3397
+ angularParamsRef,
3398
+ requiredNullableQueryParamKeys: queryParams?.requiredNullableKeys,
3199
3399
  queryParams: queryParams?.schema,
3200
3400
  headers: headers?.schema,
3201
3401
  requestOptions,
@@ -3207,12 +3407,15 @@ function generateOptions({ route, body, headers, queryParams, response, verb, re
3207
3407
  paramsSerializer,
3208
3408
  paramsSerializerOptions
3209
3409
  });
3210
- const options = axiosOptions ? `{${axiosOptions}}` : "";
3410
+ const isRawOptionsArgument = axiosOptions === "options" || axiosOptions.startsWith("(") && axiosOptions.endsWith(")");
3411
+ const optionsArgument = axiosOptions ? isRawOptionsArgument ? axiosOptions : `{${axiosOptions}}` : "";
3211
3412
  if (verb === Verbs.DELETE) {
3212
- if (!bodyOptions) return `\n \`${route}\`,${axiosOptions === "options" ? axiosOptions : options}\n `;
3213
- return `\n \`${route}\`,{${isAngular ? "body" : "data"}:${bodyOptions} ${axiosOptions === "options" ? `...${axiosOptions}` : axiosOptions}}\n `;
3413
+ if (!bodyOptions) return `\n \`${route}\`${optionsArgument ? `,${optionsArgument}` : ""}\n `;
3414
+ const deleteBodyOptions = isRawOptionsArgument ? `...${optionsArgument}` : axiosOptions;
3415
+ return `\n \`${route}\`,{${isAngular ? "body" : "data"}:${bodyOptions} ${axiosOptions ? deleteBodyOptions : ""}}\n `;
3214
3416
  }
3215
- return `\n \`${route}\`,${getIsBodyVerb(verb) ? bodyOptions || "undefined," : ""}${axiosOptions === "options" ? axiosOptions : options}\n `;
3417
+ const bodyOrOptions = getIsBodyVerb(verb) ? bodyOptions || "undefined," : "";
3418
+ return `\n \`${route}\`${bodyOrOptions || optionsArgument ? "," : ""}${bodyOrOptions}${optionsArgument}\n `;
3216
3419
  }
3217
3420
  function generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) {
3218
3421
  if (isFormData && body.formData) return ",\n data: formData";
@@ -3220,16 +3423,18 @@ function generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) {
3220
3423
  if (body.implementation) return `,\n data: ${body.implementation}`;
3221
3424
  return "";
3222
3425
  }
3223
- function generateQueryParamsAxiosConfig(response, isVue, queryParams) {
3426
+ function generateQueryParamsAxiosConfig(response, isVue, isAngular, requiredNullableQueryParamKeys, queryParams) {
3224
3427
  if (!queryParams && !response.isBlob) return "";
3225
3428
  let value = "";
3226
- if (queryParams) value += isVue ? ",\n params: unref(params)" : ",\n params";
3429
+ if (queryParams) if (isVue) value += ",\n params: unref(params)";
3430
+ else if (isAngular) value += `,\n params: ${getAngularFilteredParamsExpression("params ?? {}", requiredNullableQueryParamKeys)}`;
3431
+ else value += ",\n params";
3227
3432
  if (response.isBlob) value += `,\n responseType: 'blob'`;
3228
3433
  return value;
3229
3434
  }
3230
- function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue }) {
3435
+ function generateMutatorConfig({ route, body, headers, queryParams, response, verb, isFormData, isFormUrlEncoded, hasSignal, hasSignalParam = false, isExactOptionalPropertyTypes, isVue, isAngular }) {
3231
3436
  const bodyOptions = getIsBodyVerb(verb) ? generateBodyMutatorConfig(body, isFormData, isFormUrlEncoded) : "";
3232
- const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, queryParams);
3437
+ const queryParamsOptions = generateQueryParamsAxiosConfig(response, isVue ?? false, isAngular ?? false, queryParams?.requiredNullableKeys, queryParams);
3233
3438
  const headerOptions = body.contentType && !["multipart/form-data"].includes(body.contentType) ? `,\n headers: {'Content-Type': '${body.contentType}', ${headers ? "...headers" : ""}}` : headers ? ",\n headers" : "";
3234
3439
  const signalVar = hasSignalParam ? "querySignal" : "signal";
3235
3440
  const signalProp = hasSignalParam ? `signal: ${signalVar}` : "signal";
@@ -3862,28 +4067,30 @@ async function writeSchemas({ schemaPath, schemas, target, namingConvention, fil
3862
4067
  //#region src/writers/generate-imports-for-builder.ts
3863
4068
  function generateImportsForBuilder(output, imports, relativeSchemasPath) {
3864
4069
  const isZodSchemaOutput = isObject(output.schemas) && output.schemas.type === "zod";
3865
- if (output.indexFiles) return isZodSchemaOutput ? [{
3866
- exports: imports.map((i) => ({
3867
- ...i,
3868
- values: true
3869
- })),
4070
+ let schemaImports = [];
4071
+ if (output.indexFiles) schemaImports = isZodSchemaOutput ? [{
4072
+ exports: imports.filter((i) => !i.importPath),
3870
4073
  dependency: joinSafe(relativeSchemasPath, "index.zod")
3871
4074
  }] : [{
3872
- exports: imports,
4075
+ exports: imports.filter((i) => !i.importPath),
3873
4076
  dependency: relativeSchemasPath
3874
4077
  }];
3875
- else return uniqueBy(imports, (x) => x.name).map((i) => {
4078
+ else schemaImports = uniqueBy(imports.filter((i) => !i.importPath), (x) => x.name).map((i) => {
3876
4079
  const name = conventionName(i.schemaName ?? i.name, output.namingConvention);
3877
4080
  const suffix = isZodSchemaOutput ? ".zod" : "";
3878
4081
  const importExtension = output.fileExtension.replace(/\.ts$/, "") || "";
3879
4082
  return {
3880
- exports: isZodSchemaOutput ? [{
3881
- ...i,
3882
- values: true
3883
- }] : [i],
4083
+ exports: [i],
3884
4084
  dependency: joinSafe(relativeSchemasPath, `${name}${suffix}${importExtension}`)
3885
4085
  };
3886
4086
  });
4087
+ const otherImports = uniqueBy(imports.filter((i) => !!i.importPath), (x) => x.name + (x.importPath ?? "")).map((i) => {
4088
+ return {
4089
+ exports: [i],
4090
+ dependency: i.importPath
4091
+ };
4092
+ });
4093
+ return [...schemaImports, ...otherImports];
3887
4094
  }
3888
4095
 
3889
4096
  //#endregion
@@ -4440,5 +4647,5 @@ async function writeTagsMode({ builder, output, projectName, header, needSchema
4440
4647
  }
4441
4648
 
4442
4649
  //#endregion
4443
- export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, filterByContentType, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getArray, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getRequestBodyContentTypes, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resolveDiscriminators, resolveExampleRefs, resolveObject, resolveRef, resolveValue, sanitize, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
4650
+ export { BODY_TYPE_NAME, EnumGeneration, ErrorWithTag, FormDataArrayHandling, GetterPropType, LogLevels, NamingConvention, OutputClient, OutputHttpClient, OutputMockType, OutputMode, PropertySortOrder, RefComponentSuffix, SchemaType, TEMPLATE_TAG_REGEX, URL_REGEX, VERBS_WITH_BODY, Verbs, _filteredVerbs, addDependency, asyncReduce, camel, combineSchemas, compareVersions, conventionName, count, createDebugger, createLogger, createSuccessMessage, createTypeAliasIfNeeded, dedupeUnionType, dynamicImport, escape, filterByContentType, fixCrossDirectoryImports, fixRegularSchemaImports, generalJSTypes, generalJSTypesWithArray, generateAxiosOptions, generateBodyMutatorConfig, generateBodyOptions, generateComponentDefinition, generateDependencyImports, generateFormDataAndUrlEncodedFunction, generateImports, generateModelInline, generateModelsInline, generateMutator, generateMutatorConfig, generateMutatorImports, generateMutatorRequestOptions, generateOptions, generateParameterDefinition, generateQueryParamsAxiosConfig, generateSchemasDefinition, generateTarget, generateTargetForTags, generateVerbImports, generateVerbOptions, generateVerbsOptions, getAngularFilteredParamsCallExpression, getAngularFilteredParamsExpression, getAngularFilteredParamsHelperBody, getArray, getBody, getCombinedEnumValue, getDefaultContentType, getEnum, getEnumDescriptions, getEnumImplementation, getEnumNames, getEnumUnionFromSchema, getExtension, getFileInfo, getFormDataFieldFileType, getFullRoute, getIsBodyVerb, getKey, getMockFileExtensionByTypeName, getNumberWord, getObject, getOperationId, getOrvalGeneratedTypes, getParameters, getParams, getParamsInPath, getPropertySafe, getProps, getQueryParams, getRefInfo, getRequestBodyContentTypes, getResReqTypes, getResponse, getResponseTypeCategory, getRoute, getRouteAsArray, getScalar, getSuccessResponseType, getTypedResponse, isBinaryContentType, isBoolean, isDirectory, isFunction, isModule, isNullish, isNumber, isNumeric, isObject, isReference, isSchema, isString, isStringLike, isSyntheticDefaultImportsAllow, isUrl, isVerb, jsDoc, jsStringEscape, kebab, keyValuePairsToJsDoc, log, logError, mergeDeep, mismatchArgsMessage, pascal, removeFilesAndEmptyFolders, resolveDiscriminators, resolveExampleRefs, resolveInstalledVersion, resolveInstalledVersions, resolveObject, resolveRef, resolveValue, sanitize, snake, sortByPriority, splitSchemasByType, startMessage, stringify, toObjectString, path_exports as upath, upper, writeModelInline, writeModelsInline, writeSchema, writeSchemas, writeSingleMode, writeSplitMode, writeSplitTagsMode, writeTagsMode };
4444
4651
  //# sourceMappingURL=index.mjs.map