Skip to content

Commit 96404a5

Browse files
orhanhenrikabduvaliiev
authored andcommitted
Add support for converting constant size arrays into tuples
1 parent ee80288 commit 96404a5

19 files changed

+77
-6
lines changed

bin/index.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ const params = program
1616
.option('--name <value>', 'Custom client class name')
1717
.option('--useOptions', 'Use options instead of arguments')
1818
.option('--useUnionTypes', 'Use union types instead of enums')
19+
.option('--useTuples', 'Whether to convert constant size arrays to tuples.')
1920
.option('--exportCore <value>', 'Write core files to disk', true)
2021
.option('--exportServices <value>', 'Write services to disk', true)
2122
.option('--exportModels <value>', 'Write models to disk', true)
@@ -38,6 +39,7 @@ if (OpenAPI) {
3839
clientName: params.name,
3940
useOptions: params.useOptions,
4041
useUnionTypes: params.useUnionTypes,
42+
useTuples: params.useTuples,
4143
exportCore: JSON.parse(params.exportCore) === true,
4244
exportServices: JSON.parse(params.exportServices) === true,
4345
exportModels: JSON.parse(params.exportModels) === true,

rollup.config.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ const handlebarsPlugin = () => ({
3939
escapeComment: true,
4040
escapeDescription: true,
4141
camelCase: true,
42+
repeatTimes: true,
4243
},
4344
});
4445
return `export default ${templateSpec};`;

src/client/interfaces/Model.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ export interface Model extends Schema {
1515
enum: Enum[];
1616
enums: Model[];
1717
properties: Model[];
18+
isConstantSize?: boolean;
1819
}

src/index.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ export type Options = {
2020
clientName?: string;
2121
useOptions?: boolean;
2222
useUnionTypes?: boolean;
23+
useTuples?: boolean;
2324
exportCore?: boolean;
2425
exportServices?: boolean;
2526
exportModels?: boolean;
@@ -60,6 +61,7 @@ export const generate = async ({
6061
clientName,
6162
useOptions = false,
6263
useUnionTypes = false,
64+
useTuples = false,
6365
exportCore = true,
6466
exportServices = true,
6567
exportModels = true,
@@ -77,6 +79,7 @@ export const generate = async ({
7779
httpClient,
7880
useUnionTypes,
7981
useOptions,
82+
useTuples,
8083
});
8184

8285
switch (openApiVersion) {
@@ -91,6 +94,7 @@ export const generate = async ({
9194
httpClient,
9295
useOptions,
9396
useUnionTypes,
97+
useTuples,
9498
exportCore,
9599
exportServices,
96100
exportModels,
@@ -116,6 +120,7 @@ export const generate = async ({
116120
httpClient,
117121
useOptions,
118122
useUnionTypes,
123+
useTuples,
119124
exportCore,
120125
exportServices,
121126
exportModels,

src/openApi/v3/parser/getModel.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,28 @@ export const getModel = (
7373
}
7474

7575
if (definition.type === 'array' && definition.items) {
76+
model.export = 'array';
77+
model.isConstantSize = Boolean(
78+
definition.minItems && definition.maxItems && definition.minItems === definition.maxItems
79+
);
80+
7681
if (definition.items.$ref) {
7782
const arrayItems = getType(definition.items.$ref);
78-
model.export = 'array';
7983
model.type = arrayItems.type;
8084
model.base = arrayItems.base;
8185
model.template = arrayItems.template;
8286
model.imports.push(...arrayItems.imports);
8387
model.default = getModelDefault(definition, model);
84-
return model;
8588
} else {
8689
const arrayItems = getModel(openApi, definition.items);
87-
model.export = 'array';
8890
model.type = arrayItems.type;
8991
model.base = arrayItems.base;
9092
model.template = arrayItems.template;
9193
model.link = arrayItems;
9294
model.imports.push(...arrayItems.imports);
9395
model.default = getModelDefault(definition, model);
94-
return model;
9596
}
97+
return model;
9698
}
9799

98100
if (

src/openApi/v3/parser/getModelProperties.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ export const getModelProperties = (
9898
enum: model.enum,
9999
enums: model.enums,
100100
properties: model.properties,
101+
isConstantSize: model.isConstantSize,
101102
...propertyValues,
102103
});
103104
}

src/templates/partials/type.hbs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,17 @@
55
{{else equals export 'enum'}}
66
{{>typeEnum}}
77
{{else equals export 'array'}}
8+
9+
{{~#if @root.useTuples~}}
10+
{{~#if isConstantSize ~}}
11+
{{>typeTuple}}
12+
{{~else~}}
813
{{>typeArray}}
14+
{{~/if~}}
15+
{{~else~}}
16+
{{>typeArray}}
17+
{{~/if~}}
18+
919
{{else equals export 'dictionary'}}
1020
{{>typeDictionary}}
1121
{{else equals export 'one-of'}}

src/templates/partials/typeTuple.hbs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
{{~#if link~}}
2+
3+
[
4+
{{~#repeatTimes minItems~}}
5+
{{>type link}}
6+
{{#unless isLast}}, {{/unless}}
7+
{{~/repeatTimes~}}
8+
]
9+
{{>isNullable}}
10+
11+
{{~else~}}
12+
13+
[
14+
{{~#repeatTimes minItems~}}
15+
{{>base}}
16+
{{#unless isLast}}, {{/unless}}
17+
{{~/repeatTimes~}}
18+
]
19+
{{>isNullable}}
20+
21+
{{~/if~}}

src/utils/registerHandlebarHelpers.spec.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ describe('registerHandlebarHelpers', () => {
99
httpClient: HttpClient.FETCH,
1010
useOptions: false,
1111
useUnionTypes: false,
12+
useTuples: false,
1213
});
1314
const helpers = Object.keys(Handlebars.helpers);
1415
expect(helpers).toContain('ifdef');

src/utils/registerHandlebarHelpers.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const registerHandlebarHelpers = (root: {
1111
httpClient: HttpClient;
1212
useOptions: boolean;
1313
useUnionTypes: boolean;
14+
useTuples: boolean;
1415
}): void => {
1516
Handlebars.registerHelper('ifdef', function (this: any, ...args): string {
1617
const options = args.pop();
@@ -104,4 +105,16 @@ export const registerHandlebarHelpers = (root: {
104105
Handlebars.registerHelper('camelCase', function (value: string): string {
105106
return camelCase(value);
106107
});
108+
109+
Handlebars.registerHelper('repeatTimes', function (this: any, n, block) {
110+
let accum = '';
111+
for (let i = 0; i < n; ++i) {
112+
const t = Handlebars.createFrame(this);
113+
if (i == n - 1) {
114+
t.isLast = true;
115+
}
116+
accum += block.fn(t);
117+
}
118+
return accum;
119+
});
107120
};

0 commit comments

Comments
 (0)