Skip to content

Commit 7ceeffd

Browse files
committed
Fix enums
1 parent 5edfed4 commit 7ceeffd

5 files changed

Lines changed: 96 additions & 6 deletions

File tree

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import type { Enum } from '../client/interfaces/Enum';
2+
import type { Model } from '../client/interfaces/Model';
3+
import { postProcessModelEnums } from './postProcessModelEnums';
4+
5+
const createEnum = (name: string, value: string): Enum => ({
6+
name,
7+
value,
8+
type: 'string',
9+
description: null,
10+
});
11+
12+
const createEnumModel = (name: string, enumValues: Enum[]): Model => ({
13+
name,
14+
export: 'enum',
15+
type: 'string',
16+
base: 'string',
17+
template: null,
18+
link: null,
19+
description: null,
20+
isDefinition: false,
21+
isReadOnly: false,
22+
isNullable: false,
23+
isRequired: false,
24+
imports: [],
25+
enum: enumValues,
26+
enums: [],
27+
properties: [],
28+
});
29+
30+
describe('postProcessModelEnums', () => {
31+
it('merges enum values for duplicate nested enum names', () => {
32+
const gameKind = createEnumModel('kind', [createEnum('GAME', "'game'")]);
33+
const model = createEnumModel('FollowTarget', []);
34+
model.enums = [gameKind, createEnumModel('kind', [createEnum('EVENT', "'event'")]), gameKind];
35+
36+
expect(postProcessModelEnums(model)).toEqual([
37+
createEnumModel('kind', [createEnum('GAME', "'game'"), createEnum('EVENT', "'event'")]),
38+
]);
39+
expect(gameKind.enum).toEqual([createEnum('GAME', "'game'")]);
40+
});
41+
});

src/utils/postProcessModelEnums.ts

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,20 @@ import type { Model } from '../client/interfaces/Model';
55
* @param model The model that is post-processed
66
*/
77
export const postProcessModelEnums = (model: Model): Model[] => {
8-
return model.enums.filter((property, index, arr) => {
9-
return arr.findIndex(item => item.name === property.name) === index;
10-
});
8+
return model.enums.reduce<Model[]>((enums, property) => {
9+
const existing = enums.find(item => item.name === property.name);
10+
if (!existing) {
11+
enums.push({
12+
...property,
13+
enum: [...property.enum],
14+
});
15+
return enums;
16+
}
17+
18+
existing.enum = existing.enum.concat(
19+
property.enum.filter(enumerator => !existing.enum.some(item => item.name === enumerator.name))
20+
);
21+
22+
return enums;
23+
}, []);
1124
};

src/utils/registerHandlebarHelpers.spec.ts

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ import { HttpClient } from '../HttpClient';
44
import { registerHandlebarHelpers } from './registerHandlebarHelpers';
55

66
describe('registerHandlebarHelpers', () => {
7-
it('should register the helpers', () => {
7+
beforeEach(() => {
88
registerHandlebarHelpers({
99
httpClient: HttpClient.FETCH,
1010
useOptions: false,
1111
useUnionTypes: false,
1212
});
13+
});
14+
15+
it('should register the helpers', () => {
1316
const helpers = Object.keys(Handlebars.helpers);
1417
expect(helpers).toContain('ifdef');
1518
expect(helpers).toContain('equals');
@@ -22,4 +25,29 @@ describe('registerHandlebarHelpers', () => {
2225
expect(helpers).toContain('escapeDescription');
2326
expect(helpers).toContain('camelCase');
2427
});
28+
29+
it('should render single-value nested enums as enum members', () => {
30+
const result = Handlebars.helpers.enumerator(
31+
[{ name: 'CURATOR_LIST', value: "'curator_list'", type: 'string', description: null }],
32+
'PlayerGgFollowTarget',
33+
'kind',
34+
{ fn: (value: string) => value }
35+
);
36+
37+
expect(result).toBe('PlayerGgFollowTarget.kind.CURATOR_LIST');
38+
});
39+
40+
it('should render multi-value nested enums as enum types', () => {
41+
const result = Handlebars.helpers.enumerator(
42+
[
43+
{ name: 'GAME', value: "'game'", type: 'string', description: null },
44+
{ name: 'CURATOR_LIST', value: "'curator_list'", type: 'string', description: null },
45+
],
46+
'PlayerGgFollowTarget',
47+
'kind',
48+
{ fn: (value: string) => value }
49+
);
50+
51+
expect(result).toBe('PlayerGgFollowTarget.kind');
52+
});
2553
});

src/utils/registerHandlebarHelpers.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ export const registerHandlebarHelpers = (root: {
1212
useOptions: boolean;
1313
useUnionTypes: boolean;
1414
}): void => {
15+
const isValidPropertyAccess = (value: string): boolean => /^[A-Za-z_$][\w$]*$/.test(value);
16+
1517
Handlebars.registerHelper('ifdef', function (this: any, ...args): string {
1618
const options = args.pop();
1719
if (!args.every(value => !value)) {
@@ -79,6 +81,12 @@ export const registerHandlebarHelpers = (root: {
7981
options: Handlebars.HelperOptions
8082
) {
8183
if (!root.useUnionTypes && parent && name) {
84+
const uniqueEnumerators = enumerators.filter((enumerator, index, arr) => {
85+
return arr.findIndex(item => item.name === enumerator.name) === index;
86+
});
87+
if (uniqueEnumerators.length === 1 && isValidPropertyAccess(uniqueEnumerators[0].name)) {
88+
return `${parent}.${name}.${uniqueEnumerators[0].name}`;
89+
}
8290
return `${parent}.${name}`;
8391
}
8492
return options.fn(

0 commit comments

Comments
 (0)