@typespec/http 0.68.0-dev.6 → 0.68.0-dev.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/main.tsp CHANGED
@@ -106,11 +106,154 @@ model PlainData<Data> {
106
106
  ...Data;
107
107
  }
108
108
 
109
+ /**
110
+ * A file in an HTTP request, response, or multipart payload.
111
+ *
112
+ * Files have a special meaning that the HTTP library understands. When the body of an HTTP request, response,
113
+ * or multipart payload is _effectively_ an instance of `TypeSpec.Http.File` or any type that extends it, the
114
+ * operation is treated as a file upload or download.
115
+ *
116
+ * When using file bodies, the fields of the file model are defined to come from particular locations by default:
117
+ *
118
+ * - `contentType`: The `Content-Type` header of the request, response, or multipart payload (CANNOT be overridden or changed).
119
+ * - `contents`: The body of the request, response, or multipart payload (CANNOT be overridden or changed).
120
+ * - `filename`: The `filename` parameter value of the `Content-Disposition` header of the response or multipart payload
121
+ * (MAY be overridden or changed).
122
+ *
123
+ * A File may be used as a normal structured JSON object in a request or response, if the request specifies an explicit
124
+ * `Content-Type` header. In this case, the entire File model is serialized as if it were any other model. In a JSON payload,
125
+ * it will have a structure like:
126
+ *
127
+ * ```
128
+ * {
129
+ * "contentType": <string?>,
130
+ * "filename": <string?>,
131
+ * "contents": <string, base64>
132
+ * }
133
+ * ```
134
+ *
135
+ * The `contentType` _within_ the file defines what media types the data inside the file can be, but if the specification
136
+ * defines a `Content-Type` for the payload as HTTP metadata, that `Content-Type` metadata defines _how the file is
137
+ * serialized_. See the examples below for more information.
138
+ *
139
+ * NOTE: The `filename` and `contentType` fields are optional. Furthermore, the default location of `filename`
140
+ * (`Content-Disposition: <disposition>; filename=<filename>`) is only valid in HTTP responses and multipart payloads. If
141
+ * you wish to send the `filename` in a request, you must use HTTP metadata decorators to describe the location of the
142
+ * `filename` field. You can combine the metadata decorators with `@visibility` to control when the `filename` location
143
+ * is overridden, as shown in the examples below.
144
+ *
145
+ * @template ContentType The allowed media (MIME) types of the file contents.
146
+ * @template Contents The type of the file contents. This can be `string`, `bytes`, or any scalar that extends them.
147
+ *
148
+ * @example
149
+ * ```tsp
150
+ * // Download a file
151
+ * @get op download(): File;
152
+ *
153
+ * // Upload a file
154
+ * @post op upload(@bodyRoot file: File): void;
155
+ * ```
156
+ *
157
+ * @example
158
+ * ```tsp
159
+ * // Upload and download files in a multipart payload
160
+ * op multipartFormDataUpload(
161
+ * @multipartBody fields: {
162
+ * files: HttpPart<File>[];
163
+ * },
164
+ * ): void;
165
+ *
166
+ * op multipartFormDataDownload(): {
167
+ * @multipartBody formFields: {
168
+ * files: HttpPart<File>[];
169
+ * }
170
+ * };
171
+ * ```
172
+ *
173
+ * @example
174
+ * ```tsp
175
+ * // Declare a custom type of text file, where the filename goes in the path
176
+ * // in requests.
177
+ * model SpecFile extends File<"application/json" | "application/yaml", string> {
178
+ * // Provide a header that contains the name of the file when created or updated
179
+ * @header("x-filename")
180
+ * @path filename: string;
181
+ * }
182
+ *
183
+ * @get op downloadSpec(@path name: string): SpecFile;
184
+ *
185
+ * @post op uploadSpec(@bodyRoot spec: SpecFile): void;
186
+ * ```
187
+ *
188
+ * @example
189
+ * ```tsp
190
+ * // Declare a custom type of binary file
191
+ * model ImageFile extends File {
192
+ * contentType: "image/png" | "image/jpeg";
193
+ * @path filename: string;
194
+ * }
195
+ *
196
+ * @get op downloadImage(@path name: string): ImageFile;
197
+ *
198
+ * @post op uploadImage(@bodyRoot image: ImageFile): void;
199
+ * ```
200
+ *
201
+ * @example
202
+ * ```tsp
203
+ * // Use a File as a structured JSON object. The HTTP library will warn you that the File will be serialized as JSON,
204
+ * // so you should suppress the warning if it's really what you want instead of a binary file upload/download.
205
+ *
206
+ * // The response body is a JSON object like `{"contentType":<string?>,"filename":<string?>,"contents":<string>}`
207
+ * @get op downloadTextFileJson(): {
208
+ * @header contentType: "application/json",
209
+ * @body file: File<"text/plain", string>,
210
+ * };
211
+ *
212
+ * // The request body is a JSON object like `{"contentType":<string?>,"filename":<string?>,"contents":<base64>}`
213
+ * @post op uploadBinaryFileJson(
214
+ * @header contentType: "application/json",
215
+ * @body file: File<"image/png", bytes>,
216
+ * ): void;
217
+ *
218
+ */
219
+ @summary("A file in an HTTP request, response, or multipart payload.")
109
220
  @Private.httpFile
110
- model File {
111
- contentType?: string;
221
+ model File<ContentType extends string = string, Contents extends bytes | string = bytes> {
222
+ /**
223
+ * The allowed media (MIME) types of the file contents.
224
+ *
225
+ * In file bodies, this value comes from the `Content-Type` header of the request or response. In JSON bodies,
226
+ * this value is serialized as a field in the response.
227
+ *
228
+ * NOTE: this is not _necessarily_ the same as the `Content-Type` header of the request or response, but
229
+ * it will be for file bodies. It may be different if the file is serialized as a JSON object. It always refers to the
230
+ * _contents_ of the file, and not necessarily the way the file itself is transmitted or serialized.
231
+ */
232
+ @summary("The allowed media (MIME) types of the file contents.")
233
+ contentType?: ContentType;
234
+
235
+ /**
236
+ * The name of the file, if any.
237
+ *
238
+ * In file bodies, this value comes from the `filename` parameter of the `Content-Disposition` header of the response
239
+ * or multipart payload. In JSON bodies, this value is serialized as a field in the response.
240
+ *
241
+ * NOTE: By default, `filename` cannot be sent in request payloads and can only be sent in responses and multipart
242
+ * payloads, as the `Content-Disposition` header is not valid in requests. If you want to send the `filename` in a request,
243
+ * you must extend the `File` model and override the `filename` property with a different location defined by HTTP metadata
244
+ * decorators.
245
+ */
246
+ @summary("The name of the file, if any.")
112
247
  filename?: string;
113
- contents: bytes;
248
+
249
+ /**
250
+ * The contents of the file.
251
+ *
252
+ * In file bodies, this value comes from the body of the request, response, or multipart payload. In JSON bodies,
253
+ * this value is serialized as a field in the response.
254
+ */
255
+ @summary("The contents of the file.")
256
+ contents: Contents;
114
257
  }
115
258
 
116
259
  model HttpPartOptions {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/http",
3
- "version": "0.68.0-dev.6",
3
+ "version": "0.68.0-dev.8",
4
4
  "author": "Microsoft Corporation",
5
5
  "description": "TypeSpec HTTP protocol binding",
6
6
  "homepage": "https://github.com/microsoft/typespec",