@typespec/http 0.59.0-dev.1 → 0.59.0-dev.10

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.
Files changed (41) hide show
  1. package/README.md +47 -28
  2. package/dist/generated-defs/TypeSpec.Http.d.ts +41 -16
  3. package/dist/generated-defs/TypeSpec.Http.d.ts.map +1 -1
  4. package/dist/src/decorators.d.ts.map +1 -1
  5. package/dist/src/decorators.js +19 -29
  6. package/dist/src/decorators.js.map +1 -1
  7. package/dist/src/http-property.d.ts +4 -6
  8. package/dist/src/http-property.d.ts.map +1 -1
  9. package/dist/src/http-property.js +78 -41
  10. package/dist/src/http-property.js.map +1 -1
  11. package/dist/src/index.d.ts +2 -1
  12. package/dist/src/index.d.ts.map +1 -1
  13. package/dist/src/index.js +1 -1
  14. package/dist/src/index.js.map +1 -1
  15. package/dist/src/lib.d.ts +97 -82
  16. package/dist/src/lib.d.ts.map +1 -1
  17. package/dist/src/lib.js +13 -7
  18. package/dist/src/lib.js.map +1 -1
  19. package/dist/src/operations.js +2 -1
  20. package/dist/src/operations.js.map +1 -1
  21. package/dist/src/parameters.d.ts +1 -1
  22. package/dist/src/parameters.d.ts.map +1 -1
  23. package/dist/src/parameters.js +47 -10
  24. package/dist/src/parameters.js.map +1 -1
  25. package/dist/src/payload.js +2 -2
  26. package/dist/src/payload.js.map +1 -1
  27. package/dist/src/responses.js +2 -1
  28. package/dist/src/responses.js.map +1 -1
  29. package/dist/src/route.d.ts +2 -1
  30. package/dist/src/route.d.ts.map +1 -1
  31. package/dist/src/route.js +74 -31
  32. package/dist/src/route.js.map +1 -1
  33. package/dist/src/rules/op-reference-container-route.d.ts +1 -1
  34. package/dist/src/types.d.ts +28 -11
  35. package/dist/src/types.d.ts.map +1 -1
  36. package/dist/src/uri-template.d.ts +22 -0
  37. package/dist/src/uri-template.d.ts.map +1 -0
  38. package/dist/src/uri-template.js +41 -0
  39. package/dist/src/uri-template.js.map +1 -0
  40. package/lib/decorators.tsp +74 -16
  41. package/package.json +6 -6
@@ -0,0 +1,41 @@
1
+ const operators = ["+", "#", ".", "/", ";", "?", "&"];
2
+ const uriTemplateRegex = /\{([^{}]+)\}|([^{}]+)/g;
3
+ const expressionRegex = /([^:*]*)(?::(\d+)|(\*))?/;
4
+ /**
5
+ * Parse a URI template according to [RFC-6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3)
6
+ */
7
+ export function parseUriTemplate(template) {
8
+ const parameters = [];
9
+ const segments = [];
10
+ const matches = template.matchAll(uriTemplateRegex);
11
+ for (let [_, expression, literal] of matches) {
12
+ if (expression) {
13
+ let operator;
14
+ if (operators.includes(expression[0])) {
15
+ operator = expression[0];
16
+ expression = expression.slice(1);
17
+ }
18
+ const items = expression.split(",");
19
+ for (const item of items) {
20
+ const match = item.match(expressionRegex);
21
+ const name = match[1];
22
+ const parameter = {
23
+ name: name,
24
+ operator,
25
+ modifier: match[3]
26
+ ? { type: "explode" }
27
+ : match[2]
28
+ ? { type: "prefix", value: Number(match[2]) }
29
+ : undefined,
30
+ };
31
+ parameters.push(parameter);
32
+ segments.push(parameter);
33
+ }
34
+ }
35
+ else {
36
+ segments.push(literal);
37
+ }
38
+ }
39
+ return { segments, parameters };
40
+ }
41
+ //# sourceMappingURL=uri-template.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"uri-template.js","sourceRoot":"","sources":["../../src/uri-template.ts"],"names":[],"mappings":"AAAA,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAU,CAAC;AAc/D,MAAM,gBAAgB,GAAG,wBAAwB,CAAC;AAClD,MAAM,eAAe,GAAG,0BAA0B,CAAC;AAEnD;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAgB;IAC/C,MAAM,UAAU,GAA2B,EAAE,CAAC;IAC9C,MAAM,QAAQ,GAAsC,EAAE,CAAC;IACvD,MAAM,OAAO,GAAG,QAAQ,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;IACpD,KAAK,IAAI,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,IAAI,OAAO,EAAE,CAAC;QAC7C,IAAI,UAAU,EAAE,CAAC;YACf,IAAI,QAA8B,CAAC;YACnC,IAAI,SAAS,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAQ,CAAC,EAAE,CAAC;gBAC7C,QAAQ,GAAG,UAAU,CAAC,CAAC,CAAQ,CAAC;gBAChC,UAAU,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACnC,CAAC;YAED,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,eAAe,CAAE,CAAC;gBAC3C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;gBACtB,MAAM,SAAS,GAAyB;oBACtC,IAAI,EAAE,IAAI;oBACV,QAAQ;oBACR,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;wBAChB,CAAC,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE;wBACrB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;4BACR,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;4BAC7C,CAAC,CAAC,SAAS;iBAChB,CAAC;gBACF,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;gBAC3B,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;aAAM,CAAC;YACN,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzB,CAAC;IACH,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC;AAClC,CAAC"}
@@ -48,8 +48,21 @@ model QueryOptions {
48
48
  */
49
49
  name?: string;
50
50
 
51
+ /**
52
+ * If true send each value in the array/object as a separate query parameter.
53
+ * Equivalent of adding `*` in the path parameter as per [RFC-6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3)
54
+ *
55
+ * | Style | Explode | Uri Template | Primitive value id = 5 | Array id = [3, 4, 5] | Object id = {"role": "admin", "firstName": "Alex"} |
56
+ * | ------ | ------- | -------------- | ---------------------- | ----------------------- | -------------------------------------------------- |
57
+ * | simple | false | `/users{?id}` | `/users?id=5` | `/users?id=3,4,5` | `/users?id=role,admin,firstName,Alex` |
58
+ * | simple | true | `/users{?id*}` | `/users?id=5` | `/users?id=3&id=4&id=5` | `/users?role=admin&firstName=Alex` |
59
+ *
60
+ */
61
+ explode?: boolean;
62
+
51
63
  /**
52
64
  * Determines the format of the array if type array is used.
65
+ * **DEPRECATED**: use explode: true instead of `multi` or `@encode`
53
66
  */
54
67
  format?: "multi" | "csv" | "ssv" | "tsv" | "simple" | "form" | "pipes";
55
68
  }
@@ -63,15 +76,42 @@ model QueryOptions {
63
76
  *
64
77
  * ```typespec
65
78
  * op read(@query select: string, @query("order-by") orderBy: string): void;
66
- * op list(@query({name: "id", format: "multi"}) ids: string[]): void;
79
+ * op list(@query(#{name: "id", explode: true}) ids: string[]): void;
67
80
  * ```
68
81
  */
69
- extern dec query(target: ModelProperty, queryNameOrOptions?: string | QueryOptions);
82
+ extern dec query(target: ModelProperty, queryNameOrOptions?: valueof string | QueryOptions);
83
+
84
+ model PathOptions {
85
+ /** Name of the parameter in the uri template. */
86
+ name?: string;
87
+
88
+ /**
89
+ * When interpolating this parameter in the case of array or object expand each value using the given style.
90
+ * Equivalent of adding `*` in the path parameter as per [RFC-6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3)
91
+ */
92
+ explode?: boolean;
93
+
94
+ /**
95
+ * Different interpolating styles for the path parameter.
96
+ * - `simple`: No special encoding.
97
+ * - `label`: Using `.` separator.
98
+ * - `matrix`: `;` as separator.
99
+ * - `fragment`: `#` as separator.
100
+ * - `path`: `/` as separator.
101
+ */
102
+ style?: "simple" | "label" | "matrix" | "fragment" | "path";
103
+
104
+ /**
105
+ * When interpolating this parameter do not encode reserved characters.
106
+ * Equivalent of adding `+` in the path parameter as per [RFC-6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3)
107
+ */
108
+ allowReserved?: boolean;
109
+ }
70
110
 
71
111
  /**
72
112
  * Explicitly specify that this property is to be interpolated as a path parameter.
73
113
  *
74
- * @param paramName Optional name of the parameter in the url template.
114
+ * @param paramNameOrOptions Optional name of the parameter in the uri template or options.
75
115
  *
76
116
  * @example
77
117
  *
@@ -80,7 +120,7 @@ extern dec query(target: ModelProperty, queryNameOrOptions?: string | QueryOptio
80
120
  * op read(@path explicit: string, implicit: string): void;
81
121
  * ```
82
122
  */
83
- extern dec path(target: ModelProperty, paramName?: valueof string);
123
+ extern dec path(target: ModelProperty, paramNameOrOptions?: valueof string | PathOptions);
84
124
 
85
125
  /**
86
126
  * Explicitly specify that this property type will be exactly the HTTP body.
@@ -220,19 +260,21 @@ extern dec delete(target: Operation);
220
260
  extern dec head(target: Operation);
221
261
 
222
262
  /**
223
- * Specify the endpoint for this service.
263
+ * Specify an endpoint for this service. Multiple `@server` decorators can be used to specify multiple endpoints.
264
+ *
224
265
  * @param url Server endpoint
225
266
  * @param description Description of the endpoint
226
267
  * @param parameters Optional set of parameters used to interpolate the url.
227
268
  *
228
269
  * @example
270
+ *
229
271
  * ```typespec
230
272
  * @service
231
273
  * @server("https://example.com", "Single server endpoint")
232
274
  * namespace PetStore;
233
275
  * ```
234
276
  *
235
- * @example parameterized
277
+ * @example Parameterized
236
278
  *
237
279
  * ```typespec
238
280
  * @server("https://{region}.foo.com", "Regional endpoint", {
@@ -241,6 +283,16 @@ extern dec head(target: Operation);
241
283
  * })
242
284
  * ```
243
285
  *
286
+ * @example Multiple
287
+ * ```typespec
288
+ * @service
289
+ * @server("https://example.com", "Standard endpoint")
290
+ * @server("https://{project}.private.example.com", "Private project endpoint", {
291
+ * project: string;
292
+ * })
293
+ * namespace PetStore;
294
+ * ```
295
+ *
244
296
  */
245
297
  extern dec server(
246
298
  target: Namespace,
@@ -270,22 +322,28 @@ extern dec useAuth(target: Namespace | Interface | Operation, auth: {} | Union |
270
322
  extern dec includeInapplicableMetadataInPayload(target: unknown, value: valueof boolean);
271
323
 
272
324
  /**
273
- * Defines the relative route URI for the target operation
274
- *
275
- * The first argument should be a URI fragment that may contain one or more path parameter fields.
276
- * If the namespace or interface that contains the operation is also marked with a `@route` decorator,
277
- * it will be used as a prefix to the route URI of the operation.
325
+ * Defines the relative route URI template for the target operation as defined by [RFC 6570](https://datatracker.ietf.org/doc/html/rfc6570#section-3.2.3)
278
326
  *
279
327
  * `@route` can only be applied to operations, namespaces, and interfaces.
280
328
  *
281
- * @param path Relative route path. Cannot include query parameters.
282
- * @param options Set of parameters used to configure the route. Supports `{shared: true}` which indicates that the route may be shared by several operations.
329
+ * @param uriTemplate Uri template for this operation.
330
+ * @param options _DEPRECATED_ Set of parameters used to configure the route. Supports `{shared: true}` which indicates that the route may be shared by several operations.
283
331
  *
284
- * @example
332
+ * @example Simple path parameter
285
333
  *
286
334
  * ```typespec
287
- * @route("/widgets")
288
- * op getWidget(@path id: string): Widget;
335
+ * @route("/widgets/{id}") op getWidget(@path id: string): Widget;
336
+ * ```
337
+ *
338
+ * @example Reserved characters
339
+ * ```typespec
340
+ * @route("/files{+path}") op getFile(@path path: string): bytes;
341
+ * ```
342
+ *
343
+ * @example Query parameter
344
+ * ```typespec
345
+ * @route("/files") op list(select?: string, filter?: string): Files[];
346
+ * @route("/files{?select,filter}") op listFullUriTemplate(select?: string, filter?: string): Files[];
289
347
  * ```
290
348
  */
291
349
  extern dec route(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typespec/http",
3
- "version": "0.59.0-dev.1",
3
+ "version": "0.59.0-dev.10",
4
4
  "author": "Microsoft Corporation",
5
5
  "description": "TypeSpec HTTP protocol binding",
6
6
  "homepage": "https://github.com/microsoft/typespec",
@@ -45,12 +45,12 @@
45
45
  "@types/node": "~18.11.19",
46
46
  "@typespec/compiler": "~0.58.1 || >=0.59.0-dev <0.59.0",
47
47
  "@typespec/library-linter": "~0.58.0 || >=0.59.0-dev <0.59.0",
48
- "@vitest/coverage-v8": "^1.6.0",
49
- "@vitest/ui": "^1.6.0",
48
+ "@vitest/coverage-v8": "^2.0.4",
49
+ "@vitest/ui": "^2.0.4",
50
50
  "c8": "^10.1.2",
51
- "rimraf": "~5.0.7",
52
- "typescript": "~5.5.3",
53
- "vitest": "^1.6.0",
51
+ "rimraf": "~6.0.1",
52
+ "typescript": "~5.5.4",
53
+ "vitest": "^2.0.4",
54
54
  "@typespec/tspd": "~0.46.0"
55
55
  },
56
56
  "dependencies": {},