Skip to content

Commit 256102e

Browse files
committed
fix: support array of 1 for query parameter arrays
- introduce `x-alpha-transform` concept, allowing for a arbitrary transformation function to be applied to a schema - not yet supported by `joi` - not yet supported by `type-builder` - only really useful for this specific case so far - detect query parameters of an array type, and parse as a `T | T[]`, and then transform to a `T[]` for convenience - does not yet support `$ref`d schemas properly relates #217
1 parent 2671744 commit 256102e

File tree

7 files changed

+59
-5
lines changed

7 files changed

+59
-5
lines changed

packages/openapi-code-generator/src/core/input.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,7 @@ function normalizeSchemaObject(
368368
const base: IRModelBase = {
369369
nullable: schemaObject.nullable || false,
370370
readOnly: schemaObject.readOnly || false,
371+
"x-alpha-transform": schemaObject["x-alpha-transform"],
371372
}
372373

373374
switch (schemaObject.type) {

packages/openapi-code-generator/src/core/openapi-types-normalized.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export interface IRModelBase {
88
// Note: meaningless for top level objects, maybe we can exclude these somehow in that case
99
nullable: boolean /* false */
1010
readOnly: boolean /* false */
11+
12+
"x-alpha-transform"?: string | undefined
1113
}
1214

1315
export type IRModelNumericFormat = "int32" | "int64" | "float" | "double"

packages/openapi-code-generator/src/core/openapi-types.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,6 +248,9 @@ export interface Schema {
248248
externalDocs?: ExternalDocumentation | undefined
249249
deprecated?: boolean | undefined
250250
// xml?: XML | undefined
251+
252+
// TODO: not yet supported by type-builder or joi
253+
"x-alpha-transform"?: string | undefined
251254
}
252255

253256
export interface Discriminator {

packages/openapi-code-generator/src/typescript/common/schema-builders/abstract-schema-builder.ts

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,29 @@ export abstract class AbstractSchemaBuilder<
163163
if (parameter.required) {
164164
model.required.push(parameter.name)
165165
}
166-
model.properties[parameter.name] = parameter.schema
166+
167+
// TODO: support $ref properly
168+
if (
169+
parameter.in === "query" &&
170+
!isRef(parameter.schema) &&
171+
parameter.schema.type === "array"
172+
) {
173+
model.properties[parameter.name] = {
174+
type: "object",
175+
additionalProperties: false,
176+
properties: {},
177+
readOnly: false,
178+
allOf: [],
179+
nullable: false,
180+
oneOf: [],
181+
required: [],
182+
anyOf: [parameter.schema, parameter.schema.items],
183+
"x-alpha-transform": ((it: unknown) =>
184+
Array.isArray(it) || it === undefined ? it : [it]).toString(),
185+
}
186+
} else {
187+
model.properties[parameter.name] = parameter.schema
188+
}
167189
}
168190

169191
return this.fromModel(model, true, true)
@@ -304,6 +326,10 @@ export abstract class AbstractSchemaBuilder<
304326

305327
result = required ? this.required(result) : this.optional(result)
306328

329+
if (model["x-alpha-transform"]) {
330+
result = this.transform(result, model["x-alpha-transform"])
331+
}
332+
307333
return result
308334
}
309335

@@ -327,6 +353,11 @@ export abstract class AbstractSchemaBuilder<
327353

328354
protected abstract union(schemas: string[]): string
329355

356+
protected abstract transform(
357+
schema: string,
358+
transformation: string | ((it: unknown) => unknown),
359+
): string
360+
330361
protected abstract nullable(schema: string): string
331362

332363
protected abstract optional(schema: string): string

packages/openapi-code-generator/src/typescript/common/schema-builders/joi-schema-builder.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,14 @@ export class JoiBuilder extends AbstractSchemaBuilder<
108108
.join(".")
109109
}
110110

111+
protected transform(
112+
schema: string,
113+
transformation: string | ((it: unknown) => unknown),
114+
) {
115+
// TODO: is it possible to do arbitrary transformations with `joi`?
116+
return schema
117+
}
118+
111119
protected nullable(schema: string): string {
112120
return [schema, "allow(null)"].join(".")
113121
}

packages/openapi-code-generator/src/typescript/common/schema-builders/zod-schema-builder.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,15 @@ export class ZodBuilder extends AbstractSchemaBuilder<
133133
.join(".")
134134
}
135135

136+
protected transform(
137+
schema: string,
138+
transformation: string | ((it: unknown) => unknown),
139+
) {
140+
return [schema, `transform(${transformation.toString()})`]
141+
.filter(isDefined)
142+
.join(".")
143+
}
144+
136145
protected nullable(schema: string): string {
137146
return [schema, "nullable()"].filter(isDefined).join(".")
138147
}

packages/openapi-code-generator/src/typescript/typescript-koa/typescript-koa.generator.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ import {
2525

2626
function reduceParamsToOpenApiSchema(parameters: IRParameter[]): IRModelObject {
2727
return parameters.reduce(
28-
(acc, parameter) => {
29-
acc.properties[parameter.name] = parameter.schema
28+
(model, parameter) => {
29+
model.properties[parameter.name] = parameter.schema
3030

3131
if (parameter.required) {
32-
acc.required.push(parameter.name)
32+
model.required.push(parameter.name)
3333
}
3434

35-
return acc
35+
return model
3636
},
3737
{
3838
type: "object",

0 commit comments

Comments
 (0)