theokit 0.48.13 → 0.50.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 (327) hide show
  1. package/README.md +1 -0
  2. package/dist/{actions-virtual-module-YQXRSSMW.js → actions-virtual-module-5WBVSDOM.js} +22 -12
  3. package/dist/actions-virtual-module-5WBVSDOM.js.map +1 -0
  4. package/dist/{actions-virtual-module-LB4NGONI.js → actions-virtual-module-ZYLMNW6K.js} +13 -8
  5. package/dist/{actions-virtual-module-LB4NGONI.js.map → actions-virtual-module-ZYLMNW6K.js.map} +1 -1
  6. package/dist/adapters/agent-mount.d.ts +127 -0
  7. package/dist/adapters/agent-mount.js +24 -0
  8. package/dist/adapters/security-headers.d.ts +132 -0
  9. package/dist/adapters/security-headers.js +64 -0
  10. package/dist/adapters/security-headers.js.map +1 -0
  11. package/dist/adapters/web-shim.d.ts +100 -13
  12. package/dist/adapters/web-shim.js +158 -54
  13. package/dist/adapters/web-shim.js.map +1 -1
  14. package/dist/agent-GKUEL6OH.js +15 -0
  15. package/dist/agent-scan-BZa-pagG.d.ts +16 -0
  16. package/dist/{app-typed-client-GHO3EWZK.js → app-typed-client-4LAIEGFX.js} +23 -13
  17. package/dist/app-typed-client-4LAIEGFX.js.map +1 -0
  18. package/dist/{app-typed-client-G3J5G7E5.js → app-typed-client-DQM3Y6YY.js} +14 -9
  19. package/dist/app-typed-client-DQM3Y6YY.js.map +1 -0
  20. package/dist/aws-lambda-VKMYUMP2.js +261 -0
  21. package/dist/aws-lambda-VKMYUMP2.js.map +1 -0
  22. package/dist/{build-WU6AKKIB.js → build-FLX6VF7Q.js} +71 -26
  23. package/dist/build-FLX6VF7Q.js.map +1 -0
  24. package/dist/{bun-33RD6K7O.js → bun-L7PP6ID5.js} +105 -13
  25. package/dist/bun-L7PP6ID5.js.map +1 -0
  26. package/dist/{check-45NKUVSQ.js → check-GIPZBFTX.js} +2 -2
  27. package/dist/{chunk-KD5G3YXI.js → chunk-2AMLGJJA.js} +35 -9
  28. package/dist/chunk-2AMLGJJA.js.map +1 -0
  29. package/dist/chunk-3PBAN2YE.js +146 -0
  30. package/dist/chunk-3PBAN2YE.js.map +1 -0
  31. package/dist/{chunk-HBU2GIMZ.js → chunk-3QPVEJ7D.js} +15 -9
  32. package/dist/chunk-3QPVEJ7D.js.map +1 -0
  33. package/dist/{chunk-47CINLWF.js → chunk-44J2ANQC.js} +2 -2
  34. package/dist/{chunk-IEES3CHD.js → chunk-47MM2JUK.js} +8 -2
  35. package/dist/chunk-47MM2JUK.js.map +1 -0
  36. package/dist/chunk-4X6H2BXP.js +108 -0
  37. package/dist/chunk-4X6H2BXP.js.map +1 -0
  38. package/dist/{chunk-A7JBF5FO.js → chunk-5K4TDLRG.js} +8 -5
  39. package/dist/chunk-5K4TDLRG.js.map +1 -0
  40. package/dist/chunk-5YPXXSYY.js +181 -0
  41. package/dist/chunk-5YPXXSYY.js.map +1 -0
  42. package/dist/{chunk-YGAXV5HR.js → chunk-6J4JWHDJ.js} +191 -112
  43. package/dist/chunk-6J4JWHDJ.js.map +1 -0
  44. package/dist/chunk-72DMJBXI.js +424 -0
  45. package/dist/chunk-72DMJBXI.js.map +1 -0
  46. package/dist/chunk-7PM6K5EV.js +513 -0
  47. package/dist/chunk-7PM6K5EV.js.map +1 -0
  48. package/dist/{chunk-MTEWLGVY.js → chunk-BPYMC7SU.js} +4 -48
  49. package/dist/chunk-BPYMC7SU.js.map +1 -0
  50. package/dist/chunk-BU6RJPPJ.js +421 -0
  51. package/dist/chunk-BU6RJPPJ.js.map +1 -0
  52. package/dist/{chunk-FB2HBNIC.js → chunk-BX6EUYHU.js} +6 -2
  53. package/dist/chunk-BX6EUYHU.js.map +1 -0
  54. package/dist/{chunk-BIVCP6X5.js → chunk-C62IZEJI.js} +465 -202
  55. package/dist/chunk-C62IZEJI.js.map +1 -0
  56. package/dist/chunk-D4VP2QPR.js +16 -0
  57. package/dist/chunk-D4VP2QPR.js.map +1 -0
  58. package/dist/{chunk-J5MXCGKA.js → chunk-DHAD2O3S.js} +6 -6
  59. package/dist/chunk-DHAD2O3S.js.map +1 -0
  60. package/dist/chunk-E43VJ3E5.js +188 -0
  61. package/dist/chunk-E43VJ3E5.js.map +1 -0
  62. package/dist/chunk-EVZKNA2W.js +110 -0
  63. package/dist/chunk-EVZKNA2W.js.map +1 -0
  64. package/dist/chunk-FD4ZDTQ6.js +181 -0
  65. package/dist/chunk-FD4ZDTQ6.js.map +1 -0
  66. package/dist/chunk-FDOOBTXJ.js +17 -0
  67. package/dist/chunk-FDOOBTXJ.js.map +1 -0
  68. package/dist/chunk-FH3SQR6P.js +275 -0
  69. package/dist/chunk-FH3SQR6P.js.map +1 -0
  70. package/dist/chunk-HJHGTFEJ.js +23 -0
  71. package/dist/chunk-HJHGTFEJ.js.map +1 -0
  72. package/dist/{chunk-LXAESF4Y.js → chunk-HK4AZBKX.js} +7 -4
  73. package/dist/chunk-HK4AZBKX.js.map +1 -0
  74. package/dist/{chunk-T5C46IIU.js → chunk-HWBRS4DZ.js} +28 -269
  75. package/dist/chunk-HWBRS4DZ.js.map +1 -0
  76. package/dist/chunk-IRQGAC4L.js +52 -0
  77. package/dist/chunk-IRQGAC4L.js.map +1 -0
  78. package/dist/{chunk-FNTLKHZ7.js → chunk-JDN5SAAD.js} +7 -4
  79. package/dist/chunk-JDN5SAAD.js.map +1 -0
  80. package/dist/{chunk-GXEX4CBH.js → chunk-JIKNR5LX.js} +673 -484
  81. package/dist/chunk-JIKNR5LX.js.map +1 -0
  82. package/dist/{chunk-GRI4XHBJ.js → chunk-JWRCZIA4.js} +266 -108
  83. package/dist/chunk-JWRCZIA4.js.map +1 -0
  84. package/dist/{chunk-E576KYYT.js → chunk-KI4DOTN4.js} +25 -2
  85. package/dist/chunk-KI4DOTN4.js.map +1 -0
  86. package/dist/{chunk-ZB7D62OA.js → chunk-KUZVRJ7M.js} +3 -3
  87. package/dist/chunk-L4VFNFDL.js +248 -0
  88. package/dist/chunk-L4VFNFDL.js.map +1 -0
  89. package/dist/chunk-M2WC5MF7.js +127 -0
  90. package/dist/chunk-M2WC5MF7.js.map +1 -0
  91. package/dist/{chunk-O3JIAU3V.js → chunk-MCTC6HSE.js} +157 -103
  92. package/dist/chunk-MCTC6HSE.js.map +1 -0
  93. package/dist/{chunk-PXFXSFJL.js → chunk-NZ5JU6D3.js} +9 -9
  94. package/dist/{chunk-YRBR424R.js → chunk-OAUI273L.js} +338 -165
  95. package/dist/chunk-OAUI273L.js.map +1 -0
  96. package/dist/chunk-OGLS76RN.js +43 -0
  97. package/dist/chunk-OGLS76RN.js.map +1 -0
  98. package/dist/{chunk-7LVM22VG.js → chunk-OQCRCXCP.js} +6 -6
  99. package/dist/chunk-OQCRCXCP.js.map +1 -0
  100. package/dist/{chunk-OLGPYOLO.js → chunk-P6OS7652.js} +5 -2
  101. package/dist/chunk-P6OS7652.js.map +1 -0
  102. package/dist/chunk-Q5L5EGWZ.js +26 -0
  103. package/dist/chunk-Q5L5EGWZ.js.map +1 -0
  104. package/dist/{chunk-S433N3CT.js → chunk-QTHVHNJJ.js} +6 -36
  105. package/dist/chunk-QTHVHNJJ.js.map +1 -0
  106. package/dist/chunk-RPET332G.js +84 -0
  107. package/dist/chunk-RPET332G.js.map +1 -0
  108. package/dist/{chunk-646CA6RV.js → chunk-RQW5YMH7.js} +12 -4
  109. package/dist/chunk-RQW5YMH7.js.map +1 -0
  110. package/dist/{chunk-XALU5LCU.js → chunk-RWNYIU6A.js} +550 -146
  111. package/dist/chunk-RWNYIU6A.js.map +1 -0
  112. package/dist/chunk-SL7YUHPV.js +111 -0
  113. package/dist/chunk-SL7YUHPV.js.map +1 -0
  114. package/dist/chunk-U5PWXS3J.js +39 -0
  115. package/dist/chunk-U5PWXS3J.js.map +1 -0
  116. package/dist/chunk-ULDCFL2O.js +273 -0
  117. package/dist/chunk-ULDCFL2O.js.map +1 -0
  118. package/dist/{chunk-RWNSW4FM.js → chunk-UMNXCU3K.js} +12 -6
  119. package/dist/{chunk-RWNSW4FM.js.map → chunk-UMNXCU3K.js.map} +1 -1
  120. package/dist/chunk-VI7ZANB3.js +193 -0
  121. package/dist/chunk-VI7ZANB3.js.map +1 -0
  122. package/dist/chunk-VQPHPQ5L.js +14 -0
  123. package/dist/chunk-VQPHPQ5L.js.map +1 -0
  124. package/dist/chunk-WNJTJRM6.js +147 -0
  125. package/dist/chunk-WNJTJRM6.js.map +1 -0
  126. package/dist/chunk-WOBSEO75.js +790 -0
  127. package/dist/chunk-WOBSEO75.js.map +1 -0
  128. package/dist/{chunk-BMHS4WAN.js → chunk-XS7EX55U.js} +156 -42
  129. package/dist/chunk-XS7EX55U.js.map +1 -0
  130. package/dist/chunk-YN4W7LCX.js +31 -0
  131. package/dist/chunk-YN4W7LCX.js.map +1 -0
  132. package/dist/chunk-YSJOZEI6.js +1 -0
  133. package/dist/{chunk-JA2ZAT5Q.js → chunk-Z4PJMZLM.js} +2 -2
  134. package/dist/chunk-Z4PJMZLM.js.map +1 -0
  135. package/dist/{chunk-7VPQHEAJ.js → chunk-ZNZISJDZ.js} +6 -2
  136. package/dist/chunk-ZNZISJDZ.js.map +1 -0
  137. package/dist/chunk-ZWN3AODA.js +11 -0
  138. package/dist/chunk-ZWN3AODA.js.map +1 -0
  139. package/dist/cli/index.js +25 -10
  140. package/dist/cli/index.js.map +1 -1
  141. package/dist/client/core.d.ts +1 -1
  142. package/dist/client/core.js +2 -0
  143. package/dist/client/core.js.map +1 -1
  144. package/dist/client/index.d.ts +44 -10
  145. package/dist/client/index.js +35 -0
  146. package/dist/client/index.js.map +1 -1
  147. package/dist/cloudflare-SIG42OIW.js +335 -0
  148. package/dist/cloudflare-SIG42OIW.js.map +1 -0
  149. package/dist/config-support-WQHQIJTA.js +104 -0
  150. package/dist/config-support-WQHQIJTA.js.map +1 -0
  151. package/dist/{csrf-BBrEZSBW.d.ts → csrf-Dgot9qSM.d.ts} +1 -1
  152. package/dist/deno-deploy-LQAYOOPW.js +196 -0
  153. package/dist/deno-deploy-LQAYOOPW.js.map +1 -0
  154. package/dist/{dev-MUWJAZRD.js → dev-ANDSEVLB.js} +28 -18
  155. package/dist/dev-ANDSEVLB.js.map +1 -0
  156. package/dist/{dev-emit-GWD6IXV7.js → dev-emit-BFNMDCPB.js} +5 -5
  157. package/dist/{dev-emit-NBT6JD7R.js → dev-emit-MVAJAFGX.js} +5 -3
  158. package/dist/dev-emit-MVAJAFGX.js.map +1 -0
  159. package/dist/engine-singleton-X4R7AZBJ.js +315 -0
  160. package/dist/engine-singleton-X4R7AZBJ.js.map +1 -0
  161. package/dist/{generate-Y3GWM57K.js → generate-EN6EDITF.js} +43 -4
  162. package/dist/generate-EN6EDITF.js.map +1 -0
  163. package/dist/index-CzxtQcnp.d.ts +1058 -0
  164. package/dist/index.d.ts +4 -0
  165. package/dist/index.js +24 -13
  166. package/dist/index.js.map +1 -1
  167. package/dist/{info-XW7HGUPH.js → info-Y55RWS42.js} +8 -6
  168. package/dist/{info-XW7HGUPH.js.map → info-Y55RWS42.js.map} +1 -1
  169. package/dist/{internal-api-V5L65YSJ.js → internal-api-IP35YU3G.js} +22 -12
  170. package/dist/{internal-api-WEOSTMSN.js → internal-api-OPU456AT.js} +30 -16
  171. package/dist/internal-api-OPU456AT.js.map +1 -0
  172. package/dist/load-config-4ATXQUN3.js +16 -0
  173. package/dist/match-DmGgxjIU.d.ts +44 -0
  174. package/dist/{mcp-ULUFJNSZ.js → mcp-5LLNAGKA.js} +7 -7
  175. package/dist/netlify-C2IRCZKI.js +245 -0
  176. package/dist/netlify-C2IRCZKI.js.map +1 -0
  177. package/dist/node-OSVPYQ3D.js +10 -0
  178. package/dist/nonce-BXt7Qu_C.d.ts +31 -0
  179. package/dist/observability-bootstrap-MZMSOE66.js +15 -0
  180. package/dist/{openapi-HZXR335W.js → openapi-VFPEZSRI.js} +13 -11
  181. package/dist/{openapi-HZXR335W.js.map → openapi-VFPEZSRI.js.map} +1 -1
  182. package/dist/{plugin-runner-BFEcgtmJ.d.ts → plugin-runner-BVMOSxvb.d.ts} +1 -1
  183. package/dist/{plugin-types-D69-lJZ9.d.ts → plugin-types-BUVfUQ0V.d.ts} +13 -1
  184. package/dist/preview-GHPT2EQ5.js +23 -0
  185. package/dist/preview-GHPT2EQ5.js.map +1 -0
  186. package/dist/provider-resolver-Dx6QuWrw.d.ts +128 -0
  187. package/dist/registry-KBZDCFVQ.js +23 -0
  188. package/dist/route-config-Cm_ZMA1C.d.ts +72 -0
  189. package/dist/route-policy-BxOycCDq.d.ts +65 -0
  190. package/dist/router/element-scroll-restoration.d.ts +28 -0
  191. package/dist/router/element-scroll-restoration.js +96 -0
  192. package/dist/router/element-scroll-restoration.js.map +1 -0
  193. package/dist/{routes-OLNQX7CT.js → routes-BPLU3ISV.js} +11 -9
  194. package/dist/{routes-OLNQX7CT.js.map → routes-BPLU3ISV.js.map} +1 -1
  195. package/dist/{scan-7MJC6PYU.js → scan-YJEE4KQK.js} +2 -2
  196. package/dist/{schema-ZO3OSWVG.js → schema-SOAD43RQ.js} +7 -5
  197. package/dist/schemas-4AXHQMV3.js +25 -0
  198. package/dist/schemas-4AXHQMV3.js.map +1 -0
  199. package/dist/security-headers-Ccj7ncNx.d.ts +129 -0
  200. package/dist/server/agent/index.d.ts +2 -90
  201. package/dist/server/agent/index.js +1 -1
  202. package/dist/server/auth/index.d.ts +2 -21
  203. package/dist/server/auth/index.js +3 -2
  204. package/dist/server/cron/index.js +4 -3
  205. package/dist/server/define/index.d.ts +51 -57
  206. package/dist/server/define/index.js +10 -1
  207. package/dist/server/http/index.d.ts +7 -5
  208. package/dist/server/http/index.js +56 -12
  209. package/dist/server/index.d.ts +47 -439
  210. package/dist/server/index.js +119 -201
  211. package/dist/server/index.js.map +1 -1
  212. package/dist/server/jobs/index.js +4 -3
  213. package/dist/server/observability/index.d.ts +109 -35
  214. package/dist/server/observability/index.js +10 -7
  215. package/dist/server/plugins/index.d.ts +3 -3
  216. package/dist/server/scan/index.d.ts +47 -12
  217. package/dist/server/scan/index.js +13 -4
  218. package/dist/server/security/index.d.ts +61 -103
  219. package/dist/server/security/index.js +15 -6
  220. package/dist/server/webhook/index.d.ts +90 -3
  221. package/dist/server/webhook/index.js +12 -2
  222. package/dist/server-boundary-6B4ZQUY7.js +148 -0
  223. package/dist/server-boundary-6B4ZQUY7.js.map +1 -0
  224. package/dist/server-boundary-7VZQRPPX.js +133 -0
  225. package/dist/server-boundary-7VZQRPPX.js.map +1 -0
  226. package/dist/{services-typed-client-PSAGRPFF.js → services-typed-client-XGT5SUUN.js} +2 -2
  227. package/dist/{start-KR2JJR7K.js → start-UZDMOT7I.js} +342 -111
  228. package/dist/start-UZDMOT7I.js.map +1 -0
  229. package/dist/{static-M2W4HUWS.js → static-SVDWIOXJ.js} +24 -13
  230. package/dist/static-SVDWIOXJ.js.map +1 -0
  231. package/dist/{theo-cloud-XAHWOUFK.js → theo-cloud-3ET4G5T6.js} +9 -2
  232. package/dist/theo-cloud-3ET4G5T6.js.map +1 -0
  233. package/dist/vercel-BMCQKCWE.js +277 -0
  234. package/dist/vercel-BMCQKCWE.js.map +1 -0
  235. package/dist/vite-plugin/index.js +24 -13
  236. package/dist/vite-plugin-VKCT2LF2.js +42 -0
  237. package/dist/vite-plugin-VKCT2LF2.js.map +1 -0
  238. package/package.json +19 -6
  239. package/dist/actions-virtual-module-YQXRSSMW.js.map +0 -1
  240. package/dist/agent-7JJW3TPB.js +0 -15
  241. package/dist/app-typed-client-G3J5G7E5.js.map +0 -1
  242. package/dist/app-typed-client-GHO3EWZK.js.map +0 -1
  243. package/dist/aws-lambda-CYNDGU5O.js +0 -172
  244. package/dist/aws-lambda-CYNDGU5O.js.map +0 -1
  245. package/dist/build-WU6AKKIB.js.map +0 -1
  246. package/dist/bun-33RD6K7O.js.map +0 -1
  247. package/dist/chunk-646CA6RV.js.map +0 -1
  248. package/dist/chunk-6E5WKMDS.js +0 -67
  249. package/dist/chunk-6E5WKMDS.js.map +0 -1
  250. package/dist/chunk-6GGWS7J3.js +0 -91
  251. package/dist/chunk-6GGWS7J3.js.map +0 -1
  252. package/dist/chunk-7LVM22VG.js.map +0 -1
  253. package/dist/chunk-7VPQHEAJ.js.map +0 -1
  254. package/dist/chunk-A7JBF5FO.js.map +0 -1
  255. package/dist/chunk-AM3QABW5.js +0 -161
  256. package/dist/chunk-AM3QABW5.js.map +0 -1
  257. package/dist/chunk-BIVCP6X5.js.map +0 -1
  258. package/dist/chunk-BMHS4WAN.js.map +0 -1
  259. package/dist/chunk-E576KYYT.js.map +0 -1
  260. package/dist/chunk-FB2HBNIC.js.map +0 -1
  261. package/dist/chunk-FNTLKHZ7.js.map +0 -1
  262. package/dist/chunk-GRI4XHBJ.js.map +0 -1
  263. package/dist/chunk-GVW5EKEU.js +0 -422
  264. package/dist/chunk-GVW5EKEU.js.map +0 -1
  265. package/dist/chunk-GXEX4CBH.js.map +0 -1
  266. package/dist/chunk-HBU2GIMZ.js.map +0 -1
  267. package/dist/chunk-IEES3CHD.js.map +0 -1
  268. package/dist/chunk-J5MXCGKA.js.map +0 -1
  269. package/dist/chunk-JA2ZAT5Q.js.map +0 -1
  270. package/dist/chunk-KD5G3YXI.js.map +0 -1
  271. package/dist/chunk-LNVMHQ2Z.js +0 -54
  272. package/dist/chunk-LNVMHQ2Z.js.map +0 -1
  273. package/dist/chunk-LXAESF4Y.js.map +0 -1
  274. package/dist/chunk-MTEWLGVY.js.map +0 -1
  275. package/dist/chunk-O3JIAU3V.js.map +0 -1
  276. package/dist/chunk-OJLL4YD6.js +0 -403
  277. package/dist/chunk-OJLL4YD6.js.map +0 -1
  278. package/dist/chunk-OLGPYOLO.js.map +0 -1
  279. package/dist/chunk-S433N3CT.js.map +0 -1
  280. package/dist/chunk-T5C46IIU.js.map +0 -1
  281. package/dist/chunk-U267AOWS.js +0 -28
  282. package/dist/chunk-U267AOWS.js.map +0 -1
  283. package/dist/chunk-UW2TEAGR.js +0 -77
  284. package/dist/chunk-UW2TEAGR.js.map +0 -1
  285. package/dist/chunk-WPJOTQA5.js +0 -1
  286. package/dist/chunk-XALU5LCU.js.map +0 -1
  287. package/dist/chunk-XR74JD4M.js +0 -457
  288. package/dist/chunk-XR74JD4M.js.map +0 -1
  289. package/dist/chunk-YGAXV5HR.js.map +0 -1
  290. package/dist/chunk-YRBR424R.js.map +0 -1
  291. package/dist/cloudflare-KYUWCEPL.js +0 -122
  292. package/dist/cloudflare-KYUWCEPL.js.map +0 -1
  293. package/dist/deno-deploy-CCTB7HGS.js +0 -107
  294. package/dist/deno-deploy-CCTB7HGS.js.map +0 -1
  295. package/dist/dev-MUWJAZRD.js.map +0 -1
  296. package/dist/dev-emit-NBT6JD7R.js.map +0 -1
  297. package/dist/generate-Y3GWM57K.js.map +0 -1
  298. package/dist/index-BEtEv6ZH.d.ts +0 -575
  299. package/dist/load-config-VKD6LKWU.js +0 -14
  300. package/dist/match-CfbEFRG4.d.ts +0 -26
  301. package/dist/netlify-AFMDNKT4.js +0 -150
  302. package/dist/netlify-AFMDNKT4.js.map +0 -1
  303. package/dist/node-ZJQEJSP3.js +0 -10
  304. package/dist/registry-GKR3EWRW.js +0 -23
  305. package/dist/start-KR2JJR7K.js.map +0 -1
  306. package/dist/static-M2W4HUWS.js.map +0 -1
  307. package/dist/theo-cloud-XAHWOUFK.js.map +0 -1
  308. package/dist/vercel-SRS2DH6O.js +0 -133
  309. package/dist/vercel-SRS2DH6O.js.map +0 -1
  310. package/dist/vite-plugin-VPJFD4HK.js +0 -36
  311. /package/dist/{chunk-WPJOTQA5.js.map → adapters/agent-mount.js.map} +0 -0
  312. /package/dist/{agent-7JJW3TPB.js.map → agent-GKUEL6OH.js.map} +0 -0
  313. /package/dist/{check-45NKUVSQ.js.map → check-GIPZBFTX.js.map} +0 -0
  314. /package/dist/{chunk-47CINLWF.js.map → chunk-44J2ANQC.js.map} +0 -0
  315. /package/dist/{chunk-ZB7D62OA.js.map → chunk-KUZVRJ7M.js.map} +0 -0
  316. /package/dist/{chunk-PXFXSFJL.js.map → chunk-NZ5JU6D3.js.map} +0 -0
  317. /package/dist/{internal-api-WEOSTMSN.js.map → chunk-YSJOZEI6.js.map} +0 -0
  318. /package/dist/{dev-emit-GWD6IXV7.js.map → dev-emit-BFNMDCPB.js.map} +0 -0
  319. /package/dist/{internal-api-V5L65YSJ.js.map → internal-api-IP35YU3G.js.map} +0 -0
  320. /package/dist/{load-config-VKD6LKWU.js.map → load-config-4ATXQUN3.js.map} +0 -0
  321. /package/dist/{mcp-ULUFJNSZ.js.map → mcp-5LLNAGKA.js.map} +0 -0
  322. /package/dist/{node-ZJQEJSP3.js.map → node-OSVPYQ3D.js.map} +0 -0
  323. /package/dist/{scan-7MJC6PYU.js.map → observability-bootstrap-MZMSOE66.js.map} +0 -0
  324. /package/dist/{registry-GKR3EWRW.js.map → registry-KBZDCFVQ.js.map} +0 -0
  325. /package/dist/{schema-ZO3OSWVG.js.map → scan-YJEE4KQK.js.map} +0 -0
  326. /package/dist/{vite-plugin-VPJFD4HK.js.map → schema-SOAD43RQ.js.map} +0 -0
  327. /package/dist/{services-typed-client-PSAGRPFF.js.map → services-typed-client-XGT5SUUN.js.map} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/vite-plugin/app-typed-client.ts","../src/vite-plugin/controller-client-emit.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Codegen-time fs ops: all paths derive from `opts.serverDir` / `opts.distDir`\n * (vite plugin opts — trusted, set by the framework's CLI). The plugin only\n * runs at dev/build time, never serves user HTTP input. No path traversal\n * surface here.\n */\n/**\n * Phase 2 + Phase 4 of G1 (g1-client-codegen-plan.md):\n *\n * 1. `generateClientDts(manifest, dtsOutPath)` — pure function emitting the\n * `.theokit/client.d.ts` shape (declared module `@theo/client`).\n * 2. `appTypedClientPlugin(opts)` — Vite plugin wrapper that calls (1),\n * writes the file atomically, and rewrites on route file changes.\n *\n * Implementation notes:\n * - Pure (1) is unit-testable without Vite or a filesystem (see G1-P2 tests).\n * - EC-2: kebab-case segments → camelCase; unsafe chars → bracket-access.\n * - EC-3: collision between HTTP method name and sub-segment name → method\n * wins; a sub-segment gets a `_` suffix + a warning comment.\n * - EC-6: the write is `writeFileSync(tmp) + renameSync(tmp, final)` (POSIX atomic).\n * - EC-8: imports normalize `\\\\` → `/`.\n */\n\nimport { mkdirSync, readFileSync, renameSync, writeFileSync, existsSync } from 'node:fs'\nimport { dirname, isAbsolute, posix, relative, resolve } from 'node:path'\n\nimport type { Plugin, ViteDevServer } from 'vite'\n\nimport { HTTP_METHODS, type HttpMethod } from '../core/contracts/http-methods.js'\nimport { generateManifest, type ManifestRoute, type TheoManifest } from '../server/internal-api.js'\n\nimport { collectControllerRouteData, type ControllerRouteData } from './controller-client-emit.js'\n\nconst FILE_HEADER = `// AUTO-GENERATED by theokit — do not edit.\n// Source: theokit/packages/theo/src/vite-plugin/app-typed-client.ts (G1 plan).\n// To refresh: \\`pnpm dev\\` or \\`pnpm build\\` regenerates this file on every route change.\n\n/* eslint-disable */\n`\n\ninterface ControllerLeaf {\n /** Import alias of the controller class (`_c0`). */\n classAlias: string\n /** Controller method name backing the route (`findById`). */\n methodName: string\n /**\n * theokit#124 — module specifier + exported name of the `@Body` schema, when it has one, so the\n * emitted signature can say `z.infer<typeof import('...').zCreate>` instead of `unknown`.\n */\n bodySchema?: { importPath: string; exportName: string }\n /** theokit#124 — same for `@Query`. */\n querySchema?: { importPath: string; exportName: string }\n}\n\ninterface TreeNode {\n /** sub-namespaces — keyed by segment name (already normalized). */\n children: Map<string, TreeNode>\n /** File-based routes: HTTP method → import alias (`InferResponse<typeof alias>`). */\n methods: Map<HttpMethod, string>\n /** Decorator controllers: HTTP method → class alias + method (`Awaited<ReturnType<...>>`). */\n controllerMethods: Map<HttpMethod, ControllerLeaf>\n /** Whether any descendant declares dynamic params (for params type construction). */\n paramNamesAccumulated: string[]\n}\n\nfunction makeNode(): TreeNode {\n return {\n children: new Map(),\n methods: new Map(),\n controllerMethods: new Map(),\n paramNamesAccumulated: [],\n }\n}\n\n/**\n * Normalize a path segment to a valid TS identifier when possible.\n * EC-2: kebab-case → camelCase; pure dynamic (`:name`) → identifier `name`;\n * starts with digit or unsafe char → emit as bracket-access key.\n */\nfunction normalizeSegment(raw: string): { identifier: string; bracket: boolean } {\n // Dynamic segment: leading `:` (e.g. `:id` or `:...slug`).\n let s = raw\n if (s.startsWith(':...')) s = s.slice(4)\n else if (s.startsWith(':')) s = s.slice(1)\n\n // kebab → camel\n const camel = s.replace(/-([a-z0-9])/gi, (_, c: string) => c.toUpperCase())\n\n // Valid TS identifier (cannot start with digit, must be [a-zA-Z_$][a-zA-Z0-9_$]*)\n if (/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(camel)) {\n return { identifier: camel, bracket: false }\n }\n // Fallback: bracket-access (keep raw form intact for JSON-string key)\n return { identifier: s, bracket: true }\n}\n\nfunction importPathFor(dtsOutPath: string, routeFileAbs: string): string {\n let rel = relative(dirname(dtsOutPath), routeFileAbs)\n // EC-8: normalize Windows path separators.\n rel = rel.replace(/\\\\/g, '/')\n // Strip extension (`.ts` / `.tsx`); TS module resolution likes extensionless.\n rel = rel.replace(/\\.[jt]sx?$/, '')\n if (!rel.startsWith('.') && !rel.startsWith('/')) {\n rel = './' + rel\n }\n return rel\n}\n\n/**\n * Convert a route path (e.g. `/api/users/:id/posts`) into the tree segments\n * we want under the `client` root. Strips the `/api/` prefix and splits.\n */\nfunction routePathSegments(routePath: string): string[] {\n let p = routePath\n if (p.startsWith('/api/')) p = p.slice(5)\n else if (p.startsWith('/api')) p = p.slice(4)\n if (p.startsWith('/')) p = p.slice(1)\n if (p === '') return []\n return p.split('/').filter(Boolean)\n}\n\nfunction paramNamesFromRoute(routePath: string): string[] {\n const out: string[] = []\n const re = /:(?:\\.\\.\\.)?([^/]+)/g\n let m: RegExpExecArray | null\n while ((m = re.exec(routePath)) !== null) {\n out.push(m[1])\n }\n return out\n}\n\ninterface BuildContext {\n root: TreeNode\n /** Sequential index per route file for aliasing imports. */\n aliasCounter: { value: number }\n /** Lines emitted at the top of the declared module (one per route file). */\n importLines: string[]\n /** Diagnostic warnings rendered as block comments inside the declared module. */\n warnings: string[]\n dtsOutPath: string\n serverDir: string\n}\n\nfunction buildOneRoute(route: ManifestRoute, ctx: BuildContext): void {\n if (!route.methods || route.methods.length === 0) return\n // Build alias prefix once per route file (`_r0`, `_r1`, ...).\n const idx = ctx.aliasCounter.value++\n // Resolve absolute path for the route file (manifest stores it relative to serverDir).\n const absRouteFile = isAbsolute(route.filePath)\n ? route.filePath\n : resolve(ctx.serverDir, route.filePath)\n const importPath = importPathFor(ctx.dtsOutPath, absRouteFile)\n const aliases = route.methods\n .filter((m): m is HttpMethod => (HTTP_METHODS as readonly string[]).includes(m))\n .map((method) => ({ method, alias: `_r${idx}_${method}` }))\n if (aliases.length === 0) return\n const importClause = aliases.map((a) => `${a.method} as ${a.alias}`).join(', ')\n ctx.importLines.push(` import type { ${importClause} } from '${importPath}'`)\n\n // Walk segments + register methods at the leaf node.\n const segments = routePathSegments(route.routePath)\n let node = ctx.root\n for (const seg of segments) {\n const norm = normalizeSegment(seg)\n let child = node.children.get(norm.identifier)\n if (child === undefined) {\n child = makeNode()\n node.children.set(norm.identifier, child)\n }\n node = child\n }\n // Accumulated param names for typed params (e.g. `{ id: string }`).\n node.paramNamesAccumulated = paramNamesFromRoute(route.routePath)\n\n // Register each HTTP method (collision detection runs in a post-pass).\n for (const { method, alias } of aliases) {\n if (node.methods.has(method)) {\n ctx.warnings.push(\n `// WARNING: duplicate ${method} export at /${segments.join('/')} (route file declared twice). Keeping last definition.`,\n )\n }\n node.methods.set(method, alias)\n }\n}\n\n/**\n * #122 (T2.1) — register one decorator-controller route into the tree. The class\n * import alias is shared across the class's methods (resolved by the caller). A\n * file-based route at the same node+verb WINS (file routes are the default); the\n * controller entry is skipped with a warning to keep the emitted `.d.ts` valid.\n */\nfunction buildOneController(cr: ControllerRouteData, classAlias: string, ctx: BuildContext): void {\n const verb = cr.verb.toUpperCase()\n if (!(HTTP_METHODS as readonly string[]).includes(verb)) return\n const method = verb as HttpMethod\n\n const segments = routePathSegments(cr.fullPath)\n let node = ctx.root\n for (const seg of segments) {\n const norm = normalizeSegment(seg)\n let child = node.children.get(norm.identifier)\n if (child === undefined) {\n child = makeNode()\n node.children.set(norm.identifier, child)\n }\n node = child\n }\n node.paramNamesAccumulated = paramNamesFromRoute(cr.fullPath)\n\n if (node.methods.has(method)) {\n ctx.warnings.push(\n `WARNING (#122): controller ${cr.className}.${cr.methodName} (${method} /${segments.join('/')}) collides with a file-based route at the same path; file route wins.`,\n )\n return\n }\n if (cr.schemaNotExported === true) {\n // theokit#124 — a note, not a warning: the author did nothing wrong, and the emitted file is\n // valid. It exists so a reader who sees one typed method beside an untyped one knows the reason\n // is reachability, and knows the one-word fix.\n const note = `NOTE (#124): ${cr.className}.${cr.methodName} validates with a schema that is not exported, so its request type falls back to \\`unknown\\`. To get the type, export the schema (\\`export const zX = z.object({...})\\`).`\n if (!ctx.warnings.includes(note)) ctx.warnings.push(note)\n }\n node.controllerMethods.set(method, {\n classAlias,\n methodName: cr.methodName,\n // theokit#124 — an EXPORTED schema is referenceable from the emitted `.d.ts`; an inline one is\n // not, and falls through to the documented `unknown`.\n ...(cr.bodySchemaExport !== undefined\n ? {\n bodySchema: {\n importPath: importPathFor(ctx.dtsOutPath, cr.filePath),\n exportName: cr.bodySchemaExport,\n },\n }\n : {}),\n ...(cr.querySchemaExport !== undefined\n ? {\n querySchema: {\n importPath: importPathFor(ctx.dtsOutPath, cr.filePath),\n exportName: cr.querySchemaExport,\n },\n }\n : {}),\n })\n}\n\n/**\n * EC-3: walk the tree post-build and resolve any node where a method's\n * lowercase name clashes with a child segment. HTTP method wins (more common);\n * the offending child gets a `_` suffix + a warning entry.\n */\nfunction resolveCollisions(node: TreeNode, pathPrefix: string, warnings: string[]): void {\n const methodLowerNames = new Set<string>()\n for (const method of node.methods.keys()) {\n methodLowerNames.add(method.toLowerCase())\n }\n for (const method of node.controllerMethods.keys()) {\n methodLowerNames.add(method.toLowerCase())\n }\n const renames: { from: string; to: string }[] = []\n for (const childName of node.children.keys()) {\n if (methodLowerNames.has(childName)) {\n renames.push({ from: childName, to: `${childName}_` })\n }\n }\n for (const { from, to } of renames) {\n const old = node.children.get(from)\n if (old !== undefined) {\n node.children.delete(from)\n node.children.set(to, old)\n warnings.push(\n `WARNING (EC-3): path collision — method '${from}' clashed with sub-namespace at ${pathPrefix}/${from}; sub-namespace renamed to '${to}'.`,\n )\n }\n }\n // Recurse into all children (including the renamed ones).\n for (const [name, child] of node.children) {\n resolveCollisions(child, `${pathPrefix}/${name}`, warnings)\n }\n}\n\nfunction renderTreeNode(node: TreeNode, indent: string, _isRoot: boolean): string {\n // _isRoot is reserved for callers; current rendering is uniform across roots\n // and children (both open with `{`). Kept in the signature for future overrides.\n const lines: string[] = ['{']\n // Methods first\n for (const [method, alias] of node.methods) {\n const lower = method.toLowerCase()\n // Routes with path params (`:id`, `:name`) emit a `{ params: {...} }` object\n // intersected with TheoFetchOptions. Without the outer `{...}` wrap the\n // generated signature `(opts: params: {...} & ...)` is invalid TS syntax\n // (parser reads `params:` as a parameter label, then `{...}` as type — invalid).\n const paramsList = node.paramNamesAccumulated.map((p) => `${p}: string`).join('; ')\n const paramsField =\n node.paramNamesAccumulated.length > 0 ? `{ params: { ${paramsList} } } & ` : ''\n const optionalMark = node.paramNamesAccumulated.length === 0 ? '?' : ''\n lines.push(\n `${indent} ${lower}: (opts${optionalMark}: ${paramsField}import('theokit/client').TheoFetchOptions<typeof ${alias}>) => Promise<import('theokit/client').InferResponse<typeof ${alias}>>`,\n )\n }\n // #122 (T2.1) — decorator-controller methods. Response inferred via\n // `Awaited<ReturnType<...>>`; params typed from the route pattern.\n //\n // theokit#124 — the request side too, when the `@Body`/`@Query` schema is EXPORTED. The ADR-2\n // checkpoint was right that the type cannot come from the class (parameter decorators erase to\n // runtime metadata, so `Parameters<...>[N]` is positional-only), and right that the runtime schema\n // carries no source identifier. What it missed is that the codegen LOADS the module, so the schema\n // object can be matched back to an export by reference identity — see `exportedNameOf`. An inline\n // schema has no name to reference and keeps the documented `unknown`.\n for (const [method, leaf] of node.controllerMethods) {\n const lower = method.toLowerCase()\n const paramsList = node.paramNamesAccumulated.map((p) => `${p}: string`).join('; ')\n const paramsField =\n node.paramNamesAccumulated.length > 0 ? `{ params: { ${paramsList} } } & ` : ''\n const optionalMark = node.paramNamesAccumulated.length === 0 ? '?' : ''\n const bodyType =\n leaf.bodySchema === undefined\n ? 'body?: unknown'\n : `body: import('zod').infer<typeof import('${leaf.bodySchema.importPath}').${leaf.bodySchema.exportName}>`\n const queryType =\n leaf.querySchema === undefined\n ? 'query?: Record<string, string>'\n : `query: import('zod').infer<typeof import('${leaf.querySchema.importPath}').${leaf.querySchema.exportName}>`\n lines.push(\n `${indent} ${lower}: (opts${optionalMark}: ${paramsField}{ ${bodyType}; ${queryType} }) => Promise<Awaited<ReturnType<InstanceType<typeof ${leaf.classAlias}>['${leaf.methodName}']>>>`,\n )\n }\n // Children\n for (const [name, child] of node.children) {\n // Backslash first, then the quote: escaping the quote while leaving the escape character\n // untouched means `back\\` emits as `'back\\'`, whose trailing backslash escapes the closing\n // quote and swallows the rest of the line. A backslash is a legal POSIX filename character, so\n // it reaches here from `server/routes/`.\n const propKey = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)\n ? name\n : `'${name.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}'`\n lines.push(`${indent} ${propKey}: ${renderTreeNode(child, indent + ' ', false)}`)\n }\n lines.push(`${indent}}`)\n return lines.join('\\n')\n}\n\ninterface GenerateClientDtsOptions {\n manifest: TheoManifest\n /** Absolute path to the .d.ts that will be emitted. Used to compute import paths. */\n dtsOutPath: string\n /** Absolute serverDir; manifest's filePath entries are relative to this. */\n serverDir: string\n /**\n * #122 (T2.1) — decorator-controller routes (from `collectControllerRouteData`),\n * merged into the same `client.<ns>.<method>()` tree as file routes. Absent/empty\n * → zero controller output (ADR-5 routes-only byte-identity).\n */\n controllerRoutes?: ControllerRouteData[]\n}\n\nexport function generateClientDts({\n manifest,\n dtsOutPath,\n serverDir,\n controllerRoutes,\n}: GenerateClientDtsOptions): string {\n const ctx: BuildContext = {\n root: makeNode(),\n aliasCounter: { value: 0 },\n importLines: [],\n warnings: [],\n dtsOutPath,\n serverDir,\n }\n for (const route of manifest.routes) {\n buildOneRoute(route, ctx)\n }\n // #122 (T2.1) — merge decorator controllers into the same tree. One import\n // alias per class (shared across its methods), keyed by source file.\n if (controllerRoutes?.length) {\n const classAliases = new Map<string, string>()\n for (const cr of controllerRoutes) {\n let alias = classAliases.get(cr.filePath)\n if (alias === undefined) {\n alias = `_c${classAliases.size}`\n classAliases.set(cr.filePath, alias)\n const importPath = importPathFor(dtsOutPath, cr.filePath)\n ctx.importLines.push(` import type { ${cr.className} as ${alias} } from '${importPath}'`)\n }\n buildOneController(cr, alias, ctx)\n }\n }\n // EC-3: resolve collisions in a post-build pass (collisions materialize\n // when two routes are both processed, not during a single route's build).\n resolveCollisions(ctx.root, '', ctx.warnings)\n\n const importsBlock = ctx.importLines.length > 0 ? ctx.importLines.join('\\n') + '\\n\\n' : '\\n'\n const warningsBlock =\n ctx.warnings.length > 0 ? ' // ' + ctx.warnings.join('\\n // ') + '\\n\\n' : ''\n\n // Empty manifest (no routes with methods) → emit a stub interface so consumers\n // still get `client.X` autocomplete-friendly errors instead of \"Module not found\".\n const treeBody =\n ctx.root.children.size === 0 &&\n ctx.root.methods.size === 0 &&\n ctx.root.controllerMethods.size === 0\n ? '{\\n // No routes detected — add `server/routes/*.ts` to populate this client.\\n }'\n : renderTreeNode(ctx.root, ' ', /* isRoot */ true)\n\n return `${FILE_HEADER}\ndeclare module '@theo/client' {\n${importsBlock}${warningsBlock} export interface AppClient ${treeBody}\n export const client: AppClient\n}\n`\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Phase 4 — Vite plugin\n// ─────────────────────────────────────────────────────────────────────────────\n\ninterface AppTypedClientPluginOptions {\n /** Project root (cwd). */\n cwd: string\n /** Absolute path to the user's `server/` dir. */\n serverDir: string\n /** Absolute path to the `.theokit/` output dir (where `client.d.ts` lands). */\n distDir: string\n /**\n * Additional routes to merge into the typed client alongside file-system routes.\n * Each entry follows ManifestRoute shape (filePath, routePath, methods, paramNames).\n *\n * Used by `@theokit/http` `httpDecoratorsPlugin` to inject\n * decorator-defined routes — zero coupling between theokit core and the\n * decorator package (the walk happens in http-decorators; only data arrives here).\n */\n extraRoutes?: ManifestRoute[]\n}\n\nconst VIRTUAL_APP_CLIENT_ID = '@theo/client'\nconst RESOLVED_APP_CLIENT_ID = '\\0@theo/client'\n\n/**\n * Should a watcher file event under `routes/` or `controllers/` trigger a client\n * re-emit? Ignores the `.__decorated__.mjs` temp files that `loadControllerWithSwc`\n * writes+unlinks during controller codegen — reacting to them would create a\n * perpetual emit→temp-write→watcher→emit loop (#122 T2.1).\n */\nexport function shouldReemitForFile(\n file: string,\n routesGlob: string,\n controllersGlob: string,\n): boolean {\n const normalized = file.replace(/\\\\/g, '/')\n if (normalized.includes('.__decorated__.')) return false\n return normalized.startsWith(routesGlob) || normalized.startsWith(controllersGlob)\n}\n\n/** Atomic write via tmp + rename (EC-6). Skips when content is unchanged. */\nfunction writeFileIfChanged(filePath: string, content: string): { changed: boolean } {\n if (existsSync(filePath)) {\n try {\n const current = readFileSync(filePath, 'utf-8')\n if (current === content) return { changed: false }\n } catch {\n // fall through to write\n }\n }\n mkdirSync(dirname(filePath), { recursive: true })\n const tmp = `${filePath}.${process.pid}.tmp`\n writeFileSync(tmp, content)\n renameSync(tmp, filePath)\n return { changed: true }\n}\n\nasync function emitClientDts(\n opts: AppTypedClientPluginOptions,\n): Promise<{ changed: boolean; path: string }> {\n if (!existsSync(opts.serverDir)) {\n // No server dir — emit empty stub to avoid \"module not found\".\n const stubPath = posix.join(opts.distDir.replace(/\\\\/g, '/'), 'client.d.ts')\n return {\n changed: writeFileIfChanged(\n stubPath,\n generateClientDts({\n manifest: {\n version: 1,\n generatedAt: new Date().toISOString(),\n routes: [],\n actions: [],\n websockets: [],\n },\n dtsOutPath: stubPath,\n serverDir: opts.serverDir,\n }),\n ).changed,\n path: stubPath,\n }\n }\n const manifest = generateManifest(opts.serverDir)\n\n // Decorator-client-bridge: merge extra routes (from @theokit/http\n // or any other source) into the manifest so generateClientDts() produces a\n // SINGLE typed client covering both file-system routes AND injected routes.\n if (opts.extraRoutes?.length) {\n manifest.routes.push(...opts.extraRoutes)\n }\n\n // #122 (T2.1) — merge decorator controllers under `<serverDir>/controllers/`\n // into the same typed client. Zero output when the dir is absent/empty (ADR-5).\n const controllersDir = resolve(opts.serverDir, 'controllers')\n const controllerRoutes = existsSync(controllersDir)\n ? await collectControllerRouteData({ controllersDir })\n : []\n\n const dtsOutPath = posix.join(opts.distDir.replace(/\\\\/g, '/'), 'client.d.ts')\n const content = generateClientDts({\n manifest,\n dtsOutPath,\n serverDir: opts.serverDir,\n controllerRoutes,\n })\n const { changed } = writeFileIfChanged(dtsOutPath, content)\n return { changed, path: dtsOutPath }\n}\n\nexport function appTypedClientPlugin(opts: AppTypedClientPluginOptions): Plugin {\n let debounceTimer: NodeJS.Timeout | undefined\n let viteServer: ViteDevServer | undefined\n\n function scheduleEmit(): void {\n if (debounceTimer) clearTimeout(debounceTimer)\n debounceTimer = setTimeout(() => {\n void (async () => {\n try {\n await emitClientDts(opts)\n // Invalidate the virtual module so re-imports pick up potential new shape.\n if (viteServer) {\n const mod = viteServer.moduleGraph.getModuleById(RESOLVED_APP_CLIENT_ID)\n if (mod) viteServer.moduleGraph.invalidateModule(mod)\n }\n } catch (err) {\n // Surface but don't crash dev server.\n console.error('[theokit:app-typed-client] codegen error:', err)\n }\n })()\n }, 100)\n }\n\n return {\n name: 'theokit:app-typed-client',\n enforce: 'post',\n async configResolved() {\n try {\n await emitClientDts(opts)\n } catch (err) {\n console.error('[theokit:app-typed-client] initial codegen error:', err)\n }\n },\n async buildEnd() {\n try {\n await emitClientDts(opts)\n } catch (err) {\n console.error('[theokit:app-typed-client] buildEnd codegen error:', err)\n }\n },\n configureServer(server) {\n viteServer = server\n const routesGlob = posix.join(opts.serverDir.replace(/\\\\/g, '/'), 'routes')\n const controllersGlob = posix.join(opts.serverDir.replace(/\\\\/g, '/'), 'controllers')\n const onFile = (file: string): void => {\n if (shouldReemitForFile(file, routesGlob, controllersGlob)) scheduleEmit()\n }\n server.watcher.on('add', onFile)\n server.watcher.on('change', onFile)\n server.watcher.on('unlink', onFile)\n },\n resolveId(id) {\n if (id === VIRTUAL_APP_CLIENT_ID) return RESOLVED_APP_CLIENT_ID\n return null\n },\n load(id) {\n if (id === RESOLVED_APP_CLIENT_ID) {\n return [\n `import { createAppClient } from 'theokit/client'`,\n `export const client = createAppClient()`,\n `export default client`,\n ``,\n ].join('\\n')\n }\n return null\n },\n }\n}\n\nexport { VIRTUAL_APP_CLIENT_ID, RESOLVED_APP_CLIENT_ID, emitClientDts }\n","/**\n * #122 (T2.1) — typed-client codegen for decorator controllers.\n *\n * Collects the routing metadata of every `@Controller` under `controllersDir`\n * so the app-typed-client codegen can emit `client.<ns>.<method>()` entries.\n * Codegen loads controllers via `loadControllerWithSwc` (swc-compile + import,\n * no Vite dev server needed) — distinct from the dev SERVING path, which loads\n * through Vite's `ssrLoadModule`.\n *\n * ADR-2 checkpoint (LOCKED — see the plan's Unresolved Questions): only the\n * RESPONSE type is inferred, via `Awaited<ReturnType<InstanceType<typeof C>['m']>>`.\n * Request `@Body` types are NOT inferred from the class — parameter decorators are\n * erased runtime metadata, invisible to the type system, so `Parameters<...>[N]` is\n * positional-only and cannot tell body from param from query. Body falls back to\n * `unknown` (runtime `@Body` Zod validation from Phase 1 still applies). Full body\n * inference is tracked in the follow-up issue.\n */\nimport { loadControllerWithSwc, walkControllerMetadata } from '@theokit/http'\n\nimport {\n scanControllerModules,\n type ControllerModuleLoader,\n} from '../server/http/controller-dispatch.js'\n\n/** One controller route, flattened for the client codegen. */\nexport interface ControllerRouteData {\n /** Absolute path to the `*.controller.ts` source (for the `import type` line). */\n filePath: string\n /** The exported class name (e.g. `TasksController`). */\n className: string\n /** Full route path, e.g. `/api/v2/tasks/:id`. */\n fullPath: string\n /** HTTP verb (`GET`, `POST`, …). */\n verb: string\n /** The controller method name backing this route (e.g. `findById`). */\n methodName: string\n /**\n * theokit#124 — the EXPORTED name of the `@Body(schema)` Zod schema, when it has one.\n *\n * Absent when the schema is declared inline or otherwise not exported: there is then no\n * identifier the emitted `.d.ts` could reference, and the body stays `unknown`.\n */\n bodySchemaExport?: string\n /** theokit#124 — same for `@Query(schema)`. */\n querySchemaExport?: string\n /**\n * theokit#124 — a `@Body`/`@Query` schema EXISTS on this route but is not exported, so no name\n * could be referenced and the type degraded to `unknown`.\n *\n * Distinct from \"there is no schema at all\": that route was never going to be typed and needs no\n * explanation, while this one looks arbitrarily untyped next to a typed neighbour. The codegen\n * turns this into a note in the emitted file so the difference is legible.\n */\n schemaNotExported?: boolean\n}\n\n/**\n * Recover the EXPORTED name of a runtime schema object — theokit#124.\n *\n * `WalkResult.bodySchema` is a `z.ZodType` instance with no source identifier, which is why #122's\n * ADR-2 checkpoint concluded the request type was unrecoverable. It is recoverable, just not from\n * the metadata: the codegen already imports the module, so this object IS the one the module\n * exported, and reference identity gives back its name. No parsing, no heuristics — either some\n * export is the same object or none is.\n *\n * Returns `undefined` for an inline schema, which is a real limit rather than a bug: an unexported\n * value has no name a `.d.ts` can import.\n */\nfunction exportedNameOf(\n schema: unknown,\n moduleExports: Readonly<Record<string, unknown>>,\n): string | undefined {\n if (schema === undefined || schema === null) return undefined\n for (const [name, value] of Object.entries(moduleExports)) {\n // Reference identity, never structural comparison: two distinct schemas can be deeply equal,\n // and emitting the wrong name would type the client against the wrong contract silently.\n if (value === schema) return name\n }\n return undefined\n}\n\n/**\n * Scan `controllersDir` and flatten every controller's routes into\n * {@link ControllerRouteData}. Returns `[]` when the directory has no controllers\n * (so the codegen contributes zero bytes — ADR-5 routes-only byte-identity).\n */\nexport async function collectControllerRouteData(opts: {\n controllersDir: string\n loadModule?: ControllerModuleLoader\n}): Promise<ControllerRouteData[]> {\n const loader = opts.loadModule ?? loadControllerWithSwc\n const modules = await scanControllerModules(opts.controllersDir, loader)\n const out: ControllerRouteData[] = []\n for (const { filePath, cls, exports } of modules) {\n const className = (cls as { name: string }).name\n for (const walk of walkControllerMetadata(cls)) {\n const bodySchemaExport = exportedNameOf(walk.bodySchema, exports)\n // `walk.querySchema` is DECLARED on `WalkResult` and never populated — `walkControllerMetadata`\n // resolves a body schema and has no query counterpart, so the field always reads `undefined`\n // (grep: the only occurrence in `@theokit/http` is its own declaration). Reading the entry\n // directly is therefore not a shortcut around an API; it is the only place the schema exists.\n //\n // Deliberately NOT fixed by populating `querySchema` here: that field feeds runtime validation\n // for `@Body`, so filling the query one would start VALIDATING query strings that are not\n // validated today. This issue is about editor types; silently turning on runtime rejection\n // under it would be a behaviour change nobody asked for. Filed separately.\n const queryEntry = walk.paramEntries.find(\n (e) => e.source === 'query' && e.schema !== undefined,\n )\n const querySchemaExport = exportedNameOf(queryEntry?.schema, exports)\n out.push({\n filePath,\n className,\n fullPath: walk.fullPath,\n verb: walk.verb,\n methodName: String(walk.propertyKey),\n ...(bodySchemaExport !== undefined ? { bodySchemaExport } : {}),\n ...(querySchemaExport !== undefined ? { querySchemaExport } : {}),\n ...((walk.bodySchema !== undefined && bodySchemaExport === undefined) ||\n (queryEntry?.schema !== undefined && querySchemaExport === undefined)\n ? { schemaNotExported: true }\n : {}),\n })\n }\n }\n return out\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,261 @@
1
+ #!/usr/bin/env node
2
+ import "tsx/esm";
3
+ import {
4
+ deployedCorsFragment,
5
+ deployedCsrfFragment,
6
+ deployedRuntimeConfigFragment,
7
+ deployedTraceFragment,
8
+ describeDeployedSecurityHeaders,
9
+ renderSecurityHeadersConfigLiteral
10
+ } from "./chunk-E43VJ3E5.js";
11
+ import {
12
+ nodeAdapter
13
+ } from "./chunk-KI4DOTN4.js";
14
+ import "./chunk-RPET332G.js";
15
+ import {
16
+ assertServicesUnsupported,
17
+ readManifest
18
+ } from "./chunk-ZNZISJDZ.js";
19
+
20
+ // src/adapters/aws-lambda.ts
21
+ import { mkdirSync, writeFileSync } from "fs";
22
+ import { resolve } from "path";
23
+ var BINARY_CONTENT_TYPES = [
24
+ "application/octet-stream",
25
+ "application/pdf",
26
+ "application/zip",
27
+ "image/",
28
+ "audio/",
29
+ "video/"
30
+ ];
31
+ function isBinaryContentType(contentType) {
32
+ if (!contentType) return false;
33
+ const ct = contentType.toLowerCase();
34
+ return BINARY_CONTENT_TYPES.some((prefix) => ct.startsWith(prefix));
35
+ }
36
+ function eventV2ToRequestShape(event) {
37
+ const headers = {};
38
+ for (const [k, v] of Object.entries(event.headers ?? {})) {
39
+ if (v !== void 0) headers[k] = v;
40
+ }
41
+ let body = event.body;
42
+ if (body !== void 0 && event.isBase64Encoded) {
43
+ body = Buffer.from(body, "base64").toString("utf-8");
44
+ }
45
+ return {
46
+ method: event.requestContext.http.method,
47
+ path: event.requestContext.http.path,
48
+ headers,
49
+ body
50
+ };
51
+ }
52
+ function responseToLambdaResultV2(statusCode, headers, body) {
53
+ const isBinary = isBinaryContentType(headers["content-type"]);
54
+ return {
55
+ statusCode,
56
+ headers,
57
+ body: isBinary ? Buffer.from(body, "binary").toString("base64") : body,
58
+ isBase64Encoded: isBinary
59
+ };
60
+ }
61
+ function awsLambdaHandlerFragment(runtimeSpread) {
62
+ return [
63
+ `// #382 \u2014 this target is DELISTED for response streaming, by construction.`,
64
+ `// The Lambda v2 result object below carries \`body\` as a string, so the`,
65
+ `// response cannot exist until the run has finished, no matter how the`,
66
+ `// framework's shim writes it. Streaming here would require`,
67
+ `// \`awslambda.streamifyResponse\` plus a Function URL in RESPONSE_STREAM`,
68
+ `// invoke mode \u2014 neither of which this adapter emits, and which would break`,
69
+ `// every API Gateway deployment of it. Rather than degrade in silence, a`,
70
+ `// response that is unambiguously a stream is named in the logs below.`,
71
+ `async function responseToV2Result(response, routePath) {`,
72
+ ` const headers = {}`,
73
+ ` response.headers.forEach((v, k) => { headers[k] = v })`,
74
+ ` const ct = headers['content-type'] ?? ''`,
75
+ ` if (ct.includes('text/event-stream')) {`,
76
+ ` console.warn(`,
77
+ ` '[theo][aws-lambda] ' + routePath + ' returned a streaming response (' + ct + '), ' +`,
78
+ ` 'but the aws-lambda target buffers it whole and delivers it when the run ends. ' +`,
79
+ ` 'This target is delisted for streaming (theokit#382). Deploy streaming routes to ' +`,
80
+ ` 'cloudflare, vercel, netlify, bun, deno-deploy or node.'`,
81
+ ` )`,
82
+ ` }`,
83
+ ` const isBinary = /^application\\/(octet-stream|pdf|zip)|^(image|audio|video)\\//.test(ct)`,
84
+ ` if (isBinary) {`,
85
+ ` const buf = Buffer.from(await response.arrayBuffer())`,
86
+ ` return {`,
87
+ ` statusCode: response.status,`,
88
+ ` headers,`,
89
+ ` body: buf.toString('base64'),`,
90
+ ` isBase64Encoded: true,`,
91
+ ` }`,
92
+ ` }`,
93
+ ` return {`,
94
+ ` statusCode: response.status,`,
95
+ ` headers,`,
96
+ ` body: await response.text(),`,
97
+ ` isBase64Encoded: false,`,
98
+ ` }`,
99
+ `}`,
100
+ ``,
101
+ `// Every outcome \u2014 including both 404s \u2014 is produced as a Web Response by`,
102
+ `// routeRequest, so the security baseline is applied at ONE place and the`,
103
+ `// v2 result object is built from headers that already carry it.`,
104
+ `export const handler = async (event) => {`,
105
+ ` const path = event.requestContext?.http?.path ?? '/'`,
106
+ ` // #409 \u2014 the same event, read as a Web Request so the CORS matcher can see the method and`,
107
+ ` // the \`origin\` header. \`eventV2ToRequest\` reads a body already present in the event, so`,
108
+ ` // unlike the Node targets there is no stream to drain twice.`,
109
+ ` const corsRequest = eventV2ToRequest(event)`,
110
+ ``,
111
+ ` // The preflight is answered BEFORE anything routes: an OPTIONS the router handles is an`,
112
+ ` // OPTIONS the browser never gets a CORS answer to.`,
113
+ ` const preflight = corsPreflight(corsRequest)`,
114
+ ` const response = preflight !== null`,
115
+ ` ? withSecurityHeaders(preflight, SECURITY_HEADERS)`,
116
+ ` : withCors(corsRequest, withSecurityHeaders(await routeRequest(event, path), SECURITY_HEADERS))`,
117
+ ` return responseToV2Result(response, path)`,
118
+ `}`,
119
+ ``,
120
+ `async function routeRequest(event, path) {`,
121
+ ` if (!path.startsWith('/api/')) {`,
122
+ ` return new Response(`,
123
+ ` 'Static assets must be served from CloudFront or a separate static host.',`,
124
+ ` { status: 404, headers: { 'content-type': 'text/plain' } },`,
125
+ ` )`,
126
+ ` }`,
127
+ ``,
128
+ ` if (!routesCache) routesCache = scanServerRoutes(serverDir)`,
129
+ ` if (!loaderCache) loaderCache = createProductionLoader()`,
130
+ ``,
131
+ ` const match = matchRoute(path, routesCache)`,
132
+ ` if (!match) {`,
133
+ ` return new Response(JSON.stringify({ error: { code: 'NOT_FOUND' } }), {`,
134
+ ` status: 404,`,
135
+ ` headers: { 'content-type': 'application/json' },`,
136
+ ` })`,
137
+ ` }`,
138
+ ``,
139
+ ` const request = eventV2ToRequest(event)`,
140
+ ` const { req, res, toResponse } = createWebShim(request)`,
141
+ ...deployedTraceFragment("request", " "),
142
+ ` const method = request.method.toUpperCase()`,
143
+ ` return toResponse(executeRoute({ route: match.route, method, params: match.params, req, res, loadModule: loaderCache, serverDir, requestId, ...CSRF_CONFIG, ${runtimeSpread} }))`,
144
+ `}`
145
+ ];
146
+ }
147
+ function renderAwsLambdaEntry(opts = {}) {
148
+ const runtimeConfig = deployedRuntimeConfigFragment(opts);
149
+ return [
150
+ `// Generated by Theo \u2014 AWS Lambda Adapter`,
151
+ `// Use with API Gateway HTTP API v2 (default).`,
152
+ ``,
153
+ `import { resolve } from 'node:path'`,
154
+ `import { scanServerRoutes, matchRoute, executeRoute, createProductionLoader, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server'`,
155
+ `import { createWebShim } from 'theokit/adapters/web-shim'`,
156
+ `import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,
157
+ ``,
158
+ `const cwd = process.cwd()`,
159
+ `const serverDir = resolve(cwd, 'server')`,
160
+ `let routesCache = null`,
161
+ `let loaderCache = null`,
162
+ ``,
163
+ `// #410 \u2014 the security baseline \`theokit start\` puts on every response,`,
164
+ `// carried here as a literal because the deployed function has no`,
165
+ `// theo.config.ts to read. Non-API paths 404 here and the document is served`,
166
+ `// from CloudFront or another static host, so this covers the API and not the`,
167
+ `// page (usetheokit/theokit#412).`,
168
+ `const SECURITY_HEADERS_CONFIG = ${renderSecurityHeadersConfigLiteral(opts.securityHeaders)}`,
169
+ `const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`,
170
+ ``,
171
+ ...runtimeConfig.imports,
172
+ ...runtimeConfig.declarations,
173
+ ...deployedCsrfFragment(opts),
174
+ ``,
175
+ ...deployedCorsFragment(opts.cors, "aws-lambda"),
176
+ ``,
177
+ `function eventV2ToRequest(event) {`,
178
+ ` const method = event.requestContext?.http?.method ?? 'GET'`,
179
+ ` const path = event.requestContext?.http?.path ?? '/'`,
180
+ ` const host = event.headers?.host ?? 'lambda'`,
181
+ ` const qs = event.rawQueryString ? '?' + event.rawQueryString : ''`,
182
+ ` const url = 'https://' + host + path + qs`,
183
+ ` const headers = new Headers()`,
184
+ ` for (const [k, v] of Object.entries(event.headers ?? {})) {`,
185
+ ` if (v !== undefined) headers.set(k, String(v))`,
186
+ ` }`,
187
+ ` let body = event.body`,
188
+ ` if (body && event.isBase64Encoded) {`,
189
+ ` body = Buffer.from(body, 'base64')`,
190
+ ` }`,
191
+ ` return new Request(url, {`,
192
+ ` method,`,
193
+ ` headers,`,
194
+ ` body: method === 'GET' || method === 'HEAD' ? undefined : body,`,
195
+ ` })`,
196
+ `}`,
197
+ ``,
198
+ ...awsLambdaHandlerFragment(runtimeConfig.executeRouteSpread)
199
+ ].join("\n");
200
+ }
201
+ async function buildAwsLambda(config, cwd, deps = {}, ctx) {
202
+ assertServicesUnsupported("aws-lambda", readManifest(cwd));
203
+ if (config.ssrStreaming) {
204
+ throw new Error(
205
+ "[adapter-aws-lambda] ssrStreaming is on, but the aws-lambda target does not stream responses: the Lambda v2 result object carries the body as a string, so nothing can leave the function before the run ends. Response streaming would need awslambda.streamifyResponse plus a Function URL in RESPONSE_STREAM invoke mode, which this adapter does not emit. Build a streaming target instead (cloudflare, vercel, netlify, bun, deno-deploy, node), or set ssrStreaming: false in theo.config.ts."
206
+ );
207
+ }
208
+ const runNodeBuild = deps.runNodeBuild ?? nodeAdapter.build.bind(nodeAdapter);
209
+ await runNodeBuild(config, cwd, ctx);
210
+ const outputDir = resolve(cwd, ".theokit/aws");
211
+ const ensureDir = deps.ensureDir ?? ((p) => mkdirSync(p, { recursive: true }));
212
+ ensureDir(outputDir);
213
+ const entry = renderAwsLambdaEntry({
214
+ securityHeaders: config.security?.headers,
215
+ csrf: config.security?.csrf,
216
+ disallowed: config.security?.disallowed,
217
+ cors: config.security?.cors,
218
+ // #425 — a selector, not a transformer, so it rides as a literal like the values above.
219
+ serialization: config.serialization
220
+ });
221
+ const write = deps.writeEntry ?? ((p, c) => {
222
+ writeFileSync(p, c);
223
+ });
224
+ write(resolve(outputDir, "handler.mjs"), entry);
225
+ console.log("\n \u2713 AWS Lambda output \u2192 .theokit/aws/handler.mjs");
226
+ console.log(
227
+ `${describeDeployedSecurityHeaders({
228
+ target: "aws-lambda",
229
+ securityHeaders: config.security?.headers,
230
+ mintsNonce: false,
231
+ documentHeaders: "platform-unmanaged"
232
+ })}
233
+ `
234
+ );
235
+ }
236
+ var awsLambdaAdapter = {
237
+ name: "aws-lambda",
238
+ // #382 — delisted for streaming, deliberately. See DeployAdapter.
239
+ streamsResponses: false,
240
+ // #409 / #410 — the generated entry calls `executeRoute` with routes, loader
241
+ // and serverDir only. CSRF, route policy, file middleware and Zod validation
242
+ // still run because they live inside `executeRoute`; none of the remaining
243
+ // configurable concerns reach it. Declared explicitly rather than omitted so
244
+ // the gap is a statement in the source and not an absence.
245
+ //
246
+ // `securityHeaders` IS applied -- to every response this function returns.
247
+ // The document comes from CloudFront or another static host and does not pass
248
+ // through it (usetheokit/theokit#412).
249
+ appliesConfig: ["securityHeaders", "csrf", "disallowed", "cors", "serialization"],
250
+ build(config, cwd, ctx) {
251
+ return buildAwsLambda(config, cwd, {}, ctx);
252
+ }
253
+ };
254
+ export {
255
+ awsLambdaAdapter,
256
+ buildAwsLambda,
257
+ eventV2ToRequestShape,
258
+ renderAwsLambdaEntry,
259
+ responseToLambdaResultV2
260
+ };
261
+ //# sourceMappingURL=aws-lambda-VKMYUMP2.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/aws-lambda.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * AWS Lambda adapter. Writes to `cwd/.theokit/lambda/`. Build-time tool.\n */\nimport { mkdirSync, writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport type { TheoConfig } from '../config/schema.js'\nimport type { SecurityHeadersConfig } from '../core/contracts/security-headers.js'\nimport { assertServicesUnsupported, readManifest } from '../services/index.js'\n\nimport { deployedCorsFragment, type DeployedCorsOptions } from './deployed-cors.js'\nimport { deployedCsrfFragment, type DeployedCsrfOptions } from './deployed-csrf.js'\nimport {\n deployedRuntimeConfigFragment,\n type DeployedRuntimeConfigOptions,\n} from './deployed-runtime-config.js'\nimport { deployedTraceFragment } from './deployed-trace.js'\nimport { nodeAdapter } from './node.js'\nimport {\n describeDeployedSecurityHeaders,\n renderSecurityHeadersConfigLiteral,\n} from './security-headers.js'\nimport type { AdapterBuildContext, DeployAdapter } from './types.js'\n\nexport interface AwsLambdaBuildDeps {\n runNodeBuild?: (config: TheoConfig, cwd: string, ctx?: AdapterBuildContext) => Promise<void>\n writeEntry?: (path: string, content: string) => void\n ensureDir?: (path: string) => void\n}\n\nexport interface RequestShape {\n method: string\n path: string\n headers: Record<string, string>\n body?: string\n}\n\nexport interface LambdaResultV2 {\n statusCode: number\n headers: Record<string, string>\n body: string\n isBase64Encoded: boolean\n}\n\nconst BINARY_CONTENT_TYPES = [\n 'application/octet-stream',\n 'application/pdf',\n 'application/zip',\n 'image/',\n 'audio/',\n 'video/',\n]\n\nfunction isBinaryContentType(contentType: string | undefined): boolean {\n if (!contentType) return false\n const ct = contentType.toLowerCase()\n return BINARY_CONTENT_TYPES.some((prefix) => ct.startsWith(prefix))\n}\n\ninterface APIGatewayProxyEventV2 {\n version: string\n requestContext: {\n http: { method: string; path: string }\n }\n headers?: Record<string, string | undefined>\n body?: string\n isBase64Encoded?: boolean\n}\n\nexport function eventV2ToRequestShape(event: APIGatewayProxyEventV2): RequestShape {\n const headers: Record<string, string> = {}\n for (const [k, v] of Object.entries(event.headers ?? {})) {\n if (v !== undefined) headers[k] = v\n }\n let body: string | undefined = event.body\n if (body !== undefined && event.isBase64Encoded) {\n body = Buffer.from(body, 'base64').toString('utf-8')\n }\n return {\n method: event.requestContext.http.method,\n path: event.requestContext.http.path,\n headers,\n body,\n }\n}\n\nexport function responseToLambdaResultV2(\n statusCode: number,\n headers: Record<string, string>,\n body: string,\n): LambdaResultV2 {\n const isBinary = isBinaryContentType(headers['content-type'])\n return {\n statusCode,\n headers,\n body: isBinary ? Buffer.from(body, 'binary').toString('base64') : body,\n isBase64Encoded: isBinary,\n }\n}\n\n// Generated-code fragments — extracted so the parent emitter stays under the\n// max-lines-per-function ceiling.\n/** The v2 result conversion, the handler, and the routing that feeds them. */\nfunction awsLambdaHandlerFragment(runtimeSpread: string): string[] {\n return [\n `// #382 — this target is DELISTED for response streaming, by construction.`,\n `// The Lambda v2 result object below carries \\`body\\` as a string, so the`,\n `// response cannot exist until the run has finished, no matter how the`,\n `// framework's shim writes it. Streaming here would require`,\n `// \\`awslambda.streamifyResponse\\` plus a Function URL in RESPONSE_STREAM`,\n `// invoke mode — neither of which this adapter emits, and which would break`,\n `// every API Gateway deployment of it. Rather than degrade in silence, a`,\n `// response that is unambiguously a stream is named in the logs below.`,\n `async function responseToV2Result(response, routePath) {`,\n ` const headers = {}`,\n ` response.headers.forEach((v, k) => { headers[k] = v })`,\n ` const ct = headers['content-type'] ?? ''`,\n ` if (ct.includes('text/event-stream')) {`,\n ` console.warn(`,\n ` '[theo][aws-lambda] ' + routePath + ' returned a streaming response (' + ct + '), ' +`,\n ` 'but the aws-lambda target buffers it whole and delivers it when the run ends. ' +`,\n ` 'This target is delisted for streaming (theokit#382). Deploy streaming routes to ' +`,\n ` 'cloudflare, vercel, netlify, bun, deno-deploy or node.'`,\n ` )`,\n ` }`,\n ` const isBinary = /^application\\\\/(octet-stream|pdf|zip)|^(image|audio|video)\\\\//.test(ct)`,\n ` if (isBinary) {`,\n ` const buf = Buffer.from(await response.arrayBuffer())`,\n ` return {`,\n ` statusCode: response.status,`,\n ` headers,`,\n ` body: buf.toString('base64'),`,\n ` isBase64Encoded: true,`,\n ` }`,\n ` }`,\n ` return {`,\n ` statusCode: response.status,`,\n ` headers,`,\n ` body: await response.text(),`,\n ` isBase64Encoded: false,`,\n ` }`,\n `}`,\n ``,\n `// Every outcome — including both 404s — is produced as a Web Response by`,\n `// routeRequest, so the security baseline is applied at ONE place and the`,\n `// v2 result object is built from headers that already carry it.`,\n `export const handler = async (event) => {`,\n ` const path = event.requestContext?.http?.path ?? '/'`,\n ` // #409 — the same event, read as a Web Request so the CORS matcher can see the method and`,\n ` // the \\`origin\\` header. \\`eventV2ToRequest\\` reads a body already present in the event, so`,\n ` // unlike the Node targets there is no stream to drain twice.`,\n ` const corsRequest = eventV2ToRequest(event)`,\n ``,\n ` // The preflight is answered BEFORE anything routes: an OPTIONS the router handles is an`,\n ` // OPTIONS the browser never gets a CORS answer to.`,\n ` const preflight = corsPreflight(corsRequest)`,\n ` const response = preflight !== null`,\n ` ? withSecurityHeaders(preflight, SECURITY_HEADERS)`,\n ` : withCors(corsRequest, withSecurityHeaders(await routeRequest(event, path), SECURITY_HEADERS))`,\n ` return responseToV2Result(response, path)`,\n `}`,\n ``,\n `async function routeRequest(event, path) {`,\n ` if (!path.startsWith('/api/')) {`,\n ` return new Response(`,\n ` 'Static assets must be served from CloudFront or a separate static host.',`,\n ` { status: 404, headers: { 'content-type': 'text/plain' } },`,\n ` )`,\n ` }`,\n ``,\n ` if (!routesCache) routesCache = scanServerRoutes(serverDir)`,\n ` if (!loaderCache) loaderCache = createProductionLoader()`,\n ``,\n ` const match = matchRoute(path, routesCache)`,\n ` if (!match) {`,\n ` return new Response(JSON.stringify({ error: { code: 'NOT_FOUND' } }), {`,\n ` status: 404,`,\n ` headers: { 'content-type': 'application/json' },`,\n ` })`,\n ` }`,\n ``,\n ` const request = eventV2ToRequest(event)`,\n ` const { req, res, toResponse } = createWebShim(request)`,\n ...deployedTraceFragment('request', ' '),\n ` const method = request.method.toUpperCase()`,\n ` return toResponse(executeRoute({ route: match.route, method, params: match.params, req, res, loadModule: loaderCache, serverDir, requestId, ...CSRF_CONFIG, ${runtimeSpread} }))`,\n `}`,\n ]\n}\n\nexport function renderAwsLambdaEntry(\n opts: { securityHeaders?: SecurityHeadersConfig } & DeployedCsrfOptions &\n DeployedRuntimeConfigOptions &\n DeployedCorsOptions = {},\n): string {\n const runtimeConfig = deployedRuntimeConfigFragment(opts)\n return [\n `// Generated by Theo — AWS Lambda Adapter`,\n `// Use with API Gateway HTTP API v2 (default).`,\n ``,\n `import { resolve } from 'node:path'`,\n `import { scanServerRoutes, matchRoute, executeRoute, createProductionLoader, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server'`,\n `import { createWebShim } from 'theokit/adapters/web-shim'`,\n `import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,\n ``,\n `const cwd = process.cwd()`,\n `const serverDir = resolve(cwd, 'server')`,\n `let routesCache = null`,\n `let loaderCache = null`,\n ``,\n `// #410 — the security baseline \\`theokit start\\` puts on every response,`,\n `// carried here as a literal because the deployed function has no`,\n `// theo.config.ts to read. Non-API paths 404 here and the document is served`,\n `// from CloudFront or another static host, so this covers the API and not the`,\n `// page (usetheokit/theokit#412).`,\n `const SECURITY_HEADERS_CONFIG = ${renderSecurityHeadersConfigLiteral(opts.securityHeaders)}`,\n `const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`,\n ``,\n ...runtimeConfig.imports,\n ...runtimeConfig.declarations,\n ...deployedCsrfFragment(opts),\n ``,\n ...deployedCorsFragment(opts.cors, 'aws-lambda'),\n ``,\n `function eventV2ToRequest(event) {`,\n ` const method = event.requestContext?.http?.method ?? 'GET'`,\n ` const path = event.requestContext?.http?.path ?? '/'`,\n ` const host = event.headers?.host ?? 'lambda'`,\n ` const qs = event.rawQueryString ? '?' + event.rawQueryString : ''`,\n ` const url = 'https://' + host + path + qs`,\n ` const headers = new Headers()`,\n ` for (const [k, v] of Object.entries(event.headers ?? {})) {`,\n ` if (v !== undefined) headers.set(k, String(v))`,\n ` }`,\n ` let body = event.body`,\n ` if (body && event.isBase64Encoded) {`,\n ` body = Buffer.from(body, 'base64')`,\n ` }`,\n ` return new Request(url, {`,\n ` method,`,\n ` headers,`,\n ` body: method === 'GET' || method === 'HEAD' ? undefined : body,`,\n ` })`,\n `}`,\n ``,\n ...awsLambdaHandlerFragment(runtimeConfig.executeRouteSpread),\n ].join('\\n')\n}\n\nexport async function buildAwsLambda(\n config: TheoConfig,\n cwd: string,\n deps: AwsLambdaBuildDeps = {},\n ctx?: AdapterBuildContext,\n): Promise<void> {\n // Wave 2 (T2.2) — reject polyglot services on this adapter.\n assertServicesUnsupported('aws-lambda', readManifest(cwd))\n\n // #382 — refuse by name rather than build something that cannot do what was\n // asked. `ssrStreaming` is the config's declaration that responses stream,\n // and this target is delisted for that (see `awsLambdaAdapter.streamsResponses`).\n if (config.ssrStreaming) {\n throw new Error(\n '[adapter-aws-lambda] ssrStreaming is on, but the aws-lambda target does not stream ' +\n 'responses: the Lambda v2 result object carries the body as a string, so nothing can ' +\n 'leave the function before the run ends. Response streaming would need ' +\n 'awslambda.streamifyResponse plus a Function URL in RESPONSE_STREAM invoke mode, which ' +\n 'this adapter does not emit. Build a streaming target instead (cloudflare, vercel, ' +\n 'netlify, bun, deno-deploy, node), or set ssrStreaming: false in theo.config.ts.',\n )\n }\n\n const runNodeBuild = deps.runNodeBuild ?? nodeAdapter.build.bind(nodeAdapter)\n await runNodeBuild(config, cwd, ctx)\n\n const outputDir = resolve(cwd, '.theokit/aws')\n const ensureDir = deps.ensureDir ?? ((p: string) => mkdirSync(p, { recursive: true }))\n ensureDir(outputDir)\n\n const entry = renderAwsLambdaEntry({\n securityHeaders: config.security?.headers,\n csrf: config.security?.csrf,\n disallowed: config.security?.disallowed,\n cors: config.security?.cors,\n // #425 — a selector, not a transformer, so it rides as a literal like the values above.\n serialization: config.serialization,\n })\n const write =\n deps.writeEntry ??\n ((p, c) => {\n writeFileSync(p, c)\n })\n write(resolve(outputDir, 'handler.mjs'), entry)\n\n // eslint-disable-next-line no-console -- CLI build progress\n console.log('\\n ✓ AWS Lambda output → .theokit/aws/handler.mjs')\n // eslint-disable-next-line no-console -- CLI build progress\n console.log(\n `${describeDeployedSecurityHeaders({\n target: 'aws-lambda',\n securityHeaders: config.security?.headers,\n mintsNonce: false,\n documentHeaders: 'platform-unmanaged',\n })}\\n`,\n )\n}\n\nexport const awsLambdaAdapter: DeployAdapter = {\n name: 'aws-lambda',\n // #382 — delisted for streaming, deliberately. See DeployAdapter.\n streamsResponses: false,\n // #409 / #410 — the generated entry calls `executeRoute` with routes, loader\n // and serverDir only. CSRF, route policy, file middleware and Zod validation\n // still run because they live inside `executeRoute`; none of the remaining\n // configurable concerns reach it. Declared explicitly rather than omitted so\n // the gap is a statement in the source and not an absence.\n //\n // `securityHeaders` IS applied -- to every response this function returns.\n // The document comes from CloudFront or another static host and does not pass\n // through it (usetheokit/theokit#412).\n appliesConfig: ['securityHeaders', 'csrf', 'disallowed', 'cors', 'serialization'],\n build(config, cwd, ctx) {\n return buildAwsLambda(config, cwd, {}, ctx)\n },\n}\n"],"mappings":"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","names":[]}
@@ -3,43 +3,53 @@ import "tsx/esm";
3
3
  import {
4
4
  describeControllerArtifacts,
5
5
  emitControllerArtifacts
6
- } from "./chunk-47CINLWF.js";
7
- import {
8
- preflightNodeAndBindings
9
- } from "./chunk-KTMQUYED.js";
6
+ } from "./chunk-44J2ANQC.js";
10
7
  import {
11
8
  validateProjectStructure
12
9
  } from "./chunk-GEQJAFSV.js";
10
+ import {
11
+ preflightNodeAndBindings
12
+ } from "./chunk-KTMQUYED.js";
13
13
  import {
14
14
  emitOpenApi,
15
15
  loadRoutesForOpenApi
16
16
  } from "./chunk-47VNWTL4.js";
17
+ import "./chunk-HWBRS4DZ.js";
18
+ import "./chunk-2AMLGJJA.js";
19
+ import {
20
+ generateManifest,
21
+ writeManifest as writeManifest2
22
+ } from "./chunk-KUZVRJ7M.js";
23
+ import {
24
+ scanAgents
25
+ } from "./chunk-EVZKNA2W.js";
26
+ import {
27
+ scanServerRoutes,
28
+ scanWebSocketRoutes
29
+ } from "./chunk-XS7EX55U.js";
30
+ import {
31
+ compareByCodeUnit,
32
+ walkSourceFiles
33
+ } from "./chunk-FD4ZDTQ6.js";
17
34
  import {
18
- importUserModule,
19
35
  loadConfig
20
- } from "./chunk-S433N3CT.js";
36
+ } from "./chunk-QTHVHNJJ.js";
21
37
  import {
22
38
  loadEnv
23
- } from "./chunk-HBU2GIMZ.js";
24
- import "./chunk-GVW5EKEU.js";
39
+ } from "./chunk-3QPVEJ7D.js";
40
+ import {
41
+ importUserModule
42
+ } from "./chunk-U5PWXS3J.js";
43
+ import "./chunk-FH3SQR6P.js";
25
44
  import {
26
45
  buildManifest,
27
46
  writeManifest
28
- } from "./chunk-7VPQHEAJ.js";
29
- import "./chunk-T5C46IIU.js";
30
- import {
31
- generateManifest,
32
- writeManifest as writeManifest2
33
- } from "./chunk-ZB7D62OA.js";
34
- import "./chunk-LNVMHQ2Z.js";
35
- import "./chunk-BMHS4WAN.js";
36
- import {
37
- walkSourceFiles
38
- } from "./chunk-A7JBF5FO.js";
47
+ } from "./chunk-ZNZISJDZ.js";
48
+ import "./chunk-VI7ZANB3.js";
39
49
 
40
50
  // src/cli/commands/build.ts
41
51
  import { existsSync as existsSync4 } from "fs";
42
- import { resolve } from "path";
52
+ import { dirname as dirname2, relative, resolve, sep as sep2 } from "path";
43
53
 
44
54
  // src/adapters/types.ts
45
55
  var VALID_TARGETS = [
@@ -306,7 +316,7 @@ async function scanCronDirs(dirs) {
306
316
  throw new DuplicateCronNameError(name, paths);
307
317
  }
308
318
  }
309
- return nodes.sort((a, b) => a.name.localeCompare(b.name));
319
+ return nodes.sort((a, b) => compareByCodeUnit(a.name, b.name));
310
320
  }
311
321
 
312
322
  // src/server/jobs/job-manifest.ts
@@ -402,7 +412,7 @@ async function scanJobs(jobsDir) {
402
412
  throw new DuplicateJobNameError(name, paths);
403
413
  }
404
414
  }
405
- return nodes.sort((a, b) => a.name.localeCompare(b.name));
415
+ return nodes.sort((a, b) => compareByCodeUnit(a.name, b.name));
406
416
  }
407
417
 
408
418
  // src/cli/cleanup/cleanup.ts
@@ -543,7 +553,7 @@ async function buildCommand(options) {
543
553
  `);
544
554
  }
545
555
  async function runAdapterBuild(target, config, cwd) {
546
- const { theoPluginAsync } = await import("./vite-plugin-VPJFD4HK.js");
556
+ const { theoPluginAsync } = await import("./vite-plugin-VKCT2LF2.js");
547
557
  const { default: react } = await import("@vitejs/plugin-react");
548
558
  const ctx = {
549
559
  // `react()` may return Plugin or Plugin[] depending on version; spread the
@@ -559,10 +569,45 @@ async function runAdapterBuild(target, config, cwd) {
559
569
  serverDir: config.serverDir,
560
570
  agentsDir: config.agentsDir
561
571
  })
562
- ].flat()
572
+ ].flat(),
573
+ // #369 — the same inversion, for the same reason. A Worker has no filesystem, so the Cloudflare
574
+ // entry bakes its routes at build time; importing the scanner from `adapters/` would add the
575
+ // `adapters → server` edge that `adapters-may-only-depend-on-core-router-services` refuses. The
576
+ // CLI already imports both sides, so it composes the scan and hands over the result.
577
+ //
578
+ // Paths are made relative to the project root here, where `cwd` is known: that string is both
579
+ // the emitted import specifier and the key the executor looks a module up by, and the scanners
580
+ // return absolute paths.
581
+ scanRoutes: (serverDir) => {
582
+ const abs = resolve(cwd, serverDir);
583
+ const toProjectRelative = (p) => relative(cwd, p).split(sep2).join("/");
584
+ return {
585
+ routes: scanServerRoutes(abs).map((route) => ({
586
+ filePath: toProjectRelative(route.filePath),
587
+ routePath: route.routePath,
588
+ methods: route.methods ?? []
589
+ })),
590
+ wsRoutes: scanWebSocketRoutes(abs).map(
591
+ (ws) => toProjectRelative(typeof ws === "string" ? ws : ws.filePath)
592
+ ),
593
+ // #367 — agents are a DIFFERENT scan served by a DIFFERENT function, which is why no
594
+ // adapter had ever heard of them: the entries route `/api/` through `scanServerRoutes` +
595
+ // `executeRoute` alone, so `/api/agents/<name>` matched nothing and 404'd on every target.
596
+ // Scanned here, beside the routes, because the same inversion argument applies verbatim.
597
+ agents: scanAgents(dirname2(abs), config.agentsDir).map((agent) => ({
598
+ filePath: toProjectRelative(agent.filePath),
599
+ agentPath: agent.agentPath,
600
+ name: agent.name
601
+ }))
602
+ };
603
+ }
563
604
  };
564
- const { resolveAdapter } = await import("./registry-GKR3EWRW.js");
605
+ const { resolveAdapter } = await import("./registry-KBZDCFVQ.js");
565
606
  const adapter = await resolveAdapter(target);
607
+ const { warnUnappliedConfig } = await import("./config-support-WQHQIJTA.js");
608
+ warnUnappliedConfig(config, adapter, target, (message) => {
609
+ console.log(message);
610
+ });
566
611
  await adapter.build(config, cwd, ctx);
567
612
  }
568
613
  async function emitCronArtifacts(opts) {
@@ -629,4 +674,4 @@ function relativize3(absPath, root) {
629
674
  export {
630
675
  buildCommand
631
676
  };
632
- //# sourceMappingURL=build-WU6AKKIB.js.map
677
+ //# sourceMappingURL=build-FLX6VF7Q.js.map