Skip to content

Duplicate import names when using cross file refs with same names #2583

@narapov

Description

@narapov

Orval 7.16.1

In continuation of the issue, several uncovered cases were found:

  1. Error when using identically named schemas from different files in the request body and response of a single operation
  2. Error when using identically named parameters from different files in a single operation
  3. Error when generating different operations containing references to identically named schemas from different files

Prerequisites

  1. Create orval.config.ts
import { Options } from 'orval';

const config: Record<string, Options> = {
    bffApi: {
        output: {
            client: 'axios',
            target: './generated/bff/bff.ts',
            mode: 'split',
            schemas: './generated/bff/schemas',
            prettier: true,
        },
        input: {
            target: './docs/openapi.yaml',
        },
    },
};

export default config;
  1. Create ./docs/external-backend-service1.yaml file:
openapi: '3.0.3'
info:
  title: External backend service 1
  version: "0.0.1"
servers:
  - description: Remote
    url: "/external-backend-service1/"
  - description: Local
    url: "/"
paths:
  /test:
    get:
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/A"

components:
  parameters:
    param1:
      name: service1Param
      in: query
      schema:
        type: string
        enum:
          - service1_param_value_1
          - service1_param_value_2

  schemas:
    A:
      type: object
      properties:
        service1Prop: 
          type: string
  1. Create ./docs/external-backend-service2.yaml file:
openapi: '3.0.3'
info:
  title: External backend service 2
  version: "0.0.1"
servers:
  - description: Remote
    url: "/external-backend-service2/"
  - description: Local
    url: "/"
paths:
  /test:
    get:
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                $ref: "#/components/schemas/A"

components:
  parameters:
    param1:
      name: service2Param
      in: query
      schema:
        type: string
        enum:
          - service2_param_value_1
          - service2_param_value_2
  schemas:
    A:
      type: object
      properties:
        service2Prop: 
          type: string

Identically named schemas from different files in the request body and response of a single operation

  1. Fill prerequisites
  2. Create ./docs/openapi.yaml file:
openapi: '3.0.3'
info:
  title: My bff service
  version: "0.0.1"
servers:
  - description: Local
    url: "/"
paths:
  /transform-service1-a-to-service2-a:
    post:
      requestBody:
        description: body
        content:
          'application/json':
            schema:
              $ref: "./external-backend-service1.yaml#/components/schemas/A"
      responses:
        200:
          description: Transformed value
          content:
            application/json:
              schema:
                $ref: './external-backend-service2.yaml#/components/schemas/A'
  1. Generate client using orval

Actual behavior

File ./generated/bff/bff.ts has duplicated import names from different files

/**
 * Generated by orval v7.16.1 🍺
 * Do not edit manually.
 * My bff service
 * OpenAPI spec version: 0.0.1
 */
import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';

import type { A } from './schemas/external-backend-service2';
import type { A } from './schemas/external-backend-service1';

export const getMyBffService = () => {
    const postTransformService1AToService2A = <TData = AxiosResponse<A>>(
        a: A,
        options?: AxiosRequestConfig,
    ): Promise<TData> => {
        return axios.post(`/transform-service1-a-to-service2-a`, a, options);
    };

    return { postTransformService1AToService2A };
};
export type PostTransformService1AToService2AResult = AxiosResponse<A>;

Expected behavior

File ./generated/bff/bff.ts must use import aliases like:

import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';

import type { A } from './schemas/external-backend-service2';
import type { A as ExternalBackendService1__A } from './schemas/external-backend-service1';

export const getMyBffService = () => {
    const postTransformService1AToService2A = <TData = AxiosResponse<A>>(
        a: ExternalBackendService1__A,
        options?: AxiosRequestConfig,
    ): Promise<TData> => {
        return axios.post(`/transform-service1-a-to-service2-a`, a, options);
    };

    return { postTransformService1AToService2A };
};
export type PostTransformService1AToService2AResult = AxiosResponse<A>;

Identically named parameters from different files in a single operation

  1. Fill prerequisites
  2. Create ./docs/openapi.yaml file:
openapi: '3.0.3'
info:
  title: My bff service
  version: "0.0.1"
servers:
  - description: Local
    url: "/"
paths:
  /test:
    get:
      parameters:
        - $ref: '#/components/parameters/param1'
        - $ref: './external-backend-service1.yaml#/components/parameters/param1'
        - $ref: './external-backend-service2.yaml#/components/parameters/param1'
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                type: object
components:                
  parameters:
    param1:
      name: selfParam
      in: query
      schema:
        type: string
        enum:
          - self_param_value_1
          - self_param_value_2
  1. Generate client using orval

Actual behavior

File ./generated/bff/schemas/getTestParams.ts has duplicated import names from different files

/**
 * Generated by orval v7.16.1 🍺
 * Do not edit manually.
 * My bff service
 * OpenAPI spec version: 0.0.1
 */
import type { Param1Parameter } from './param1Parameter';
import type { Param1Parameter } from './external-backend-service1/param1Parameter';
import type { Param1Parameter } from './external-backend-service2/param1Parameter';

export type GetTestParams = {
    selfParam?: Param1Parameter;
    service1Param?: Param1Parameter;
    service2Param?: Param1Parameter;
};

Expected behavior

File ./generated/bff/schemas/getTestParams.ts must use import aliases like:

import type { Param1Parameter } from './param1Parameter';
import type { Param1Parameter as ExternalBackendService1__Param1Parameter } from './external-backend-service1/param1Parameter';
import type { Param1Parameter as ExternalBackendService2__Param1Parameter } from './external-backend-service2/param1Parameter';

export type GetTestParams = {
    selfParam?: Param1Parameter;
    service1Param?: ExternalBackendService1__Param1Parameter;
    service2Param?: ExternalBackendService2__Param1Parameter;
};

Generating different operations containing references to identically named schemas

  1. Fill prerequisites
  2. Create ./docs/openapi.yaml file:
openapi: '3.0.3'
info:
  title: My bff service
  version: "0.0.1"
servers:
  - description: Local
    url: "/"
paths:
  /test1:
    get:
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                $ref: './external-backend-service1.yaml#/components/schemas/A'
  /test2:
    get:
      responses:
        200:
          description: OK
          content:
            application/json:
              schema:
                $ref: './external-backend-service2.yaml#/components/schemas/A'
  1. Generate client using orval

Actual behavior

File ./generated/bff/bff.ts has duplicated import names from different files

/**
 * Generated by orval v7.16.1 🍺
 * Do not edit manually.
 * My bff service
 * OpenAPI spec version: 0.0.1
 */
import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';

import type { A } from './schemas/external-backend-service1';
import type { A } from './schemas/external-backend-service2';

export const getMyBffService = () => {
    const getTest1 = <TData = AxiosResponse<A>>(options?: AxiosRequestConfig): Promise<TData> => {
        return axios.get(`/test1`, options);
    };

    const getTest2 = <TData = AxiosResponse<A>>(options?: AxiosRequestConfig): Promise<TData> => {
        return axios.get(`/test2`, options);
    };

    return { getTest1, getTest2 };
};
export type GetTest1Result = AxiosResponse<A>;
export type GetTest2Result = AxiosResponse<A>;

Expected behavior

File ./generated/bff/bff.ts must use import aliases like:

import axios from 'axios';
import type { AxiosRequestConfig, AxiosResponse } from 'axios';

import type { A } from './schemas/external-backend-service1';
import type { A as ExternalBackendService2__A } from './schemas/external-backend-service2';

export const getMyBffService = () => {
    const getTest1 = <TData = AxiosResponse<A>>(options?: AxiosRequestConfig): Promise<TData> => {
        return axios.get(`/test1`, options);
    };

    const getTest2 = <TData = AxiosResponse<ExternalBackendService2__A>>(options?: AxiosRequestConfig): Promise<TData> => {
        return axios.get(`/test2`, options);
    };

    return { getTest1, getTest2 };
};
export type GetTest1Result = AxiosResponse<A>;
export type GetTest2Result = AxiosResponse<ExternalBackendService2__A>;

Metadata

Metadata

Assignees

Labels

bugSomething isn't working

Type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions