Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,7 @@ The following flags are supported in the CLI:
| `--path-params-as-types` | | `false` | Allow dynamic string lookups on the `paths` object |
| `--root-types` | | `false` | Exports types from `components` as root level type aliases |
| `--root-types-no-schema-prefix` | | `false` | Do not add "Schema" prefix to types at the root level (should only be used with --root-types) |
| `--root-types-keep-casing` | | `false` | Do not convert root type names to pascal case |
| `--make-paths-enum` | | `false` | Generate ApiPaths enum for all paths |
| `--generate-path-params` | | `false` | Generate path parameters for all paths where they are undefined by schema |

Expand Down
7 changes: 7 additions & 0 deletions packages/openapi-typescript/bin/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ Options
--root-types (optional) Export schemas types at root level
--root-types-no-schema-prefix (optional)
Do not add "Schema" prefix to types at the root level (should only be used with --root-types)
--root-types-keep-casing Keep casing of root types (should only be used with --root-types)
--make-paths-enum Generate ApiPaths enum for all paths
`;

Expand Down Expand Up @@ -63,6 +64,10 @@ if (args.includes("--root-types-no-schema-prefix") && !args.includes("--root-typ
// biome-ignore lint/suspicious/noConsole: this is a CLI
console.warn("--root-types-no-schema-prefix has no effect without --root-types flag");
}
if (args.includes("--root-types-keep-casing") && !args.includes("--root-types")) {
// biome-ignore lint/suspicious/noConsole: this is a CLI
console.warn("--root-types-keep-casing has no effect without --root-types flag");
}

const flags = parser(args, {
boolean: [
Expand All @@ -84,6 +89,7 @@ const flags = parser(args, {
"pathParamsAsTypes",
"rootTypes",
"rootTypesNoSchemaPrefix",
"rootTypesKeepCasing",
"makePathsEnum",
"generatePathParams",
],
Expand Down Expand Up @@ -147,6 +153,7 @@ async function generateSchema(schema, { redocly, silent = false }) {
pathParamsAsTypes: flags.pathParamsAsTypes,
rootTypes: flags.rootTypes,
rootTypesNoSchemaPrefix: flags.rootTypesNoSchemaPrefix,
rootTypesKeepCasing: flags.rootTypesKeepCasing,
makePathsEnum: flags.makePathsEnum,
generatePathParams: flags.generatePathParams,
redocly,
Expand Down
1 change: 1 addition & 0 deletions packages/openapi-typescript/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ export default async function openapiTS(
immutable: options.immutable ?? false,
rootTypes: options.rootTypes ?? false,
rootTypesNoSchemaPrefix: options.rootTypesNoSchemaPrefix ?? false,
rootTypesKeepCasing: options.rootTypesKeepCasing ?? false,
injectFooter: [],
pathParamsAsTypes: options.pathParamsAsTypes ?? false,
postTransform: typeof options.postTransform === "function" ? options.postTransform : undefined,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,14 +101,15 @@ export default function transformComponentsObject(componentsObject: ComponentsOb

if (!shouldSkipEnumSchema) {
const componentKey = changeCase.pascalCase(singularizeComponentKey(key));
let aliasName = `${componentKey}${changeCase.pascalCase(name)}`;
const componentName = ctx.rootTypesKeepCasing && key === "schemas" ? name : changeCase.pascalCase(name);
let aliasName = `${componentKey}${componentName}`;

// Add counter suffix (e.g. "_2") if conflict in name
let conflictCounter = 1;

while (rootTypeAliases[aliasName] !== undefined) {
conflictCounter++;
aliasName = `${componentKey}${changeCase.pascalCase(name)}_${conflictCounter}`;
aliasName = `${componentKey}${componentName}_${conflictCounter}`;
}
const ref = ts.factory.createTypeReferenceNode(`components['${key}']['${name}']`);
if (ctx.rootTypesNoSchemaPrefix && key === "schemas") {
Expand Down
3 changes: 3 additions & 0 deletions packages/openapi-typescript/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -668,6 +668,8 @@ export interface OpenAPITSOptions {
rootTypes?: boolean;
/** (optional) Do not add Schema prefix to types at root level */
rootTypesNoSchemaPrefix?: boolean;
/** (optional) Keep casing of root types */
rootTypesKeepCasing?: boolean;
/**
* Configure Redocly for validation, schema fetching, and bundling
* @see https://redocly.com/docs/cli/configuration/
Expand Down Expand Up @@ -705,6 +707,7 @@ export interface GlobalContext {
propertiesRequiredByDefault: boolean;
rootTypes: boolean;
rootTypesNoSchemaPrefix: boolean;
rootTypesKeepCasing: boolean;
redoc: RedoclyConfig;
silent: boolean;
transform: OpenAPITSOptions["transform"];
Expand Down
1 change: 1 addition & 0 deletions packages/openapi-typescript/test/test-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const DEFAULT_CTX: GlobalContext = {
propertiesRequiredByDefault: false,
rootTypes: false,
rootTypesNoSchemaPrefix: false,
rootTypesKeepCasing: false,
redoc: await createConfig({}, { extends: ["minimal"] }),
resolve($ref) {
return resolveRef({}, $ref, { silent: false });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,49 @@ export type Item = components['schemas']['Item'];
export type Document = components['schemas']['Document'];
export type Error = components['schemas']['Error'];
`,
options: { ...DEFAULT_OPTIONS, rootTypes: true, rootTypesNoSchemaPrefix: true },
options: {
...DEFAULT_OPTIONS,
rootTypes: true,
rootTypesNoSchemaPrefix: true,
},
},
],
[
"options > rootTypes: true but keep casing",
{
given: {
schemas: {
ItemDTO: {
type: "object",
required: ["name", "url"],
properties: {
name: { type: "string" },
url: { type: "string" },
},
},
},
},
want: `{
schemas: {
ItemDTO: {
name: string;
url: string;
};
};
responses: never;
parameters: never;
requestBodies: never;
headers: never;
pathItems: never;
}
export type ItemDTO = components['schemas']['ItemDTO'];
`,
options: {
...DEFAULT_OPTIONS,
rootTypes: true,
rootTypesNoSchemaPrefix: true,
rootTypesKeepCasing: true,
},
},
],
[
Expand Down
Loading