Skip to content

Commit

Permalink
Merge pull request #573 from hey-api/fix/enums-clash
Browse files Browse the repository at this point in the history
fix: deduplicate inlined enums
  • Loading branch information
mrlubos authored May 15, 2024
2 parents 67beaab + 9e6e409 commit 56e31bf
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 21 deletions.
5 changes: 5 additions & 0 deletions .changeset/mean-phones-beg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hey-api/openapi-ts": patch
---

fix: deduplicate inlined enums
10 changes: 2 additions & 8 deletions packages/openapi-ts/src/openApi/v3/parser/getModel.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
import { unescapeName } from '../../../utils/escape';
import { enumMeta } from '../../../utils/enum';
import type { Model, ModelMeta } from '../../common/interfaces/client';
import { getDefault } from '../../common/parser/getDefault';
import { getEnums } from '../../common/parser/getEnums';
import { getPattern } from '../../common/parser/getPattern';
import { ensureValidTypeScriptJavaScriptIdentifier } from '../../common/parser/sanitize';
import { getType } from '../../common/parser/type';
import type { OpenApi } from '../interfaces/OpenApi';
import type { OpenApiSchema } from '../interfaces/OpenApiSchema';
Expand Down Expand Up @@ -99,12 +98,7 @@ export const getModel = ({
model.type = 'string';
model.default = getDefault(definition, model);
if (!model.meta) {
model.meta = {
$ref: `enum/${model.name}`,
name: ensureValidTypeScriptJavaScriptIdentifier(
unescapeName(model.name),
),
};
model.meta = enumMeta(model);
}
return model;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
import { unescapeName } from '../../../utils/escape';
import { enumMeta } from '../../../utils/enum';
import type { OperationParameter } from '../../common/interfaces/client';
import { getDefault } from '../../common/parser/getDefault';
import { getPattern } from '../../common/parser/getPattern';
import { getRef } from '../../common/parser/getRef';
import { getOperationParameterName } from '../../common/parser/operation';
import { ensureValidTypeScriptJavaScriptIdentifier } from '../../common/parser/sanitize';
import { getType } from '../../common/parser/type';
import type { OpenApi } from '../interfaces/OpenApi';
import type { OpenApiParameter } from '../interfaces/OpenApiParameter';
Expand Down Expand Up @@ -110,12 +109,7 @@ export const getOperationParameter = (
(operationParameter.enum.length || operationParameter.enums.length) &&
!operationParameter.meta
) {
operationParameter.meta = {
$ref: `enum/${operationParameter.name}`,
name: ensureValidTypeScriptJavaScriptIdentifier(
unescapeName(operationParameter.name),
),
};
operationParameter.meta = enumMeta(operationParameter);
}
operationParameter.default = model.default;
return operationParameter;
Expand Down
27 changes: 26 additions & 1 deletion packages/openapi-ts/src/utils/enum.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
import type { Enum } from '../openApi';
import type { Enum, Model } from '../openApi';
import { ensureValidTypeScriptJavaScriptIdentifier } from '../openApi/common/parser/sanitize';
import { unescapeName } from './escape';
import { sort } from './sort';
import { unique } from './unique';

/**
Expand Down Expand Up @@ -49,3 +52,25 @@ export const enumValue = (value?: string | number, union: boolean = false) => {
}
return value;
};

export const enumEntry = (enumerator: Enum) => {
const key = enumKey(enumerator.value, enumerator.customName);
const value = enumValue(enumerator.value);
return { key, value };
};

/**
* Represent enum in `meta` object for deduplication
*/
export const enumMeta = (model: Model): Required<Model>['meta'] => {
// serialize enum values in namespace for quick lookup
const serialized = model.enum
.map((enumerator) => enumEntry(enumerator))
.sort((a, b) => sort(a.key, b.key))
.map((enumerator) => `${enumerator.key}=${enumerator.value}`)
.join('&');
return {
$ref: `enum/${model.name}/${serialized}`,
name: ensureValidTypeScriptJavaScriptIdentifier(unescapeName(model.name)),
};
};
5 changes: 2 additions & 3 deletions packages/openapi-ts/src/utils/write/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
import type { Model, OperationParameter, Service } from '../../openApi';
import type { Client } from '../../types/client';
import { getConfig } from '../config';
import { enumKey, enumUnionType, enumValue } from '../enum';
import { enumEntry, enumUnionType } from '../enum';
import { escapeComment } from '../escape';
import { sortByName, sorterByName } from '../sort';
import { operationDataTypeName, operationResponseTypeName } from './services';
Expand Down Expand Up @@ -103,8 +103,7 @@ const processEnum = (client: Client, model: Model, onNode: OnNode) => {
const properties: Record<string | number, unknown> = {};
const comments: Record<string | number, Comments> = {};
model.enum.forEach((enumerator) => {
const key = enumKey(enumerator.value, enumerator.customName);
const value = enumValue(enumerator.value);
const { key, value } = enumEntry(enumerator);
properties[key] = value;
const comment = enumerator.customDescription || enumerator.description;
if (comment) {
Expand Down
2 changes: 1 addition & 1 deletion packages/openapi-ts/test/sample.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const main = async () => {
// export: false,
},
types: {
// enums: 'javascript',
enums: 'typescript',
// include: '^NestedAnyOfArraysNullable',
// name: 'PascalCase',
},
Expand Down

0 comments on commit 56e31bf

Please sign in to comment.