Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support multipart form data encoding #3514

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ export function convertHttpRequestBody({
wireValue: property.key,
name: property.key
}),
isOptional: property.isOptional
isOptional: property.isOptional,
contentType: property.contentType
})
);
} else {
Expand All @@ -61,7 +62,8 @@ export function convertHttpRequestBody({
wireValue: property.key,
name: property.key
}),
isOptional: property.isOptional
isOptional: property.isOptional,
contentType: property.contentType
})
);
}
Expand Down Expand Up @@ -147,6 +149,7 @@ function convertInlinedRequestProperty({
wireValue: propertyKey,
name: getPropertyName({ propertyKey, property: propertyDefinition }).name
}),
valueType: file.parseTypeReference(propertyDefinition)
valueType: file.parseTypeReference(propertyDefinition),
contentType: typeof propertyDefinition !== "string" ? propertyDefinition["content-type"] : undefined
};
}
1 change: 1 addition & 0 deletions packages/cli/openapi-ir-sdk/fern/definition/finalIr.yml
Original file line number Diff line number Diff line change
Expand Up @@ -320,6 +320,7 @@ types:
properties:
key: string
schema: MultipartSchema
contentType: optional<string>

FileSchema:
properties:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ import * as FernOpenapiIr from "../../..";
export interface MultipartRequestProperty extends FernOpenapiIr.WithDescription {
key: string;
schema: FernOpenapiIr.MultipartSchema;
contentType: string | undefined;
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,14 @@ export const MultipartRequestProperty: core.serialization.ObjectSchema<
.objectWithoutOptionalProperties({
key: core.serialization.string(),
schema: core.serialization.lazy(async () => (await import("../../..")).MultipartSchema),
contentType: core.serialization.string().optional(),
})
.extend(core.serialization.lazyObject(async () => (await import("../../..")).WithDescription));

export declare namespace MultipartRequestProperty {
interface Raw extends serializers.WithDescription.Raw {
key: string;
schema: serializers.MultipartSchema.Raw;
contentType?: string | null;
}
}
30 changes: 24 additions & 6 deletions packages/cli/openapi-ir-to-fern/src/buildEndpoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -428,16 +428,19 @@ function getRequest({
} else {
// multipart
const properties = Object.fromEntries(
request.properties.map((property) => {
request.properties.map((property): [string, RawSchemas.ObjectPropertySchema] => {
if (property.schema.type === "file") {
const fileType = property.schema.isArray ? "list<file>" : "file";
return [property.key, property.schema.isOptional ? `optional<${fileType}>` : fileType];
} else {
const propertyTypeReference = buildTypeReference({
schema: property.schema.value,
fileContainingReference: declarationFile,
context
});
const propertyTypeReference = withContentType(
buildTypeReference({
schema: property.schema.value,
fileContainingReference: declarationFile,
context
}),
property.contentType
);
return [property.key, propertyTypeReference];
}
})
Expand All @@ -456,3 +459,18 @@ function getRequest({
};
}
}

function withContentType(
typeReference: RawSchemas.TypeReferenceWithDocsSchema,
contentType: string | undefined
): RawSchemas.ObjectPropertySchema {
if (contentType == null) {
return typeReference;
}

return {
type: getTypeFromTypeReference(typeReference),
docs: getDocsFromTypeReference(typeReference),
"content-type": contentType
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -6516,6 +6516,7 @@ exports[`open api parser deel parse open api 1`] = `
"name": null,
"properties": [
{
"contentType": null,
"description": null,
"key": "file",
"schema": {
Expand Down Expand Up @@ -6734,6 +6735,7 @@ exports[`open api parser deel parse open api 1`] = `
"name": null,
"properties": [
{
"contentType": null,
"description": null,
"key": "file",
"schema": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ exports[`file-upload file-upload parse open api 1`] = `
"name": null,
"properties": [
{
"contentType": null,
"description": "The file to upload",
"key": "file",
"schema": {
Expand All @@ -49,6 +50,7 @@ exports[`file-upload file-upload parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "maybe_file",
"schema": {
Expand All @@ -58,6 +60,7 @@ exports[`file-upload file-upload parse open api 1`] = `
},
},
{
"contentType": null,
"description": "The list of files to upload",
"key": "file_list",
"schema": {
Expand All @@ -67,6 +70,7 @@ exports[`file-upload file-upload parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "maybe_file_list",
"schema": {
Expand All @@ -76,6 +80,7 @@ exports[`file-upload file-upload parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "maybe_files_allof_list",
"schema": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2349,6 +2349,7 @@ exports[`open api parser hathora parse open api 1`] = `
"name": null,
"properties": [
{
"contentType": null,
"description": null,
"key": "file",
"schema": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ exports[`optional-multipart optional-multipart parse open api 1`] = `
"name": "SpeechBody",
"properties": [
{
"contentType": null,
"description": "The audio file.",
"key": "audio",
"schema": {
Expand All @@ -101,6 +102,7 @@ exports[`optional-multipart optional-multipart parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "model_id",
"schema": {
Expand All @@ -127,6 +129,7 @@ exports[`optional-multipart optional-multipart parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "voice_settings",
"schema": {
Expand Down Expand Up @@ -278,6 +281,7 @@ exports[`optional-multipart optional-multipart parse open api 1`] = `
"name": "SpeechBodyStream",
"properties": [
{
"contentType": null,
"description": "The audio file.",
"key": "audio",
"schema": {
Expand All @@ -287,6 +291,7 @@ exports[`optional-multipart optional-multipart parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "model_id",
"schema": {
Expand All @@ -313,6 +318,7 @@ exports[`optional-multipart optional-multipart parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "voice_settings",
"schema": {
Expand All @@ -339,6 +345,7 @@ exports[`optional-multipart optional-multipart parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "my_enum",
"schema": {
Expand Down Expand Up @@ -386,6 +393,7 @@ exports[`optional-multipart optional-multipart parse open api 1`] = `
},
},
{
"contentType": null,
"description": null,
"key": "my_ref",
"schema": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37052,6 +37052,7 @@ You will be assigned as owner of the new team automatically.",
"name": null,
"properties": [
{
"contentType": null,
"description": null,
"key": "file",
"schema": {
Expand Down Expand Up @@ -38291,6 +38292,7 @@ You will be assigned as owner of the new team automatically.",
"name": null,
"properties": [
{
"contentType": null,
"description": null,
"key": "file",
"schema": {
Expand Down Expand Up @@ -39524,6 +39526,7 @@ You will be assigned as owner of the new team automatically.",
"name": null,
"properties": [
{
"contentType": null,
"description": null,
"key": "file",
"schema": {
Expand Down Expand Up @@ -42876,6 +42879,7 @@ The client secret is auto generated on the server and returned. The client does
"name": null,
"properties": [
{
"contentType": null,
"description": null,
"key": "file",
"schema": {
Expand Down