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

Multipart explicit parts #3342

Merged
merged 47 commits into from
Jun 3, 2024
Merged
Show file tree
Hide file tree
Changes from 46 commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
e74bdae
Add new decorators
timotheeguerin May 10, 2024
c1aa4c3
Add other models and decorators
timotheeguerin May 13, 2024
8c5f8b1
Add new types
timotheeguerin May 13, 2024
c45a660
Progress
timotheeguerin May 13, 2024
510f97e
progress
timotheeguerin May 13, 2024
6645dd2
Fix
timotheeguerin May 13, 2024
340c328
basic support in openapi3
timotheeguerin May 13, 2024
20d963c
Boilerplate for encoding
timotheeguerin May 13, 2024
fc1f1cb
Fix
timotheeguerin May 14, 2024
bef6684
Refactor better resolution of property
timotheeguerin May 14, 2024
922d86b
Standarized handling of http properties
timotheeguerin May 14, 2024
4299e33
fix
timotheeguerin May 14, 2024
15fb6a7
Include headers
timotheeguerin May 14, 2024
4eceb53
rename
timotheeguerin May 14, 2024
78a74b4
.
timotheeguerin May 14, 2024
1ea94bd
Renmae
timotheeguerin May 14, 2024
118e4e0
Add nameless part validation for form-data
timotheeguerin May 14, 2024
2790391
Resolve correct
timotheeguerin May 14, 2024
c486f63
omit uncessary contnet types
timotheeguerin May 14, 2024
47fe13b
Get content type from file
timotheeguerin May 14, 2024
98f1a78
Multipart http tests
timotheeguerin May 14, 2024
574a98e
Initial openapi3 tests
timotheeguerin May 14, 2024
84dc941
Merge branch 'main' into feature/multipart-v2
timotheeguerin May 14, 2024
506fa04
Create feature-multipart-v2-2024-4-14-22-58-52.md
timotheeguerin May 14, 2024
62704d1
Create feature-multipart-v2-2024-4-14-23-5-59.md
timotheeguerin May 14, 2024
fee0142
ADd more tests
timotheeguerin May 14, 2024
aa429ad
tweaks
timotheeguerin May 14, 2024
e39a029
Merge branch 'feature/multipart-v2' of https://github.com/timotheegue…
timotheeguerin May 14, 2024
8bccf0a
Missing
timotheeguerin May 14, 2024
f83b5c1
Sample
timotheeguerin May 14, 2024
644edff
Fix
timotheeguerin May 14, 2024
d9a9ee8
Fix deprecation
timotheeguerin May 14, 2024
2ef886c
fix types
timotheeguerin May 15, 2024
b69d897
Regen docs
timotheeguerin May 15, 2024
d0ebc08
Merge branch 'main' into feature/multipart-v2
timotheeguerin May 17, 2024
727c997
Merge branch 'main' into feature/multipart-v2
timotheeguerin May 17, 2024
cb1d07b
Merge branch 'main' of https://github.com/microsoft/typespec into fea…
timotheeguerin May 22, 2024
a63a6f6
regen docs
timotheeguerin May 22, 2024
54b2abe
Fix
timotheeguerin May 22, 2024
f999aaf
Split contenttype into its own property
timotheeguerin May 22, 2024
f34ef31
Merge branch 'main' into feature/multipart-v2
timotheeguerin May 23, 2024
3f6193b
fix
timotheeguerin May 23, 2024
e6aa61c
fix
timotheeguerin May 24, 2024
77037e0
Merge branch 'main' of https://github.com/microsoft/typespec into fea…
timotheeguerin Jun 3, 2024
23a6709
Fix deprecatged parmaeter not set
timotheeguerin Jun 3, 2024
0a08dbc
fix
timotheeguerin Jun 3, 2024
f233546
Merge branch 'main' of https://github.com/microsoft/typespec into fea…
timotheeguerin Jun 3, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .chronus/changes/feature-multipart-v2-2024-4-14-16-27-48.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
changeKind: internal
packages:
- "@typespec/rest"
---

15 changes: 15 additions & 0 deletions .chronus/changes/feature-multipart-v2-2024-4-14-22-58-52.md
timotheeguerin marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: feature
packages:
- "@typespec/http"
---

Add new multipart handling. Using `@multipartBody` with `HttpPart<Type, Options>`. See [multipart docs] for more information https://typespec.io/docs/next/libraries/http/multipart

```tsp
op upload(@header contentType: "multipart/mixed", @multipartBody body: {
name: HttpPart<string>;
avatar: HttpPart<bytes>[];
}): void;
```
8 changes: 8 additions & 0 deletions .chronus/changes/feature-multipart-v2-2024-4-14-23-5-59.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
# Change versionKind to one of: internal, fix, dependencies, feature, deprecation, breaking
changeKind: fix
packages:
- "@typespec/openapi3"
---

Add support for new multipart constructs in http library
1 change: 1 addition & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"**/node_modules/**": true,
"packages/compiler/templates/__snapshots__/**": true,
"packages/website/versioned_docs/**": true,
"packages/http-client-csharp/**/Generated/**": true,
"packages/samples/scratch/**": false // Those files are in gitignore but we still want to search for them
},
"files.exclude": {
Expand Down
43 changes: 43 additions & 0 deletions docs/libraries/http/reference/data-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,20 @@ model TypeSpec.Http.CreatedResponse
| ---------- | ----- | ---------------- |
| statusCode | `201` | The status code. |

### `File` {#TypeSpec.Http.File}

```typespec
model TypeSpec.Http.File
```

#### Properties

| Name | Type | Description |
| ------------ | -------- | ----------- |
| contentType? | `string` | |
| filename? | `string` | |
| contents | `bytes` | |

### `ForbiddenResponse` {#TypeSpec.Http.ForbiddenResponse}

Access is forbidden.
Expand Down Expand Up @@ -234,6 +248,35 @@ model TypeSpec.Http.HeaderOptions
| name? | `string` | Name of the header when sent over HTTP. |
| format? | `"csv" \| "multi" \| "tsv" \| "ssv" \| "pipes" \| "simple" \| "form"` | Determines the format of the array if type array is used. |

### `HttpPart` {#TypeSpec.Http.HttpPart}

```typespec
model TypeSpec.Http.HttpPart<Type, Options>
```

#### Template Parameters

| Name | Description |
| ------- | ----------- |
| Type | |
| Options | |

#### Properties

None

### `HttpPartOptions` {#TypeSpec.Http.HttpPartOptions}

```typespec
model TypeSpec.Http.HttpPartOptions
```

#### Properties

| Name | Type | Description |
| ----- | -------- | ------------------------------------------- |
| name? | `string` | Name of the part when using the array form. |

### `ImplicitFlow` {#TypeSpec.Http.ImplicitFlow}

Implicit flow
Expand Down
26 changes: 26 additions & 0 deletions docs/libraries/http/reference/decorators.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,32 @@ Specify if inapplicable metadata should be included in the payload for the given
| ----- | ----------------- | --------------------------------------------------------------- |
| value | `valueof boolean` | If true, inapplicable metadata will be included in the payload. |

### `@multipartBody` {#@TypeSpec.Http.multipartBody}

```typespec
@TypeSpec.Http.multipartBody
```

#### Target

`ModelProperty`

#### Parameters

None

#### Examples

```tsp
op upload(
@header `content-type`: "multipart/form-data",
@multipartBody body: {
fullName: HttpPart<string>;
headShots: HttpPart<Image>[];
},
): void;
```

### `@patch` {#@TypeSpec.Http.patch}

Specify the HTTP verb for the target operation to be `PATCH`.
Expand Down
4 changes: 4 additions & 0 deletions docs/libraries/http/reference/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ npm install --save-peer @typespec/http
- [`@head`](./decorators.md#@TypeSpec.Http.head)
- [`@header`](./decorators.md#@TypeSpec.Http.header)
- [`@includeInapplicableMetadataInPayload`](./decorators.md#@TypeSpec.Http.includeInapplicableMetadataInPayload)
- [`@multipartBody`](./decorators.md#@TypeSpec.Http.multipartBody)
- [`@patch`](./decorators.md#@TypeSpec.Http.patch)
- [`@path`](./decorators.md#@TypeSpec.Http.path)
- [`@post`](./decorators.md#@TypeSpec.Http.post)
Expand All @@ -66,8 +67,11 @@ npm install --save-peer @typespec/http
- [`ClientCredentialsFlow`](./data-types.md#TypeSpec.Http.ClientCredentialsFlow)
- [`ConflictResponse`](./data-types.md#TypeSpec.Http.ConflictResponse)
- [`CreatedResponse`](./data-types.md#TypeSpec.Http.CreatedResponse)
- [`File`](./data-types.md#TypeSpec.Http.File)
- [`ForbiddenResponse`](./data-types.md#TypeSpec.Http.ForbiddenResponse)
- [`HeaderOptions`](./data-types.md#TypeSpec.Http.HeaderOptions)
- [`HttpPart`](./data-types.md#TypeSpec.Http.HttpPart)
- [`HttpPartOptions`](./data-types.md#TypeSpec.Http.HttpPartOptions)
- [`ImplicitFlow`](./data-types.md#TypeSpec.Http.ImplicitFlow)
- [`LocationHeader`](./data-types.md#TypeSpec.Http.LocationHeader)
- [`MovedResponse`](./data-types.md#TypeSpec.Http.MovedResponse)
Expand Down
27 changes: 27 additions & 0 deletions packages/http/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ Available ruleSets:
- [`@head`](#@head)
- [`@header`](#@header)
- [`@includeInapplicableMetadataInPayload`](#@includeinapplicablemetadatainpayload)
- [`@multipartBody`](#@multipartbody)
- [`@patch`](#@patch)
- [`@path`](#@path)
- [`@post`](#@post)
Expand Down Expand Up @@ -272,6 +273,32 @@ Specify if inapplicable metadata should be included in the payload for the given
| ----- | ----------------- | --------------------------------------------------------------- |
| value | `valueof boolean` | If true, inapplicable metadata will be included in the payload. |

#### `@multipartBody`

```typespec
@TypeSpec.Http.multipartBody
```

##### Target

`ModelProperty`

##### Parameters

None

##### Examples

```tsp
op upload(
@header `content-type`: "multipart/form-data",
@multipartBody body: {
fullName: HttpPart<string>;
headShots: HttpPart<Image>[];
},
): void;
```

#### `@patch`

Specify the HTTP verb for the target operation to be `PATCH`.
Expand Down
11 changes: 10 additions & 1 deletion packages/http/generated-defs/TypeSpec.Http.Private.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,12 @@
import type { DecoratorContext, Model } from "@typespec/compiler";
import type { DecoratorContext, Model, Type } from "@typespec/compiler";

export type PlainDataDecorator = (context: DecoratorContext, target: Model) => void;

export type HttpFileDecorator = (context: DecoratorContext, target: Model) => void;

export type HttpPartDecorator = (
context: DecoratorContext,
target: Model,
type: Type,
options: unknown
) => void;
17 changes: 17 additions & 0 deletions packages/http/generated-defs/TypeSpec.Http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,23 @@ export type BodyRootDecorator = (context: DecoratorContext, target: ModelPropert
*/
export type BodyIgnoreDecorator = (context: DecoratorContext, target: ModelProperty) => void;

/**
*
*
*
* @example
* ```tsp
* op upload(
* @header `content-type`: "multipart/form-data",
* @multipartBody body: {
* fullName: HttpPart<string>,
* headShots: HttpPart<Image>[]
* }
* ): void;
* ```
*/
export type MultipartBodyDecorator = (context: DecoratorContext, target: ModelProperty) => void;

/**
* Specify the HTTP verb for the target operation to be `GET`.
*
Expand Down
4 changes: 4 additions & 0 deletions packages/http/generated-defs/TypeSpec.Http.ts-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
$head,
$header,
$includeInapplicableMetadataInPayload,
$multipartBody,
$patch,
$path,
$post,
Expand All @@ -28,6 +29,7 @@ import type {
HeadDecorator,
HeaderDecorator,
IncludeInapplicableMetadataInPayloadDecorator,
MultipartBodyDecorator,
PatchDecorator,
PathDecorator,
PostDecorator,
Expand All @@ -48,6 +50,7 @@ type Decorators = {
$path: PathDecorator;
$bodyRoot: BodyRootDecorator;
$bodyIgnore: BodyIgnoreDecorator;
$multipartBody: MultipartBodyDecorator;
$get: GetDecorator;
$put: PutDecorator;
$post: PostDecorator;
Expand All @@ -70,6 +73,7 @@ const _: Decorators = {
$path,
$bodyRoot,
$bodyIgnore,
$multipartBody,
$get,
$put,
$post,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,21 @@ extern dec bodyRoot(target: ModelProperty);
*/
extern dec bodyIgnore(target: ModelProperty);

/**
* @example
*
* ```tsp
* op upload(
* @header `content-type`: "multipart/form-data",
* @multipartBody body: {
* fullName: HttpPart<string>,
* headShots: HttpPart<Image>[]
* }
* ): void;
* ```
*/
extern dec multipartBody(target: ModelProperty);

/**
* Specify the status code for this response. Property type must be a status code integer or a union of status code integer.
*
Expand Down Expand Up @@ -291,10 +306,3 @@ extern dec route(
* ```
*/
extern dec sharedRoute(target: Operation);

/**
* Private decorators. Those are meant for internal use inside Http types only.
*/
namespace Private {
extern dec plainData(target: TypeSpec.Reflection.Model);
}
18 changes: 17 additions & 1 deletion packages/http/lib/http.tsp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import "../dist/src/index.js";
import "./http-decorators.tsp";
import "./decorators.tsp";
import "./private.decorators.tsp";
import "./auth.tsp";

namespace TypeSpec.Http;
Expand Down Expand Up @@ -104,3 +105,18 @@ model ConflictResponse is Response<409>;
model PlainData<Data> {
...Data;
}

@Private.httpFile
model File {
contentType?: string;
filename?: string;
contents: bytes;
}

model HttpPartOptions {
/** Name of the part when using the array form. */
name?: string;
}

@Private.httpPart(Type, Options)
model HttpPart<Type, Options extends valueof HttpPartOptions = #{}> {}
14 changes: 14 additions & 0 deletions packages/http/lib/private.decorators.tsp
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import "../dist/src/private.decorators.js";

/**
* Private decorators. Those are meant for internal use inside Http types only.
*/
namespace TypeSpec.Http.Private;

extern dec plainData(target: TypeSpec.Reflection.Model);
extern dec httpFile(target: TypeSpec.Reflection.Model);
extern dec httpPart(
target: TypeSpec.Reflection.Model,
type: unknown,
options: valueof HttpPartOptions
);
Loading
Loading