@typespec/http-server-js 0.58.0-alpha.10-dev.3

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 (215) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/LICENSE +21 -0
  3. package/README.md +183 -0
  4. package/build-helpers.ts +170 -0
  5. package/dist/generated-defs/helpers/header.d.ts +4 -0
  6. package/dist/generated-defs/helpers/header.d.ts.map +1 -0
  7. package/dist/generated-defs/helpers/header.js +76 -0
  8. package/dist/generated-defs/helpers/header.js.map +1 -0
  9. package/dist/generated-defs/helpers/http.d.ts +4 -0
  10. package/dist/generated-defs/helpers/http.d.ts.map +1 -0
  11. package/dist/generated-defs/helpers/http.js +134 -0
  12. package/dist/generated-defs/helpers/http.js.map +1 -0
  13. package/dist/generated-defs/helpers/index.d.ts +4 -0
  14. package/dist/generated-defs/helpers/index.d.ts.map +1 -0
  15. package/dist/generated-defs/helpers/index.js +21 -0
  16. package/dist/generated-defs/helpers/index.js.map +1 -0
  17. package/dist/generated-defs/helpers/multipart.d.ts +4 -0
  18. package/dist/generated-defs/helpers/multipart.d.ts.map +1 -0
  19. package/dist/generated-defs/helpers/multipart.js +249 -0
  20. package/dist/generated-defs/helpers/multipart.js.map +1 -0
  21. package/dist/generated-defs/helpers/router.d.ts +4 -0
  22. package/dist/generated-defs/helpers/router.d.ts.map +1 -0
  23. package/dist/generated-defs/helpers/router.js +259 -0
  24. package/dist/generated-defs/helpers/router.js.map +1 -0
  25. package/dist/src/common/declaration.d.ts +13 -0
  26. package/dist/src/common/declaration.d.ts.map +1 -0
  27. package/dist/src/common/declaration.js +45 -0
  28. package/dist/src/common/declaration.js.map +1 -0
  29. package/dist/src/common/documentation.d.ts +12 -0
  30. package/dist/src/common/documentation.d.ts.map +1 -0
  31. package/dist/src/common/documentation.js +21 -0
  32. package/dist/src/common/documentation.js.map +1 -0
  33. package/dist/src/common/enum.d.ts +10 -0
  34. package/dist/src/common/enum.d.ts.map +1 -0
  35. package/dist/src/common/enum.js +21 -0
  36. package/dist/src/common/enum.js.map +1 -0
  37. package/dist/src/common/interface.d.ts +50 -0
  38. package/dist/src/common/interface.d.ts.map +1 -0
  39. package/dist/src/common/interface.js +194 -0
  40. package/dist/src/common/interface.js.map +1 -0
  41. package/dist/src/common/model.d.ts +26 -0
  42. package/dist/src/common/model.d.ts.map +1 -0
  43. package/dist/src/common/model.js +115 -0
  44. package/dist/src/common/model.js.map +1 -0
  45. package/dist/src/common/namespace.d.ts +38 -0
  46. package/dist/src/common/namespace.d.ts.map +1 -0
  47. package/dist/src/common/namespace.js +184 -0
  48. package/dist/src/common/namespace.js.map +1 -0
  49. package/dist/src/common/reference.d.ts +46 -0
  50. package/dist/src/common/reference.d.ts.map +1 -0
  51. package/dist/src/common/reference.js +243 -0
  52. package/dist/src/common/reference.js.map +1 -0
  53. package/dist/src/common/scalar.d.ts +50 -0
  54. package/dist/src/common/scalar.d.ts.map +1 -0
  55. package/dist/src/common/scalar.js +144 -0
  56. package/dist/src/common/scalar.js.map +1 -0
  57. package/dist/src/common/serialization/index.d.ts +11 -0
  58. package/dist/src/common/serialization/index.d.ts.map +1 -0
  59. package/dist/src/common/serialization/index.js +72 -0
  60. package/dist/src/common/serialization/index.js.map +1 -0
  61. package/dist/src/common/serialization/json.d.ts +6 -0
  62. package/dist/src/common/serialization/json.d.ts.map +1 -0
  63. package/dist/src/common/serialization/json.js +341 -0
  64. package/dist/src/common/serialization/json.js.map +1 -0
  65. package/dist/src/common/union.d.ts +23 -0
  66. package/dist/src/common/union.d.ts.map +1 -0
  67. package/dist/src/common/union.js +57 -0
  68. package/dist/src/common/union.js.map +1 -0
  69. package/dist/src/ctx.d.ts +242 -0
  70. package/dist/src/ctx.d.ts.map +1 -0
  71. package/dist/src/ctx.js +211 -0
  72. package/dist/src/ctx.js.map +1 -0
  73. package/dist/src/helpers/header.d.ts +14 -0
  74. package/dist/src/helpers/header.d.ts.map +1 -0
  75. package/dist/src/helpers/header.js +38 -0
  76. package/dist/src/helpers/header.js.map +1 -0
  77. package/dist/src/helpers/http.d.ts +70 -0
  78. package/dist/src/helpers/http.d.ts.map +1 -0
  79. package/dist/src/helpers/http.js +86 -0
  80. package/dist/src/helpers/http.js.map +1 -0
  81. package/dist/src/helpers/multipart.d.ts +26 -0
  82. package/dist/src/helpers/multipart.d.ts.map +1 -0
  83. package/dist/src/helpers/multipart.js +182 -0
  84. package/dist/src/helpers/multipart.js.map +1 -0
  85. package/dist/src/helpers/router.d.ts +176 -0
  86. package/dist/src/helpers/router.d.ts.map +1 -0
  87. package/dist/src/helpers/router.js +55 -0
  88. package/dist/src/helpers/router.js.map +1 -0
  89. package/dist/src/http/index.d.ts +24 -0
  90. package/dist/src/http/index.d.ts.map +1 -0
  91. package/dist/src/http/index.js +52 -0
  92. package/dist/src/http/index.js.map +1 -0
  93. package/dist/src/http/server/index.d.ts +11 -0
  94. package/dist/src/http/server/index.d.ts.map +1 -0
  95. package/dist/src/http/server/index.js +413 -0
  96. package/dist/src/http/server/index.js.map +1 -0
  97. package/dist/src/http/server/multipart.d.ts +16 -0
  98. package/dist/src/http/server/multipart.d.ts.map +1 -0
  99. package/dist/src/http/server/multipart.js +214 -0
  100. package/dist/src/http/server/multipart.js.map +1 -0
  101. package/dist/src/http/server/router.d.ts +15 -0
  102. package/dist/src/http/server/router.d.ts.map +1 -0
  103. package/dist/src/http/server/router.js +459 -0
  104. package/dist/src/http/server/router.js.map +1 -0
  105. package/dist/src/index.d.ts +5 -0
  106. package/dist/src/index.d.ts.map +1 -0
  107. package/dist/src/index.js +38 -0
  108. package/dist/src/index.js.map +1 -0
  109. package/dist/src/lib.d.ts +141 -0
  110. package/dist/src/lib.d.ts.map +1 -0
  111. package/dist/src/lib.js +116 -0
  112. package/dist/src/lib.js.map +1 -0
  113. package/dist/src/scripts/scaffold/bin.d.mts +14 -0
  114. package/dist/src/scripts/scaffold/bin.d.mts.map +1 -0
  115. package/dist/src/scripts/scaffold/bin.mjs +559 -0
  116. package/dist/src/scripts/scaffold/bin.mjs.map +1 -0
  117. package/dist/src/testing/index.d.ts +3 -0
  118. package/dist/src/testing/index.d.ts.map +1 -0
  119. package/dist/src/testing/index.js +6 -0
  120. package/dist/src/testing/index.js.map +1 -0
  121. package/dist/src/util/case.d.ts +81 -0
  122. package/dist/src/util/case.d.ts.map +1 -0
  123. package/dist/src/util/case.js +111 -0
  124. package/dist/src/util/case.js.map +1 -0
  125. package/dist/src/util/differentiate.d.ts +251 -0
  126. package/dist/src/util/differentiate.d.ts.map +1 -0
  127. package/dist/src/util/differentiate.js +580 -0
  128. package/dist/src/util/differentiate.js.map +1 -0
  129. package/dist/src/util/error.d.ts +13 -0
  130. package/dist/src/util/error.d.ts.map +1 -0
  131. package/dist/src/util/error.js +25 -0
  132. package/dist/src/util/error.js.map +1 -0
  133. package/dist/src/util/extends.d.ts +10 -0
  134. package/dist/src/util/extends.d.ts.map +1 -0
  135. package/dist/src/util/extends.js +31 -0
  136. package/dist/src/util/extends.js.map +1 -0
  137. package/dist/src/util/iter.d.ts +39 -0
  138. package/dist/src/util/iter.d.ts.map +1 -0
  139. package/dist/src/util/iter.js +72 -0
  140. package/dist/src/util/iter.js.map +1 -0
  141. package/dist/src/util/keywords.d.ts +10 -0
  142. package/dist/src/util/keywords.d.ts.map +1 -0
  143. package/dist/src/util/keywords.js +85 -0
  144. package/dist/src/util/keywords.js.map +1 -0
  145. package/dist/src/util/name.d.ts +12 -0
  146. package/dist/src/util/name.d.ts.map +1 -0
  147. package/dist/src/util/name.js +26 -0
  148. package/dist/src/util/name.js.map +1 -0
  149. package/dist/src/util/once-queue.d.ts +24 -0
  150. package/dist/src/util/once-queue.d.ts.map +1 -0
  151. package/dist/src/util/once-queue.js +34 -0
  152. package/dist/src/util/once-queue.js.map +1 -0
  153. package/dist/src/util/openapi3.d.ts +23 -0
  154. package/dist/src/util/openapi3.d.ts.map +1 -0
  155. package/dist/src/util/openapi3.js +40 -0
  156. package/dist/src/util/openapi3.js.map +1 -0
  157. package/dist/src/util/pluralism.d.ts +23 -0
  158. package/dist/src/util/pluralism.d.ts.map +1 -0
  159. package/dist/src/util/pluralism.js +36 -0
  160. package/dist/src/util/pluralism.js.map +1 -0
  161. package/dist/src/util/scope.d.ts +85 -0
  162. package/dist/src/util/scope.d.ts.map +1 -0
  163. package/dist/src/util/scope.js +111 -0
  164. package/dist/src/util/scope.js.map +1 -0
  165. package/dist/src/write.d.ts +23 -0
  166. package/dist/src/write.d.ts.map +1 -0
  167. package/dist/src/write.js +62 -0
  168. package/dist/src/write.js.map +1 -0
  169. package/generated-defs/helpers/header.ts +83 -0
  170. package/generated-defs/helpers/http.ts +141 -0
  171. package/generated-defs/helpers/index.ts +27 -0
  172. package/generated-defs/helpers/multipart.ts +256 -0
  173. package/generated-defs/helpers/router.ts +266 -0
  174. package/package.json +71 -0
  175. package/src/common/declaration.ts +52 -0
  176. package/src/common/documentation.ts +26 -0
  177. package/src/common/enum.ts +28 -0
  178. package/src/common/interface.ts +264 -0
  179. package/src/common/model.ts +160 -0
  180. package/src/common/namespace.ts +243 -0
  181. package/src/common/reference.ts +319 -0
  182. package/src/common/scalar.ts +173 -0
  183. package/src/common/serialization/index.ts +124 -0
  184. package/src/common/serialization/json.ts +444 -0
  185. package/src/common/union.ts +76 -0
  186. package/src/ctx.ts +497 -0
  187. package/src/helpers/header.ts +55 -0
  188. package/src/helpers/http.ts +113 -0
  189. package/src/helpers/multipart.ts +228 -0
  190. package/src/helpers/router.ts +238 -0
  191. package/src/http/index.ts +81 -0
  192. package/src/http/server/index.ts +548 -0
  193. package/src/http/server/multipart.ts +272 -0
  194. package/src/http/server/router.ts +686 -0
  195. package/src/index.ts +56 -0
  196. package/src/lib.ts +130 -0
  197. package/src/scripts/scaffold/bin.mts +781 -0
  198. package/src/testing/index.ts +10 -0
  199. package/src/util/case.ts +182 -0
  200. package/src/util/differentiate.ts +957 -0
  201. package/src/util/error.ts +28 -0
  202. package/src/util/extends.ts +43 -0
  203. package/src/util/iter.ts +85 -0
  204. package/src/util/keywords.ts +90 -0
  205. package/src/util/name.ts +33 -0
  206. package/src/util/once-queue.ts +55 -0
  207. package/src/util/openapi3.ts +53 -0
  208. package/src/util/pluralism.ts +37 -0
  209. package/src/util/scope.ts +211 -0
  210. package/src/write.ts +88 -0
  211. package/temp/tsconfig.tsbuildinfo +1 -0
  212. package/test/header.test.ts +26 -0
  213. package/test/multipart.test.ts +169 -0
  214. package/tsconfig.json +10 -0
  215. package/vitest.config.ts +4 -0
@@ -0,0 +1,86 @@
1
+ // Copyright (c) Microsoft Corporation.
2
+ // Licensed under the MIT License.
3
+ export const HTTP_RESPONDER = Symbol.for("@typespec/http-server-js.HttpResponder");
4
+ /**
5
+ * Determines if a value is an HttpResponder.
6
+ * @param value - The value to check.
7
+ * @returns `true` if the value is an HttpResponder, otherwise `false`.
8
+ */
9
+ export function isHttpResponder(value) {
10
+ return (typeof value === "object" &&
11
+ value !== null &&
12
+ HTTP_RESPONDER in value &&
13
+ typeof value[HTTP_RESPONDER] === "function");
14
+ }
15
+ /**
16
+ * An Error that can respond to an HTTP request if thrown from a route handler.
17
+ */
18
+ export class HttpResponderError extends Error {
19
+ #statusCode;
20
+ constructor(statusCode, message) {
21
+ super(message);
22
+ this.#statusCode = statusCode;
23
+ }
24
+ [HTTP_RESPONDER](ctx) {
25
+ ctx.response.statusCode = this.#statusCode;
26
+ ctx.response.setHeader("Content-Type", "text/plain");
27
+ ctx.response.end(this.message);
28
+ }
29
+ }
30
+ /**
31
+ * The requested resource was not found.
32
+ */
33
+ export class NotFoundError extends HttpResponderError {
34
+ constructor() {
35
+ super(404, "Not Found");
36
+ }
37
+ }
38
+ /**
39
+ * The request was malformed.
40
+ */
41
+ export class BadRequestError extends HttpResponderError {
42
+ constructor() {
43
+ super(400, "Bad Request");
44
+ }
45
+ }
46
+ /**
47
+ * The request is missing required authentication credentials.
48
+ */
49
+ export class UnauthorizedError extends HttpResponderError {
50
+ constructor() {
51
+ super(401, "Unauthorized");
52
+ }
53
+ }
54
+ /**
55
+ * The request is missing required permissions.
56
+ */
57
+ export class ForbiddenError extends HttpResponderError {
58
+ constructor() {
59
+ super(403, "Forbidden");
60
+ }
61
+ }
62
+ /**
63
+ * The request conflicts with the current state of the server.
64
+ */
65
+ export class ConflictError extends HttpResponderError {
66
+ constructor() {
67
+ super(409, "Conflict");
68
+ }
69
+ }
70
+ /**
71
+ * The server encountered an unexpected condition that prevented it from fulfilling the request.
72
+ */
73
+ export class InternalServerError extends HttpResponderError {
74
+ constructor() {
75
+ super(500, "Internal Server Error");
76
+ }
77
+ }
78
+ /**
79
+ * The server does not support the functionality required to fulfill the request.
80
+ */
81
+ export class NotImplementedError extends HttpResponderError {
82
+ constructor() {
83
+ super(501, "Not Implemented");
84
+ }
85
+ }
86
+ //# sourceMappingURL=http.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.js","sourceRoot":"","sources":["../../../src/helpers/http.ts"],"names":[],"mappings":"AAAA,uCAAuC;AACvC,kCAAkC;AAIlC,MAAM,CAAC,MAAM,cAAc,GAAG,MAAM,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;AAcnF;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,KAAc;IAC5C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,cAAc,IAAI,KAAK;QACvB,OAAO,KAAK,CAAC,cAAc,CAAC,KAAK,UAAU,CAC5C,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAC3C,WAAW,CAAS;IAEpB,YAAY,UAAkB,EAAE,OAAe;QAC7C,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC;IAChC,CAAC;IAED,CAAC,cAAc,CAAC,CAAC,GAAgB;QAC/B,GAAG,CAAC,QAAQ,CAAC,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC;QAC3C,GAAG,CAAC,QAAQ,CAAC,SAAS,CAAC,cAAc,EAAE,YAAY,CAAC,CAAC;QACrD,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACjC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,kBAAkB;IACnD;QACE,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC1B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,eAAgB,SAAQ,kBAAkB;IACrD;QACE,KAAK,CAAC,GAAG,EAAE,aAAa,CAAC,CAAC;IAC5B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,iBAAkB,SAAQ,kBAAkB;IACvD;QACE,KAAK,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC7B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,cAAe,SAAQ,kBAAkB;IACpD;QACE,KAAK,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;IAC1B,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,aAAc,SAAQ,kBAAkB;IACnD;QACE,KAAK,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;IACzB,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,kBAAkB;IACzD;QACE,KAAK,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC;IACtC,CAAC;CACF;AAED;;GAEG;AACH,MAAM,OAAO,mBAAoB,SAAQ,kBAAkB;IACzD;QACE,KAAK,CAAC,GAAG,EAAE,iBAAiB,CAAC,CAAC;IAChC,CAAC;CACF"}
@@ -0,0 +1,26 @@
1
+ import type * as http from "node:http";
2
+ export interface HttpPart {
3
+ headers: {
4
+ [k: string]: string | undefined;
5
+ };
6
+ body: ReadableStream<Buffer>;
7
+ }
8
+ /**
9
+ * Processes a request as a multipart request, returning a stream of `HttpPart` objects, each representing an individual
10
+ * part in the multipart request.
11
+ *
12
+ * Only call this function if you have already validated the content type of the request and confirmed that it is a
13
+ * multipart request.
14
+ *
15
+ * @throws Error if the content-type header is missing or does not contain a boundary field.
16
+ *
17
+ * @param request - the incoming request to parse as multipart
18
+ * @returns a stream of HttpPart objects, each representing an individual part in the multipart request
19
+ */
20
+ export declare function createMultipartReadable(request: http.IncomingMessage): ReadableStream<HttpPart>;
21
+ declare global {
22
+ interface ReadableStream<R> {
23
+ [Symbol.asyncIterator](): AsyncIterableIterator<R>;
24
+ }
25
+ }
26
+ //# sourceMappingURL=multipart.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart.d.ts","sourceRoot":"","sources":["../../../src/helpers/multipart.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,IAAI,MAAM,WAAW,CAAC;AAEvC,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE;QAAE,CAAC,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAA;KAAE,CAAC;IAC7C,IAAI,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;CAC9B;AAmKD;;;;;;;;;;;GAWG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,IAAI,CAAC,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC,CAqB/F;AAmBD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,cAAc,CAAC,CAAC;QACxB,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,qBAAqB,CAAC,CAAC,CAAC,CAAC;KACpD;CACF"}
@@ -0,0 +1,182 @@
1
+ // Copyright (c) Microsoft Corporation
2
+ // Licensed under the MIT license.
3
+ /**
4
+ * Consumes a stream of incoming data and splits it into individual streams for each part of a multipart request, using
5
+ * the provided `boundary` value.
6
+ */
7
+ function MultipartBoundaryTransformStream(boundary) {
8
+ let buffer = Buffer.alloc(0);
9
+ // Initialize subcontroller to an object that does nothing. Multipart bodies may contain a preamble before the first
10
+ // boundary, so this dummy controller will discard it.
11
+ let subController = {
12
+ enqueue() { },
13
+ close() { },
14
+ };
15
+ let boundarySplit = Buffer.from(`--${boundary}`);
16
+ let initialized = false;
17
+ // We need to keep at least the length of the boundary split plus room for CRLFCRLF in the buffer to detect the boundaries.
18
+ // We subtract one from this length because if the whole thing were in the buffer, we would detect it and move past it.
19
+ const bufferKeepLength = boundarySplit.length + BUF_CRLFCRLF.length - 1;
20
+ let _readableController = null;
21
+ const readable = new ReadableStream({
22
+ start(controller) {
23
+ _readableController = controller;
24
+ },
25
+ });
26
+ const readableController = _readableController;
27
+ const writable = new WritableStream({
28
+ write: async (chunk) => {
29
+ buffer = Buffer.concat([buffer, chunk]);
30
+ let index;
31
+ while ((index = buffer.indexOf(boundarySplit)) !== -1) {
32
+ // We found a boundary, emit everything before it and initialize a new stream for the next part.
33
+ // We are initialized if we have found the boundary at least once.
34
+ //
35
+ // Cases
36
+ // 1. If the index is zero and we aren't initialized, there was no preamble.
37
+ // 2. If the index is zero and we are initialized, then we had to have found \r\n--boundary, nothing special to do.
38
+ // 3. If the index is not zero, and we are initialized, then we found \r\n--boundary somewhere in the middle,
39
+ // nothing special to do.
40
+ // 4. If the index is not zero and we aren't initialized, then we need to check that boundarySplit was preceded
41
+ // by \r\n for validity, because the preamble must end with \r\n.
42
+ if (index > 0) {
43
+ if (!initialized) {
44
+ if (!buffer.subarray(index - 2, index).equals(Buffer.from("\r\n"))) {
45
+ readableController.error(new Error("Invalid preamble in multipart body."));
46
+ }
47
+ else {
48
+ await enqueueSub(buffer.subarray(0, index - 2));
49
+ }
50
+ }
51
+ else {
52
+ await enqueueSub(buffer.subarray(0, index));
53
+ }
54
+ }
55
+ // We enqueued everything before the boundary, so we clear the buffer past the boundary
56
+ buffer = buffer.subarray(index + boundarySplit.length);
57
+ // We're done with the current part, so close the stream. If this is the opening boundary, there won't be a
58
+ // subcontroller yet.
59
+ subController?.close();
60
+ subController = null;
61
+ if (!initialized) {
62
+ initialized = true;
63
+ boundarySplit = Buffer.from(`\r\n${boundarySplit}`);
64
+ }
65
+ }
66
+ if (buffer.length > bufferKeepLength) {
67
+ await enqueueSub(buffer.subarray(0, -bufferKeepLength));
68
+ buffer = buffer.subarray(-bufferKeepLength);
69
+ }
70
+ },
71
+ close() {
72
+ if (!/--(\r\n)?/.test(buffer.toString("utf-8"))) {
73
+ readableController.error(new Error("Unexpected characters after final boundary."));
74
+ }
75
+ subController?.close();
76
+ readableController.close();
77
+ },
78
+ });
79
+ async function enqueueSub(s) {
80
+ subController ??= await new Promise((resolve) => {
81
+ readableController.enqueue(new ReadableStream({
82
+ start: (controller) => resolve(controller),
83
+ }));
84
+ });
85
+ subController.enqueue(s);
86
+ }
87
+ return { readable, writable };
88
+ }
89
+ const BUF_CRLFCRLF = Buffer.from("\r\n\r\n");
90
+ /**
91
+ * Consumes a stream of the contents of a single part of a multipart request and emits an `HttpPart` object for each part.
92
+ * This consumes just enough of the stream to read the headers, and then forwards the rest of the stream as the body.
93
+ */
94
+ class HttpPartTransform extends TransformStream {
95
+ constructor() {
96
+ super({
97
+ transform: async (partRaw, controller) => {
98
+ const reader = partRaw.getReader();
99
+ let buf = Buffer.alloc(0);
100
+ let idx;
101
+ while ((idx = buf.indexOf(BUF_CRLFCRLF)) === -1) {
102
+ const { done, value } = await reader.read();
103
+ if (done) {
104
+ throw new Error("Unexpected end of part.");
105
+ }
106
+ buf = Buffer.concat([buf, value]);
107
+ }
108
+ const headerText = buf.subarray(0, idx).toString("utf-8").trim();
109
+ const headers = Object.fromEntries(headerText.split("\r\n").map((line) => {
110
+ const [name, value] = line.split(": ", 2);
111
+ return [name.toLowerCase(), value];
112
+ }));
113
+ const body = new ReadableStream({
114
+ start(controller) {
115
+ controller.enqueue(buf.subarray(idx + BUF_CRLFCRLF.length));
116
+ },
117
+ async pull(controller) {
118
+ const { done, value } = await reader.read();
119
+ if (done) {
120
+ controller.close();
121
+ }
122
+ else {
123
+ controller.enqueue(value);
124
+ }
125
+ },
126
+ });
127
+ controller.enqueue({ headers, body });
128
+ },
129
+ });
130
+ }
131
+ }
132
+ /**
133
+ * Processes a request as a multipart request, returning a stream of `HttpPart` objects, each representing an individual
134
+ * part in the multipart request.
135
+ *
136
+ * Only call this function if you have already validated the content type of the request and confirmed that it is a
137
+ * multipart request.
138
+ *
139
+ * @throws Error if the content-type header is missing or does not contain a boundary field.
140
+ *
141
+ * @param request - the incoming request to parse as multipart
142
+ * @returns a stream of HttpPart objects, each representing an individual part in the multipart request
143
+ */
144
+ export function createMultipartReadable(request) {
145
+ const boundary = request.headers["content-type"]
146
+ ?.split(";")
147
+ .find((s) => s.includes("boundary="))
148
+ ?.split("=", 2)[1];
149
+ if (!boundary) {
150
+ throw new Error("Invalid request: missing boundary in content-type.");
151
+ }
152
+ const bodyStream = new ReadableStream({
153
+ start(controller) {
154
+ request.on("data", (chunk) => {
155
+ controller.enqueue(chunk);
156
+ });
157
+ request.on("end", () => controller.close());
158
+ },
159
+ });
160
+ return bodyStream
161
+ .pipeThrough(MultipartBoundaryTransformStream(boundary))
162
+ .pipeThrough(new HttpPartTransform());
163
+ }
164
+ // Gross polyfill because Safari doesn't support this yet.
165
+ //
166
+ // https://bugs.webkit.org/show_bug.cgi?id=194379
167
+ // https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream#browser_compatibility
168
+ ReadableStream.prototype[Symbol.asyncIterator] ??= async function* () {
169
+ const reader = this.getReader();
170
+ try {
171
+ while (true) {
172
+ const { done, value } = await reader.read();
173
+ if (done)
174
+ return value;
175
+ yield value;
176
+ }
177
+ }
178
+ finally {
179
+ reader.releaseLock();
180
+ }
181
+ };
182
+ //# sourceMappingURL=multipart.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"multipart.js","sourceRoot":"","sources":["../../../src/helpers/multipart.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,176 @@
1
+ import type * as http from "node:http";
2
+ /** A policy that can be applied to a route or a set of routes. */
3
+ export interface Policy {
4
+ /** Optional policy name. */
5
+ name?: string;
6
+ /**
7
+ * Applies the policy to the request.
8
+ *
9
+ * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate,
10
+ * and _MUST NOT_ do both.
11
+ *
12
+ * If the policy passes a `request` object to `next()`, that request object will be used instead of the original
13
+ * request object for the remainder of the policy chain. If the policy does _not_ pass a request object to `next()`,
14
+ * the same object that was passed to this policy will be forwarded to the next policy automatically.
15
+ *
16
+ * @param request - The incoming HTTP request.
17
+ * @param response - The outgoing HTTP response.
18
+ * @param next - Calls the next policy in the chain.
19
+ */
20
+ (ctx: HttpContext, next: (request?: http.IncomingMessage) => void): void;
21
+ }
22
+ /**
23
+ * Create a function from a chain of policies.
24
+ *
25
+ * This returns a single function that will apply the policy chain and eventually call the provided `next()` function.
26
+ *
27
+ * @param name - The name to give to the policy chain function.
28
+ * @param policies - The policies to apply to the request.
29
+ * @param out - The function to call after the policies have been applied.
30
+ */
31
+ export declare function createPolicyChain<Out extends (ctx: HttpContext, ...rest: any[]) => void>(name: string, policies: Policy[], out: Out): Out;
32
+ /**
33
+ * The type of an error encountered during request validation.
34
+ */
35
+ export type ValidationError = string;
36
+ /**
37
+ * An object specifying the policies for a given route configuration.
38
+ */
39
+ export type RoutePolicies<RouteConfig extends {
40
+ [k: string]: object;
41
+ }> = {
42
+ [Interface in keyof RouteConfig]?: {
43
+ before?: Policy[];
44
+ after?: Policy[];
45
+ methodPolicies?: {
46
+ [Method in keyof RouteConfig[Interface]]?: Policy[];
47
+ };
48
+ };
49
+ };
50
+ /**
51
+ * Create a policy chain for a given route.
52
+ *
53
+ * This function calls `createPolicyChain` internally and orders the policies based on the route configuration.
54
+ *
55
+ * Interface-level `before` policies run first, then method-level policies, then Interface-level `after` policies.
56
+ *
57
+ * @param name - The name to give to the policy chain function.
58
+ * @param routePolicies - The policies to apply to the routes (part of the route configuration).
59
+ * @param interfaceName - The name of the interface that the route belongs to.
60
+ * @param methodName - The name of the method that the route corresponds to.
61
+ * @param out - The function to call after the policies have been applied.
62
+ */
63
+ export declare function createPolicyChainForRoute<RouteConfig extends {
64
+ [k: string]: object;
65
+ }, InterfaceName extends keyof RouteConfig, Out extends (ctx: HttpContext, ...rest: any[]) => void>(name: string, routePolicies: RoutePolicies<RouteConfig>, interfaceName: InterfaceName, methodName: keyof RouteConfig[InterfaceName], out: Out): Out;
66
+ /**
67
+ * Options for configuring a router with additional functionality.
68
+ */
69
+ export interface RouterOptions<RouteConfig extends {
70
+ [k: string]: object;
71
+ } = {
72
+ [k: string]: object;
73
+ }> {
74
+ /**
75
+ * The base path of the router.
76
+ *
77
+ * This should include any leading slashes, but not a trailing slash, and should not include any component
78
+ * of the URL authority (e.g. the scheme, host, or port).
79
+ *
80
+ * Defaults to "".
81
+ */
82
+ basePath?: string;
83
+ /**
84
+ * A list of policies to apply to all routes _before_ routing.
85
+ *
86
+ * Policies are applied in the order they are listed.
87
+ *
88
+ * By default, the policy list is empty.
89
+ *
90
+ * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate
91
+ * the response and _MUST NOT_ do both.
92
+ */
93
+ policies?: Policy[];
94
+ /**
95
+ * A record of policies that apply to specific routes.
96
+ *
97
+ * The policies are provided as a nested record where the keys are the business-logic interface names, and the values
98
+ * are records of the method names in the given interface and the policies that apply to them.
99
+ *
100
+ * By default, no additional policies are applied to the routes.
101
+ *
102
+ * Policies _MUST_ call `next()` to pass the request to the next policy _OR_ call `response.end()` to terminate
103
+ * the response and _MUST NOT_ do both.
104
+ */
105
+ routePolicies?: RoutePolicies<RouteConfig>;
106
+ /**
107
+ * A handler for requests where the resource is not found.
108
+ *
109
+ * The router will call this function when no route matches the incoming request.
110
+ *
111
+ * If this handler is not provided, a 404 Not Found response with a text body will be returned.
112
+ *
113
+ * You _MUST_ call `response.end()` to terminate the response.
114
+ *
115
+ * This handler is unreachable when using the Express middleware, as it will forward non-matching requests to the
116
+ * next middleware layer in the stack.
117
+ *
118
+ * @param ctx - The HTTP context for the request.
119
+ */
120
+ onRequestNotFound?: (ctx: HttpContext) => void;
121
+ /**
122
+ * A handler for requests that fail to validate inputs.
123
+ *
124
+ * If this handler is not provided, a 400 Bad Request response with a JSON body containing some basic information
125
+ * about the error will be returned to the client.
126
+ *
127
+ * You _MUST_ call `response.end()` to terminate the response.
128
+ *
129
+ * @param ctx - The HTTP context for the request.
130
+ * @param route - The route that was matched.
131
+ * @param error - The validation error that was thrown.
132
+ */
133
+ onInvalidRequest?: (ctx: HttpContext, route: string, error: ValidationError) => void;
134
+ /**
135
+ * A handler for requests that throw an error during processing.
136
+ *
137
+ * If this handler is not provided, a 500 Internal Server Error response with a text body and no error details will be
138
+ * returned to the client.
139
+ *
140
+ * You _MUST_ call `response.end()` to terminate the response.
141
+ *
142
+ * If this handler itself throws an Error, the router will respond with a 500 Internal Server Error
143
+ *
144
+ * @param ctx - The HTTP context for the request.
145
+ * @param error - The error that was thrown.
146
+ */
147
+ onInternalError?(ctx: HttpContext, error: Error): void;
148
+ }
149
+ /** Context information for operations carried over the HTTP protocol. */
150
+ export interface HttpContext {
151
+ /** The incoming request to the server. */
152
+ request: http.IncomingMessage;
153
+ /** The outgoing response object. */
154
+ response: http.ServerResponse;
155
+ /**
156
+ * Error handling functions provided by the HTTP router. Service implementations may call these methods in case a
157
+ * resource is not found, a request is invalid, or an internal error occurs.
158
+ *
159
+ * These methods will respond to the client with the appropriate status code and message.
160
+ */
161
+ errorHandlers: {
162
+ /**
163
+ * Signals that the requested resource was not found.
164
+ */
165
+ onRequestNotFound: Exclude<RouterOptions["onRequestNotFound"], undefined>;
166
+ /**
167
+ * Signals that the request was invalid.
168
+ */
169
+ onInvalidRequest: Exclude<RouterOptions["onInvalidRequest"], undefined>;
170
+ /**
171
+ * Signals that an internal error occurred.
172
+ */
173
+ onInternalError: Exclude<RouterOptions["onInternalError"], undefined>;
174
+ };
175
+ }
176
+ //# sourceMappingURL=router.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../../../src/helpers/router.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,55 @@
1
+ // Copyright (c) Microsoft Corporation
2
+ // Licensed under the MIT license.
3
+ /**
4
+ * Create a function from a chain of policies.
5
+ *
6
+ * This returns a single function that will apply the policy chain and eventually call the provided `next()` function.
7
+ *
8
+ * @param name - The name to give to the policy chain function.
9
+ * @param policies - The policies to apply to the request.
10
+ * @param out - The function to call after the policies have been applied.
11
+ */
12
+ export function createPolicyChain(name, policies, out) {
13
+ let outParams;
14
+ if (policies.length === 0) {
15
+ return out;
16
+ }
17
+ function applyPolicy(ctx, index) {
18
+ if (index >= policies.length) {
19
+ return out(ctx, ...outParams);
20
+ }
21
+ policies[index](ctx, function nextPolicy(nextRequest) {
22
+ applyPolicy({
23
+ ...ctx,
24
+ request: nextRequest ?? ctx.request,
25
+ }, index + 1);
26
+ });
27
+ }
28
+ return {
29
+ [name](ctx, ...params) {
30
+ outParams = params;
31
+ applyPolicy(ctx, 0);
32
+ },
33
+ }[name];
34
+ }
35
+ /**
36
+ * Create a policy chain for a given route.
37
+ *
38
+ * This function calls `createPolicyChain` internally and orders the policies based on the route configuration.
39
+ *
40
+ * Interface-level `before` policies run first, then method-level policies, then Interface-level `after` policies.
41
+ *
42
+ * @param name - The name to give to the policy chain function.
43
+ * @param routePolicies - The policies to apply to the routes (part of the route configuration).
44
+ * @param interfaceName - The name of the interface that the route belongs to.
45
+ * @param methodName - The name of the method that the route corresponds to.
46
+ * @param out - The function to call after the policies have been applied.
47
+ */
48
+ export function createPolicyChainForRoute(name, routePolicies, interfaceName, methodName, out) {
49
+ return createPolicyChain(name, [
50
+ ...(routePolicies[interfaceName]?.before ?? []),
51
+ ...(routePolicies[interfaceName]?.methodPolicies?.[methodName] ?? []),
52
+ ...(routePolicies[interfaceName]?.after ?? []),
53
+ ], out);
54
+ }
55
+ //# sourceMappingURL=router.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"router.js","sourceRoot":"","sources":["../../../src/helpers/router.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,kCAAkC;AA0BlC;;;;;;;;GAQG;AACH,MAAM,UAAU,iBAAiB,CAC/B,IAAY,EACZ,QAAkB,EAClB,GAAQ;IAER,IAAI,SAAgB,CAAC;IACrB,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,SAAS,WAAW,CAAC,GAAgB,EAAE,KAAa;QAClD,IAAI,KAAK,IAAI,QAAQ,CAAC,MAAM,EAAE,CAAC;YAC7B,OAAO,GAAG,CAAC,GAAG,EAAE,GAAG,SAAS,CAAC,CAAC;QAChC,CAAC;QAED,QAAQ,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,SAAS,UAAU,CAAC,WAAW;YAClD,WAAW,CACT;gBACE,GAAG,GAAG;gBACN,OAAO,EAAE,WAAW,IAAI,GAAG,CAAC,OAAO;aACpC,EACD,KAAK,GAAG,CAAC,CACV,CAAC;QACJ,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO;QACL,CAAC,IAAI,CAAC,CAAC,GAAgB,EAAE,GAAG,MAAa;YACvC,SAAS,GAAG,MAAM,CAAC;YACnB,WAAW,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACtB,CAAC;KACF,CAAC,IAAI,CAAQ,CAAC;AACjB,CAAC;AAoBD;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,yBAAyB,CAKvC,IAAY,EACZ,aAAyC,EACzC,aAA4B,EAC5B,UAA4C,EAC5C,GAAQ;IAER,OAAO,iBAAiB,CACtB,IAAI,EACJ;QACE,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC;QAC/C,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,cAAc,EAAE,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QACrE,GAAG,CAAC,aAAa,CAAC,aAAa,CAAC,EAAE,KAAK,IAAI,EAAE,CAAC;KAC/C,EACD,GAAG,CACJ,CAAC;AACJ,CAAC"}
@@ -0,0 +1,24 @@
1
+ import { HttpServer, HttpService } from "@typespec/http";
2
+ import { JsContext, Module } from "../ctx.js";
3
+ /**
4
+ * Additional context items used by the HTTP emitter.
5
+ */
6
+ export interface HttpContext extends JsContext {
7
+ /**
8
+ * The HTTP-level representation of the service.
9
+ */
10
+ httpService: HttpService;
11
+ /**
12
+ * The root module for HTTP-specific code.
13
+ */
14
+ httpModule: Module;
15
+ /**
16
+ * The server definitions of the service (\@server decorator)
17
+ */
18
+ servers: HttpServer[];
19
+ }
20
+ /**
21
+ * Emits bindings for the service to be carried over the HTTP protocol.
22
+ */
23
+ export declare function emitHttp(ctx: JsContext): Promise<void>;
24
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/http/index.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,UAAU,EAAE,WAAW,EAA8B,MAAM,gBAAgB,CAAC;AACrF,OAAO,EAAE,SAAS,EAAE,MAAM,EAAgB,MAAM,WAAW,CAAC;AAM5D;;GAEG;AACH,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C;;OAEG;IACH,WAAW,EAAE,WAAW,CAAC;IACzB;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,OAAO,EAAE,UAAU,EAAE,CAAC;CACvB;AAED;;GAEG;AACH,wBAAsB,QAAQ,CAAC,GAAG,EAAE,SAAS,iBAgD5C"}
@@ -0,0 +1,52 @@
1
+ // Copyright (c) Microsoft Corporation
2
+ // Licensed under the MIT license.
3
+ import { NoTarget } from "@typespec/compiler";
4
+ import { getHttpService, getServers } from "@typespec/http";
5
+ import { createModule } from "../ctx.js";
6
+ import { reportDiagnostic } from "../lib.js";
7
+ import { getOpenApi3Emitter, getOpenApi3ServiceRecord, tryGetOpenApi3 } from "../util/openapi3.js";
8
+ import { emitRawServer } from "./server/index.js";
9
+ import { emitRouter } from "./server/router.js";
10
+ /**
11
+ * Emits bindings for the service to be carried over the HTTP protocol.
12
+ */
13
+ export async function emitHttp(ctx) {
14
+ const [httpService, diagnostics] = getHttpService(ctx.program, ctx.service.type);
15
+ const diagnosticsAreError = diagnostics.some((d) => d.severity === "error");
16
+ if (diagnosticsAreError) {
17
+ reportDiagnostic(ctx.program, {
18
+ code: "http-emit-disabled",
19
+ target: NoTarget,
20
+ messageId: "default",
21
+ });
22
+ return;
23
+ }
24
+ const servers = getServers(ctx.program, ctx.service.type) ?? [];
25
+ const httpModule = createModule("http", ctx.generatedModule);
26
+ const httpContext = {
27
+ ...ctx,
28
+ httpService,
29
+ httpModule,
30
+ servers,
31
+ };
32
+ const openapi3Emitter = await getOpenApi3Emitter();
33
+ const openapi3 = await tryGetOpenApi3(ctx.program, ctx.service);
34
+ if (openapi3) {
35
+ const openApiDocumentModule = createModule("openapi3", httpModule);
36
+ openApiDocumentModule.declarations.push([
37
+ `export const openApiDocument = ${JSON.stringify(openapi3)}`,
38
+ ]);
39
+ }
40
+ else if (openapi3Emitter) {
41
+ const serviceRecord = await getOpenApi3ServiceRecord(ctx.program, ctx.service);
42
+ reportDiagnostic(ctx.program, {
43
+ code: "openapi3-document-not-generated",
44
+ target: ctx.service.type,
45
+ messageId: serviceRecord?.versioned ? "versioned" : "unable",
46
+ });
47
+ }
48
+ const operationsModule = createModule("operations", httpModule);
49
+ const serverRawModule = emitRawServer(httpContext, operationsModule);
50
+ emitRouter(httpContext, httpService, serverRawModule);
51
+ }
52
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/http/index.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,kCAAkC;AAElC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAA2B,cAAc,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACrF,OAAO,EAAqB,YAAY,EAAE,MAAM,WAAW,CAAC;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,kBAAkB,EAAE,wBAAwB,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAoBhD;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,GAAc;IAC3C,MAAM,CAAC,WAAW,EAAE,WAAW,CAAC,GAAG,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjF,MAAM,mBAAmB,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC;IAE5E,IAAI,mBAAmB,EAAE,CAAC;QACxB,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE;YAC5B,IAAI,EAAE,oBAAoB;YAC1B,MAAM,EAAE,QAAQ;YAChB,SAAS,EAAE,SAAS;SACrB,CAAC,CAAC;QACH,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;IAEhE,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,eAAe,CAAC,CAAC;IAE7D,MAAM,WAAW,GAAgB;QAC/B,GAAG,GAAG;QACN,WAAW;QACX,UAAU;QACV,OAAO;KACR,CAAC;IAEF,MAAM,eAAe,GAAG,MAAM,kBAAkB,EAAE,CAAC;IACnD,MAAM,QAAQ,GAAG,MAAM,cAAc,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;IAEhE,IAAI,QAAQ,EAAE,CAAC;QACb,MAAM,qBAAqB,GAAG,YAAY,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAEnE,qBAAqB,CAAC,YAAY,CAAC,IAAI,CAAC;YACtC,kCAAkC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE;SAC7D,CAAC,CAAC;IACL,CAAC;SAAM,IAAI,eAAe,EAAE,CAAC;QAC3B,MAAM,aAAa,GAAG,MAAM,wBAAwB,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,OAAO,CAAC,CAAC;QAE/E,gBAAgB,CAAC,GAAG,CAAC,OAAO,EAAE;YAC5B,IAAI,EAAE,iCAAiC;YACvC,MAAM,EAAE,GAAG,CAAC,OAAO,CAAC,IAAI;YACxB,SAAS,EAAE,aAAa,EAAE,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ;SAC7D,CAAC,CAAC;IACL,CAAC;IAED,MAAM,gBAAgB,GAAG,YAAY,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAEhE,MAAM,eAAe,GAAG,aAAa,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IACrE,UAAU,CAAC,WAAW,EAAE,WAAW,EAAE,eAAe,CAAC,CAAC;AACxD,CAAC"}
@@ -0,0 +1,11 @@
1
+ import { Module } from "../../ctx.js";
2
+ import { HttpContext } from "../index.js";
3
+ /**
4
+ * Emits raw operations for handling incoming server requests.
5
+ *
6
+ * @param ctx - The HTTP emitter context.
7
+ * @param operationsModule - The module to emit the operations into.
8
+ * @returns the module containing the raw server operations.
9
+ */
10
+ export declare function emitRawServer(ctx: HttpContext, operationsModule: Module): Module;
11
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/http/server/index.ts"],"names":[],"mappings":"AAoBA,OAAO,EAAE,MAAM,EAA6C,MAAM,cAAc,CAAC;AAMjF,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAa1C;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,GAAG,MAAM,CA0BhF"}