Migrating

While we try to avoid breaking changes, sometimes it's unavoidable in order to offer you the latest features. This page lists changes that require updates to your code. If you run into a problem with migration, please open an issue.

v0.96.0

Removed Node 20 support

This release bumps the minimum required Node version to 22.13.

v0.95.0

Validator request schemas

Valibot and Zod plugins no longer export composite request Data schemas. Instead, each layer is exported as a separate schema. If you're using validators with SDKs, you can preserve the composite schema with shouldExtract:

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      name: 'sdk',
      validator: 'zod',
    },
    {
      name: 'zod',
      requests: { 
        shouldExtract: true, 
      }, 
    },
  ],
};

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      name: 'sdk',
      validator: 'valibot',
    },
    {
      name: 'valibot',
      requests: { 
        shouldExtract: true, 
      }, 
    },
  ],
};

Removed plugin.getSymbol() function

This function has been removed. You can use plugin.querySymbol() instead. It accepts the same arguments and returns the same result.

v0.93.0

Removed resolver node

Valibot and Zod plugins no longer expose the enum.nodes.nullable node. Both plugins were refactored so that nullable values are handled outside of resolvers.

v0.92.0

Updated Symbol interface

The exportFrom property has been replaced with the getExportFromFilePath() function. This allows you to dynamically determine export paths based on symbol properties. This is a low-level feature, so you're most likely unaffected.

v0.91.0

Removed CommonJS (CJS) support

@hey-api/openapi-ts is now ESM-only. This change simplifies the codebase, improves tree-shaking, and enables better integration with modern bundlers and TypeScript tooling.

CommonJS entry points (require(), module.exports) are no longer supported. If you are in a CJS environment, you can still load the package dynamically using import() like:

js

const { defineConfig } = await import('@hey-api/openapi-ts');

If you have previously written:

js

const { defineConfig } = require('@hey-api/openapi-ts');

Migrate by updating your static imports:

js

import { defineConfig } from '@hey-api/openapi-ts';

If your environment cannot use ESM, pin to a previous version.

v0.90.0

Resolvers API

The Resolvers API has been simplified and expanded to provide a more consistent behavior across plugins. You can view a few common examples on the Resolvers page.

Structure API

The SDK plugin and Angular plugin now implement the Structure API, enabling more complex structures and fixing several known issues.

Some Structure APIs are incompatible with the previous configuration, most notably the methodNameBuilder function, which accepted the operation object as an argument. You can read the SDK Output section to familiarize yourself with the Structure API.

Please open an issue if you're unable to migrate your configuration to the new syntax.

v0.89.0

Prefer named exports

This release changes the default for index.ts to prefer named exports. Named exports may lead to better IDE and bundler performance compared to asterisk (*) as your tooling doesn't have to inspect the underlying module to discover exports.

While this change is merely cosmetic, you can set output.preferExportAll to true if you prefer to use the asterisk.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: {
    path: 'src/client',
    preferExportAll: true, 
  },
};

Removed symbol:setValue:* events

These events have been removed in favor of node:set:* events.

v0.88.0

Removed compiler and tsc exports

This release removes the compiler utility functions. Instead, it introduces a new TypeScript DSL exposed under the $ symbol. All plugins now use this interface, so you may notice slight changes in the generated output.

v0.87.0

Removed legacy clients

This release removes support for legacy clients and plugins. Please migrate to the new clients if you haven't done so yet. If you're unable to do so due to a missing feature, let us know on GitHub.

v0.86.0

Removed Node 18 support

This release bumps the minimum required Node version to 20.19.

v0.85.0

Updated output options

We made the output configuration more consistent by using null to represent disabled options. This change does not affect boolean options.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: {
    format: false, 
    format: null, 
    lint: false, 
    lint: null, 
    path: 'src/client',
    tsConfigPath: 'off', 
    tsConfigPath: null, 
  },
};

Updated Pinia Colada query options

Pinia Colada query options now use defineQueryOptions to improve reactivity support. Instead of calling the query options function, you can use one of the following approaches.

ts

useQuery(getPetsQuery);

ts

useQuery(getPetByIdQuery, () => ({
  path: {
    petId: 1,
  },
}));

ts

const petId = ref<number | null>(1);

useQuery(getPetByIdQuery, () => ({
  path: {
    petId: petId.value,
  },
}));

ts

const petId = ref<number | null>(1);

useQuery(() => ({
  ...getPetByIdQuery({
    path: { petId: petId.value as number },
  }),
  enabled: () => petId.value !== null,
}));

v0.84.0

Symbol API

This release improves the Symbol API, which adds the capability to place symbols in arbitrary files. We preserved the previous output structure for all plugins except Angular.

You can preserve the previous Angular output by writing your own placement function.

TypeScript renderer

We ship a dedicated TypeScript renderer for .ts files. This release improves the renderer's ability to group and sort imported modules, resulting in a more polished output.

Removed output plugin option

Due to the Symbol API release, this option has been removed from the Plugin API.

v0.83.0

Symbol API

This release adds the Symbol API, which significantly reduces the risk of naming collisions. While the generated output should only include formatting changes, this feature introduces breaking changes to the Plugin API that affect custom plugins.

We will update the custom plugin guide once the Plugin API becomes more stable.

Removed groupByTag Pinia Colada option

This option has been removed to provide a more consistent API across plugins. We plan to bring it back in a future release.

v0.82.0

Hooks API

This release adds the Hooks API, giving you granular control over which operations generate queries and mutations. As a result, we tightened the previous behavior and POST operations no longer generate queries by default. To preserve the old behavior, add a custom matcher.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  parser: {
    hooks: {
      operations: {
        isQuery: (op) => (op.method === 'post' ? true : undefined), 
      },
    },
  },
};

v0.81.0

Server-Sent Events (SSE)

This release adds support for server-sent events (SSE). Instead of treating text/event-stream content types as regular HTTP methods, we now generate SSE streams. In practice, you will want to update your affected endpoints to process streamed events.

js

const { data } = await foo();
console.log(data.type);

js

const { stream } = await foo();
for await (const event of stream) {
  console.log(event.type);
}

v0.80.0

Added Zod 4 and Zod Mini

This release adds support for Zod 4 and Zod Mini. By default, the zod plugin will generate output for Zod 4. If you want to preserve the previous output for Zod 3 or use Zod Mini, set compatibilityVersion to 3 or mini.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      name: 'zod',
      compatibilityVersion: 3, 
    },
  ],
};

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      name: 'zod',
      compatibilityVersion: 'mini', 
    },
  ],
};

v0.79.0

Removed typescript+namespace enums mode

Due to a simpler TypeScript plugin implementation, the typescript+namespace enums mode is no longer necessary. This mode was used in the past to group inline enums under the same namespace. With the latest changes, this behavior is no longer supported. You can either choose to ignore inline enums (default), or use the enums transform (added in v0.78.0) to convert them into reusable components which will get exported as usual.

v0.78.0

Added parser options

Previously, @hey-api/typescript would generate correct types, but the validator plugins would have to re-implement the same logic or generate schemas that didn't match the generated types.

Since neither option was ideal, this release adds a dedicated place for parser options. Parser is responsible for preparing the input so plugins can generate more accurate output with less effort.

You can learn more about configuring parser on the Parser page.

Moved input options

The following options were moved to the new parser group.

  • input.filters moved to parser.filters
  • input.pagination moved to parser.pagination
  • input.patch moved to parser.patch
  • input.validate_EXPERIMENTAL moved to parser.validate_EXPERIMENTAL

Updated typescript options

The following options were renamed.

  • enumsCase moved to enums.case
  • enumsConstantsIgnoreNull moved to enums.constantsIgnoreNull

Moved typescript options

The following options were moved to the new parser group.

  • exportInlineEnums moved to parser.transforms.enums
  • readOnlyWriteOnlyBehavior moved to parser.transforms.readWrite.enabled
  • readableNameBuilder moved to parser.transforms.readWrite.responses.name
  • writableNameBuilder moved to parser.transforms.readWrite.requests.name

Updated readWrite.responses name

Additionally, the naming pattern for response schemas has changed from {name}Readable to {name}. This is to prevent your code from breaking by default when using a schema that gets updated with a write-only field.

v0.77.0

Updated sdk.validator option

Clients can now validate both request and response data. As a result, passing a boolean or string to validator will control both of these options. To preserve the previous behavior, set validator.request to false and validator.response to your previous configuration.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      name: '@hey-api/sdk',
      validator: true, 
      validator: { 
        request: false, 
        response: true, 
      }, 
    },
  ],
};

Updated Plugin API

Please refer to the custom plugin tutorial for the latest guide.

v0.76.0

Single Valibot schema per request

Previously, we generated a separate schema for each endpoint parameter and request body. In v0.76.0, a single request schema is generated for the whole endpoint. It may contain a request body, parameters, and headers.

ts

const vData = v.object({
  body: v.optional(
    v.object({
      foo: v.optional(v.string()),
      bar: v.optional(v.union([v.number(), v.null()])),
    }),
  ),
  headers: v.optional(v.never()),
  path: v.object({
    baz: v.string(),
  }),
  query: v.optional(v.never()),
});

If you need to access individual fields, you can do so using the .entries API. For example, we can get the request body schema with vData.entries.body.

v0.75.0

Updated TanStack Query options

The TanStack Query plugin options have been expanded to support more naming and casing patterns. As a result, the following options have been renamed.

  • queryOptionsNameBuilder renamed to queryOptions
  • infiniteQueryOptionsNameBuilder renamed to infiniteQueryOptions
  • mutationOptionsNameBuilder renamed to mutationOptions
  • queryKeyNameBuilder renamed to queryKeys
  • infiniteQueryKeyNameBuilder renamed to infiniteQueryKeys

Added plugin.forEach() method

This method replaces the .subscribe() method. Additionally, .forEach() is executed immediately, which means we don't need the before and after events – simply move your code before and after the .forEach() block.

ts

plugin.subscribe('operation', (event) => { 
  // do something with event
}); 
plugin.subscribe('schema', (event) => { 
plugin.forEach('operation', 'schema', (event) => { 
  // do something with event
});

v0.74.0

Single Zod schema per request

Previously, we generated a separate schema for each endpoint parameter and request body. In v0.74.0, a single request schema is generated for the whole endpoint. It may contain a request body, parameters, and headers.

ts

const zData = z.object({
  body: z
    .object({
      foo: z.string().optional(),
      bar: z.union([z.number(), z.null()]).optional(),
    })
    .optional(),
  headers: z.never().optional(),
  path: z.object({
    baz: z.string(),
  }),
  query: z.never().optional(),
});

If you need to access individual fields, you can do so using the .shape API. For example, we can get the request body schema with zData.shape.body.

v0.73.0

Bundle @hey-api/client-* plugins

In previous releases, you had to install a separate client package to generate a fully working output, e.g., npm add @hey-api/client-fetch. This created a few challenges: getting started was slower, upgrading was sometimes painful, and bundling too. Beginning with v0.73.0, all Hey API clients are bundled by default and don't require installing any additional dependencies. You can remove any installed client packages and re-run @hey-api/openapi-ts.

sh

npm uninstall @hey-api/client-fetch

v0.72.0

Added sdk.classStructure option

When generating class-based SDKs, we now try to infer the ideal structure using operationId keywords. If you'd like to preserve the previous behavior, set classStructure to off.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      classStructure: 'off', 
      name: '@hey-api/sdk',
    },
  ],
};

v0.71.0

Renamed sdk.serviceNameBuilder option

This option has been renamed to sdk.classNameBuilder to better represent its functionality. Additionally, it's no longer set by default. To preserve the previous behavior, update your configuration.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      classNameBuilder: '{{name}}Service', 
      name: '@hey-api/sdk',
      serviceNameBuilder: '{{name}}Service', 
    },
  ],
};

v0.68.0

Upgraded input filters

Input filters now avoid generating invalid output without requiring you to specify every missing schema as in the previous releases. As part of this release, we changed the way filters are configured and removed the support for regular expressions. Let us know if regular expressions are still useful for you and want to bring them back!

js

export default {
  input: {
    // match only the schema named `foo` and `GET` operation for the `/api/v1/foo` path
    filters: {
      operations: {
        include: ['GET /api/v1/foo'], 
      },
      schemas: {
        include: ['foo'], 
      },
    },
    include: '^(#/components/schemas/foo|#/paths/api/v1/foo/get)$', 
    path: 'hey-api/backend', // sign up at app.heyapi.dev
  },
  output: 'src/client',
  plugins: ['@hey-api/client-fetch'],
};

js

export default {
  input: {
    // match everything except for the schema named `foo` and `GET` operation for the `/api/v1/foo` path
    exclude: '^(#/components/schemas/foo|#/paths/api/v1/foo/get)$', 
    filters: {
      operations: {
        exclude: ['GET /api/v1/foo'], 
      },
      schemas: {
        exclude: ['foo'], 
      },
    },
    path: 'hey-api/backend', // sign up at app.heyapi.dev
  },
  output: 'src/client',
  plugins: ['@hey-api/client-fetch'],
};

v0.67.0

Respecting moduleResolution value in tsconfig.json

This release introduces functionality related to your tsconfig.json file. The initial feature properly respects the value of your moduleResolution field. If you're using nodenext, the relative module paths in your output will be appended with .js. To preserve the previous behavior where we never appended .js to relative module paths, set output.tsConfigPath to off.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: {
    path: 'src/client',
    tsConfigPath: 'off', 
  },
};

v0.66.0

Read-only and write-only fields

Starting with v0.66.0, @hey-api/typescript will generate separate types for payloads and responses if it detects any read-only or write-only fields. To preserve the previous behavior and generate a single type regardless, set readOnlyWriteOnlyBehavior to off.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      name: '@hey-api/typescript',
      readOnlyWriteOnlyBehavior: 'off', 
    },
  ],
};

v0.64.0

Added ClientOptions interface

The Config interface now accepts an optional generic extending ClientOptions instead of boolean type ThrowOnError.

ts

type Foo = Config<false>; 
type Foo = Config<{ throwOnError: false }>; 

Added client.baseUrl option

You can use this option to configure the default base URL for the generated client. By default, we will attempt to resolve the first defined server or infer the base URL from the input path. If you'd like to preserve the previous behavior, set baseUrl to false.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    {
      baseUrl: false, 
      name: '@hey-api/client-fetch',
    },
  ],
};

v0.63.0

Client plugins

Clients are now plugins generating their own client.gen.ts file. There's no migration needed if you're using CLI. If you're using the configuration file, move client options to plugins.

js

export default {
  client: '@hey-api/client-fetch', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: ['@hey-api/client-fetch'], 
};

Added client.gen.ts file

Related to above, the internal client instance previously located in sdk.gen.ts is now defined in client.gen.ts. If you're importing it in your code, update the import module.

js

import { client } from 'client/sdk.gen'; 
import { client } from 'client/client.gen'; 

Moved sdk.throwOnError option

This SDK configuration option has been moved to the client plugins where applicable. Not every client can be configured to throw on error, so it didn't make sense to expose the option when it didn't have any effect.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    {
      name: '@hey-api/client-fetch',
      throwOnError: true, 
    },
    {
      name: '@hey-api/sdk',
      throwOnError: true, 
    },
  ],
};

v0.62.0

Changed parser

Formerly known as the experimental parser, this is now the default parser. This change should not impact the generated output's functionality. However, there might be cases where this results in breaking changes due to different handling of certain scenarios. If you need to revert to the legacy parser, set the experimentalParser flag to false.

js

export default {
  client: '@hey-api/client-fetch',
  experimentalParser: false, 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
};

Note that the legacy parser is no longer supported and will be removed in the v1 release.

v0.61.0

Added auth option

Client package functions accessToken and apiKey were replaced with a single auth function for fetching auth tokens. If your API supports multiple auth mechanisms, you can use the auth argument to return the appropriate token.

js

import { client } from 'client/sdk.gen';

client.setConfig({
  accessToken: () => '<my_token>', 
  apiKey: () => '<my_token>', 
  auth: (auth) => '<my_token>', 
});

Due to conflict with the Axios native auth option, we removed support for configuring Axios auth. Please let us know if you require this feature added back.

Added watch option

While this is a new feature, supporting it involved replacing the @apidevtools/json-schema-ref-parser dependency with our own implementation. Since this was a big change, we're applying caution and marking this as a breaking change.

Changed parseAs: 'auto' behavior

The Fetch API client will return raw response body as ReadableStream when Content-Type response header is undefined and parseAs is auto.

v0.60.0

Added sdk.transformer option

When generating SDKs, you now have to specify transformer in order to modify response data. By default, adding @hey-api/transformers to your plugins will only produce additional output. To preserve the previous functionality, set sdk.transformer to true.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      dates: true,
      name: '@hey-api/transformers',
    },
    {
      name: '@hey-api/sdk',
      transformer: true, 
    },
  ],
};

v0.59.0

Added logs.level option

You can now configure different log levels. As part of this feature, we had to introduce a breaking change by moving the debug option to logs.level. This will affect you if you're calling @hey-api/openapi-ts from Node.js (not CLI) or using the configuration file.

js

export default {
  client: '@hey-api/client-fetch',
  debug: true, 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  logs: {
    level: 'debug', 
  },
  output: 'src/client',
};

Updated default plugins

@hey-api/schemas has been removed from the default plugins. To continue using it, add it to your plugins array.

js

export default {
  client: '@hey-api/client-fetch',
  experimentalParser: true,
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    '@hey-api/schemas', 
  ],
};

v0.58.0

Removed schemas.gen.ts re-export

index.ts will no longer re-export schemas.gen.ts to reduce the chance of producing broken output. Please update your code to import from schemas.gen.ts directly.

js

import { mySchema } from 'client'; 
import { mySchema } from 'client/schemas.gen'; 

Removed transformers.gen.ts re-export

index.ts will no longer re-export transformers.gen.ts to reduce the chance of producing broken output. Please update your code to import from transformers.gen.ts directly.

js

import { myTransformer } from 'client'; 
import { myTransformer } from 'client/transformers.gen'; 

Added output.clean option

By default, the output.path folder will be emptied on every run. To preserve the previous behavior, set output.clean to false.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: {
    clean: false, 
    path: 'src/client',
  },
};

Added typescript.identifierCase option

This change affects only the experimental parser. By default, the generated TypeScript interfaces will follow the PascalCase naming convention. In the previous versions, we tried to preserve the original name as much as possible. To keep the previous behavior, set typescript.identifierCase to preserve.

js

export default {
  client: '@hey-api/client-fetch',
  experimentalParser: true,
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      identifierCase: 'preserve', 
      name: '@hey-api/typescript',
    },
  ],
};

v0.57.0

Renamed @hey-api/services plugin

This plugin has been renamed to @hey-api/sdk.

Changed sdk.output value

To align with the updated name, the @hey-api/sdk plugin will generate an sdk.gen.ts file. This will result in a breaking change if you're importing from services.gen.ts. Please update your imports to reflect this change.

js

import { client } from 'client/services.gen'; 
import { client } from 'client/sdk.gen'; 

Renamed @hey-api/types plugin

This plugin has been renamed to @hey-api/typescript.

Added typescript.exportInlineEnums option

By default, inline enums (enums not defined as reusable components in the input file) will be generated only as inlined union types. You can set exportInlineEnums to true to treat inline enums as reusable components. When true, the exported enums will follow the style defined in enums.

This is a breaking change since in the previous versions, inline enums were always treated as reusable components. To preserve your current output, set exportInlineEnums to true. This feature works only with the experimental parser.

js

export default {
  client: '@hey-api/client-fetch',
  experimentalParser: true,
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  plugins: [
    // ...other plugins
    {
      exportInlineEnums: true, 
      name: '@hey-api/typescript',
    },
  ],
};

v0.56.0

Deprecated tree in @hey-api/types

This config option is deprecated and will be removed when the experimental parser becomes the default.

v0.55.0

This release adds the ability to filter your OpenAPI specification before it's processed. This feature will be useful if you are working with a large specification and are interested in generating output only from a small subset.

This feature is available only in the experimental parser. In the future, this will become the default parser. To opt-in to the experimental parser, set the experimentalParser flag in your configuration to true.

Deprecated include in @hey-api/types

This config option is deprecated and will be removed when the experimental parser becomes the default.

Deprecated filter in @hey-api/services

This config option is deprecated and will be removed when the experimental parser becomes the default.

Added input.include option

This config option can be used to replace the deprecated options. It accepts a regular expression string matching against references within the bundled specification.

js

export default {
  client: '@hey-api/client-fetch',
  experimentalParser: true,
  input: {
    include: '^(#/components/schemas/foo|#/paths/api/v1/foo/get)$', 
    path: 'hey-api/backend', // sign up at app.heyapi.dev
  },
  output: 'src/client',
};

The configuration above will process only the schema named foo and GET operation for the /api/v1/foo path.

v0.54.0

This release makes plugins first-class citizens. In order to achieve that, the following breaking changes were introduced.

Removed CLI options

The --types, --schemas, and --services CLI options have been removed. You can list which plugins you'd like to use explicitly by passing a list of plugins as --plugins <plugin1> <plugin2>

Removed *.export option

Previously, you could explicitly disable export of certain artifacts using the *.export option or its shorthand variant. These were both removed. You can now disable export of specific artifacts by manually defining an array of plugins and excluding the unwanted plugin.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  schemas: false, 
  plugins: ['@hey-api/types', '@hey-api/services'], 
};

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  schemas: {
    export: false, 
  },
  plugins: ['@hey-api/types', '@hey-api/services'], 
};

Renamed schemas.name option

Each plugin definition contains a name field. This was conflicting with the schemas.name option. As a result, it has been renamed to nameBuilder.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  schemas: {
    name: (name) => `${name}Schema`, 
  },
  plugins: [
    // ...other plugins
    {
      nameBuilder: (name) => `${name}Schema`, 
      name: '@hey-api/schemas',
    },
  ],
};

Removed services.include shorthand option

Previously, you could use a string value as a shorthand for the services.include configuration option. You can now achieve the same result using the include option.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  services: '^MySchema', 
  plugins: [
    // ...other plugins
    {
      include: '^MySchema', 
      name: '@hey-api/services',
    },
  ],
};

Renamed services.name option

Each plugin definition contains a name field. This was conflicting with the services.name option. As a result, it has been renamed to serviceNameBuilder.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  services: {
    name: '{{name}}Service', 
  },
  plugins: [
    // ...other plugins
    {
      serviceNameBuilder: '{{name}}Service', 
      name: '@hey-api/services',
    },
  ],
};

Renamed types.dates option

Previously, you could set types.dates to a boolean or a string value, depending on whether you wanted to transform only type strings into dates, or runtime code too. Many people found these options confusing, so they have been simplified to a boolean and extracted into a separate @hey-api/transformers plugin.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  types: {
    dates: 'types+transform', 
  },
  plugins: [
    // ...other plugins
    {
      dates: true, 
      name: '@hey-api/transformers',
    },
  ],
};

Removed types.include shorthand option

Previously, you could use a string value as a shorthand for the types.include configuration option. You can now achieve the same result using the include option.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  types: '^MySchema', 
  plugins: [
    // ...other plugins
    {
      include: '^MySchema', 
      name: '@hey-api/types',
    },
  ],
};

Renamed types.name option

Each plugin definition contains a name field. This was conflicting with the types.name option. As a result, it has been renamed to style.

js

export default {
  client: '@hey-api/client-fetch',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  types: {
    name: 'PascalCase', 
  },
  plugins: [
    // ...other plugins
    {
      name: '@hey-api/types',
      style: 'PascalCase', 
    },
  ],
};

v0.53.0

Changed schemas name pattern

Previously, generated schemas would have their definition names prefixed with $. This was problematic when using them with Svelte due to reserved keyword conflicts. The new naming pattern for schemas suffixes their definition names with Schema. You can continue using the previous pattern by setting the schemas.name configuration option.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  schemas: {
    name: (name) => `$${name}`, 
  },
};

Renamed legacy clients

Legacy clients were renamed to signal they are deprecated more clearly. To continue using legacy clients, you will need to update your configuration and prefix them with legacy/.

js

export default {
  client: 'fetch', 
  client: 'legacy/fetch', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
};

js

export default {
  client: 'axios', 
  client: 'legacy/axios', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
};

js

export default {
  client: 'angular', 
  client: 'legacy/angular', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
};

js

export default {
  client: 'node', 
  client: 'legacy/node', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
};

js

export default {
  client: 'xhr', 
  client: 'legacy/xhr', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
};

v0.52.0

Removed internal client export

Previously, client packages would create a default client which you'd then import and configure.

js

import { client, createClient } from '@hey-api/client-fetch';

createClient({
  baseUrl: 'https://example.com',
});

console.log(client.getConfig().baseUrl); // <-- 'https://example.com'

This client instance was used internally by services unless overridden. Apart from running createClient() twice, people were confused about the meaning of global configuration option.

Starting with v0.52.0, client packages will not create a default client. Instead, services will define their own client. You can now achieve the same configuration by importing client from services and using the new setConfig() method.

js

import { client } from 'client/services.gen';

client.setConfig({
  baseUrl: 'https://example.com',
});

console.log(client.getConfig().baseUrl); // <-- 'https://example.com'

v0.51.0

Required client option

Client now has to be explicitly specified and @hey-api/openapi-ts will no longer generate a legacy Fetch API client by default. To preserve the previous default behavior, set the client option to fetch.

js

export default {
  client: 'fetch', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
};

v0.48.0

Changed methodNameBuilder() signature

The services.methodNameBuilder() function now provides a single operation argument instead of multiple cherry-picked properties from it.

js

import { createClient } from '@hey-api/openapi-ts';

createClient({
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  services: {
    methodNameBuilder: (service, name) => name, 
    methodNameBuilder: (operation) => operation.name, 
  },
});

v0.46.0

Tree-shakeable services

By default, your services will now support tree-shaking. You can either use wildcard imports

js

import { DefaultService } from 'client/services.gen'; 
import * as DefaultService from 'client/services.gen'; 

DefaultService.foo(); // only import needs to be changed

or update all references to service classes

js

import { DefaultService } from 'client/services.gen'; 
import { foo } from 'client/services.gen'; 

foo(); // all references need to be changed

If you want to preserve the old behavior, you can set the newly exposed services.asClass option to true.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  services: {
    asClass: true, 
  },
};

v0.45.0

Removed client inference

@hey-api/openapi-ts will no longer infer which client you want to generate. By default, we will create a fetch client. If you want a different client, you can specify it using the client option.

js

export default {
  client: 'axios', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
};

v0.44.0

Moved format

This config option has been moved. You can now configure formatter using the output.format option.

js

export default {
  format: 'prettier', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: {
    format: 'prettier', 
    path: 'src/client',
  },
};

Moved lint

This config option has been moved. You can now configure linter using the output.lint option.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  lint: 'eslint', 
  output: {
    lint: 'eslint', 
    path: 'src/client',
  },
};

v0.43.0

Removed enums.gen.ts

This file has been removed. Instead, enums are exported from types.gen.ts. If you use imports from enums.gen.ts, you should be able to easily find and replace all instances.

js

import { Foo } from 'client/enums.gen'; 
import { Foo } from 'client/types.gen'; 

Removed Enum postfix

Generated enum names are no longer postfixed with Enum. You can either alias your imports

js

import { FooEnum } from 'client/types.gen'; 
import { Foo as FooEnum } from 'client/types.gen'; 

console.log(FooEnum.value); // only import needs to be changed

or update all references to enums

js

import { FooEnum } from 'client/types.gen'; 
import { Foo } from 'client/types.gen'; 

console.log(Foo.value); // all references need to be changed

Moved enums

This config option has been moved. You can now configure enums using the types.enums option.

js

export default {
  enums: 'javascript', 
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  types: {
    enums: 'javascript', 
  },
};

v0.42.0

Changed format

This config option has changed. You now need to specify a value (biome or prettier) to format the output (default: false).

js

export default {
  format: 'prettier',
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
}

Changed lint

This config option has changed. You now need to specify a value (biome or eslint) to lint the output (default: false).

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  lint: 'eslint',
  output: 'src/client',
}

Moved operationId

This config option has been moved. You can now configure it using the services.operationId option.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  services: {
    operationId: true,
  },
}

v0.41.0

Removed postfixServices

This config option has been removed. You can now transform service names using the string pattern parameter.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  services: {
    name: 'myAwesome{{name}}Api',
  },
}

Removed serviceResponse

This config option has been removed. You can now configure service responses using the services.response option.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  services: {
    response: 'body',
  },
}

Removed useDateType

This config option has been removed. You can now configure date type using the types.dates option.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  type: {
    dates: true,
  },
}

v0.40.0

Renamed models.gen.ts file

models.gen.ts is now called types.gen.ts. If you use imports from models.gen.ts, you should be able to easily find and replace all instances.

js

import type { Model } from 'client/models.gen'
import type { Model } from 'client/types.gen'

Renamed exportModels

This config option is now called types.

PascalCase for types

You can now choose to export types using the PascalCase naming convention.

js

export default {
  input: 'hey-api/backend', // sign up at app.heyapi.dev
  output: 'src/client',
  types: {
    name: 'PascalCase',
  },
}

Exported enums.gen.ts file

Enums are now re-exported from the main index.ts file.

v0.39.0

Single enums.gen.ts file

Enums are now exported from a separate file. If you use imports from models.ts, you can change them to enums.gen.ts.

js

import { Enum } from 'client/models'; 
import { Enum } from 'client/enums.gen'; 

Renamed models.ts file

models.ts is now called models.gen.ts. If you use imports from models.ts, you should be able to easily find and replace all instances.

js

import type { Model } from 'client/models'
import type { Model } from 'client/models.gen'

Renamed schemas.ts file

schemas.ts is now called schemas.gen.ts. If you use imports from schemas.ts, you should be able to easily find and replace all instances.

js

import { $Schema } from 'client/schemas'; 
import { $Schema } from 'client/schemas.gen'; 

Renamed services.ts file

services.ts is now called services.gen.ts. If you use imports from services.ts, you should be able to easily find and replace all instances.

js

import { DefaultService } from 'client/services'; 
import { DefaultService } from 'client/services.gen'; 

Deprecated exports from index.ts

Until this release, index.ts file exported all generated artifacts. Starting from this release, enums are no longer exported from index.ts. Models, schemas, and services will continue to be exported from index.ts to avoid a huge migration lift, but we recommend migrating to import groups per artifact type.

js

import { Enum, type Model, $Schema, DefaultService } from 'client'
import { Enum } from 'client/enums.gen'
import type { Model } from 'client/models.gen'
import { $Schema } from 'client/schemas.gen'
import { DefaultService } from 'client/services.gen'

Prefer unknown

Types that cannot be determined will now be generated as unknown instead of any. To dismiss any errors, you can cast your variables back to any, but we recommend updating your code to work with unknown types.

v0.38.0

Renamed write

This config option is now called dryRun (file) or --dry-run (CLI). To restore existing functionality, invert the value, ie. write: true is dryRun: false and write: false is dryRun: true.

v0.36.0

JSON Schema 2020-12

Schemas are exported directly from OpenAPI specification. This means your schemas might change depending on which OpenAPI version you're using. If this release caused a field to be removed, consult the JSON Schema documentation on how to obtain the same value from JSON Schema (eg. required properties).

Renamed exportSchemas

This config option is now called schemas.

v0.35.0

Removed postfixModels

This config option has been removed.

v0.34.0

Single services.ts file

Services are now exported from a single file. If you used imports from individual service files, these will need to be updated to refer to the single services.ts file.

v0.31.1

Merged enums options

useLegacyEnums config option is now enums: 'typescript' and existing enums: true option is now enums: 'javascript'.

v0.31.0

Single models.ts file

TypeScript interfaces are now exported from a single file. If you used imports from individual model files, these will need to be updated to refer to the single models.ts file.

Single schemas.ts file

Schemas are now exported from a single file. If you used imports from individual schema files, these will need to be updated to refer to the single schemas.ts file.

v0.27.38

useOptions: true

By default, generated clients will use a single object argument to pass values to API calls. This is a significant change from the previous default of unspecified array of arguments. If migrating your application in one go isn't feasible, we recommend deprecating your old client and generating a new client.

ts

import { DefaultService } from 'client/services'; // <-- old client with array arguments

import { DefaultService } from 'client_v2/services'; // <-- new client with options argument

This way, you can gradually switch over to the new syntax as you update parts of your code. Once you've removed all instances of client imports, you can safely delete the old client folder and find and replace all client_v2 calls to client.

v0.27.36

exportSchemas: true

By default, we will create schemas from your OpenAPI specification. Use exportSchemas: false to preserve the old behavior.

v0.27.32

Renamed Config interface

This interface is now called UserConfig.

v0.27.29

Renamed openapi CLI command

This command is now called openapi-ts.

v0.27.26

Removed indent

This config option has been removed. Use a code formatter to modify the generated files code style according to your preferences.

v0.27.24

Removed useUnionTypes

This config option has been removed. Generated types will behave the same as useUnionTypes: true before.

OpenAPI TypeScript Codegen

@hey-api/openapi-ts was originally forked from Ferdi Koomen's openapi-typescript-codegen. Therefore, we want you to be able to migrate your projects. Migration should be relatively straightforward if you follow the release notes on this page. Start on v0.27.24 and scroll to the release you're migrating to.