@torpor/build 0.4.14 → 1.0.0

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 (176) hide show
  1. package/README.md +20 -2
  2. package/dist/Jsonify-Dg6gChd3.d.mts +10 -0
  3. package/dist/Jsonify-Dg6gChd3.d.mts.map +1 -0
  4. package/dist/ParseRouteParams-DBmqlmLh.d.mts +42 -0
  5. package/dist/ParseRouteParams-DBmqlmLh.d.mts.map +1 -0
  6. package/dist/{RouteType-B6BMOyYw.mjs → Router-C4ADUfhv.mjs} +30 -42
  7. package/dist/Router-C4ADUfhv.mjs.map +1 -0
  8. package/dist/{Server-CF5wDJp6.d.mts → Server-C_IKav_e.d.mts} +44 -16
  9. package/dist/Server-C_IKav_e.d.mts.map +1 -0
  10. package/dist/{ServerEvent-CxPwA4lH.mjs → ServerEvent-Dljn5i7A.mjs} +37 -11
  11. package/dist/ServerEvent-Dljn5i7A.mjs.map +1 -0
  12. package/dist/Site-CMa153FA.d.mts +565 -0
  13. package/dist/Site-CMa153FA.d.mts.map +1 -0
  14. package/dist/StandardSchema-D28L8_zZ.d.mts +100 -0
  15. package/dist/StandardSchema-D28L8_zZ.d.mts.map +1 -0
  16. package/dist/TypedResponse-6lznqN4U.d.mts +22 -0
  17. package/dist/TypedResponse-6lznqN4U.d.mts.map +1 -0
  18. package/dist/{_page-BQs4WvCO.mjs → _page-4cQKs_Dn.mjs} +3 -5
  19. package/dist/_page-4cQKs_Dn.mjs.map +1 -0
  20. package/dist/bin/index.d.mts +1 -1
  21. package/dist/bin/index.js +15 -11
  22. package/dist/bin/index.js.map +1 -1
  23. package/dist/flattenHeaders-C_YYLdOq.mjs +114 -0
  24. package/dist/flattenHeaders-C_YYLdOq.mjs.map +1 -0
  25. package/dist/form.d.mts +35 -0
  26. package/dist/form.d.mts.map +1 -0
  27. package/dist/form.mjs +48 -0
  28. package/dist/form.mjs.map +1 -0
  29. package/dist/index.d.mts +72 -156
  30. package/dist/index.d.mts.map +1 -1
  31. package/dist/index.mjs +158 -26
  32. package/dist/index.mjs.map +1 -1
  33. package/dist/nav.d.mts +58 -5
  34. package/dist/nav.d.mts.map +1 -1
  35. package/dist/nav.mjs +116 -38
  36. package/dist/nav.mjs.map +1 -1
  37. package/dist/openapi.d.mts +144 -0
  38. package/dist/openapi.d.mts.map +1 -0
  39. package/dist/openapi.mjs +2 -0
  40. package/dist/pathTrie-D4Ax2Mu9.mjs +160 -0
  41. package/dist/pathTrie-D4Ax2Mu9.mjs.map +1 -0
  42. package/dist/plugin-D8Www11B.mjs +202 -0
  43. package/dist/plugin-D8Www11B.mjs.map +1 -0
  44. package/dist/{response-C5TtAsh1.mjs → response-Bg4w2S1q.mjs} +16 -39
  45. package/dist/response-Bg4w2S1q.mjs.map +1 -0
  46. package/dist/response.d.mts +309 -289
  47. package/dist/response.d.mts.map +1 -1
  48. package/dist/response.mjs +3 -4
  49. package/dist/run.d.mts +11 -4
  50. package/dist/run.d.mts.map +1 -1
  51. package/dist/run.mjs +2 -8
  52. package/dist/runOpenApi-BUi1RH1l.mjs +1381 -0
  53. package/dist/runOpenApi-BUi1RH1l.mjs.map +1 -0
  54. package/dist/schema.d.mts +32 -0
  55. package/dist/schema.d.mts.map +1 -0
  56. package/dist/schema.mjs +2 -0
  57. package/dist/server.d.mts +10 -8
  58. package/dist/server.d.mts.map +1 -1
  59. package/dist/server.mjs +132 -4
  60. package/dist/server.mjs.map +1 -0
  61. package/dist/state.d.mts.map +1 -1
  62. package/dist/state.mjs +2 -3
  63. package/dist/test.d.mts +8 -10
  64. package/dist/test.d.mts.map +1 -1
  65. package/dist/test.mjs +283 -79
  66. package/dist/test.mjs.map +1 -1
  67. package/dist/{seeOther-B4Yhu9iq.mjs → unprocessable-DAZbrDeR.mjs} +34 -13
  68. package/dist/unprocessable-DAZbrDeR.mjs.map +1 -0
  69. package/dist/validate-Ok4krlkX.mjs +40 -0
  70. package/dist/validate-Ok4krlkX.mjs.map +1 -0
  71. package/package.json +28 -17
  72. package/src/bin/index.ts +13 -2
  73. package/src/dev.ts +10 -0
  74. package/src/form/formDataToRecord.ts +23 -0
  75. package/src/form/readForm.ts +71 -0
  76. package/src/form.ts +4 -0
  77. package/src/index.ts +53 -1
  78. package/src/nav/api.test-d.ts +79 -0
  79. package/src/nav/api.ts +104 -0
  80. package/src/nav/formSubmit.ts +18 -4
  81. package/src/nav/navigate.ts +40 -15
  82. package/src/nav/route.ts +38 -0
  83. package/src/nav.ts +3 -1
  84. package/src/openapi/docsHtml.ts +25 -0
  85. package/src/openapi/document.ts +154 -0
  86. package/src/openapi/plugin.ts +78 -0
  87. package/src/openapi/types.ts +82 -0
  88. package/src/openapi.ts +14 -0
  89. package/src/response/TypedResponse.ts +17 -0
  90. package/src/response/badRequest.ts +14 -2
  91. package/src/response/created.ts +13 -2
  92. package/src/response/found.ts +2 -2
  93. package/src/response/movedPermanently.ts +2 -2
  94. package/src/response/notModified.ts +2 -2
  95. package/src/response/ok.ts +13 -4
  96. package/src/response/response.ts +4 -4
  97. package/src/response/unprocessable.ts +14 -2
  98. package/src/run/depCache.ts +175 -0
  99. package/src/run/devPlugin.ts +128 -0
  100. package/src/run/prepareTemplate.ts +6 -3
  101. package/src/run/run.ts +63 -39
  102. package/src/run/runBuild.ts +63 -12
  103. package/src/run/runDev.ts +146 -58
  104. package/src/run/runOpenApi.ts +52 -0
  105. package/src/run/runPreview.ts +17 -26
  106. package/src/run/staleTorpCopies.ts +100 -0
  107. package/src/run.ts +2 -1
  108. package/src/schema.ts +7 -0
  109. package/src/server/CookieHelper.ts +17 -7
  110. package/src/server/Server.ts +54 -30
  111. package/src/server/ServerEvent.ts +24 -1
  112. package/src/server/connect/connectMiddleware.ts +44 -40
  113. package/src/server/connect/flattenHeaders.ts +1 -23
  114. package/src/server/connect/requestToNodeMessage.ts +6 -3
  115. package/src/server/types/MiddlewareFunction.ts +18 -4
  116. package/src/site/Router.ts +52 -41
  117. package/src/site/Site.ts +184 -10
  118. package/src/site/checkLayoutSlots.ts +114 -0
  119. package/src/site/checkRoutes.ts +435 -0
  120. package/src/site/clientEntry.ts +22 -9
  121. package/src/site/layoutSlots.ts +53 -0
  122. package/src/site/manifest.ts +125 -6
  123. package/src/site/serverEntry.ts +341 -132
  124. package/src/state/$page.ts +2 -1
  125. package/src/state/$serverPage.ts +22 -0
  126. package/src/test/runTest.ts +306 -118
  127. package/src/types/Adapter.ts +12 -0
  128. package/src/types/Jsonify.ts +20 -0
  129. package/src/types/PageData.test-d.ts +136 -0
  130. package/src/types/PageData.ts +35 -0
  131. package/src/types/PageEndPoint.ts +25 -9
  132. package/src/types/PageForm.test-d.ts +78 -0
  133. package/src/types/PageForm.ts +29 -0
  134. package/src/types/PageLoadEvent.ts +16 -4
  135. package/src/types/PageLoadReturn.ts +13 -0
  136. package/src/types/PageProps.ts +14 -0
  137. package/src/types/PageServerAction.ts +8 -2
  138. package/src/types/PageServerEndPoint.test-d.ts +105 -0
  139. package/src/types/PageServerEndPoint.ts +99 -5
  140. package/src/types/PageServerLoad.ts +11 -3
  141. package/src/types/ParseRouteParams.test-d.ts +84 -0
  142. package/src/types/ParseRouteParams.ts +64 -0
  143. package/src/types/Route.ts +20 -1
  144. package/src/types/RouteHandler.ts +8 -1
  145. package/src/types/ServerEndPoint.test-d.ts +77 -0
  146. package/src/types/ServerEndPoint.ts +148 -16
  147. package/src/types/ServerHook.ts +10 -3
  148. package/src/types/ServerLoadEvent.ts +48 -3
  149. package/src/types/ServerRequest.ts +10 -2
  150. package/src/types/SitePlugin.ts +24 -0
  151. package/src/types/StandardSchema.ts +109 -0
  152. package/src/utils/pathToRegex.ts +4 -2
  153. package/src/utils/pathTrie.ts +182 -0
  154. package/src/utils/searchParamsToRecord.ts +18 -0
  155. package/src/utils/torporPackages.ts +150 -0
  156. package/src/utils/tsconfigAliases.ts +90 -0
  157. package/src/validation/ValidationError.ts +18 -0
  158. package/src/validation/endpoint.ts +83 -0
  159. package/src/validation/validate.ts +26 -0
  160. package/dist/RouteType-B6BMOyYw.mjs.map +0 -1
  161. package/dist/Server-CF5wDJp6.d.mts.map +0 -1
  162. package/dist/ServerEvent-CxPwA4lH.mjs.map +0 -1
  163. package/dist/Site-DgC6WWn1.d.mts +0 -78
  164. package/dist/Site-DgC6WWn1.d.mts.map +0 -1
  165. package/dist/_page-BQs4WvCO.mjs.map +0 -1
  166. package/dist/connectMiddleware-D7nehjj3.mjs +0 -252
  167. package/dist/connectMiddleware-D7nehjj3.mjs.map +0 -1
  168. package/dist/pathToRegex-TUAMc3zS.mjs +0 -11
  169. package/dist/pathToRegex-TUAMc3zS.mjs.map +0 -1
  170. package/dist/response-C5TtAsh1.mjs.map +0 -1
  171. package/dist/run-BPFtSYA3.mjs +0 -332
  172. package/dist/run-BPFtSYA3.mjs.map +0 -1
  173. package/dist/seeOther-B4Yhu9iq.mjs.map +0 -1
  174. package/src/server/Routerx.ts +0 -72
  175. package/src/server/connect/bufferToArrayBuffer.ts +0 -8
  176. package/src/server/connect/readableToBuffer.ts +0 -16
@@ -1 +0,0 @@
1
- {"version":3,"file":"RouteType-B6BMOyYw.mjs","names":["#sortRoutes","#loadHandler","#findLayouts","#findServer","#findServerHook","layouts: LayoutHandler[]"],"sources":["../src/site/Router.ts","../src/types/RouteType.ts"],"sourcesContent":["import type LayoutHandler from \"../types/LayoutHandler\";\nimport type ManifestRoute from \"../types/ManifestRoute\";\nimport type RouteHandler from \"../types/RouteHandler\";\nimport pathToRegex from \"../utils/pathToRegex\";\n\n/**\n * A router that handles file routes with layouts, hooks, etc.\n */\nexport default class Router {\n\troutes: Route[] = [];\n\n\tconstructor() {}\n\n\t//add(path: string, file: string) {\n\t//\t// TODO: Call the specific addX method based on the file path\n\t//\tthis.addPage(route, file);\n\t//}\n\n\taddPages(routes: ManifestRoute[]): this {\n\t\tfor (let r of routes) {\n\t\t\tthis.routes.push(\n\t\t\t\tnew Route(r.path, {\n\t\t\t\t\tpath: r.path,\n\t\t\t\t\ttype: r.type,\n\t\t\t\t\tendPoint: r.endPoint,\n\t\t\t\t\tsubFolder: r.subFolder,\n\t\t\t\t}),\n\t\t\t);\n\t\t}\n\t\tthis.#sortRoutes();\n\t\treturn this;\n\t}\n\n\t// TODO: Allow calling with the endpoint itself, so that you can setup an app with no scaffold\n\taddPage(path: string, type: number, endPoint: () => Promise<any>, subFolder?: string): this {\n\t\tthis.routes.push(\n\t\t\tnew Route(path, {\n\t\t\t\tpath,\n\t\t\t\ttype,\n\t\t\t\tendPoint,\n\t\t\t\tsubFolder,\n\t\t\t}),\n\t\t);\n\t\tthis.#sortRoutes();\n\t\treturn this;\n\t}\n\n\t/*\n\tloadPage(ev: ServerEvent, file: string): Response {\n\t\tlet page = this.pages.get(file);\n\t\tif (!page) {\n\t\t\tpage = {};\n\t\t\tthis.pages.set(file, page);\n\t\t}\n\t}\n\t*/\n\n\tmatch(path: string, query: URLSearchParams): RouteMatch | undefined {\n\t\tfor (let route of this.routes) {\n\t\t\tlet match = path.match(route.regex);\n\t\t\tif (match) {\n\t\t\t\t// Lazy load server endpoints and layouts\n\t\t\t\tif (!route.handler.loaded) {\n\t\t\t\t\tthis.#loadHandler(route.handler, route.path);\n\t\t\t\t}\n\n\t\t\t\treturn {\n\t\t\t\t\thandler: route.handler,\n\t\t\t\t\tparams: match.groups,\n\t\t\t\t\tquery,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t}\n\n\t#loadHandler(handler: RouteHandler, path: string) {\n\t\thandler.layouts = this.#findLayouts(path, handler);\n\t\thandler.serverEndPoint = this.#findServer(path);\n\t\thandler.serverHook = this.#findServerHook(handler);\n\t}\n\n\t#findLayouts(path: string, handler: RouteHandler): LayoutHandler[] | undefined {\n\t\tlet layouts: LayoutHandler[] = [];\n\t\tlet parts = path\n\t\t\t// Strip the trailing`~/server` (so we don't look for `~/server/_layout`\n\t\t\t// which will never exist)\n\t\t\t.replace(/\\/~server$/, \"\")\n\t\t\t// The path will always start with / so splitting e.g. `/first/second`\n\t\t\t// will result in ['', 'first', 'second'] and checks for `/_layout`,\n\t\t\t// `/first/_layout` and `/second/_layout`\n\t\t\t.split(\"/\");\n\t\tlet basePath = \"\";\n\t\tfor (let i = 0; i < parts.length; i++) {\n\t\t\tif (i > 0) {\n\t\t\t\tbasePath += \"/\" + parts[i];\n\t\t\t}\n\t\t\tconst layoutPath = basePath + \"/_layout\";\n\t\t\tconst layoutRoute = this.routes.find((r) => r.path === layoutPath);\n\t\t\tif (layoutRoute && layoutRoute.handler.subFolder === handler.subFolder) {\n\t\t\t\tlayouts.push({\n\t\t\t\t\tpath: layoutPath,\n\t\t\t\t\tendPoint: layoutRoute.handler.endPoint,\n\t\t\t\t\tserverEndPoint: this.#findServer(layoutPath),\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn layouts.length ? layouts : undefined;\n\t}\n\n\t#findServer(path: string): (() => Promise<any>) | undefined {\n\t\tconst serverPath = path.replace(/\\/$/, \"\") + \"/~server\";\n\t\tconst serverRoute = this.routes.find((r) => r.path === serverPath);\n\t\treturn serverRoute && serverRoute.handler.endPoint;\n\t}\n\n\t#findServerHook(handler: RouteHandler): (() => Promise<any>) | undefined {\n\t\t// TODO: Should this be a collection, like layouts?\n\t\tlet serverHookPath = \"/_hook/~server\";\n\t\tif (handler.subFolder !== undefined) {\n\t\t\tserverHookPath = handler.subFolder + serverHookPath;\n\t\t}\n\t\tconst serverHookRoute = this.routes.find((r) => r.path === serverHookPath);\n\t\treturn serverHookRoute && serverHookRoute.handler.endPoint;\n\t}\n\n\t// HACK: We're doing this here as well as in Site, so that you can use the\n\t// Router externally without Site\n\t#sortRoutes() {\n\t\tthis.routes = this.routes.sort((a, b) => {\n\t\t\t// Sort [param]s after paths\n\t\t\t// There might be a quicker/easier way to do this\n\t\t\tfor (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {\n\t\t\t\tif (a.path[i] === \"[\" && b.path[i] !== \"[\") {\n\t\t\t\t\treturn 1;\n\t\t\t\t} else if (b.path[i] === \"[\" && a.path[i] !== \"[\") {\n\t\t\t\t\treturn -1;\n\t\t\t\t} else if (a.path[i] === b.path[i]) {\n\t\t\t\t\t// Keep going...\n\t\t\t\t} else {\n\t\t\t\t\treturn a.path[i].localeCompare(b.path[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn a.path.length - b.path.length;\n\t\t});\n\t}\n}\n\nclass Route {\n\tpath: string;\n\tregex: RegExp;\n\thandler: RouteHandler;\n\n\tconstructor(path: string, handler: RouteHandler) {\n\t\tthis.path = path;\n\t\tthis.regex = pathToRegex(path);\n\t\tthis.handler = handler;\n\t}\n}\n\ninterface RouteMatch {\n\thandler: RouteHandler;\n\tparams?: Record<string, string>;\n\tquery: URLSearchParams;\n}\n","export const PAGE_ROUTE = 0;\nexport const PAGE_SERVER_ROUTE = 1;\nexport const SERVER_ROUTE = 3;\nexport const LAYOUT_ROUTE = 4;\nexport const LAYOUT_SERVER_ROUTE = 5;\nexport const HOOK_ROUTE = 6;\nexport const HOOK_SERVER_ROUTE = 7;\nexport const ERROR_ROUTE = 8;\n\nexport type RouteType =\n\t| typeof PAGE_ROUTE\n\t| typeof PAGE_SERVER_ROUTE\n\t| typeof SERVER_ROUTE\n\t| typeof LAYOUT_ROUTE\n\t| typeof LAYOUT_SERVER_ROUTE\n\t| typeof HOOK_ROUTE\n\t| typeof HOOK_SERVER_ROUTE\n\t| typeof ERROR_ROUTE\n\t| -1;\n"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"Server-CF5wDJp6.d.mts","names":[],"sources":["../src/server/CookieHelper.ts","../src/server/HeaderHelper.ts","../src/server/ServerEvent.ts","../src/server/types/MiddlewareFunction.ts","../src/server/types/ServerFunction.ts","../src/server/Server.ts"],"sourcesContent":[],"mappings":";;;cAEqB,YAAA;WACX;EAHyC,OAE9B,EAEX,GAFW,CAAA,MAAA,EAAA,MAAA,CAAA;EACX,WAAA,CAAA,OAAA,EAGY,OAHZ;EACA,GAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EAEY,GAAA,CAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EAcsB,gBAdtB,CAAA,EAAA,IAAA;EAcsB,MAAA,CAAA,IAAA,EAAA,MAAA,EAAA,OAAA,CAAA,EASZ,gBATY,CAAA,EAAA,IAAA;;;;cCpBvB,YAAA;WACX;WACA;EDFyC,WAE9B,CAAA,OAAA,ECEC,ODFD;EACX,GAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,MAAA,GAAA,SAAA;EACA,GAAA,CAAA,IAAA,EAAA,MAAA,EAAA,KAAA,EAAA,MAAA,CAAA,EAAA,IAAA;EAEY,MAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EAAA,IAAA;;;;cEHD,WAAA;EFH8B,OAE9B,EEEX,OFFW;EACX,QAAA,EEEC,QFFD,GAAA,SAAA,GAAA,IAAA;EACA,MAAA,CAAA,EEGA,MFHA,CAAA,MAAA,EAAA,MAAA,CAAA;EAEY,OAAA,EAAA,GAAA;EAcsB,OAAA,EETlC,YFSkC;EASZ,OAAA,EEjBtB,YFiBsB;EAAA,WAAA,CAAA,OAAA,EEfV,OFeU,EAAA,MAAA,CAAA,EEfQ,MFeR,CAAA,MAAA,EAAA,MAAA,CAAA;;;;;KG3B3B,kBAAA,QACA,gCACe,yBACR;;;KCHP,cAAA,OACD,gBACC,8BAA8B,QAAQ;;;;AJJQ;;AAIzC,cKMW,MAAA,CLNX;EAEY,CAAA,OAAA;EAcsB,MAAA,EKRnC,YLQmC,EAAA;EASZ,UAAA,EKfnB,kBLemB,EAAA;EAAA,WAAA,CAAA;;;;;;EC3BtB,KAAA,EAAA,CAAA,KAAA,EIwBa,WJxBb,GIwB2B,GJxB3B,EAAA,IAAA,CAAA,EIwBuC,WJxBvC,EAAA,GIwBqD,OJxBrD,CIwB6D,QJxB7D,CAAA;EAEY;;;;;ACHG;EAGf,GAAA,CAAA,IAAA,EAAA,MAAA,EAAA,EAAA,EGkEa,cHlEb,CAAA,EGkE8B,MHlE9B;EACC,KAAA,CAAA,IAAA,EAAA,MAAA,CAAA,EGuEW,KHvEX,GAAA,SAAA;EAED,GAAA,CAAA,GAAA,EAAA,EGoFE,kBHpFF,EAAA,CAAA,EGoFyB,MHpFzB;;cG6GJ,YAAA,CHxGI;EAEY,IAAA,EAAA,MAAA;EAAkB,KAAA,EGwGhC,MHxGgC;EAAA,EAAA,EGyGnC,cHzGmC;gCG2GT;;UAmBrB,KAAA;EF5Ic,EAAA,EE6InB,cF3IA;EACA,MAAA,CAAA,EE2IK,MF3IL,CAAA,MAAA,EAAA,MAAA,CAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"ServerEvent-CxPwA4lH.mjs","names":[],"sources":["../src/server/CookieHelper.ts","../src/server/HeaderHelper.ts","../src/server/ServerEvent.ts"],"sourcesContent":["import { SerializeOptions, parse, serialize } from \"cookie\";\n\nexport default class CookieHelper {\n\trequest: Request;\n\tcookies: Map<string, string> = new Map();\n\n\tconstructor(request: Request) {\n\t\tthis.request = request;\n\t}\n\n\tget(name: string): string | undefined {\n\t\t// If it's been set, return the value from the map\n\t\tif (this.cookies.has(name)) {\n\t\t\treturn parse(this.cookies.get(name)!)[name];\n\t\t}\n\t\t// Otherwise, return the value from the `cookie` header\n\t\tconst header = this.request.headers.get(\"cookie\");\n\t\treturn parse(header ?? \"\")[name];\n\t}\n\n\tset(name: string, value: string, options?: SerializeOptions): void {\n\t\t// Set a cookie header with some default values for security\n\t\toptions ??= {};\n\t\toptions.httpOnly ??= true;\n\t\toptions.secure ??= true;\n\t\toptions.sameSite ??= \"lax\";\n\t\tthis.cookies.set(name, serialize(name, value, options));\n\t}\n\n\tdelete(name: string, options?: SerializeOptions): void {\n\t\t// Set a cookie header with an immediate expiry date\n\t\toptions ??= {};\n\t\toptions.expires = new Date(0);\n\t\tthis.cookies.set(name, serialize(name, \"\", options));\n\t}\n}\n","export default class HeaderHelper {\n\trequest: Request;\n\theaders: Map<string, string> = new Map();\n\n\tconstructor(request: Request) {\n\t\tthis.request = request;\n\t}\n\n\tget(name: string): string | undefined {\n\t\t// If it's been set, return the updated value\n\t\tif (this.headers.has(name)) {\n\t\t\treturn this.headers.get(name);\n\t\t}\n\t\t// Otherwise, return the value from the header\n\t\treturn this.request.headers.get(name) ?? undefined;\n\t}\n\n\tset(name: string, value: string): void {\n\t\tthis.headers.set(name, value);\n\t}\n\n\tdelete(name: string): void {\n\t\tthis.headers.delete(name);\n\t}\n}\n","import CookieHelper from \"./CookieHelper\";\nimport HeaderHelper from \"./HeaderHelper\";\n\nexport default class ServerEvent {\n\trequest: Request;\n\tresponse: Response | undefined | void;\n\t// TODO: Should we cast types??\n\tparams?: Record<string, string>;\n\n\tadapter: any;\n\n\tcookies: CookieHelper;\n\theaders: HeaderHelper;\n\n\tconstructor(request: Request, params?: Record<string, string>) {\n\t\tthis.request = request;\n\t\tthis.params = params;\n\t\tthis.cookies = new CookieHelper(request);\n\t\tthis.headers = new HeaderHelper(request);\n\n\t\t// Adapters may have added the `adapter` property to globalThis\n\t\t// @ts-ignore\n\t\tthis.adapter = globalThis.adapter;\n\t}\n\n\taddHeaders(): void {\n\t\tif (!this.response) {\n\t\t\tthrow new Error(\"Response not created yet\");\n\t\t}\n\n\t\tfor (let cookie of this.cookies.cookies.values()) {\n\t\t\tthis.response.headers.append(\"set-cookie\", cookie);\n\t\t}\n\n\t\tfor (let header of this.headers.headers.entries()) {\n\t\t\tthis.response.headers.append(header[0], header[1]);\n\t\t}\n\t}\n}\n"],"mappings":";;;AAEA,IAAqB,eAArB,MAAkC;CACjC;CACA,0BAA+B,IAAI,KAAK;CAExC,YAAY,SAAkB;AAC7B,OAAK,UAAU;;CAGhB,IAAI,MAAkC;AAErC,MAAI,KAAK,QAAQ,IAAI,KAAK,CACzB,QAAO,MAAM,KAAK,QAAQ,IAAI,KAAK,CAAE,CAAC;AAIvC,SAAO,MADQ,KAAK,QAAQ,QAAQ,IAAI,SAAS,IAC1B,GAAG,CAAC;;CAG5B,IAAI,MAAc,OAAe,SAAkC;AAElE,cAAY,EAAE;AACd,UAAQ,aAAa;AACrB,UAAQ,WAAW;AACnB,UAAQ,aAAa;AACrB,OAAK,QAAQ,IAAI,MAAM,UAAU,MAAM,OAAO,QAAQ,CAAC;;CAGxD,OAAO,MAAc,SAAkC;AAEtD,cAAY,EAAE;AACd,UAAQ,0BAAU,IAAI,KAAK,EAAE;AAC7B,OAAK,QAAQ,IAAI,MAAM,UAAU,MAAM,IAAI,QAAQ,CAAC;;;;;;ACjCtD,IAAqB,eAArB,MAAkC;CACjC;CACA,0BAA+B,IAAI,KAAK;CAExC,YAAY,SAAkB;AAC7B,OAAK,UAAU;;CAGhB,IAAI,MAAkC;AAErC,MAAI,KAAK,QAAQ,IAAI,KAAK,CACzB,QAAO,KAAK,QAAQ,IAAI,KAAK;AAG9B,SAAO,KAAK,QAAQ,QAAQ,IAAI,KAAK,IAAI;;CAG1C,IAAI,MAAc,OAAqB;AACtC,OAAK,QAAQ,IAAI,MAAM,MAAM;;CAG9B,OAAO,MAAoB;AAC1B,OAAK,QAAQ,OAAO,KAAK;;;;;;ACnB3B,IAAqB,cAArB,MAAiC;CAChC;CACA;CAEA;CAEA;CAEA;CACA;CAEA,YAAY,SAAkB,QAAiC;AAC9D,OAAK,UAAU;AACf,OAAK,SAAS;AACd,OAAK,UAAU,IAAI,aAAa,QAAQ;AACxC,OAAK,UAAU,IAAI,aAAa,QAAQ;AAIxC,OAAK,UAAU,WAAW;;CAG3B,aAAmB;AAClB,MAAI,CAAC,KAAK,SACT,OAAM,IAAI,MAAM,2BAA2B;AAG5C,OAAK,IAAI,UAAU,KAAK,QAAQ,QAAQ,QAAQ,CAC/C,MAAK,SAAS,QAAQ,OAAO,cAAc,OAAO;AAGnD,OAAK,IAAI,UAAU,KAAK,QAAQ,QAAQ,SAAS,CAChD,MAAK,SAAS,QAAQ,OAAO,OAAO,IAAI,OAAO,GAAG"}
@@ -1,78 +0,0 @@
1
- import { t as Server } from "./Server-CF5wDJp6.mjs";
2
- import { Plugin, UserConfig } from "vite";
3
-
4
- //#region src/types/Adapter.d.ts
5
- interface Adapter {
6
- prebuild?: (site: Site) => Promise<void> | void;
7
- postbuild?: (site: Site) => Promise<void> | void;
8
- serve: (server: Server, site: Site) => void;
9
- }
10
- //#endregion
11
- //#region src/types/RouteType.d.ts
12
- declare const PAGE_ROUTE = 0;
13
- declare const PAGE_SERVER_ROUTE = 1;
14
- declare const SERVER_ROUTE = 3;
15
- declare const LAYOUT_ROUTE = 4;
16
- declare const LAYOUT_SERVER_ROUTE = 5;
17
- declare const HOOK_ROUTE = 6;
18
- declare const HOOK_SERVER_ROUTE = 7;
19
- declare const ERROR_ROUTE = 8;
20
- type RouteType = typeof PAGE_ROUTE | typeof PAGE_SERVER_ROUTE | typeof SERVER_ROUTE | typeof LAYOUT_ROUTE | typeof LAYOUT_SERVER_ROUTE | typeof HOOK_ROUTE | typeof HOOK_SERVER_ROUTE | typeof ERROR_ROUTE | -1;
21
- //#endregion
22
- //#region src/types/Route.d.ts
23
- /**
24
- * A route that is added to the Site.
25
- */
26
- interface Route {
27
- path: string;
28
- file: string;
29
- type: RouteType;
30
- subFolder?: string;
31
- }
32
- //#endregion
33
- //#region src/site/Site.d.ts
34
- /**
35
- * The Site class contains the information necessary to setup a @torpor/build
36
- * site, including routes, plugins, and options.
37
- */
38
- declare class Site {
39
- #private;
40
- root: string;
41
- routes: Route[];
42
- plugins: Plugin[];
43
- adapter: Adapter;
44
- /**
45
- * Extra inputs, as absolute file paths, that will be compiled with the
46
- * output. What you do with them after that is up to you. File paths ending
47
- * with server.ts/js will only be compiled with the server output
48
- */
49
- inputs: string[];
50
- /**
51
- * Vite config options to merge with the standard Torpor build options.
52
- * `plugins` and `build.rollupOptions.input` will be overridden, so you
53
- * should set `Site.plugins` and `Site.inputs` instead. Other options may be
54
- * overridden or incompatible, so experimentation may be required
55
- */
56
- viteConfig?: UserConfig;
57
- constructor();
58
- /**
59
- * Adds a folder of routes, based on the names of the files in the folder
60
- * @param folder The folder containing the routes
61
- * @param subFolder If a subFolder is set, all routes in the folder will be
62
- * placed under the subFolder, and only hooks, layouts etc will be used if
63
- * they have the same subFolder. This can be used to create e.g. an `api`
64
- * set of routes with their own hook for authorization from various clients
65
- */
66
- addRouteFolder(folder: string, subFolder?: string): Promise<void>;
67
- /**
68
- * Adds a file route, which can have a standard name (e.g. +page.ts) or any
69
- * name if you pass the type
70
- * @param path The route path
71
- * @param file The file
72
- * @param type The file type (if the file name is non-standard)
73
- */
74
- addRouteFile(path: string, file: string, type?: "+page" | "+page.server" | "+server" | "_layout" | "_layout.server" | "_hook" | "_hook.server" | "_error", subFolder?: string): void;
75
- }
76
- //#endregion
77
- export { Adapter as n, Site as t };
78
- //# sourceMappingURL=Site-DgC6WWn1.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"Site-DgC6WWn1.d.mts","names":[],"sources":["../src/types/Adapter.ts","../src/types/RouteType.ts","../src/types/Route.ts","../src/site/Site.ts"],"sourcesContent":[],"mappings":";;;;UAGyB,OAAA;oBACN,SAAS;EAHX,SAEQ,CAAA,EAAA,CAAA,IAAA,EAEL,IAFK,EAAA,GAEI,OAFJ,CAAA,IAAA,CAAA,GAAA,IAAA;EACN,KAAA,EAAA,CAAA,MAAA,EAEF,MAFE,EAAA,IAAA,EAEY,IAFZ,EAAA,GAAA,IAAA;;;;cCJN,UAAA;cACA,iBAAA;cACA,YAAA;cACA,YAAA;ADAY,cCCZ,mBAAA,GDDY,CAAA;AACN,cCCN,UAAA,GDDM,CAAA;AAAS,cCEf,iBAAA,GDFe,CAAA;AACR,cCEP,WAAA,GDFO,CAAA;AAAS,KCIjB,SAAA,GDJiB,OCKnB,UDLmB,GAAA,OCMnB,iBDNmB,GAAA,OCOnB,YDPmB,GAAA,OCQnB,YDRmB,GAAA,OCSnB,mBDTmB,GAAA,OCUnB,UDVmB,GAAA,OCWnB,iBDXmB,GAAA,OCYnB,WDZmB,GAAA,CAAA,CAAA;;;;;;AAFJ,UEEA,KAAA,CFFA;EACN,IAAA,EAAA,MAAA;EAAS,IAAA,EAAA,MAAA;EACR,IAAA,EEGb,SFHa;EAAS,SAAA,CAAA,EAAA,MAAA;;;;;AAJZ;;;AAIG,cGuBC,IAAA,CHvBD;EAAS,CAAA,OAAA;EACZ,IAAA,EAAA,MAAA;EAAc,MAAA,EGwBtB,KHxBsB,EAAA;EAAA,OAAA,EG6BrB,MH7BqB,EAAA;WG+BrB;;;AFrCV;AACA;AACA;EACA,MAAa,EAAA,MAAA,EAAA;EACb;AACA;AACA;AACA;AAEA;;EAEU,UAAA,CAAA,EEuCI,UFvCJ;EACA,WAAA,CAAA;EACA;;;;;;;;sDEmDiD;EDhE5B;;;;ACKR;;;EAgCb,YAAA,CAAA,IAAA,EAAA,MAAA,EAAA,IAAA,EAAA,MAAA,EAAA,IAAA,CAAA,EAAA,OAAA,GAAA,cAAA,GAAA,SAAA,GAAA,SAAA,GAAA,gBAAA,GAAA,OAAA,GAAA,cAAA,GAAA,QAAA,EAAA,SAAA,CAAA,EAAA,MAAA,CAAA,EAAA,IAAA"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"_page-BQs4WvCO.mjs","names":["PAGE_SYMBOL: unique symbol","$page: PageState"],"sources":["../src/state/$page.ts"],"sourcesContent":["import { $watch } from \"@torpor/view\";\nimport type PageState from \"../types/PageState\";\n\nconst PAGE_SYMBOL: unique symbol = Symbol.for(\"torp.Page\");\n\nconst $page: PageState =\n\t// @ts-ignore\n\t(globalThis[PAGE_SYMBOL] ??=\n\t\t// TODO: Should use the SSR $watch if entering via serverEntry\n\t\t$watch(\n\t\t\t{\n\t\t\t\tstatus: 404,\n\t\t\t\turl: new URL(\"http://localhost\"),\n\t\t\t\tform: undefined,\n\t\t\t\terror: {\n\t\t\t\t\tmessage: \"\",\n\t\t\t\t},\n\t\t\t},\n\t\t\t{\n\t\t\t\tshallow: true,\n\t\t\t},\n\t\t));\n\nexport default $page;\n"],"mappings":";;;AAGA,MAAMA,cAA6B,OAAO,IAAI,YAAY;AAE1D,MAAMC,QAEJ,WAAW,iBAEX,OACC;CACC,QAAQ;CACR,KAAK,IAAI,IAAI,mBAAmB;CAChC,MAAM;CACN,OAAO,EACN,SAAS,IACT;CACD,EACD,EACC,SAAS,MACT,CACD;AAEH,oBAAe"}
@@ -1,252 +0,0 @@
1
- import { t as pathToRegex } from "./pathToRegex-TUAMc3zS.mjs";
2
- import { t as ServerEvent } from "./ServerEvent-CxPwA4lH.mjs";
3
- import { ServerResponse } from "node:http";
4
- import { PassThrough, Readable } from "node:stream";
5
-
6
- //#region src/server/Server.ts
7
- const noop = () => {};
8
- /**
9
- * A Fetch API Request/Response server.
10
- */
11
- var Server = class {
12
- routes = [];
13
- middleware = [];
14
- constructor() {
15
- this.routes = [];
16
- this.middleware = [];
17
- }
18
- /**
19
- * The standard Fetch API method that should work in any runtime (including
20
- * Node with polyfills).
21
- * @returns
22
- */
23
- fetch = async (input, init) => {
24
- const request = new Request(input, init);
25
- const url = new URL(request.url);
26
- const match = this.match(url.pathname);
27
- let ev = new ServerEvent(request, match?.params);
28
- if (this.middleware.length) {
29
- await this.middleware[0](ev, buildNext(this.middleware, 0));
30
- function buildNext(middleware, i) {
31
- if (ev.response) return noop;
32
- if (i < middleware.length - 1) {
33
- let next = middleware[i + 1];
34
- return async () => next(ev, buildNext(middleware, i + 1));
35
- } else return match ? async () => {
36
- ev.response = await match.fn(ev);
37
- } : noop;
38
- }
39
- } else if (match) ev.response = await match.fn(ev);
40
- else return new Response(null, { status: 404 });
41
- ev.response ??= new Response(null, { status: 200 });
42
- ev.addHeaders();
43
- return ev.response;
44
- };
45
- /**
46
- * Adds a server function at a route path.
47
- * @param path The route path pattern.
48
- * @param fn The function to call when the pattern is matched.
49
- * @returns
50
- */
51
- add(path, fn) {
52
- this.routes.push(new RouteHandler(path, fn));
53
- this.#sortRoutes();
54
- return this;
55
- }
56
- match(path) {
57
- for (let handler of this.routes) {
58
- let match = path.match(handler.regex);
59
- if (match) return {
60
- fn: handler.fn,
61
- params: match.groups
62
- };
63
- }
64
- console.log(`Server path not found: ${path}`);
65
- }
66
- use(...fn) {
67
- this.middleware = this.middleware.concat(fn);
68
- return this;
69
- }
70
- #sortRoutes() {
71
- this.routes = this.routes.sort((a, b) => {
72
- for (let i = 0; i < Math.min(a.path.length, b.path.length); i++) if (a.path[i] === "[" && b.path[i] !== "[") return 1;
73
- else if (b.path[i] === "[" && a.path[i] !== "[") return -1;
74
- else if (a.path[i] === b.path[i]) {} else return a.path[i].localeCompare(b.path[i]);
75
- return a.path.length - b.path.length;
76
- });
77
- }
78
- };
79
- var RouteHandler = class {
80
- path;
81
- regex;
82
- fn;
83
- constructor(path, fn) {
84
- this.path = path;
85
- this.regex = pathToRegex(path);
86
- this.fn = fn;
87
- }
88
- };
89
-
90
- //#endregion
91
- //#region src/server/connect/bufferToArrayBuffer.ts
92
- function bufferToArrayBuffer(buffer) {
93
- return buffer.buffer.slice(buffer.byteOffset, buffer.byteOffset + buffer.byteLength);
94
- }
95
-
96
- //#endregion
97
- //#region src/server/connect/flattenHeaders.ts
98
- function flattenHeaders(headers) {
99
- const flatHeaders = new Headers();
100
- for (const [key, value] of Object.entries(headers)) if (value === void 0 || value === null) continue;
101
- else if (Array.isArray(value)) {
102
- for (const v of value) if (v !== void 0 && v !== null) value.forEach((v$1) => flatHeaders.append(key, v$1));
103
- } else flatHeaders.set(key, String(value));
104
- return flatHeaders;
105
- }
106
-
107
- //#endregion
108
- //#region src/server/connect/nodeMessageToNodeResponse.ts
109
- /**
110
- * Creates a custom ServerResponse object that allows for intercepting and
111
- * streaming the response.
112
- *
113
- * @param incomingMessage The incoming HTTP request message.
114
- * @returns An object containing the custom ServerResponse and a function that
115
- * takes a callback to invoke when the response is readable, providing an object
116
- * with the readable stream, headers and status code.
117
- */
118
- function nodeMessageToNodeResponse(incomingMessage) {
119
- const res = new ServerResponse(incomingMessage);
120
- const passThrough = new PassThrough();
121
- let handled = false;
122
- const onReadable = (cb) => {
123
- const handleReadable = () => {
124
- if (handled) return;
125
- handled = true;
126
- cb({
127
- readable: Readable.from(passThrough),
128
- headers: res.getHeaders(),
129
- status: res.statusCode
130
- });
131
- };
132
- passThrough.once("readable", handleReadable);
133
- passThrough.once("end", handleReadable);
134
- };
135
- passThrough.once("finish", () => {
136
- res.emit("finish");
137
- });
138
- passThrough.once("close", () => {
139
- res.destroy();
140
- res.emit("close");
141
- });
142
- passThrough.on("drain", () => {
143
- res.emit("drain");
144
- });
145
- res.write = passThrough.write.bind(passThrough);
146
- res.end = passThrough.end.bind(passThrough);
147
- res.writeHead = function writeHead(statusCode, statusMessage, headers) {
148
- res.statusCode = statusCode;
149
- if (typeof statusMessage === "object") {
150
- headers = statusMessage;
151
- statusMessage = void 0;
152
- }
153
- if (headers) {
154
- for (const [key, value] of Object.entries(headers)) if (value !== void 0) res.setHeader(key, value);
155
- }
156
- return res;
157
- };
158
- return {
159
- res,
160
- onReadable
161
- };
162
- }
163
-
164
- //#endregion
165
- //#region src/server/connect/readableToBuffer.ts
166
- function readableToBuffer(req) {
167
- return new Promise((resolve, reject) => {
168
- const chunks = [];
169
- req.on("data", (chunk) => {
170
- chunks.push(chunk);
171
- });
172
- req.on("end", () => {
173
- resolve(Buffer.concat(chunks));
174
- });
175
- req.on("error", (err) => {
176
- reject(err);
177
- });
178
- });
179
- }
180
-
181
- //#endregion
182
- //#region src/server/connect/requestToNodeMessage.ts
183
- const DUMMY_BASE_URL = "http://localhost";
184
- /**
185
- * Creates an IncomingMessage object from a web Request.
186
- *
187
- * @param {Request} request - The web Request object.
188
- * @returns {IncomingMessage} An IncomingMessage-like object compatible with Node.js HTTP module.
189
- */
190
- function requestToNodeMessage(request) {
191
- const parsedUrl = new URL(request.url, DUMMY_BASE_URL);
192
- const pathAndQuery = (parsedUrl.pathname || "") + (parsedUrl.search || "");
193
- const body = Readable.from([]);
194
- return Object.assign(body, {
195
- url: pathAndQuery,
196
- method: request.method,
197
- headers: Object.fromEntries(request.headers)
198
- });
199
- }
200
-
201
- //#endregion
202
- //#region src/server/connect/connectMiddleware.ts
203
- /**
204
- * Converts a Connect-style middleware to a web-compatible request handler.
205
- *
206
- * @param handler - The Connect-style middleware function to be converted.
207
- * @returns A function that handles web requests and returns a Response or undefined.
208
- */
209
- function connectMiddleware(handler) {
210
- return async (ev, next) => {
211
- const req = requestToNodeMessage(ev.request);
212
- const { res, onReadable } = nodeMessageToNodeResponse(req);
213
- return new Promise(async (resolve, reject) => {
214
- onReadable(async ({ readable, headers, status }) => {
215
- const responseBody = statusCodesWithoutBody.includes(status) ? null : bufferToArrayBuffer(await readableToBuffer(readable));
216
- ev.response = new Response(responseBody, {
217
- status,
218
- headers: flattenHeaders(headers)
219
- });
220
- resolve();
221
- });
222
- const cnext = async (error) => {
223
- if (error) reject(error instanceof Error ? error : new Error(String(error)));
224
- else {
225
- await next();
226
- resolve();
227
- }
228
- };
229
- try {
230
- if (await handler(req, res, cnext) === false) {
231
- res.destroy();
232
- resolve();
233
- }
234
- } catch (e) {
235
- await cnext(e);
236
- }
237
- });
238
- };
239
- }
240
- const statusCodesWithoutBody = [
241
- 100,
242
- 101,
243
- 102,
244
- 103,
245
- 204,
246
- 205,
247
- 304
248
- ];
249
-
250
- //#endregion
251
- export { Server as n, connectMiddleware as t };
252
- //# sourceMappingURL=connectMiddleware-D7nehjj3.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"connectMiddleware-D7nehjj3.mjs","names":["#sortRoutes","v","chunks: Buffer[]"],"sources":["../src/server/Server.ts","../src/server/connect/bufferToArrayBuffer.ts","../src/server/connect/flattenHeaders.ts","../src/server/connect/nodeMessageToNodeResponse.ts","../src/server/connect/readableToBuffer.ts","../src/server/connect/requestToNodeMessage.ts","../src/server/connect/connectMiddleware.ts"],"sourcesContent":["import pathToRegex from \"../utils/pathToRegex\";\nimport ServerEvent from \"./ServerEvent\";\nimport type MiddlewareFunction from \"./types/MiddlewareFunction\";\nimport type ServerFunction from \"./types/ServerFunction\";\n\nconst noop = () => {};\n\n/**\n * A Fetch API Request/Response server.\n */\nexport default class Server {\n\t// TODO: We don't use any of the routes, just add(\"*\") in runDev/runBuild...\n\troutes: RouteHandler[] = [];\n\t// TODO: We only use the Vite middleware here\n\tmiddleware: MiddlewareFunction[] = [];\n\n\tconstructor() {\n\t\tthis.routes = [];\n\t\tthis.middleware = [];\n\t}\n\n\t/**\n\t * The standard Fetch API method that should work in any runtime (including\n\t * Node with polyfills).\n\t * @returns\n\t */\n\tfetch = async (input: RequestInfo | URL, init?: RequestInit): Promise<Response> => {\n\t\tconst request = new Request(input, init);\n\t\tconst url = new URL(request.url);\n\t\tconst match = this.match(url.pathname);\n\t\tlet ev = new ServerEvent(request, match?.params);\n\n\t\tif (this.middleware.length) {\n\t\t\t// TODO: Get middleware that applies to this route only?\n\t\t\tawait this.middleware[0](ev, buildNext(this.middleware, 0));\n\t\t\tfunction buildNext(middleware: MiddlewareFunction[], i: number): () => void | Promise<void> {\n\t\t\t\tif (ev.response) {\n\t\t\t\t\treturn noop;\n\t\t\t\t}\n\n\t\t\t\tif (i < middleware.length - 1) {\n\t\t\t\t\tlet next = middleware[i + 1];\n\t\t\t\t\treturn async () => next(ev, buildNext(middleware, i + 1));\n\t\t\t\t} else {\n\t\t\t\t\treturn match\n\t\t\t\t\t\t? async () => {\n\t\t\t\t\t\t\t\tev.response = await match.fn(ev);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t: noop;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if (match) {\n\t\t\tev.response = await match.fn(ev);\n\t\t} else {\n\t\t\treturn new Response(null, { status: 404 });\n\t\t}\n\n\t\t// TODO: Should I be returning 200 if there's no response? Because it's not an error??\n\t\tev.response ??= new Response(null, { status: 200 });\n\t\tev.addHeaders();\n\n\t\treturn ev.response;\n\t};\n\n\t/**\n\t * Adds a server function at a route path.\n\t * @param path The route path pattern.\n\t * @param fn The function to call when the pattern is matched.\n\t * @returns\n\t */\n\tadd(path: string, fn: ServerFunction): Server {\n\t\tthis.routes.push(new RouteHandler(path, fn));\n\t\tthis.#sortRoutes();\n\t\treturn this;\n\t}\n\n\tmatch(path: string): Match | undefined {\n\t\tfor (let handler of this.routes) {\n\t\t\tlet match = path.match(handler.regex);\n\t\t\tif (match) {\n\t\t\t\treturn {\n\t\t\t\t\tfn: handler.fn,\n\t\t\t\t\tparams: match.groups,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\t\tconsole.log(`Server path not found: ${path}`);\n\t}\n\n\t// TODO:\n\t//use(path: string, ...fn: MiddlewareFunction[])\n\tuse(...fn: MiddlewareFunction[]): Server {\n\t\tthis.middleware = this.middleware.concat(fn);\n\t\treturn this;\n\t}\n\n\t#sortRoutes() {\n\t\tthis.routes = this.routes.sort((a, b) => {\n\t\t\t// Sort [param]s after paths\n\t\t\t// There might be a quicker/easier way to do this\n\t\t\tfor (let i = 0; i < Math.min(a.path.length, b.path.length); i++) {\n\t\t\t\tif (a.path[i] === \"[\" && b.path[i] !== \"[\") {\n\t\t\t\t\treturn 1;\n\t\t\t\t} else if (b.path[i] === \"[\" && a.path[i] !== \"[\") {\n\t\t\t\t\treturn -1;\n\t\t\t\t} else if (a.path[i] === b.path[i]) {\n\t\t\t\t\t// Keep going...\n\t\t\t\t} else {\n\t\t\t\t\treturn a.path[i].localeCompare(b.path[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn a.path.length - b.path.length;\n\t\t});\n\t}\n}\n\nclass RouteHandler {\n\tpath: string;\n\tregex: RegExp;\n\tfn: ServerFunction;\n\n\tconstructor(path: string, fn: ServerFunction) {\n\t\tthis.path = path;\n\t\tthis.regex = pathToRegex(path);\n\t\tthis.fn = fn;\n\t}\n}\n\n//class MiddlewareHandler {\n//\tpath: string;\n//\tregex: RegExp;\n//\tfn: MiddlewareFunction;\n//\n//\tconstructor(path: string, fn: MiddlewareFunction) {\n//\t\tthis.path = path;\n//\t\tthis.regex = pathToRegex(path);\n//\t\tthis.fn = fn;\n//\t}\n//}\n\ninterface Match {\n\tfn: ServerFunction;\n\tparams?: Record<string, string>;\n}\n","// From https://stackoverflow.com/a/79345620\n// No idea why it is needed\nexport default function bufferToArrayBuffer(buffer: Buffer): ArrayBuffer {\n\treturn buffer.buffer.slice(\n\t\tbuffer.byteOffset,\n\t\tbuffer.byteOffset + buffer.byteLength,\n\t) as ArrayBuffer;\n}\n","import { IncomingHttpHeaders } from \"node:http\";\nimport { OutgoingHttpHeaders } from \"node:http2\";\n\nexport default function flattenHeaders(\n\theaders: IncomingHttpHeaders | OutgoingHttpHeaders,\n): HeadersInit {\n\tconst flatHeaders = new Headers();\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t} else if (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tif (v !== undefined && v !== null) {\n\t\t\t\t\tvalue.forEach((v) => flatHeaders.append(key, v));\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflatHeaders.set(key, String(value));\n\t\t}\n\t}\n\treturn flatHeaders;\n\n\t/*\n const flatHeaders: [string, string][] = [];\n\n\tfor (const [key, value] of Object.entries(headers)) {\n\t\tif (value === undefined || value === null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tif (v != null) {\n\t\t\t\t\tflatHeaders.push([key, String(v)]);\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tflatHeaders.push([key, String(value)]);\n\t\t}\n\t}\n\n\treturn flatHeaders;\n */\n}\n","import {\n\ttype IncomingMessage,\n\ttype OutgoingHttpHeader,\n\ttype OutgoingHttpHeaders,\n\tServerResponse,\n} from \"node:http\";\nimport { PassThrough, Readable } from \"node:stream\";\n\n// From https://github.com/vikejs/vike-node/blob/main/packages/vike-node/src/runtime/adapters/createServerResponse.ts\n\n/**\n * Creates a custom ServerResponse object that allows for intercepting and\n * streaming the response.\n *\n * @param incomingMessage The incoming HTTP request message.\n * @returns An object containing the custom ServerResponse and a function that\n * takes a callback to invoke when the response is readable, providing an object\n * with the readable stream, headers and status code.\n */\nexport default function nodeMessageToNodeResponse(\n\tincomingMessage: IncomingMessage,\n): ServerResponseResponse {\n\tconst res = new ServerResponse(incomingMessage);\n\tconst passThrough = new PassThrough();\n\tlet handled = false;\n\n\tconst onReadable = (\n\t\tcb: (result: { readable: Readable; headers: OutgoingHttpHeaders; status: number }) => void,\n\t) => {\n\t\tconst handleReadable = () => {\n\t\t\tif (handled) return;\n\t\t\thandled = true;\n\t\t\tcb({\n\t\t\t\treadable: Readable.from(passThrough),\n\t\t\t\theaders: res.getHeaders(),\n\t\t\t\tstatus: res.statusCode,\n\t\t\t});\n\t\t};\n\n\t\tpassThrough.once(\"readable\", handleReadable);\n\t\tpassThrough.once(\"end\", handleReadable);\n\t};\n\n\tpassThrough.once(\"finish\", () => {\n\t\tres.emit(\"finish\");\n\t});\n\tpassThrough.once(\"close\", () => {\n\t\tres.destroy();\n\t\tres.emit(\"close\");\n\t});\n\tpassThrough.on(\"drain\", () => {\n\t\tres.emit(\"drain\");\n\t});\n\n\tres.write = passThrough.write.bind(passThrough);\n\tres.end = passThrough.end.bind(passThrough) as any;\n\n\tres.writeHead = function writeHead(\n\t\tstatusCode: number,\n\t\tstatusMessage?: string | OutgoingHttpHeaders | OutgoingHttpHeader[],\n\t\theaders?: OutgoingHttpHeaders | OutgoingHttpHeader[],\n\t): ServerResponse {\n\t\tres.statusCode = statusCode;\n\t\tif (typeof statusMessage === \"object\") {\n\t\t\theaders = statusMessage;\n\t\t\tstatusMessage = undefined;\n\t\t}\n\t\tif (headers) {\n\t\t\tfor (const [key, value] of Object.entries(headers)) {\n\t\t\t\tif (value !== undefined) {\n\t\t\t\t\tres.setHeader(key, value);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn res;\n\t};\n\n\treturn {\n\t\tres,\n\t\tonReadable,\n\t};\n}\n\ninterface ServerResponseResponse {\n\tres: ServerResponse;\n\tonReadable: (\n\t\tcb: (result: { readable: Readable; headers: OutgoingHttpHeaders; status: number }) => void,\n\t) => void;\n}\n","import { Readable } from \"node:stream\";\n\nexport default function readableToBuffer(req: Readable): Promise<Buffer> {\n\treturn new Promise<Buffer>((resolve, reject) => {\n\t\tconst chunks: Buffer[] = [];\n\t\treq.on(\"data\", (chunk: Buffer) => {\n\t\t\tchunks.push(chunk);\n\t\t});\n\t\treq.on(\"end\", () => {\n\t\t\tresolve(Buffer.concat(chunks));\n\t\t});\n\t\treq.on(\"error\", (err) => {\n\t\t\treject(err);\n\t\t});\n\t});\n}\n","import { type IncomingMessage } from \"node:http\";\nimport { Readable } from \"node:stream\";\n\n// From https://github.com/vikejs/vike-node/blob/main/packages/vike-node/src/runtime/adapters/connectToWeb.ts\n\nconst DUMMY_BASE_URL = \"http://localhost\";\n\n/**\n * Creates an IncomingMessage object from a web Request.\n *\n * @param {Request} request - The web Request object.\n * @returns {IncomingMessage} An IncomingMessage-like object compatible with Node.js HTTP module.\n */\nexport default function requestToNodeMessage(request: Request): IncomingMessage {\n\tconst parsedUrl = new URL(request.url, DUMMY_BASE_URL);\n\tconst pathAndQuery = (parsedUrl.pathname || \"\") + (parsedUrl.search || \"\");\n\t// HACK: Using Readable.fromWeb locks request.body so that the request cannot be used again\n\t// As we're only using this for Vite middlewares, it's safe to discard the body for now?\n\tconst body = /*request.body ? Readable.fromWeb(request.body as any) :*/ Readable.from([]);\n\n\treturn Object.assign(body, {\n\t\turl: pathAndQuery,\n\t\tmethod: request.method,\n\t\theaders: Object.fromEntries(request.headers),\n\t}) as IncomingMessage;\n}\n","import { IncomingMessage, ServerResponse } from \"node:http\";\nimport type MiddlewareFunction from \"../types/MiddlewareFunction\";\nimport bufferToArrayBuffer from \"./bufferToArrayBuffer\";\nimport flattenHeaders from \"./flattenHeaders\";\nimport nodeMessageToNodeResponse from \"./nodeMessageToNodeResponse\";\nimport readableToBuffer from \"./readableToBuffer\";\nimport requestToNodeMessage from \"./requestToNodeMessage\";\n\n// From https://github.com/vikejs/vike-node/blob/main/packages/vike-node/src/runtime/adapters/connectToWeb.ts\n\n/**\n * Converts a Connect-style middleware to a web-compatible request handler.\n *\n * @param handler - The Connect-style middleware function to be converted.\n * @returns A function that handles web requests and returns a Response or undefined.\n */\nexport default function connectMiddleware(\n\thandler: ConnectMiddleware | ConnectMiddlewareBoolean,\n): MiddlewareFunction {\n\treturn async (ev, next) => {\n\t\tconst req = requestToNodeMessage(ev.request);\n\t\tconst { res, onReadable } = nodeMessageToNodeResponse(req);\n\n\t\treturn new Promise<void>(async (resolve, reject) => {\n\t\t\tonReadable(async ({ readable, headers, status }) => {\n\t\t\t\tconst responseBody = statusCodesWithoutBody.includes(status)\n\t\t\t\t\t? null\n\t\t\t\t\t: //(Readable.toWeb(readable) as ReadableStream);\n\t\t\t\t\t\t// HACK: Chunked bodies are not being\n\t\t\t\t\t\t// read correctly somewhere...\n\t\t\t\t\t\tbufferToArrayBuffer(await readableToBuffer(readable));\n\t\t\t\tev.response = new Response(responseBody, {\n\t\t\t\t\tstatus,\n\t\t\t\t\theaders: flattenHeaders(headers),\n\t\t\t\t});\n\t\t\t\tresolve();\n\t\t\t});\n\n\t\t\tconst cnext = async (error?: unknown) => {\n\t\t\t\tif (error) {\n\t\t\t\t\t// eslint-disable-next-line no-base-to-string\n\t\t\t\t\treject(error instanceof Error ? error : new Error(String(error)));\n\t\t\t\t} else {\n\t\t\t\t\t// TODO: Can we nest the next functions less? This is a bit weird\n\t\t\t\t\tawait next();\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t};\n\n\t\t\ttry {\n\t\t\t\tconst handled = await handler(req, res, cnext);\n\t\t\t\tif (handled === false) {\n\t\t\t\t\tres.destroy();\n\t\t\t\t\tresolve();\n\t\t\t\t}\n\t\t\t} catch (e) {\n\t\t\t\tawait cnext(e);\n\t\t\t}\n\t\t});\n\t};\n}\n\nconst statusCodesWithoutBody = [\n\t100, // Continue\n\t101, // Switching Protocols\n\t102, // Processing (WebDAV)\n\t103, // Early Hints\n\t204, // No Content\n\t205, // Reset Content\n\t304, // Not Modified\n];\n\ntype NextFunction = (err?: unknown) => void;\ntype ConnectMiddleware<\n\tPlatformRequest extends IncomingMessage = IncomingMessage,\n\tPlatformResponse extends ServerResponse = ServerResponse,\n> = (req: PlatformRequest, res: PlatformResponse, next: NextFunction) => void | Promise<void>;\ntype ConnectMiddlewareBoolean<\n\tPlatformRequest extends IncomingMessage = IncomingMessage,\n\tPlatformResponse extends ServerResponse = ServerResponse,\n> = (req: PlatformRequest, res: PlatformResponse, next: NextFunction) => boolean | Promise<boolean>;\n"],"mappings":"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"}
@@ -1,11 +0,0 @@
1
- //#region src/utils/pathToRegex.ts
2
- function pathToRegex(path) {
3
- const pattern = path.split("/").map((p) => {
4
- return p.replace(/\[([^/]+?)\]/, "(?<$1>[^\\/]+?)");
5
- }).join("\\/").replaceAll("*", ".*") + "/*";
6
- return /* @__PURE__ */ new RegExp(`^${pattern}/*$`);
7
- }
8
-
9
- //#endregion
10
- export { pathToRegex as t };
11
- //# sourceMappingURL=pathToRegex-TUAMc3zS.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"pathToRegex-TUAMc3zS.mjs","names":[],"sources":["../src/utils/pathToRegex.ts"],"sourcesContent":["export default function pathToRegex(path: string): RegExp {\n\tconst pattern =\n\t\tpath\n\t\t\t.split(\"/\")\n\t\t\t// Replace `[slug]` with a grouped match so we can pull out params\n\t\t\t.map((p) => {\n\t\t\t\treturn p.replace(/\\[([^/]+?)\\]/, \"(?<$1>[^\\\\/]+?)\");\n\t\t\t})\n\t\t\t.join(\"\\\\/\")\n\t\t\t// Replace globs with regex syntax\n\t\t\t.replaceAll(\"*\", \".*\") +\n\t\t// Ignore trailing slashes -- `/path` should be treated the same as `/path/`\n\t\t\"/*\";\n\treturn new RegExp(`^${pattern}/*$`);\n}\n"],"mappings":";AAAA,SAAwB,YAAY,MAAsB;CACzD,MAAM,UACL,KACE,MAAM,IAAI,CAEV,KAAK,MAAM;AACX,SAAO,EAAE,QAAQ,gBAAgB,kBAAkB;GAClD,CACD,KAAK,MAAM,CAEX,WAAW,KAAK,KAAK,GAEvB;AACD,wBAAO,IAAI,OAAO,IAAI,QAAQ,KAAK"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"response-C5TtAsh1.mjs","names":["permRedirect"],"sources":["../src/response/badRequest.ts","../src/response/created.ts","../src/response/forbidden.ts","../src/response/found.ts","../src/response/methodNotAllowed.ts","../src/response/movedPermanently.ts","../src/response/notModified.ts","../src/response/permanentRedirect.ts","../src/response/serverError.ts","../src/response/temporaryRedirect.ts","../src/response/unauthorized.ts","../src/response/unprocessable.ts"],"sourcesContent":["import response from \"./response\";\n\n/**\n * 400 Bad Request\n *\n * The HTTP 400 Bad Request client error response status code indicates that the\n * server would not process the request due to something the server considered\n * to be a client error. The reason for a 400 response is typically due to\n * malformed request syntax, invalid request message framing, or deceptive\n * request routing.\n *\n * Clients that receive a 400 response should expect that repeating the request\n * without modification will fail with the same error.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/400\n */\nexport default function badRequest(body?: object | string): Response {\n\treturn response(400, body ?? \"Bad request\");\n}\n","import response from \"./response\";\n\n/**\n * 201 Created\n *\n * The HTTP 201 Created successful response status code indicates that the HTTP\n * request has led to the creation of a resource. This status code is commonly\n * sent as the result of a POST request.\n *\n * The new resource, or a description and link to the new resource, is created\n * before the response is returned. The newly-created items can be returned in\n * the body of the response message, but must be locatable by the URL of the\n * initiating request or by the URL in the value of the Location header provided\n * with the response.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/201\n */\nexport default function created(body?: object | string): Response {\n\treturn response(201, body);\n}\n","import response from \"./response\";\n\n/**\n * 403 Forbidden\n *\n * The HTTP 403 Forbidden client error response status code indicates that the\n * server understood the request but refused to process it. This status is\n * similar to 401, except that for 403 Forbidden responses, authenticating or\n * re-authenticating makes no difference. The request failure is tied to\n * application logic, such as insufficient permissions to a resource or action.\n *\n * Clients that receive a 403 response should expect that repeating the request\n * without modification will fail with the same error. Server owners may decide\n * to send a 404 response instead of a 403 if acknowledging the existence of a\n * resource to clients with insufficient privileges is not desired.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/403\n */\nexport default function forbidden(body?: object | string): Response {\n\treturn response(403, body ?? \"Forbidden\");\n}\n","import transfer from \"./transfer\";\n\n/**\n * 302 Found\n *\n * The HTTP 302 Found redirection response status code indicates that the\n * requested resource has been temporarily moved to the URL in the Location\n * header.\n *\n * A browser receiving this status will automatically request the resource at\n * the URL in the Location header, redirecting the user to the new page. Search\n * engines receiving this response will not attribute links to the original URL\n * to the new resource, meaning no SEO value is transferred to the new URL.\n *\n * > Note: In the Fetch Standard, when a user agent receives a 302 in response\n * > to a POST request, it uses the GET method in the subsequent redirection\n * > request, as permitted by the HTTP specification. To avoid user agents\n * > modifying the request, use 307 Temporary Redirect instead, as altering the\n * > method after a 307 response is prohibited.\n *\n * > In cases where you want any request method to be changed to GET, use 303\n * > See Other. This is useful when you want to give a response to a PUT method\n * > that is not the uploaded resource but a confirmation message such as: \"you\n * > successfully uploaded XYZ\".\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/302\n */\nexport default function permRedirect(location: string): Response {\n\treturn transfer(308, location);\n}\n","import response from \"./response\";\n\n/**\n * 405 Method Not Allowed\n *\n * The HTTP 405 Method Not Allowed client error response status code indicates\n * that the server knows the request method, but the target resource doesn't\n * support this method. The server must generate an Allow header in a 405\n * response with a list of methods that the target resource currently supports.\n *\n * Improper server-side permissions set on files or directories may cause a 405\n * response when the request would otherwise be expected to succeed.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/405\n */\nexport default function methodNotAllowed(body?: object | string): Response {\n\treturn response(405, body ?? \"Method not allowed\");\n}\n","import transfer from \"./transfer\";\n\n/**\n * 301 Moved Permanently\n *\n * The HTTP 301 Moved Permanently redirection response status code indicates\n * that the requested resource has been permanently moved to the URL in the\n * Location header.\n *\n * A browser receiving this status will automatically request the resource at\n * the URL in the Location header, redirecting the user to the new page. Search\n * engines receiving this response will attribute links to the original URL to\n * the redirected resource, passing the SEO ranking to the new URL.\n *\n * > Note: In the Fetch Standard, when a user agent receives a 301 in response\n * > to a POST request, it uses the GET method in the subsequent redirection\n * > request, as permitted by the HTTP specification. To avoid user agents\n * > modifying the request, use 308 Permanent Redirect instead, as altering the\n * > method after a 308 response is prohibited.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/301\n */\nexport default function permRedirect(location: string): Response {\n\treturn transfer(308, location);\n}\n","import transfer from \"./transfer\";\n\n/**\n * 304 Not Modified\n *\n * The HTTP 304 Not Modified redirection response status code indicates that\n * there is no need to retransmit the requested resources.\n *\n * This response code is sent when the request is a conditional GET or HEAD\n * request with an If-None-Match or an If-Modified-Since header and the\n * condition evaluates to 'false'. It confirms that the resource cached by the\n * client is still valid and that the server would have sent a 200 OK response\n * with the resource if the condition evaluated to 'true'. See HTTP caching for\n * more information.\n *\n * The response must not contain a body and must include the headers that would\n * have been sent in an equivalent 200 response, such as:\n *\n * - Cache-Control\n * - Content-Location\n * - Date\n * - ETag\n * - Expires\n * - Vary\n *\n * > Note: Many developer tools' network panels of browsers create extraneous\n * > requests leading to 304 responses, so that access to the local cache is\n * > visible to developers.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/304\n */\nexport default function notModified(location: string): Response {\n\treturn transfer(304, location);\n}\n","import transfer from \"./transfer\";\n\n/**\n * 308 Permanent Redirect\n *\n * The HTTP 308 Permanent Redirect redirection response status code indicates\n * that the requested resource has been permanently moved to the URL given by\n * the Location header.\n *\n * A browser receiving this status will automatically request the resource at\n * the URL in the Location header, redirecting the user to the new page. Search\n * engines receiving this response will attribute links to the original URL to\n * the redirected resource, passing the SEO ranking to the new URL.\n *\n * The request method and the body will not be modified by the client in the\n * redirected request. A 301 Moved Permanently requires the request method and\n * the body to remain unchanged when redirection is performed, but this is\n * incorrectly handled by older clients to use the GET method instead.\n *\n * > Note: Some Web applications may use the 308 Permanent Redirect in a\n * > non-standard way and for different purposes. For example, Google Drive uses\n * > a 308 Resume Incomplete response to indicate to the client when an\n * > unfinished upload has stalled. See Perform a resumable download on the\n * > Google Drive documentation for more information.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/308\n */\nexport default function permanentRedirect(location: string): Response {\n\treturn transfer(308, location);\n}\n","import response from \"./response\";\n\n/**\n * 500 Server Error\n *\n * The HTTP 500 Internal Server Error server error response status code\n * indicates that the server encountered an unexpected condition that prevented\n * it from fulfilling the request. This error is a generic \"catch-all\" response\n * to server issues, indicating that the server cannot find a more appropriate\n * 5XX error to respond with.\n *\n * If you're a visitor seeing 500 errors on a web page, these issues require\n * investigation by server owners or administrators. There are many possible\n * causes of 500 errors, including: improper server configuration, out-of-memory\n * (OOM) issues, unhandled exceptions, improper file permissions, or other\n * complex factors. Server administrators may proactively log occurrences of\n * server error responses, like the 500 status code, with details about the\n * initiating requests to improve the stability of a service in the future.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/500\n */\nexport default function serverError(body?: object | string): Response {\n\treturn response(500, body ?? \"Server error\");\n}\n","import transfer from \"./transfer\";\n\n/**\n * 307 Temporary Redirect\n *\n * The HTTP 307 Temporary Redirect redirection response status code indicates\n * that the resource requested has been temporarily moved to the URL in the\n * Location header.\n *\n * A browser receiving this status will automatically request the resource at\n * the URL in the Location header, redirecting the user to the new page. Search\n * engines receiving this response will not attribute links to the original URL\n * to the new resource, meaning no SEO value is transferred to the new URL.\n *\n * The method and the body of the original request are reused to perform the\n * redirected request. In the cases where you want the request method to be\n * changed to GET, use 303 See Other instead. This is useful when you want to\n * give an answer to a successful PUT request that is not the uploaded resource,\n * but a status monitor or confirmation message like \"You have successfully\n * uploaded XYZ\".\n *\n * The difference between 307 and 302 is that 307 guarantees that the client\n * will not change the request method and body when the redirected request is\n * made. With 302, older clients incorrectly changed the method to GET. 307 and\n * 302 responses are identical when the request method is GET.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/307\n */\nexport default function temporaryRedirect(location: string): Response {\n\treturn transfer(307, location);\n}\n","import response from \"./response\";\n\n/**\n * 401 Unauthorized\n *\n * The HTTP 401 Unauthorized client error response status code indicates that a\n * request was not successful because it lacks valid authentication credentials\n * for the requested resource. This status code is sent with an HTTP\n * WWW-Authenticate response header that contains information on the\n * authentication scheme the server expects the client to include to make the\n * request successfully.\n *\n * A 401 Unauthorized is similar to the 403 Forbidden response, except that a\n * 403 is returned when a request contains valid credentials, but the client\n * does not have permissions to perform a certain action.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/401\n */\nexport default function unauthorized(body?: object | string): Response {\n\treturn response(401, body ?? \"Unauthorized\");\n}\n","import response from \"./response\";\n\n/**\n * 422 Unprocessable Content\n *\n * The HTTP 422 Unprocessable Content client error response status code\n * indicates that the server understood the content type of the request content,\n * and the syntax of the request content was correct, but it was unable to\n * process the contained instructions.\n *\n * Clients that receive a 422 response should expect that repeating the request\n * without modification will fail with the same error.\n *\n * See https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status/422\n */\nexport default function unprocessable(body?: object | string): Response {\n\treturn response(422, body ?? \"Unprocessable\");\n}\n"],"mappings":";;;;;;;;;;;;;;;;;AAgBA,SAAwB,WAAW,MAAkC;AACpE,QAAO,SAAS,KAAK,QAAQ,cAAc;;;;;;;;;;;;;;;;;;;;ACA5C,SAAwB,QAAQ,MAAkC;AACjE,QAAO,SAAS,KAAK,KAAK;;;;;;;;;;;;;;;;;;;;;ACA3B,SAAwB,UAAU,MAAkC;AACnE,QAAO,SAAS,KAAK,QAAQ,YAAY;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACQ1C,SAAwB,aAAa,UAA4B;AAChE,QAAO,SAAS,KAAK,SAAS;;;;;;;;;;;;;;;;;;ACb/B,SAAwB,iBAAiB,MAAkC;AAC1E,QAAO,SAAS,KAAK,QAAQ,qBAAqB;;;;;;;;;;;;;;;;;;;;;;;;;ACMnD,SAAwBA,eAAa,UAA4B;AAChE,QAAO,SAAS,KAAK,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACQ/B,SAAwB,YAAY,UAA4B;AAC/D,QAAO,SAAS,KAAK,SAAS;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACL/B,SAAwB,kBAAkB,UAA4B;AACrE,QAAO,SAAS,KAAK,SAAS;;;;;;;;;;;;;;;;;;;;;;;;ACP/B,SAAwB,YAAY,MAAkC;AACrE,QAAO,SAAS,KAAK,QAAQ,eAAe;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACM7C,SAAwB,kBAAkB,UAA4B;AACrE,QAAO,SAAS,KAAK,SAAS;;;;;;;;;;;;;;;;;;;;;ACX/B,SAAwB,aAAa,MAAkC;AACtE,QAAO,SAAS,KAAK,QAAQ,eAAe;;;;;;;;;;;;;;;;;;ACJ7C,SAAwB,cAAc,MAAkC;AACvE,QAAO,SAAS,KAAK,QAAQ,gBAAgB"}