@ecopages/core 0.2.0-alpha.1

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 (342) hide show
  1. package/CHANGELOG.md +89 -0
  2. package/LICENSE +21 -0
  3. package/README.md +32 -0
  4. package/package.json +279 -0
  5. package/src/adapters/abstract/application-adapter.d.ts +168 -0
  6. package/src/adapters/abstract/application-adapter.js +109 -0
  7. package/src/adapters/abstract/application-adapter.ts +337 -0
  8. package/src/adapters/abstract/router-adapter.d.ts +26 -0
  9. package/src/adapters/abstract/router-adapter.js +5 -0
  10. package/src/adapters/abstract/router-adapter.ts +30 -0
  11. package/src/adapters/abstract/server-adapter.d.ts +69 -0
  12. package/src/adapters/abstract/server-adapter.js +15 -0
  13. package/src/adapters/abstract/server-adapter.ts +79 -0
  14. package/src/adapters/bun/client-bridge.d.ts +34 -0
  15. package/src/adapters/bun/client-bridge.js +48 -0
  16. package/src/adapters/bun/client-bridge.ts +62 -0
  17. package/src/adapters/bun/create-app.d.ts +60 -0
  18. package/src/adapters/bun/create-app.js +117 -0
  19. package/src/adapters/bun/create-app.ts +189 -0
  20. package/src/adapters/bun/define-api-handler.d.ts +61 -0
  21. package/src/adapters/bun/define-api-handler.js +15 -0
  22. package/src/adapters/bun/define-api-handler.ts +114 -0
  23. package/src/adapters/bun/hmr-manager.d.ts +84 -0
  24. package/src/adapters/bun/hmr-manager.js +227 -0
  25. package/src/adapters/bun/hmr-manager.ts +281 -0
  26. package/src/adapters/bun/index.d.ts +3 -0
  27. package/src/adapters/bun/index.js +8 -0
  28. package/src/adapters/bun/index.ts +3 -0
  29. package/src/adapters/bun/server-adapter.d.ts +155 -0
  30. package/src/adapters/bun/server-adapter.js +368 -0
  31. package/src/adapters/bun/server-adapter.ts +492 -0
  32. package/src/adapters/bun/server-lifecycle.d.ts +52 -0
  33. package/src/adapters/bun/server-lifecycle.js +120 -0
  34. package/src/adapters/bun/server-lifecycle.ts +154 -0
  35. package/src/adapters/index.d.ts +6 -0
  36. package/src/adapters/index.js +14 -0
  37. package/src/adapters/index.ts +6 -0
  38. package/src/adapters/node/create-app.d.ts +21 -0
  39. package/src/adapters/node/create-app.js +143 -0
  40. package/src/adapters/node/create-app.ts +179 -0
  41. package/src/adapters/node/index.d.ts +4 -0
  42. package/src/adapters/node/index.js +8 -0
  43. package/src/adapters/node/index.ts +9 -0
  44. package/src/adapters/node/node-client-bridge.d.ts +26 -0
  45. package/src/adapters/node/node-client-bridge.js +66 -0
  46. package/src/adapters/node/node-client-bridge.ts +79 -0
  47. package/src/adapters/node/node-hmr-manager.d.ts +62 -0
  48. package/src/adapters/node/node-hmr-manager.js +221 -0
  49. package/src/adapters/node/node-hmr-manager.ts +271 -0
  50. package/src/adapters/node/server-adapter.d.ts +190 -0
  51. package/src/adapters/node/server-adapter.js +420 -0
  52. package/src/adapters/node/server-adapter.ts +561 -0
  53. package/src/adapters/node/static-content-server.d.ts +24 -0
  54. package/src/adapters/node/static-content-server.js +166 -0
  55. package/src/adapters/node/static-content-server.ts +203 -0
  56. package/src/adapters/shared/api-response.d.ts +52 -0
  57. package/src/adapters/shared/api-response.js +96 -0
  58. package/src/adapters/shared/api-response.ts +104 -0
  59. package/src/adapters/shared/application-adapter.d.ts +18 -0
  60. package/src/adapters/shared/application-adapter.js +90 -0
  61. package/src/adapters/shared/application-adapter.ts +199 -0
  62. package/src/adapters/shared/explicit-static-route-matcher.d.ts +38 -0
  63. package/src/adapters/shared/explicit-static-route-matcher.js +100 -0
  64. package/src/adapters/shared/explicit-static-route-matcher.ts +134 -0
  65. package/src/adapters/shared/file-route-middleware-pipeline.d.ts +65 -0
  66. package/src/adapters/shared/file-route-middleware-pipeline.js +98 -0
  67. package/src/adapters/shared/file-route-middleware-pipeline.ts +123 -0
  68. package/src/adapters/shared/fs-server-response-factory.d.ts +19 -0
  69. package/src/adapters/shared/fs-server-response-factory.js +97 -0
  70. package/src/adapters/shared/fs-server-response-factory.ts +118 -0
  71. package/src/adapters/shared/fs-server-response-matcher.d.ts +71 -0
  72. package/src/adapters/shared/fs-server-response-matcher.js +155 -0
  73. package/src/adapters/shared/fs-server-response-matcher.ts +198 -0
  74. package/src/adapters/shared/render-context.d.ts +14 -0
  75. package/src/adapters/shared/render-context.js +69 -0
  76. package/src/adapters/shared/render-context.ts +105 -0
  77. package/src/adapters/shared/server-adapter.d.ts +87 -0
  78. package/src/adapters/shared/server-adapter.js +353 -0
  79. package/src/adapters/shared/server-adapter.ts +442 -0
  80. package/src/adapters/shared/server-route-handler.d.ts +89 -0
  81. package/src/adapters/shared/server-route-handler.js +120 -0
  82. package/src/adapters/shared/server-route-handler.ts +166 -0
  83. package/src/adapters/shared/server-static-builder.d.ts +38 -0
  84. package/src/adapters/shared/server-static-builder.js +46 -0
  85. package/src/adapters/shared/server-static-builder.ts +82 -0
  86. package/src/build/build-adapter.d.ts +74 -0
  87. package/src/build/build-adapter.js +54 -0
  88. package/src/build/build-adapter.ts +132 -0
  89. package/src/build/build-types.d.ts +57 -0
  90. package/src/build/build-types.js +0 -0
  91. package/src/build/build-types.ts +83 -0
  92. package/src/build/esbuild-build-adapter.d.ts +69 -0
  93. package/src/build/esbuild-build-adapter.js +390 -0
  94. package/src/build/esbuild-build-adapter.ts +510 -0
  95. package/src/config/config-builder.d.ts +227 -0
  96. package/src/config/config-builder.js +392 -0
  97. package/src/config/config-builder.ts +474 -0
  98. package/src/constants.d.ts +32 -0
  99. package/src/constants.js +21 -0
  100. package/src/constants.ts +39 -0
  101. package/src/create-app.d.ts +17 -0
  102. package/src/create-app.js +66 -0
  103. package/src/create-app.ts +87 -0
  104. package/src/declarations.d.ts +26 -0
  105. package/src/define-api-handler.d.ts +25 -0
  106. package/src/define-api-handler.js +15 -0
  107. package/src/define-api-handler.ts +66 -0
  108. package/src/dev/sc-server.d.ts +30 -0
  109. package/src/dev/sc-server.js +111 -0
  110. package/src/dev/sc-server.ts +143 -0
  111. package/src/eco/README.md +636 -0
  112. package/src/eco/component-render-context.d.ts +105 -0
  113. package/src/eco/component-render-context.js +77 -0
  114. package/src/eco/component-render-context.ts +202 -0
  115. package/src/eco/eco.d.ts +9 -0
  116. package/src/eco/eco.js +110 -0
  117. package/src/eco/eco.ts +221 -0
  118. package/src/eco/eco.types.d.ts +170 -0
  119. package/src/eco/eco.types.js +0 -0
  120. package/src/eco/eco.types.ts +202 -0
  121. package/src/eco/eco.utils.d.ts +40 -0
  122. package/src/eco/eco.utils.js +40 -0
  123. package/src/eco/eco.utils.ts +89 -0
  124. package/src/eco/global-injector-map.d.ts +16 -0
  125. package/src/eco/global-injector-map.js +80 -0
  126. package/src/eco/global-injector-map.ts +112 -0
  127. package/src/eco/lazy-injector-map.d.ts +8 -0
  128. package/src/eco/lazy-injector-map.js +70 -0
  129. package/src/eco/lazy-injector-map.ts +120 -0
  130. package/src/eco/module-dependencies.d.ts +18 -0
  131. package/src/eco/module-dependencies.js +49 -0
  132. package/src/eco/module-dependencies.ts +75 -0
  133. package/src/env.d.ts +20 -0
  134. package/src/errors/http-error.d.ts +31 -0
  135. package/src/errors/http-error.js +50 -0
  136. package/src/errors/http-error.ts +72 -0
  137. package/src/errors/index.d.ts +2 -0
  138. package/src/errors/index.js +4 -0
  139. package/src/errors/index.ts +2 -0
  140. package/src/errors/locals-access-error.d.ts +4 -0
  141. package/src/errors/locals-access-error.js +9 -0
  142. package/src/errors/locals-access-error.ts +7 -0
  143. package/src/global/app-logger.d.ts +2 -0
  144. package/src/global/app-logger.js +6 -0
  145. package/src/global/app-logger.ts +4 -0
  146. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-have-HMR-script-injected-in-page-1.png +0 -0
  147. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-HMR-Server-Integration-should-load-fixture-app-page-1.png +0 -0
  148. package/src/hmr/client/__screenshots__/hmr-runtime.test.browser.ts/HMR-Runtime-WebSocket-Connection-should-connect-to-correct-HMR-endpoint-1.png +0 -0
  149. package/src/hmr/client/hmr-runtime.d.ts +10 -0
  150. package/src/hmr/client/hmr-runtime.js +86 -0
  151. package/src/hmr/client/hmr-runtime.ts +121 -0
  152. package/src/hmr/hmr-strategy.d.ts +159 -0
  153. package/src/hmr/hmr-strategy.js +29 -0
  154. package/src/hmr/hmr-strategy.ts +172 -0
  155. package/src/hmr/hmr.test.e2e.d.ts +1 -0
  156. package/src/hmr/hmr.test.e2e.js +50 -0
  157. package/src/hmr/hmr.test.e2e.ts +75 -0
  158. package/src/hmr/strategies/default-hmr-strategy.d.ts +43 -0
  159. package/src/hmr/strategies/default-hmr-strategy.js +34 -0
  160. package/src/hmr/strategies/default-hmr-strategy.ts +60 -0
  161. package/src/hmr/strategies/js-hmr-strategy.d.ts +136 -0
  162. package/src/hmr/strategies/js-hmr-strategy.js +179 -0
  163. package/src/hmr/strategies/js-hmr-strategy.ts +308 -0
  164. package/src/index.browser.d.ts +3 -0
  165. package/src/index.browser.js +4 -0
  166. package/src/index.browser.ts +3 -0
  167. package/src/index.d.ts +5 -0
  168. package/src/index.js +10 -0
  169. package/src/index.ts +5 -0
  170. package/src/integrations/ghtml/ghtml-renderer.d.ts +15 -0
  171. package/src/integrations/ghtml/ghtml-renderer.js +60 -0
  172. package/src/integrations/ghtml/ghtml-renderer.ts +93 -0
  173. package/src/integrations/ghtml/ghtml.plugin.d.ts +20 -0
  174. package/src/integrations/ghtml/ghtml.plugin.js +21 -0
  175. package/src/integrations/ghtml/ghtml.plugin.ts +32 -0
  176. package/src/internal-types.d.ts +200 -0
  177. package/src/internal-types.js +0 -0
  178. package/src/internal-types.ts +212 -0
  179. package/src/plugins/alias-resolver-plugin.d.ts +2 -0
  180. package/src/plugins/alias-resolver-plugin.js +39 -0
  181. package/src/plugins/alias-resolver-plugin.ts +45 -0
  182. package/src/plugins/eco-component-meta-plugin.d.ts +95 -0
  183. package/src/plugins/eco-component-meta-plugin.js +157 -0
  184. package/src/plugins/eco-component-meta-plugin.ts +474 -0
  185. package/src/plugins/integration-plugin.d.ts +102 -0
  186. package/src/plugins/integration-plugin.js +100 -0
  187. package/src/plugins/integration-plugin.ts +184 -0
  188. package/src/plugins/processor.d.ts +82 -0
  189. package/src/plugins/processor.js +122 -0
  190. package/src/plugins/processor.ts +220 -0
  191. package/src/public-types.d.ts +1094 -0
  192. package/src/public-types.js +0 -0
  193. package/src/public-types.ts +1255 -0
  194. package/src/route-renderer/GRAPH.md +387 -0
  195. package/src/route-renderer/README.md +135 -0
  196. package/src/route-renderer/component-graph-executor.d.ts +32 -0
  197. package/src/route-renderer/component-graph-executor.js +31 -0
  198. package/src/route-renderer/component-graph-executor.ts +84 -0
  199. package/src/route-renderer/component-graph.d.ts +42 -0
  200. package/src/route-renderer/component-graph.js +72 -0
  201. package/src/route-renderer/component-graph.ts +159 -0
  202. package/src/route-renderer/component-marker.d.ts +52 -0
  203. package/src/route-renderer/component-marker.js +46 -0
  204. package/src/route-renderer/component-marker.ts +117 -0
  205. package/src/route-renderer/dependency-resolver.d.ts +24 -0
  206. package/src/route-renderer/dependency-resolver.js +428 -0
  207. package/src/route-renderer/dependency-resolver.ts +596 -0
  208. package/src/route-renderer/html-post-processing.service.d.ts +40 -0
  209. package/src/route-renderer/html-post-processing.service.js +86 -0
  210. package/src/route-renderer/html-post-processing.service.ts +103 -0
  211. package/src/route-renderer/integration-renderer.d.ts +339 -0
  212. package/src/route-renderer/integration-renderer.js +526 -0
  213. package/src/route-renderer/integration-renderer.ts +696 -0
  214. package/src/route-renderer/marker-graph-resolver.d.ts +76 -0
  215. package/src/route-renderer/marker-graph-resolver.js +93 -0
  216. package/src/route-renderer/marker-graph-resolver.ts +153 -0
  217. package/src/route-renderer/page-module-loader.d.ts +61 -0
  218. package/src/route-renderer/page-module-loader.js +102 -0
  219. package/src/route-renderer/page-module-loader.ts +153 -0
  220. package/src/route-renderer/render-execution.service.d.ts +69 -0
  221. package/src/route-renderer/render-execution.service.js +91 -0
  222. package/src/route-renderer/render-execution.service.ts +158 -0
  223. package/src/route-renderer/render-preparation.service.d.ts +112 -0
  224. package/src/route-renderer/render-preparation.service.js +243 -0
  225. package/src/route-renderer/render-preparation.service.ts +358 -0
  226. package/src/route-renderer/route-renderer.d.ts +26 -0
  227. package/src/route-renderer/route-renderer.js +68 -0
  228. package/src/route-renderer/route-renderer.ts +80 -0
  229. package/src/router/fs-router-scanner.d.ts +41 -0
  230. package/src/router/fs-router-scanner.js +155 -0
  231. package/src/router/fs-router-scanner.ts +217 -0
  232. package/src/router/fs-router.d.ts +26 -0
  233. package/src/router/fs-router.js +100 -0
  234. package/src/router/fs-router.ts +122 -0
  235. package/src/services/asset-processing-service/asset-processing.service.d.ts +41 -0
  236. package/src/services/asset-processing-service/asset-processing.service.js +250 -0
  237. package/src/services/asset-processing-service/asset-processing.service.ts +306 -0
  238. package/src/services/asset-processing-service/asset.factory.d.ts +17 -0
  239. package/src/services/asset-processing-service/asset.factory.js +82 -0
  240. package/src/services/asset-processing-service/asset.factory.ts +105 -0
  241. package/src/services/asset-processing-service/assets.types.d.ts +88 -0
  242. package/src/services/asset-processing-service/assets.types.js +0 -0
  243. package/src/services/asset-processing-service/assets.types.ts +112 -0
  244. package/src/services/asset-processing-service/index.d.ts +3 -0
  245. package/src/services/asset-processing-service/index.js +3 -0
  246. package/src/services/asset-processing-service/index.ts +3 -0
  247. package/src/services/asset-processing-service/processor.interface.d.ts +22 -0
  248. package/src/services/asset-processing-service/processor.interface.js +6 -0
  249. package/src/services/asset-processing-service/processor.interface.ts +27 -0
  250. package/src/services/asset-processing-service/processor.registry.d.ts +8 -0
  251. package/src/services/asset-processing-service/processor.registry.js +15 -0
  252. package/src/services/asset-processing-service/processor.registry.ts +18 -0
  253. package/src/services/asset-processing-service/processors/base/base-processor.d.ts +24 -0
  254. package/src/services/asset-processing-service/processors/base/base-processor.js +59 -0
  255. package/src/services/asset-processing-service/processors/base/base-processor.ts +76 -0
  256. package/src/services/asset-processing-service/processors/base/base-script-processor.d.ts +16 -0
  257. package/src/services/asset-processing-service/processors/base/base-script-processor.js +80 -0
  258. package/src/services/asset-processing-service/processors/base/base-script-processor.ts +105 -0
  259. package/src/services/asset-processing-service/processors/index.d.ts +5 -0
  260. package/src/services/asset-processing-service/processors/index.js +5 -0
  261. package/src/services/asset-processing-service/processors/index.ts +5 -0
  262. package/src/services/asset-processing-service/processors/script/content-script.processor.d.ts +5 -0
  263. package/src/services/asset-processing-service/processors/script/content-script.processor.js +57 -0
  264. package/src/services/asset-processing-service/processors/script/content-script.processor.ts +66 -0
  265. package/src/services/asset-processing-service/processors/script/file-script.processor.d.ts +8 -0
  266. package/src/services/asset-processing-service/processors/script/file-script.processor.js +76 -0
  267. package/src/services/asset-processing-service/processors/script/file-script.processor.ts +88 -0
  268. package/src/services/asset-processing-service/processors/script/node-module-script.processor.d.ts +7 -0
  269. package/src/services/asset-processing-service/processors/script/node-module-script.processor.js +74 -0
  270. package/src/services/asset-processing-service/processors/script/node-module-script.processor.ts +84 -0
  271. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.d.ts +5 -0
  272. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.js +25 -0
  273. package/src/services/asset-processing-service/processors/stylesheet/content-stylesheet.processor.ts +27 -0
  274. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.d.ts +9 -0
  275. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.js +63 -0
  276. package/src/services/asset-processing-service/processors/stylesheet/file-stylesheet.processor.ts +77 -0
  277. package/src/services/cache/cache.types.d.ts +107 -0
  278. package/src/services/cache/cache.types.js +0 -0
  279. package/src/services/cache/cache.types.ts +126 -0
  280. package/src/services/cache/index.d.ts +7 -0
  281. package/src/services/cache/index.js +7 -0
  282. package/src/services/cache/index.ts +18 -0
  283. package/src/services/cache/memory-cache-store.d.ts +42 -0
  284. package/src/services/cache/memory-cache-store.js +98 -0
  285. package/src/services/cache/memory-cache-store.ts +130 -0
  286. package/src/services/cache/page-cache-service.d.ts +70 -0
  287. package/src/services/cache/page-cache-service.js +152 -0
  288. package/src/services/cache/page-cache-service.ts +202 -0
  289. package/src/services/html-transformer.service.d.ts +50 -0
  290. package/src/services/html-transformer.service.js +163 -0
  291. package/src/services/html-transformer.service.ts +217 -0
  292. package/src/services/page-module-import.service.d.ts +37 -0
  293. package/src/services/page-module-import.service.js +88 -0
  294. package/src/services/page-module-import.service.ts +129 -0
  295. package/src/services/page-request-cache-coordinator.service.d.ts +75 -0
  296. package/src/services/page-request-cache-coordinator.service.js +107 -0
  297. package/src/services/page-request-cache-coordinator.service.ts +128 -0
  298. package/src/services/schema-validation-service.d.ts +122 -0
  299. package/src/services/schema-validation-service.js +101 -0
  300. package/src/services/schema-validation-service.ts +204 -0
  301. package/src/services/validation/standard-schema.types.d.ts +65 -0
  302. package/src/services/validation/standard-schema.types.js +0 -0
  303. package/src/services/validation/standard-schema.types.ts +68 -0
  304. package/src/static-site-generator/static-site-generator.d.ts +57 -0
  305. package/src/static-site-generator/static-site-generator.js +272 -0
  306. package/src/static-site-generator/static-site-generator.ts +359 -0
  307. package/src/utils/css.d.ts +1 -0
  308. package/src/utils/css.js +7 -0
  309. package/src/utils/css.ts +5 -0
  310. package/src/utils/deep-merge.d.ts +14 -0
  311. package/src/utils/deep-merge.js +32 -0
  312. package/src/utils/deep-merge.ts +47 -0
  313. package/src/utils/hash.d.ts +1 -0
  314. package/src/utils/hash.js +7 -0
  315. package/src/utils/hash.ts +5 -0
  316. package/src/utils/html.d.ts +1 -0
  317. package/src/utils/html.js +4 -0
  318. package/src/utils/html.ts +1 -0
  319. package/src/utils/invariant.d.ts +5 -0
  320. package/src/utils/invariant.js +11 -0
  321. package/src/utils/invariant.ts +15 -0
  322. package/src/utils/locals-utils.d.ts +15 -0
  323. package/src/utils/locals-utils.js +24 -0
  324. package/src/utils/locals-utils.ts +37 -0
  325. package/src/utils/parse-cli-args.d.ts +24 -0
  326. package/src/utils/parse-cli-args.js +47 -0
  327. package/src/utils/parse-cli-args.ts +83 -0
  328. package/src/utils/path-utils.module.d.ts +5 -0
  329. package/src/utils/path-utils.module.js +14 -0
  330. package/src/utils/path-utils.module.ts +14 -0
  331. package/src/utils/runtime.d.ts +11 -0
  332. package/src/utils/runtime.js +40 -0
  333. package/src/utils/runtime.ts +44 -0
  334. package/src/utils/server-utils.module.d.ts +19 -0
  335. package/src/utils/server-utils.module.js +56 -0
  336. package/src/utils/server-utils.module.ts +67 -0
  337. package/src/watchers/project-watcher.d.ts +120 -0
  338. package/src/watchers/project-watcher.js +238 -0
  339. package/src/watchers/project-watcher.test-helpers.d.ts +4 -0
  340. package/src/watchers/project-watcher.test-helpers.js +51 -0
  341. package/src/watchers/project-watcher.test-helpers.ts +40 -0
  342. package/src/watchers/project-watcher.ts +306 -0
@@ -0,0 +1,166 @@
1
+ import { createServer } from "node:http";
2
+ import { extname, join, normalize, sep } from "node:path";
3
+ import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT, STATUS_MESSAGE } from "../../constants.js";
4
+ import { fileSystem } from "@ecopages/file-system";
5
+ import { ServerUtils } from "../../utils/server-utils.module.js";
6
+ class NodeStaticContentServer {
7
+ appConfig;
8
+ options;
9
+ server = null;
10
+ constructor({ appConfig, options }) {
11
+ this.appConfig = appConfig;
12
+ this.options = {
13
+ hostname: options?.hostname ?? DEFAULT_ECOPAGES_HOSTNAME,
14
+ port: options?.port ?? DEFAULT_ECOPAGES_PORT
15
+ };
16
+ }
17
+ shouldServeGzip(contentType) {
18
+ return ["text/javascript", "text/css"].includes(contentType);
19
+ }
20
+ sanitizePath(pathname) {
21
+ const withoutLeadingSlash = pathname.replace(/^\/+/, "");
22
+ const normalizedPath = normalize(withoutLeadingSlash);
23
+ if (normalizedPath.startsWith("..") || normalizedPath.includes(`..${sep}`)) {
24
+ return null;
25
+ }
26
+ return normalizedPath;
27
+ }
28
+ sendResponse(res, status, headers, body) {
29
+ res.statusCode = status;
30
+ for (const [key, value] of Object.entries(headers)) {
31
+ res.setHeader(key, value);
32
+ }
33
+ if (!body) {
34
+ res.end();
35
+ return;
36
+ }
37
+ res.end(body);
38
+ }
39
+ sendNotFoundPage(req, res) {
40
+ const error404TemplatePath = join(this.appConfig.absolutePaths.distDir, "404.html");
41
+ const isHead = (req.method ?? "GET").toUpperCase() === "HEAD";
42
+ if (!fileSystem.exists(error404TemplatePath)) {
43
+ this.sendResponse(
44
+ res,
45
+ 404,
46
+ { "Content-Type": "text/plain" },
47
+ isHead ? void 0 : Buffer.from(STATUS_MESSAGE[404])
48
+ );
49
+ return;
50
+ }
51
+ const file = fileSystem.readFileAsBuffer(error404TemplatePath);
52
+ this.sendResponse(res, 404, { "Content-Type": "text/html" }, isHead ? void 0 : file);
53
+ }
54
+ serveFile(req, res, filePath, status = 200) {
55
+ const contentType = ServerUtils.getContentType(extname(filePath));
56
+ const acceptsGzip = req.headers["accept-encoding"]?.includes("gzip");
57
+ const isHead = (req.method ?? "GET").toUpperCase() === "HEAD";
58
+ if (acceptsGzip && this.shouldServeGzip(contentType)) {
59
+ const gzipPath = `${filePath}.gz`;
60
+ if (fileSystem.exists(gzipPath)) {
61
+ const file2 = fileSystem.readFileAsBuffer(gzipPath);
62
+ this.sendResponse(
63
+ res,
64
+ status,
65
+ {
66
+ "Content-Type": contentType,
67
+ "Content-Encoding": "gzip",
68
+ Vary: "Accept-Encoding"
69
+ },
70
+ isHead ? void 0 : file2
71
+ );
72
+ return;
73
+ }
74
+ }
75
+ if (!fileSystem.exists(filePath)) {
76
+ this.sendNotFoundPage(req, res);
77
+ return;
78
+ }
79
+ const file = fileSystem.readFileAsBuffer(filePath);
80
+ this.sendResponse(res, status, { "Content-Type": contentType }, isHead ? void 0 : file);
81
+ }
82
+ handleRequest(req, res) {
83
+ const method = (req.method ?? "GET").toUpperCase();
84
+ const isHead = method === "HEAD";
85
+ if (method !== "GET" && method !== "HEAD") {
86
+ this.sendResponse(
87
+ res,
88
+ 405,
89
+ { Allow: "GET, HEAD", "Content-Type": "text/plain" },
90
+ isHead ? void 0 : Buffer.from("Method Not Allowed")
91
+ );
92
+ return;
93
+ }
94
+ const url = new URL(req.url ?? "/", "http://localhost");
95
+ let decodedPathname = "/";
96
+ try {
97
+ decodedPathname = decodeURIComponent(url.pathname);
98
+ } catch {
99
+ this.sendResponse(
100
+ res,
101
+ 400,
102
+ { "Content-Type": "text/plain" },
103
+ isHead ? void 0 : Buffer.from("Invalid path")
104
+ );
105
+ return;
106
+ }
107
+ const pathname = decodedPathname === "/" ? "/index.html" : decodedPathname;
108
+ const relativePath = this.sanitizePath(pathname);
109
+ if (!relativePath) {
110
+ this.sendResponse(
111
+ res,
112
+ 400,
113
+ { "Content-Type": "text/plain" },
114
+ isHead ? void 0 : Buffer.from("Invalid path")
115
+ );
116
+ return;
117
+ }
118
+ const basePath = join(this.appConfig.absolutePaths.distDir, relativePath);
119
+ if (pathname.includes(".")) {
120
+ this.serveFile(req, res, basePath);
121
+ return;
122
+ }
123
+ const htmlCandidates = [`${basePath}.html`, join(basePath, "index.html")];
124
+ for (const candidate of htmlCandidates) {
125
+ if (fileSystem.exists(candidate)) {
126
+ this.serveFile(req, res, candidate);
127
+ return;
128
+ }
129
+ }
130
+ this.sendNotFoundPage(req, res);
131
+ }
132
+ async start() {
133
+ if (this.server) {
134
+ return this.server;
135
+ }
136
+ this.server = createServer(this.handleRequest.bind(this));
137
+ const hostname = this.options.hostname ?? DEFAULT_ECOPAGES_HOSTNAME;
138
+ const port = this.options.port ?? DEFAULT_ECOPAGES_PORT;
139
+ await new Promise((resolve) => {
140
+ this.server.listen(port, hostname, () => resolve());
141
+ });
142
+ return this.server;
143
+ }
144
+ async stop(force = true) {
145
+ if (!this.server) {
146
+ return;
147
+ }
148
+ const activeServer = this.server;
149
+ this.server = null;
150
+ await new Promise((resolve, reject) => {
151
+ activeServer.close((error) => {
152
+ if (error) {
153
+ reject(error);
154
+ return;
155
+ }
156
+ resolve();
157
+ });
158
+ if (force) {
159
+ activeServer.closeAllConnections();
160
+ }
161
+ });
162
+ }
163
+ }
164
+ export {
165
+ NodeStaticContentServer
166
+ };
@@ -0,0 +1,203 @@
1
+ import { createServer, type IncomingMessage, type Server as NodeHttpServer, type ServerResponse } from 'node:http';
2
+ import { extname, join, normalize, sep } from 'node:path';
3
+ import { DEFAULT_ECOPAGES_HOSTNAME, DEFAULT_ECOPAGES_PORT, STATUS_MESSAGE } from '../../constants.ts';
4
+ import { fileSystem } from '@ecopages/file-system';
5
+ import type { EcoPagesAppConfig } from '../../internal-types.ts';
6
+ import { ServerUtils } from '../../utils/server-utils.module.ts';
7
+
8
+ type NodeStaticContentServerOptions = {
9
+ hostname?: string;
10
+ port?: number;
11
+ };
12
+
13
+ export class NodeStaticContentServer {
14
+ private readonly appConfig: EcoPagesAppConfig;
15
+ private readonly options: NodeStaticContentServerOptions;
16
+ private server: NodeHttpServer | null = null;
17
+
18
+ constructor({ appConfig, options }: { appConfig: EcoPagesAppConfig; options?: NodeStaticContentServerOptions }) {
19
+ this.appConfig = appConfig;
20
+ this.options = {
21
+ hostname: options?.hostname ?? DEFAULT_ECOPAGES_HOSTNAME,
22
+ port: options?.port ?? DEFAULT_ECOPAGES_PORT,
23
+ };
24
+ }
25
+
26
+ private shouldServeGzip(contentType: string): boolean {
27
+ return ['text/javascript', 'text/css'].includes(contentType);
28
+ }
29
+
30
+ private sanitizePath(pathname: string): string | null {
31
+ const withoutLeadingSlash = pathname.replace(/^\/+/, '');
32
+ const normalizedPath = normalize(withoutLeadingSlash);
33
+
34
+ if (normalizedPath.startsWith('..') || normalizedPath.includes(`..${sep}`)) {
35
+ return null;
36
+ }
37
+
38
+ return normalizedPath;
39
+ }
40
+
41
+ private sendResponse(res: ServerResponse, status: number, headers: Record<string, string>, body?: Buffer): void {
42
+ res.statusCode = status;
43
+ for (const [key, value] of Object.entries(headers)) {
44
+ res.setHeader(key, value);
45
+ }
46
+
47
+ if (!body) {
48
+ res.end();
49
+ return;
50
+ }
51
+
52
+ res.end(body);
53
+ }
54
+
55
+ private sendNotFoundPage(req: IncomingMessage, res: ServerResponse): void {
56
+ const error404TemplatePath = join(this.appConfig.absolutePaths.distDir, '404.html');
57
+ const isHead = (req.method ?? 'GET').toUpperCase() === 'HEAD';
58
+
59
+ if (!fileSystem.exists(error404TemplatePath)) {
60
+ this.sendResponse(
61
+ res,
62
+ 404,
63
+ { 'Content-Type': 'text/plain' },
64
+ isHead ? undefined : Buffer.from(STATUS_MESSAGE[404]),
65
+ );
66
+ return;
67
+ }
68
+
69
+ const file = fileSystem.readFileAsBuffer(error404TemplatePath);
70
+ this.sendResponse(res, 404, { 'Content-Type': 'text/html' }, isHead ? undefined : file);
71
+ }
72
+
73
+ private serveFile(req: IncomingMessage, res: ServerResponse, filePath: string, status = 200): void {
74
+ const contentType = ServerUtils.getContentType(extname(filePath));
75
+ const acceptsGzip = req.headers['accept-encoding']?.includes('gzip');
76
+ const isHead = (req.method ?? 'GET').toUpperCase() === 'HEAD';
77
+
78
+ if (acceptsGzip && this.shouldServeGzip(contentType)) {
79
+ const gzipPath = `${filePath}.gz`;
80
+ if (fileSystem.exists(gzipPath)) {
81
+ const file = fileSystem.readFileAsBuffer(gzipPath);
82
+ this.sendResponse(
83
+ res,
84
+ status,
85
+ {
86
+ 'Content-Type': contentType,
87
+ 'Content-Encoding': 'gzip',
88
+ Vary: 'Accept-Encoding',
89
+ },
90
+ isHead ? undefined : file,
91
+ );
92
+ return;
93
+ }
94
+ }
95
+
96
+ if (!fileSystem.exists(filePath)) {
97
+ this.sendNotFoundPage(req, res);
98
+ return;
99
+ }
100
+
101
+ const file = fileSystem.readFileAsBuffer(filePath);
102
+ this.sendResponse(res, status, { 'Content-Type': contentType }, isHead ? undefined : file);
103
+ }
104
+
105
+ private handleRequest(req: IncomingMessage, res: ServerResponse): void {
106
+ const method = (req.method ?? 'GET').toUpperCase();
107
+ const isHead = method === 'HEAD';
108
+ if (method !== 'GET' && method !== 'HEAD') {
109
+ this.sendResponse(
110
+ res,
111
+ 405,
112
+ { Allow: 'GET, HEAD', 'Content-Type': 'text/plain' },
113
+ isHead ? undefined : Buffer.from('Method Not Allowed'),
114
+ );
115
+ return;
116
+ }
117
+
118
+ const url = new URL(req.url ?? '/', 'http://localhost');
119
+ let decodedPathname = '/';
120
+ try {
121
+ decodedPathname = decodeURIComponent(url.pathname);
122
+ } catch {
123
+ this.sendResponse(
124
+ res,
125
+ 400,
126
+ { 'Content-Type': 'text/plain' },
127
+ isHead ? undefined : Buffer.from('Invalid path'),
128
+ );
129
+ return;
130
+ }
131
+
132
+ const pathname = decodedPathname === '/' ? '/index.html' : decodedPathname;
133
+ const relativePath = this.sanitizePath(pathname);
134
+
135
+ if (!relativePath) {
136
+ this.sendResponse(
137
+ res,
138
+ 400,
139
+ { 'Content-Type': 'text/plain' },
140
+ isHead ? undefined : Buffer.from('Invalid path'),
141
+ );
142
+ return;
143
+ }
144
+
145
+ const basePath = join(this.appConfig.absolutePaths.distDir, relativePath);
146
+
147
+ if (pathname.includes('.')) {
148
+ this.serveFile(req, res, basePath);
149
+ return;
150
+ }
151
+
152
+ const htmlCandidates = [`${basePath}.html`, join(basePath, 'index.html')];
153
+
154
+ for (const candidate of htmlCandidates) {
155
+ if (fileSystem.exists(candidate)) {
156
+ this.serveFile(req, res, candidate);
157
+ return;
158
+ }
159
+ }
160
+
161
+ this.sendNotFoundPage(req, res);
162
+ }
163
+
164
+ public async start(): Promise<NodeHttpServer> {
165
+ if (this.server) {
166
+ return this.server;
167
+ }
168
+
169
+ this.server = createServer(this.handleRequest.bind(this));
170
+ const hostname = this.options.hostname ?? DEFAULT_ECOPAGES_HOSTNAME;
171
+ const port = this.options.port ?? DEFAULT_ECOPAGES_PORT;
172
+
173
+ await new Promise<void>((resolve) => {
174
+ this.server!.listen(port, hostname, () => resolve());
175
+ });
176
+
177
+ return this.server;
178
+ }
179
+
180
+ public async stop(force = true): Promise<void> {
181
+ if (!this.server) {
182
+ return;
183
+ }
184
+
185
+ const activeServer = this.server;
186
+ this.server = null;
187
+
188
+ await new Promise<void>((resolve, reject) => {
189
+ activeServer.close((error) => {
190
+ if (error) {
191
+ reject(error);
192
+ return;
193
+ }
194
+
195
+ resolve();
196
+ });
197
+
198
+ if (force) {
199
+ activeServer.closeAllConnections();
200
+ }
201
+ });
202
+ }
203
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * A builder class for creating Response objects fluently.
3
+ */
4
+ export declare class ApiResponseBuilder {
5
+ private _status;
6
+ private _headers;
7
+ /**
8
+ * Sets the HTTP status code for the response.
9
+ * @param code - The HTTP status code.
10
+ * @returns The builder instance for chaining.
11
+ */
12
+ status(code: Response['status']): this;
13
+ /**
14
+ * Adds or merges headers for the response.
15
+ * @param headersInit - Headers to add or merge.
16
+ * @returns The builder instance for chaining.
17
+ */
18
+ headers(headersInit: HeadersInit): this;
19
+ /**
20
+ * Creates a JSON response using the configured status and headers.
21
+ * @param data - The data to serialize.
22
+ * @returns A Response object.
23
+ */
24
+ json(data: any): Response;
25
+ /**
26
+ * Creates a plain text response using the configured status and headers.
27
+ * @param data - The text content.
28
+ * @returns A Response object.
29
+ */
30
+ text(data: string): Response;
31
+ /**
32
+ * Creates an HTML response using the configured status and headers.
33
+ * @param data - The HTML content.
34
+ * @returns A Response object.
35
+ */
36
+ html(data: string): Response;
37
+ /**
38
+ * Creates a redirect response.
39
+ * @param url - The URL to redirect to.
40
+ * @param explicitStatus - Optional explicit status code (overrides status() if provided). Defaults to 302 if not set via status().
41
+ * @returns A Response object.
42
+ */
43
+ redirect(url: string, explicitStatus?: Response['status']): Response;
44
+ /**
45
+ * Creates an error response using the configured status and headers.
46
+ * If data is an object, it's treated as JSON, otherwise as text.
47
+ * @param data - The error data (string or object).
48
+ * @param explicitStatus - Optional explicit status code (overrides status() if provided). Defaults to 500 if not set via status().
49
+ * @returns A Response object.
50
+ */
51
+ error(data: string | object, explicitStatus?: Response['status']): Response;
52
+ }
@@ -0,0 +1,96 @@
1
+ class ApiResponseBuilder {
2
+ _status = 200;
3
+ _headers = new Headers();
4
+ /**
5
+ * Sets the HTTP status code for the response.
6
+ * @param code - The HTTP status code.
7
+ * @returns The builder instance for chaining.
8
+ */
9
+ status(code) {
10
+ this._status = code;
11
+ return this;
12
+ }
13
+ /**
14
+ * Adds or merges headers for the response.
15
+ * @param headersInit - Headers to add or merge.
16
+ * @returns The builder instance for chaining.
17
+ */
18
+ headers(headersInit) {
19
+ const inputHeaders = new Headers(headersInit);
20
+ inputHeaders.forEach((value, key) => {
21
+ this._headers.set(key, value);
22
+ });
23
+ return this;
24
+ }
25
+ /**
26
+ * Creates a JSON response using the configured status and headers.
27
+ * @param data - The data to serialize.
28
+ * @returns A Response object.
29
+ */
30
+ json(data) {
31
+ if (!this._headers.has("Content-Type")) {
32
+ this._headers.set("Content-Type", "application/json; charset=utf-8");
33
+ }
34
+ return new Response(JSON.stringify(data), { status: this._status, headers: this._headers });
35
+ }
36
+ /**
37
+ * Creates a plain text response using the configured status and headers.
38
+ * @param data - The text content.
39
+ * @returns A Response object.
40
+ */
41
+ text(data) {
42
+ if (!this._headers.has("Content-Type")) {
43
+ this._headers.set("Content-Type", "text/plain; charset=utf-8");
44
+ }
45
+ return new Response(data, { status: this._status, headers: this._headers });
46
+ }
47
+ /**
48
+ * Creates an HTML response using the configured status and headers.
49
+ * @param data - The HTML content.
50
+ * @returns A Response object.
51
+ */
52
+ html(data) {
53
+ if (!this._headers.has("Content-Type")) {
54
+ this._headers.set("Content-Type", "text/html; charset=utf-8");
55
+ }
56
+ return new Response(data, { status: this._status, headers: this._headers });
57
+ }
58
+ /**
59
+ * Creates a redirect response.
60
+ * @param url - The URL to redirect to.
61
+ * @param explicitStatus - Optional explicit status code (overrides status() if provided). Defaults to 302 if not set via status().
62
+ * @returns A Response object.
63
+ */
64
+ redirect(url, explicitStatus) {
65
+ const redirectStatus = explicitStatus ?? (this._status === 200 ? 302 : this._status);
66
+ this._headers.set("Location", url);
67
+ return new Response(null, { status: redirectStatus, headers: this._headers });
68
+ }
69
+ /**
70
+ * Creates an error response using the configured status and headers.
71
+ * If data is an object, it's treated as JSON, otherwise as text.
72
+ * @param data - The error data (string or object).
73
+ * @param explicitStatus - Optional explicit status code (overrides status() if provided). Defaults to 500 if not set via status().
74
+ * @returns A Response object.
75
+ */
76
+ error(data, explicitStatus) {
77
+ const errorStatus = explicitStatus ?? (this._status === 200 ? 500 : this._status);
78
+ this.status(errorStatus);
79
+ if (typeof data === "object" && data !== null) {
80
+ if (!this._headers.has("Content-Type")) {
81
+ this._headers.set("Content-Type", "application/json; charset=utf-8");
82
+ }
83
+ return new Response(JSON.stringify({ error: data }), {
84
+ status: this._status,
85
+ headers: this._headers
86
+ });
87
+ }
88
+ if (!this._headers.has("Content-Type")) {
89
+ this._headers.set("Content-Type", "text/plain; charset=utf-8");
90
+ }
91
+ return new Response(String(data), { status: this._status, headers: this._headers });
92
+ }
93
+ }
94
+ export {
95
+ ApiResponseBuilder
96
+ };
@@ -0,0 +1,104 @@
1
+ /**
2
+ * A builder class for creating Response objects fluently.
3
+ */
4
+ export class ApiResponseBuilder {
5
+ private _status: Response['status'] = 200;
6
+ private _headers: Headers = new Headers();
7
+
8
+ /**
9
+ * Sets the HTTP status code for the response.
10
+ * @param code - The HTTP status code.
11
+ * @returns The builder instance for chaining.
12
+ */
13
+ status(code: Response['status']): this {
14
+ this._status = code;
15
+ return this;
16
+ }
17
+
18
+ /**
19
+ * Adds or merges headers for the response.
20
+ * @param headersInit - Headers to add or merge.
21
+ * @returns The builder instance for chaining.
22
+ */
23
+ headers(headersInit: HeadersInit): this {
24
+ const inputHeaders = new Headers(headersInit);
25
+ inputHeaders.forEach((value, key) => {
26
+ this._headers.set(key, value);
27
+ });
28
+ return this;
29
+ }
30
+
31
+ /**
32
+ * Creates a JSON response using the configured status and headers.
33
+ * @param data - The data to serialize.
34
+ * @returns A Response object.
35
+ */
36
+ json(data: any): Response {
37
+ if (!this._headers.has('Content-Type')) {
38
+ this._headers.set('Content-Type', 'application/json; charset=utf-8');
39
+ }
40
+ return new Response(JSON.stringify(data), { status: this._status, headers: this._headers });
41
+ }
42
+
43
+ /**
44
+ * Creates a plain text response using the configured status and headers.
45
+ * @param data - The text content.
46
+ * @returns A Response object.
47
+ */
48
+ text(data: string): Response {
49
+ if (!this._headers.has('Content-Type')) {
50
+ this._headers.set('Content-Type', 'text/plain; charset=utf-8');
51
+ }
52
+ return new Response(data, { status: this._status, headers: this._headers });
53
+ }
54
+
55
+ /**
56
+ * Creates an HTML response using the configured status and headers.
57
+ * @param data - The HTML content.
58
+ * @returns A Response object.
59
+ */
60
+ html(data: string): Response {
61
+ if (!this._headers.has('Content-Type')) {
62
+ this._headers.set('Content-Type', 'text/html; charset=utf-8');
63
+ }
64
+ return new Response(data, { status: this._status, headers: this._headers });
65
+ }
66
+
67
+ /**
68
+ * Creates a redirect response.
69
+ * @param url - The URL to redirect to.
70
+ * @param explicitStatus - Optional explicit status code (overrides status() if provided). Defaults to 302 if not set via status().
71
+ * @returns A Response object.
72
+ */
73
+ redirect(url: string, explicitStatus?: Response['status']): Response {
74
+ const redirectStatus = explicitStatus ?? (this._status === 200 ? 302 : this._status); // Default to 302 if status wasn't explicitly set
75
+ this._headers.set('Location', url);
76
+ return new Response(null, { status: redirectStatus, headers: this._headers });
77
+ }
78
+
79
+ /**
80
+ * Creates an error response using the configured status and headers.
81
+ * If data is an object, it's treated as JSON, otherwise as text.
82
+ * @param data - The error data (string or object).
83
+ * @param explicitStatus - Optional explicit status code (overrides status() if provided). Defaults to 500 if not set via status().
84
+ * @returns A Response object.
85
+ */
86
+ error(data: string | object, explicitStatus?: Response['status']): Response {
87
+ const errorStatus = explicitStatus ?? (this._status === 200 ? 500 : this._status); // Default to 500 if status wasn't explicitly set
88
+ this.status(errorStatus);
89
+
90
+ if (typeof data === 'object' && data !== null) {
91
+ if (!this._headers.has('Content-Type')) {
92
+ this._headers.set('Content-Type', 'application/json; charset=utf-8');
93
+ }
94
+ return new Response(JSON.stringify({ error: data }), {
95
+ status: this._status,
96
+ headers: this._headers,
97
+ });
98
+ }
99
+ if (!this._headers.has('Content-Type')) {
100
+ this._headers.set('Content-Type', 'text/plain; charset=utf-8');
101
+ }
102
+ return new Response(String(data), { status: this._status, headers: this._headers });
103
+ }
104
+ }
@@ -0,0 +1,18 @@
1
+ import type { ApiHandler, ApiHandlerContext, Middleware, RouteGroupBuilder, RouteOptions } from '../../public-types.js';
2
+ import { AbstractApplicationAdapter, type ApplicationAdapterOptions, type RouteGroupDefinition, type RouteHandler } from '../abstract/application-adapter.js';
3
+ export declare abstract class SharedApplicationAdapter<TOptions extends ApplicationAdapterOptions = ApplicationAdapterOptions, TServer = any, TRequest extends Request = Request> extends AbstractApplicationAdapter<TOptions, TServer, TRequest> {
4
+ protected register<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, method: ApiHandler['method'], handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
5
+ get<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
6
+ post<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
7
+ put<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
8
+ delete<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
9
+ patch<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
10
+ options<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
11
+ head<P extends string, TContext extends ApiHandlerContext<TRequest, TServer> = ApiHandlerContext<TRequest, TServer>>(path: P, handler: RouteHandler<TRequest, TServer, TContext>, options?: RouteOptions<TRequest, TServer, TContext>): this;
12
+ route<P extends string>(path: P, method: ApiHandler['method'], handler: RouteHandler<TRequest, TServer>, options?: RouteOptions<TRequest, TServer>): this;
13
+ add(handler: ApiHandler<string, TRequest, TServer>): this;
14
+ group<TMiddleware extends readonly Middleware<TRequest, TServer, any>[] = []>(prefixOrGroup: string | RouteGroupDefinition<TRequest, TServer>, callback?: (builder: TMiddleware extends readonly Middleware<TRequest, TServer, infer TContext>[] ? RouteGroupBuilder<TRequest, TServer, TContext> : RouteGroupBuilder<TRequest, TServer>) => void, options?: {
15
+ middleware?: TMiddleware;
16
+ }): this;
17
+ private registerGroup;
18
+ }