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,335 @@
1
+ #!/usr/bin/env node
2
+ import "tsx/esm";
3
+ import {
4
+ deployedAgentsFragment,
5
+ planDeployedPlugins
6
+ } from "./chunk-M2WC5MF7.js";
7
+ import {
8
+ deployedCorsFragment,
9
+ deployedCsrfFragment,
10
+ deployedRuntimeConfigFragment,
11
+ deployedTraceFragment,
12
+ describeDeployedSecurityHeaders,
13
+ renderSecurityHeadersConfigLiteral
14
+ } from "./chunk-E43VJ3E5.js";
15
+ import {
16
+ findRootDiv
17
+ } from "./chunk-3PWQQWT6.js";
18
+ import {
19
+ nodeAdapter
20
+ } from "./chunk-KI4DOTN4.js";
21
+ import "./chunk-RPET332G.js";
22
+ import {
23
+ assertServicesUnsupported,
24
+ readManifest
25
+ } from "./chunk-ZNZISJDZ.js";
26
+
27
+ // src/adapters/cloudflare.ts
28
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
29
+ import { resolve } from "path";
30
+ function readDocumentShell(cwd, streaming) {
31
+ if (!streaming) return {};
32
+ const indexPath = resolve(cwd, ".theokit/client/index.html");
33
+ if (!existsSync(indexPath)) {
34
+ throw new Error(
35
+ `[adapter-cloudflare] ssrStreaming is on but ${indexPath} does not exist, so the worker would serve a document with no <head> and no client entry. Run the client build first, or set ssrStreaming: false in theo.config.ts.`
36
+ );
37
+ }
38
+ const indexHtml = readFileSync(indexPath, "utf-8");
39
+ const rootDiv = findRootDiv(indexHtml);
40
+ if (rootDiv === void 0) {
41
+ throw new Error(
42
+ `[adapter-cloudflare] ${indexPath} has no <div id="root">, so the streamed document has nowhere to put the app. Add one, or set ssrStreaming: false in theo.config.ts.`
43
+ );
44
+ }
45
+ return {
46
+ htmlHead: indexHtml.slice(0, rootDiv.insertAt),
47
+ htmlTail: indexHtml.slice(rootDiv.insertAt)
48
+ };
49
+ }
50
+ function renderBakedRoutes(routes) {
51
+ const routeVar = (index) => `__theoRoute${String(index)}`;
52
+ return {
53
+ routeImports: routes.map(
54
+ (route, index) => `import * as ${routeVar(index)} from '../../${route.filePath}'`
55
+ ),
56
+ routeModuleEntries: routes.map(
57
+ (route, index) => ` ${JSON.stringify(route.filePath)}: ${routeVar(index)},`
58
+ ),
59
+ routeTableEntries: routes.map(
60
+ (route) => ` { filePath: ${JSON.stringify(route.filePath)}, routePath: ${JSON.stringify(route.routePath)}, methods: ${JSON.stringify([...route.methods ?? []])}, ...compilePattern(${JSON.stringify(route.routePath)}) },`
61
+ )
62
+ };
63
+ }
64
+ function routeRuntimeLines(moduleEntries, tableEntries) {
65
+ return [
66
+ `// #369 \u2014 the routes are baked at build time. The Worker used to reach for`,
67
+ `// \`scanServerRoutes\` on the server directory \u2014 a readdirSync, in a runtime with no`,
68
+ `// filesystem. The pattern is recompiled here from the same routePath the scanner`,
69
+ `// used, so one function decides precedence on every target.`,
70
+ `const ROUTE_MODULES = {`,
71
+ ...moduleEntries,
72
+ `}`,
73
+ ``,
74
+ `const routes = [`,
75
+ ...tableEntries,
76
+ `]`,
77
+ ``,
78
+ `// The executor asks for a module by the path the table names. Anything else was`,
79
+ `// never bundled, and saying so beats returning undefined and failing later on a`,
80
+ `// property access far from the cause.`,
81
+ `async function loadModule(path) {`,
82
+ ` const mod = ROUTE_MODULES[path]`,
83
+ ` if (mod === undefined) {`,
84
+ // No backticks in this message: it is emitted INTO a template literal, and a stray one closes
85
+ // it. That is how #344 shipped a SyntaxError, and the emitted-entry parse gate caught this one
86
+ // before it left the branch.
87
+ " throw new Error(`Route module '${path}' was not bundled into this Worker. A Worker has no filesystem, so every route is imported at build time. Re-run: theokit build --target cloudflare`)",
88
+ ` }`,
89
+ ` return mod`,
90
+ `}`,
91
+ ``
92
+ ];
93
+ }
94
+ function renderCloudflareWorkerEntry(opts = {}) {
95
+ const streamingImport = opts.ssrStreaming ? `import { renderStreamingWeb } from '/@theo/entry-server'` : `// (ssrStreaming off: renderStreamingWeb not imported)`;
96
+ const nonApiBranch = opts.ssrStreaming ? [
97
+ ` // T2.3 \u2014 streaming SSR for non-API routes`,
98
+ ` // The same primitive \`theokit start\` uses, not a second one:`,
99
+ ` // 16 bytes of Web Crypto entropy, base64.`,
100
+ ` const nonce = generateNonce()`,
101
+ ` return withSecurityHeaders(`,
102
+ ` await renderStreamingWeb(request, {`,
103
+ ` htmlHead: ${JSON.stringify(opts.htmlHead ?? "")},`,
104
+ ` htmlTail: ${JSON.stringify(opts.htmlTail ?? "")},`,
105
+ ` nonce,`,
106
+ ` }),`,
107
+ ` buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true }, { nonce }),`,
108
+ ` )`
109
+ ].join("\n") : [
110
+ ` // #412 \u2014 the document, served by the worker so it carries the same baseline every`,
111
+ ` // API response carries. It used to return 404 here while wrangler.toml declared a`,
112
+ ` // \`[site]\` bucket nothing read, so the page was missing rather than unprotected.`,
113
+ ` const assets = env?.ASSETS`,
114
+ ` // A wrangler.toml that predates this binding has no ASSETS. Reading .fetch off`,
115
+ ` // undefined would turn every page request into a 500; 404 is what this target`,
116
+ ` // answered before, which is the honest fallback rather than a new failure.`,
117
+ ` if (assets === undefined) return notFoundResponse()`,
118
+ ` return withSecurityHeaders(await assets.fetch(request), SECURITY_HEADERS)`
119
+ ].join("\n");
120
+ const { routeImports, routeModuleEntries, routeTableEntries } = renderBakedRoutes(
121
+ opts.routes ?? []
122
+ );
123
+ const runtimeConfig = deployedRuntimeConfigFragment(opts);
124
+ const agentsFragment = deployedAgentsFragment(
125
+ opts.agents === void 0 ? void 0 : { kind: "baked", agents: opts.agents },
126
+ { wrapSecurityHeaders: true }
127
+ );
128
+ return [
129
+ `// Generated by Theo \u2014 Cloudflare Workers Adapter`,
130
+ `//`,
131
+ `// REQUIREMENTS (EC-3):`,
132
+ `// - wrangler.toml MUST include compatibility_flags = ["nodejs_compat"]`,
133
+ `// (still required for transitive theokit/server deps, e.g. busboy)`,
134
+ `// - package.json MUST list "theokit" in dependencies (not devDependencies)`,
135
+ `// so Wrangler bundles theokit and its transitive deps`,
136
+ `// - Deploy: wrangler deploy`,
137
+ ``,
138
+ `import { matchRoute, executeRoute, compilePattern, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server'`,
139
+ `import { createWebShim } from 'theokit/adapters/web-shim'`,
140
+ opts.ssrStreaming ? `import { buildSecurityHeaders, generateNonce, withSecurityHeaders } from 'theokit/adapters/security-headers'` : `import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,
141
+ `// T3.4 \u2014 WS bridge for Cloudflare Workers`,
142
+ `import { createCloudflareWsBridge } from 'theokit/adapters/ws-shim'`,
143
+ streamingImport,
144
+ ``,
145
+ ...runtimeConfig.imports,
146
+ ...agentsFragment.imports,
147
+ ...routeImports,
148
+ ``,
149
+ `// CR-006: server directory is a build-time literal \u2014 Workers cannot`,
150
+ `// call process.cwd() and resolving paths at runtime returned '/server'.`,
151
+ `const serverDir = 'server'`,
152
+ ``,
153
+ ...routeRuntimeLines(routeModuleEntries, routeTableEntries),
154
+ `// #410 \u2014 the security baseline \`theokit start\` puts on every response, carried`,
155
+ `// here as a literal because a Worker has no theo.config.ts to read. Same`,
156
+ `// function, same input, so the deployed page and the local one cannot`,
157
+ `// disagree about what the configuration means.`,
158
+ `const SECURITY_HEADERS_CONFIG = ${renderSecurityHeadersConfigLiteral(opts.securityHeaders)}`,
159
+ `const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`,
160
+ ``,
161
+ ...deployedCsrfFragment(opts, "a Worker"),
162
+ ``,
163
+ ...runtimeConfig.declarations,
164
+ ...agentsFragment.declarations,
165
+ ...deployedCorsFragment(opts.cors, "cloudflare"),
166
+ `// #369 \u2014 whether this project declares a WebSocket route, decided at build time. It used`,
167
+ `// to answer it with \`scanWebSocketRoutes\`, which is the same readdirSync.`,
168
+ `const HAS_WS_ROUTES = ${String((opts.wsRoutes ?? []).length > 0)}`,
169
+ ``,
170
+ `function notFoundResponse() {`,
171
+ ` return withSecurityHeaders(`,
172
+ ` new Response(`,
173
+ ` JSON.stringify({ error: { code: 'NOT_FOUND', message: 'Route not found' } }),`,
174
+ ` { status: 404, headers: { 'Content-Type': 'application/json' } },`,
175
+ ` ),`,
176
+ ` SECURITY_HEADERS,`,
177
+ ` )`,
178
+ `}`,
179
+ ``,
180
+ ...cloudflareHandleRequestFragment(
181
+ nonApiBranch,
182
+ runtimeConfig.executeRouteSpread,
183
+ agentsFragment.branch
184
+ )
185
+ ].join("\n");
186
+ }
187
+ function cloudflareHandleRequestFragment(nonApiBranch, runtimeSpread, agentBranch) {
188
+ return [
189
+ `async function handleRequest(request, url, env) {`,
190
+ ` if (!url.pathname.startsWith('/api/')) {`,
191
+ nonApiBranch,
192
+ ` }`,
193
+ ``,
194
+ ...agentBranch,
195
+ ``,
196
+ ` const match = matchRoute(url.pathname, routes)`,
197
+ ` if (!match) return notFoundResponse()`,
198
+ ``,
199
+ ` const { req, res, toResponse } = createWebShim(request, { trustedProxy: 'platform' })`,
200
+ ...deployedTraceFragment("request", " "),
201
+ ` const method = request.method.toUpperCase()`,
202
+ ` // #382 \u2014 the run is NOT awaited before the Response is taken. toResponse()`,
203
+ ` // settles as soon as status + headers are known and carries a live body, so`,
204
+ ` // the Worker starts flushing while the handler is still writing. Awaiting`,
205
+ ` // executeRoute() first would re-buffer the whole response here even though`,
206
+ ` // the shim streams; awaiting toResponse() does not \u2014 it settles at the head.`,
207
+ ` return withSecurityHeaders(await toResponse(executeRoute({`,
208
+ ` route: match.route, method, params: match.params,`,
209
+ ` req, res, loadModule, serverDir, requestId, ...CSRF_CONFIG, ${runtimeSpread}`,
210
+ ` })), SECURITY_HEADERS)`,
211
+ `}`,
212
+ ``,
213
+ `export default {`,
214
+ ` async fetch(request, env, ctx) {`,
215
+ ` const url = new URL(request.url)`,
216
+ ``,
217
+ ` // T3.4 \u2014 Detect WebSocket upgrade and delegate to the CF bridge.`,
218
+ ` // A 101 carries no document and no script, so the security baseline does`,
219
+ ` // not apply to it.`,
220
+ ` if (request.headers.get('upgrade')?.toLowerCase() === 'websocket') {`,
221
+ ` if (!HAS_WS_ROUTES) return notFoundResponse()`,
222
+ ` const cfWs = createCloudflareWsBridge({`,
223
+ ` onOpen: () => {},`,
224
+ ` onMessage: (ws, data) => { ws.send(data) },`,
225
+ ` onClose: () => {},`,
226
+ ` })`,
227
+ ` return cfWs.handle(request)`,
228
+ ` }`,
229
+ ``,
230
+ ` // #409 \u2014 the preflight is answered BEFORE anything routes: an OPTIONS the router handles`,
231
+ ` // is an OPTIONS the browser never gets a CORS answer to. The WebSocket upgrade above is`,
232
+ ` // deliberately upstream of it \u2014 a 101 is not a CORS-governed response.`,
233
+ ` const preflight = corsPreflight(request)`,
234
+ ` if (preflight !== null) return withSecurityHeaders(preflight, SECURITY_HEADERS)`,
235
+ ``,
236
+ ` return withCors(request, await handleRequest(request, url, env))`,
237
+ ` },`,
238
+ `}`
239
+ ];
240
+ }
241
+ function renderWranglerToml() {
242
+ return [
243
+ `# Generated by Theo \u2014 Cloudflare Workers`,
244
+ `name = "theo-app"`,
245
+ `main = ".theokit/cloudflare/worker.mjs"`,
246
+ `compatibility_date = "2025-09-01"`,
247
+ `compatibility_flags = ["nodejs_compat"]`,
248
+ ``,
249
+ `# #412 \u2014 \`[assets]\` with a BINDING, not the legacy \`[site]\` bucket.`,
250
+ `#`,
251
+ `# \`[site]\` uploads to KV and is read through \`kv-asset-handler\` and a`,
252
+ `# \`__STATIC_CONTENT\` binding \u2014 neither of which this worker has ever had. So the`,
253
+ `# bucket was declared, uploaded, and consumed by nothing: with ssrStreaming off, a`,
254
+ `# deploy answered 404 for its own page. This binding is what the worker calls.`,
255
+ `[assets]`,
256
+ `directory = ".theokit/client"`,
257
+ `binding = "ASSETS"`,
258
+ `# A client-routed app asks for /dashboard, which is no file. Without this the asset`,
259
+ `# handler 404s a deep link and the SPA never boots.`,
260
+ `not_found_handling = "single-page-application"`,
261
+ ``,
262
+ `# Environment variables are set via wrangler secret or dashboard`,
263
+ `# Example: wrangler secret put DATABASE_URL`
264
+ ].join("\n");
265
+ }
266
+ var cloudflareAdapter = {
267
+ name: "cloudflare",
268
+ streamsResponses: true,
269
+ // #409 / #410 — the generated entry calls `executeRoute` with routes, loader
270
+ // and serverDir only. CSRF, route policy, file middleware and Zod validation
271
+ // still run because they live inside `executeRoute`; none of the remaining
272
+ // configurable concerns reach it. Declared explicitly rather than omitted so
273
+ // the gap is a statement in the source and not an absence.
274
+ //
275
+ // `securityHeaders` IS applied: the worker carries `security.headers` as a
276
+ // literal and puts the built baseline on every response it returns, including
277
+ // the streamed SSR document — with a per-request nonce, the only deploy path
278
+ // that can mint one (`adapters/security-headers.ts`).
279
+ servesAgents: true,
280
+ appliesConfig: ["securityHeaders", "csrf", "disallowed", "cors", "serialization", "plugins"],
281
+ async build(config, cwd, ctx) {
282
+ assertServicesUnsupported("cloudflare", readManifest(cwd));
283
+ await nodeAdapter.build(config, cwd, ctx);
284
+ const outputDir = resolve(cwd, ".theokit/cloudflare");
285
+ mkdirSync(outputDir, { recursive: true });
286
+ const shell = readDocumentShell(cwd, config.ssrStreaming);
287
+ const scanned = ctx?.scanRoutes?.(config.serverDir) ?? { routes: [], wsRoutes: [], agents: [] };
288
+ const pluginsPlan = planDeployedPlugins(config.plugins, "cloudflare");
289
+ if (pluginsPlan !== void 0) {
290
+ writeFileSync(resolve(outputDir, "theo.plugins.mjs"), pluginsPlan.source);
291
+ }
292
+ writeFileSync(
293
+ resolve(outputDir, "worker.mjs"),
294
+ renderCloudflareWorkerEntry({
295
+ ssrStreaming: config.ssrStreaming,
296
+ ...shell,
297
+ securityHeaders: config.security?.headers,
298
+ csrf: config.security?.csrf,
299
+ disallowed: config.security?.disallowed,
300
+ cors: config.security?.cors,
301
+ // #425 — a selector, not a transformer, so it rides as a literal like the values above.
302
+ serialization: config.serialization,
303
+ // #425 — the ONE concern that is not a literal. A closure cannot be baked, so a plugin
304
+ // declared by module specifier is imported by the emitted module instead; a constructed one
305
+ // is refused by name at build time rather than dropped in silence.
306
+ runtimeConfigModule: pluginsPlan?.moduleSpecifier,
307
+ routes: scanned.routes,
308
+ // #367 — a Worker has no filesystem, so its agents are decided here like its routes.
309
+ agents: scanned.agents,
310
+ wsRoutes: scanned.wsRoutes
311
+ })
312
+ );
313
+ writeFileSync(resolve(cwd, "wrangler.toml"), renderWranglerToml());
314
+ console.log("\n \u2713 Cloudflare output \u2192 .theokit/cloudflare/ + wrangler.toml");
315
+ console.log(
316
+ `${describeDeployedSecurityHeaders({
317
+ target: "cloudflare",
318
+ securityHeaders: config.security?.headers,
319
+ // Only the streaming worker renders HTML per request, so only it can put
320
+ // the same nonce on the header and on the script tag it emits.
321
+ mintsNonce: config.ssrStreaming,
322
+ // #412 — either way the worker returns the document now: streamed by
323
+ // `renderStreamingWeb`, or from the ASSETS binding it finally calls.
324
+ documentHeaders: "handler"
325
+ })}
326
+ `
327
+ );
328
+ }
329
+ };
330
+ export {
331
+ cloudflareAdapter,
332
+ renderCloudflareWorkerEntry,
333
+ renderWranglerToml
334
+ };
335
+ //# sourceMappingURL=cloudflare-SIG42OIW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/cloudflare.ts"],"sourcesContent":["/* eslint-disable security/detect-non-literal-fs-filename --\n * Cloudflare deploy adapter. All write paths are under `cwd/.theokit/cloudflare/`\n * and `cwd/wrangler.toml`. Build-time tool — no HTTP input.\n */\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\n\nimport type { TheoConfig } from '../config/schema.js'\nimport { findRootDiv } from '../core/contracts/find-root-div.js'\nimport type { SecurityHeadersConfig } from '../core/contracts/security-headers.js'\nimport { assertServicesUnsupported, readManifest } from '../services/index.js'\n\nimport { deployedAgentsFragment, type DeployedAgent } from './deployed-agents.js'\nimport { deployedCorsFragment, type DeployedCorsOptions } from './deployed-cors.js'\nimport { deployedCsrfFragment, type DeployedCsrfOptions } from './deployed-csrf.js'\nimport { planDeployedPlugins } from './deployed-plugins-module.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\n/**\n * T2.1 — Cloudflare adapter rewritten to consume `theokit/adapters/web-shim`\n * instead of emitting an inline plain-object Request/Response shim. Reduces\n * template from ~50 lines to ~25 and centralizes maintenance.\n */\n\n/**\n * The built `index.html` split into the part before `<div id=\"root\">` and the\n * part after it.\n *\n * Refuses by name when streaming is on and the template is missing, rather than\n * emitting a worker that serves a headless document. A build that cannot produce\n * a correct artifact should say so at build time; the alternative is a deploy\n * that looks successful and serves pages with no stylesheet.\n */\nfunction readDocumentShell(\n cwd: string,\n streaming: boolean,\n): { htmlHead?: string; htmlTail?: string } {\n if (!streaming) return {}\n\n const indexPath = resolve(cwd, '.theokit/client/index.html')\n if (!existsSync(indexPath)) {\n throw new Error(\n `[adapter-cloudflare] ssrStreaming is on but ${indexPath} does not exist, so the worker ` +\n `would serve a document with no <head> and no client entry. Run the client build first, ` +\n `or set ssrStreaming: false in theo.config.ts.`,\n )\n }\n\n const indexHtml = readFileSync(indexPath, 'utf-8')\n const rootDiv = findRootDiv(indexHtml)\n if (rootDiv === undefined) {\n throw new Error(\n `[adapter-cloudflare] ${indexPath} has no <div id=\"root\">, so the streamed document has ` +\n `nowhere to put the app. Add one, or set ssrStreaming: false in theo.config.ts.`,\n )\n }\n\n return {\n htmlHead: indexHtml.slice(0, rootDiv.insertAt),\n htmlTail: indexHtml.slice(rootDiv.insertAt),\n }\n}\n\n/**\n * The routes, turned into source: static imports, a module map and a literal table (#369).\n *\n * Extracted so the worker renderer stays inside its length budget, and because this is the whole of\n * what changed about how a Worker finds a route — it reads as one idea rather than as three loops\n * inside a hundred lines of template.\n *\n * `../../` because the worker is written to `.theokit/cloudflare/worker.mjs` and `filePath` is\n * relative to the project root. The imports are static so Wrangler's bundler follows them:\n * `wrangler.toml` uploads `.theokit/client` and has never uploaded `server/`, so a module not\n * bundled INTO the worker is not on the platform at all.\n */\nfunction renderBakedRoutes(\n routes: readonly { filePath: string; routePath: string; methods?: readonly string[] }[],\n): { routeImports: string[]; routeModuleEntries: string[]; routeTableEntries: string[] } {\n const routeVar = (index: number): string => `__theoRoute${String(index)}`\n return {\n routeImports: routes.map(\n (route, index) => `import * as ${routeVar(index)} from '../../${route.filePath}'`,\n ),\n routeModuleEntries: routes.map(\n (route, index) => ` ${JSON.stringify(route.filePath)}: ${routeVar(index)},`,\n ),\n routeTableEntries: routes.map(\n (route) =>\n ` { filePath: ${JSON.stringify(route.filePath)}, routePath: ${JSON.stringify(route.routePath)}, ` +\n `methods: ${JSON.stringify([...(route.methods ?? [])])}, ` +\n `...compilePattern(${JSON.stringify(route.routePath)}) },`,\n ),\n }\n}\n\n/**\n * The route-resolution runtime the Worker gets instead of a directory scan (#369).\n *\n * A module map, the literal table, and a loader that refuses anything the build did not bake.\n * Emitted as its own block because it replaces one idea — \"find the routes\" — wholesale.\n */\nfunction routeRuntimeLines(moduleEntries: string[], tableEntries: string[]): string[] {\n return [\n `// #369 — the routes are baked at build time. The Worker used to reach for`,\n `// \\`scanServerRoutes\\` on the server directory — a readdirSync, in a runtime with no`,\n `// filesystem. The pattern is recompiled here from the same routePath the scanner`,\n `// used, so one function decides precedence on every target.`,\n `const ROUTE_MODULES = {`,\n ...moduleEntries,\n `}`,\n ``,\n `const routes = [`,\n ...tableEntries,\n `]`,\n ``,\n `// The executor asks for a module by the path the table names. Anything else was`,\n `// never bundled, and saying so beats returning undefined and failing later on a`,\n `// property access far from the cause.`,\n `async function loadModule(path) {`,\n ` const mod = ROUTE_MODULES[path]`,\n ` if (mod === undefined) {`,\n // No backticks in this message: it is emitted INTO a template literal, and a stray one closes\n // it. That is how #344 shipped a SyntaxError, and the emitted-entry parse gate caught this one\n // before it left the branch.\n \" throw new Error(`Route module '\" +\n '${path}' +\n \"' was not bundled into this Worker. \" +\n 'A Worker has no filesystem, so every route is imported at build time. ' +\n 'Re-run: theokit build --target cloudflare`)',\n ` }`,\n ` return mod`,\n `}`,\n ``,\n ]\n}\n\nexport function renderCloudflareWorkerEntry(\n opts: {\n ssrStreaming?: boolean\n htmlHead?: string\n htmlTail?: string\n securityHeaders?: SecurityHeadersConfig\n /**\n * The server routes, scanned on the BUILD machine (#369).\n *\n * A Worker has no filesystem, so the worker used to call `scanServerRoutes` — a `readdirSync` —\n * against a directory that does not exist there, and load each module through `import()` of a\n * file path. Both are baked here instead, which is the road this adapter already takes for the\n * document shell one function away.\n *\n * `filePath` is relative to the project root and is used for two things: the key the executor\n * looks a module up by, and the specifier the static import uses. Paths are emitted relative to\n * `.theokit/cloudflare/`, where the worker is written.\n */\n routes?: readonly { filePath: string; routePath: string; methods?: readonly string[] }[]\n /**\n * The two concerns #410 could not bake (#425), composed from one place so the six targets\n * cannot drift into six spellings. `serialization` is a literal like the security values above;\n * `plugins` is an import, because a closure has no literal.\n */\n runtimeConfigModule?: DeployedRuntimeConfigOptions['runtimeConfigModule']\n serialization?: DeployedRuntimeConfigOptions['serialization']\n /**\n * The app's agents, scanned on the build machine (#367).\n *\n * A different scan from `routes` and served by a different function — which is why a worker\n * that only consulted the route table answered every `/api/agents/<name>` with a 404.\n */\n agents?: readonly DeployedAgent[]\n /** WebSocket route files, scanned on the build machine. Only their presence is used (#369). */\n wsRoutes?: readonly string[]\n } & DeployedCsrfOptions &\n DeployedCorsOptions = {},\n): string {\n const streamingImport = opts.ssrStreaming\n ? `import { renderStreamingWeb } from '/@theo/entry-server'`\n : `// (ssrStreaming off: renderStreamingWeb not imported)`\n // #343 — the document shell is inlined as a build-time literal because a Worker\n // has no filesystem to read `index.html` from at request time. Without it,\n // `renderStreamingWeb` falls back to its empty-string defaults and the response\n // is React output with no `<html>`, no `<head>`, no stylesheet and no client\n // entry — hydration data for a page that cannot hydrate. The streaming\n // assembly was fixed in the generated entry and this, its only caller, was\n // left passing nothing.\n //\n // `JSON.stringify` and not a template literal: the shell contains quotes,\n // angle brackets and a `</script>`, and embedding it naively produces a worker\n // that fails to parse at deploy time rather than here.\n //\n // #410 — this is also the ONE deploy path that renders HTML at request time,\n // so the one that can mint a per-request CSP nonce: `renderStreamingWeb`\n // threads `options.nonce` into `renderToReadableStream` and into the hydration\n // script (`router/entry-server.ts`). Every other response below carries the\n // nonce-less baseline, which is what `buildSecurityHeaders` already does for a\n // prerendered route (EC-4).\n const nonApiBranch = opts.ssrStreaming\n ? [\n ` // T2.3 — streaming SSR for non-API routes`,\n ` // The same primitive \\`theokit start\\` uses, not a second one:`,\n ` // 16 bytes of Web Crypto entropy, base64.`,\n ` const nonce = generateNonce()`,\n ` return withSecurityHeaders(`,\n ` await renderStreamingWeb(request, {`,\n ` htmlHead: ${JSON.stringify(opts.htmlHead ?? '')},`,\n ` htmlTail: ${JSON.stringify(opts.htmlTail ?? '')},`,\n ` nonce,`,\n ` }),`,\n ` buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true }, { nonce }),`,\n ` )`,\n ].join('\\n')\n : [\n ` // #412 — the document, served by the worker so it carries the same baseline every`,\n ` // API response carries. It used to return 404 here while wrangler.toml declared a`,\n ` // \\`[site]\\` bucket nothing read, so the page was missing rather than unprotected.`,\n ` const assets = env?.ASSETS`,\n ` // A wrangler.toml that predates this binding has no ASSETS. Reading .fetch off`,\n ` // undefined would turn every page request into a 500; 404 is what this target`,\n ` // answered before, which is the honest fallback rather than a new failure.`,\n ` if (assets === undefined) return notFoundResponse()`,\n ` return withSecurityHeaders(await assets.fetch(request), SECURITY_HEADERS)`,\n ].join('\\n')\n // CR-006: Workers lack `process.cwd()` and the `node:*` import surface\n // is brittle even under `nodejs_compat`. We use the Web Crypto\n // `crypto.randomUUID()` instead of `node:crypto.randomUUID`, and embed\n // the server directory as a build-time literal instead of resolving via\n // `node:path` at runtime.\n const { routeImports, routeModuleEntries, routeTableEntries } = renderBakedRoutes(\n opts.routes ?? [],\n )\n const runtimeConfig = deployedRuntimeConfigFragment(opts)\n const agentsFragment = deployedAgentsFragment(\n opts.agents === undefined ? undefined : { kind: 'baked', agents: opts.agents },\n { wrapSecurityHeaders: true },\n )\n\n return [\n `// Generated by Theo — Cloudflare Workers Adapter`,\n `//`,\n `// REQUIREMENTS (EC-3):`,\n `// - wrangler.toml MUST include compatibility_flags = [\"nodejs_compat\"]`,\n `// (still required for transitive theokit/server deps, e.g. busboy)`,\n `// - package.json MUST list \"theokit\" in dependencies (not devDependencies)`,\n `// so Wrangler bundles theokit and its transitive deps`,\n `// - Deploy: wrangler deploy`,\n ``,\n `import { matchRoute, executeRoute, compilePattern, extractTraceIdFromRequest, TRACE_HEADER, createCorsWebHandler } from 'theokit/server'`,\n `import { createWebShim } from 'theokit/adapters/web-shim'`,\n opts.ssrStreaming\n ? `import { buildSecurityHeaders, generateNonce, withSecurityHeaders } from 'theokit/adapters/security-headers'`\n : `import { buildSecurityHeaders, withSecurityHeaders } from 'theokit/adapters/security-headers'`,\n `// T3.4 — WS bridge for Cloudflare Workers`,\n `import { createCloudflareWsBridge } from 'theokit/adapters/ws-shim'`,\n streamingImport,\n ``,\n ...runtimeConfig.imports,\n ...agentsFragment.imports,\n ...routeImports,\n ``,\n `// CR-006: server directory is a build-time literal — Workers cannot`,\n `// call process.cwd() and resolving paths at runtime returned '/server'.`,\n `const serverDir = 'server'`,\n ``,\n ...routeRuntimeLines(routeModuleEntries, routeTableEntries),\n `// #410 — the security baseline \\`theokit start\\` puts on every response, carried`,\n `// here as a literal because a Worker has no theo.config.ts to read. Same`,\n `// function, same input, so the deployed page and the local one cannot`,\n `// disagree about what the configuration means.`,\n `const SECURITY_HEADERS_CONFIG = ${renderSecurityHeadersConfigLiteral(opts.securityHeaders)}`,\n `const SECURITY_HEADERS = buildSecurityHeaders(SECURITY_HEADERS_CONFIG, { production: true })`,\n ``,\n ...deployedCsrfFragment(opts, 'a Worker'),\n ``,\n ...runtimeConfig.declarations,\n ...agentsFragment.declarations,\n ...deployedCorsFragment(opts.cors, 'cloudflare'),\n `// #369 — whether this project declares a WebSocket route, decided at build time. It used`,\n `// to answer it with \\`scanWebSocketRoutes\\`, which is the same readdirSync.`,\n `const HAS_WS_ROUTES = ${String((opts.wsRoutes ?? []).length > 0)}`,\n ``,\n `function notFoundResponse() {`,\n ` return withSecurityHeaders(`,\n ` new Response(`,\n ` JSON.stringify({ error: { code: 'NOT_FOUND', message: 'Route not found' } }),`,\n ` { status: 404, headers: { 'Content-Type': 'application/json' } },`,\n ` ),`,\n ` SECURITY_HEADERS,`,\n ` )`,\n `}`,\n ``,\n ...cloudflareHandleRequestFragment(\n nonApiBranch,\n runtimeConfig.executeRouteSpread,\n agentsFragment.branch,\n ),\n ].join('\\n')\n}\n\n/**\n * The Worker's request handler, as generated source.\n *\n * Extracted for the reason `vercel.ts` extracts its own fragments: the emitter is one array\n * literal, so every line the entry gains counts against `max-lines-per-function`, and #410 added\n * the CSRF literal to an emitter already sitting exactly at the ceiling.\n *\n * @param nonApiBranch - what a non-`/api/` request gets, which differs with `ssrStreaming`\n */\nfunction cloudflareHandleRequestFragment(\n nonApiBranch: string,\n runtimeSpread: string,\n agentBranch: readonly string[],\n): string[] {\n return [\n `async function handleRequest(request, url, env) {`,\n ` if (!url.pathname.startsWith('/api/')) {`,\n nonApiBranch,\n ` }`,\n ``,\n ...agentBranch,\n ``,\n ` const match = matchRoute(url.pathname, routes)`,\n ` if (!match) return notFoundResponse()`,\n ``,\n ` const { req, res, toResponse } = createWebShim(request, { trustedProxy: 'platform' })`,\n ...deployedTraceFragment('request', ' '),\n ` const method = request.method.toUpperCase()`,\n ` // #382 — the run is NOT awaited before the Response is taken. toResponse()`,\n ` // settles as soon as status + headers are known and carries a live body, so`,\n ` // the Worker starts flushing while the handler is still writing. Awaiting`,\n ` // executeRoute() first would re-buffer the whole response here even though`,\n ` // the shim streams; awaiting toResponse() does not — it settles at the head.`,\n ` return withSecurityHeaders(await toResponse(executeRoute({`,\n ` route: match.route, method, params: match.params,`,\n ` req, res, loadModule, serverDir, requestId, ...CSRF_CONFIG, ${runtimeSpread}`,\n ` })), SECURITY_HEADERS)`,\n `}`,\n ``,\n `export default {`,\n ` async fetch(request, env, ctx) {`,\n ` const url = new URL(request.url)`,\n ``,\n ` // T3.4 — Detect WebSocket upgrade and delegate to the CF bridge.`,\n ` // A 101 carries no document and no script, so the security baseline does`,\n ` // not apply to it.`,\n ` if (request.headers.get('upgrade')?.toLowerCase() === 'websocket') {`,\n ` if (!HAS_WS_ROUTES) return notFoundResponse()`,\n ` const cfWs = createCloudflareWsBridge({`,\n ` onOpen: () => {},`,\n ` onMessage: (ws, data) => { ws.send(data) },`,\n ` onClose: () => {},`,\n ` })`,\n ` return cfWs.handle(request)`,\n ` }`,\n ``,\n ` // #409 — the preflight is answered BEFORE anything routes: an OPTIONS the router handles`,\n ` // is an OPTIONS the browser never gets a CORS answer to. The WebSocket upgrade above is`,\n ` // deliberately upstream of it — a 101 is not a CORS-governed response.`,\n ` const preflight = corsPreflight(request)`,\n ` if (preflight !== null) return withSecurityHeaders(preflight, SECURITY_HEADERS)`,\n ``,\n ` return withCors(request, await handleRequest(request, url, env))`,\n ` },`,\n `}`,\n ]\n}\n\nexport function renderWranglerToml(): string {\n return [\n `# Generated by Theo — Cloudflare Workers`,\n `name = \"theo-app\"`,\n `main = \".theokit/cloudflare/worker.mjs\"`,\n `compatibility_date = \"2025-09-01\"`,\n `compatibility_flags = [\"nodejs_compat\"]`,\n ``,\n `# #412 — \\`[assets]\\` with a BINDING, not the legacy \\`[site]\\` bucket.`,\n `#`,\n `# \\`[site]\\` uploads to KV and is read through \\`kv-asset-handler\\` and a`,\n `# \\`__STATIC_CONTENT\\` binding — neither of which this worker has ever had. So the`,\n `# bucket was declared, uploaded, and consumed by nothing: with ssrStreaming off, a`,\n `# deploy answered 404 for its own page. This binding is what the worker calls.`,\n `[assets]`,\n `directory = \".theokit/client\"`,\n `binding = \"ASSETS\"`,\n `# A client-routed app asks for /dashboard, which is no file. Without this the asset`,\n `# handler 404s a deep link and the SPA never boots.`,\n `not_found_handling = \"single-page-application\"`,\n ``,\n `# Environment variables are set via wrangler secret or dashboard`,\n `# Example: wrangler secret put DATABASE_URL`,\n ].join('\\n')\n}\n\nexport const cloudflareAdapter: DeployAdapter = {\n name: 'cloudflare',\n streamsResponses: true,\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: the worker carries `security.headers` as a\n // literal and puts the built baseline on every response it returns, including\n // the streamed SSR document — with a per-request nonce, the only deploy path\n // that can mint one (`adapters/security-headers.ts`).\n servesAgents: true,\n appliesConfig: ['securityHeaders', 'csrf', 'disallowed', 'cors', 'serialization', 'plugins'],\n\n async build(config: TheoConfig, cwd: string, ctx?: AdapterBuildContext): Promise<void> {\n // Wave 2 (T2.2) — reject polyglot services on this adapter.\n assertServicesUnsupported('cloudflare', readManifest(cwd))\n\n // 1. Run the standard Node build first (ctx forwarded so nodeAdapter has makeVitePlugins)\n await nodeAdapter.build(config, cwd, ctx)\n\n const outputDir = resolve(cwd, '.theokit/cloudflare')\n mkdirSync(outputDir, { recursive: true })\n\n // 2. Emit Worker entry (now uses the shared web-shim)\n //\n // The document shell is read HERE, after the Node build produced\n // `.theokit/client/index.html`, and inlined into the worker: a Worker has no\n // filesystem at request time. Split on the root div with the same helper the\n // Node server uses (`ssr-setup.ts`), so the two paths cannot disagree about\n // where the shell ends (#343).\n const shell = readDocumentShell(cwd, config.ssrStreaming)\n\n // #369 — the routes are resolved HERE, on the build machine, for the same reason the document\n // shell above is read here: a Worker has no filesystem at request time, and the worker used to\n // run the scan itself against a directory that does not exist there.\n //\n // The scanner is INJECTED rather than imported: importing it would add an `adapters → server`\n // edge, which is the layering inversion ADR-0001 v3 removed for `vite-plugin` and which\n // `adapters-may-only-depend-on-core-router-services` refuses. An absent scanner emits a worker\n // with no routes rather than falling back to a runtime scan — the fallback IS the defect.\n const scanned = ctx?.scanRoutes?.(config.serverDir) ?? { routes: [], wsRoutes: [], agents: [] }\n\n const pluginsPlan = planDeployedPlugins(config.plugins, 'cloudflare')\n if (pluginsPlan !== undefined) {\n // Beside the worker, so the emitted import is a sibling. Wrangler bundles from here, which is\n // what lets the static import reach the app's own module at all (#425).\n writeFileSync(resolve(outputDir, 'theo.plugins.mjs'), pluginsPlan.source)\n }\n\n writeFileSync(\n resolve(outputDir, 'worker.mjs'),\n renderCloudflareWorkerEntry({\n ssrStreaming: config.ssrStreaming,\n ...shell,\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 // #425 — the ONE concern that is not a literal. A closure cannot be baked, so a plugin\n // declared by module specifier is imported by the emitted module instead; a constructed one\n // is refused by name at build time rather than dropped in silence.\n runtimeConfigModule: pluginsPlan?.moduleSpecifier,\n routes: scanned.routes,\n // #367 — a Worker has no filesystem, so its agents are decided here like its routes.\n agents: scanned.agents,\n wsRoutes: scanned.wsRoutes,\n }),\n )\n\n // 3. Emit wrangler.toml (with nodejs_compat enforced)\n writeFileSync(resolve(cwd, 'wrangler.toml'), renderWranglerToml())\n\n // eslint-disable-next-line no-console -- CLI build progress\n console.log('\\n ✓ Cloudflare output → .theokit/cloudflare/ + wrangler.toml')\n // eslint-disable-next-line no-console -- CLI build progress\n console.log(\n `${describeDeployedSecurityHeaders({\n target: 'cloudflare',\n securityHeaders: config.security?.headers,\n // Only the streaming worker renders HTML per request, so only it can put\n // the same nonce on the header and on the script tag it emits.\n mintsNonce: config.ssrStreaming,\n // #412 — either way the worker returns the document now: streamed by\n // `renderStreamingWeb`, or from the ASSETS binding it finally calls.\n documentHeaders: 'handler',\n })}\\n`,\n )\n },\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,104 @@
1
+ #!/usr/bin/env node
2
+ import "tsx/esm";
3
+ import {
4
+ nodeAdapter
5
+ } from "./chunk-KI4DOTN4.js";
6
+ import "./chunk-ZNZISJDZ.js";
7
+
8
+ // src/adapters/config-support.ts
9
+ var CONFIG_CONCERNS = [
10
+ "rateLimit",
11
+ "cors",
12
+ "csrf",
13
+ "disallowed",
14
+ "serialization",
15
+ "plugins",
16
+ "securityHeaders"
17
+ ];
18
+ function appliedByNoTarget(concern) {
19
+ const applied = nodeAdapter.appliesConfig;
20
+ if (applied === void 0 || applied === "runtime-not-emitted-here") return true;
21
+ return !applied.includes(concern);
22
+ }
23
+ var CONFIG_KEY = {
24
+ rateLimit: "rateLimit",
25
+ cors: "security.cors",
26
+ csrf: "security.csrf",
27
+ disallowed: "security.disallowed",
28
+ serialization: "serialization",
29
+ plugins: "plugins",
30
+ securityHeaders: "security.headers"
31
+ };
32
+ function isDeclared(config, concern) {
33
+ const security = config.security;
34
+ switch (concern) {
35
+ case "rateLimit":
36
+ return config.rateLimit !== void 0;
37
+ case "cors":
38
+ return security?.cors !== void 0;
39
+ case "csrf":
40
+ return security?.csrf !== void 0 && security.csrf !== "strict";
41
+ case "disallowed":
42
+ return security?.disallowed !== void 0 && security.disallowed.routes.length > 0;
43
+ case "securityHeaders":
44
+ return security?.headers !== void 0;
45
+ case "serialization":
46
+ return config.serialization !== "json";
47
+ case "plugins":
48
+ return config.plugins !== void 0 && config.plugins.length > 0;
49
+ }
50
+ }
51
+ function findUnappliedConfig(config, adapter) {
52
+ const applied = adapter.appliesConfig ?? [];
53
+ if (applied === "runtime-not-emitted-here") return [];
54
+ return CONFIG_CONCERNS.filter(
55
+ (concern) => isDeclared(config, concern) && !applied.includes(concern)
56
+ );
57
+ }
58
+ function describeUnappliedConfig(target, dropped) {
59
+ if (dropped.length === 0) return "";
60
+ const one = dropped.length === 1;
61
+ const list = dropped.map((concern) => ` - ${CONFIG_KEY[concern]}`).join("\n");
62
+ const elsewhere = dropped.filter((concern) => !appliedByNoTarget(concern));
63
+ const nowhere = dropped.filter(appliedByNoTarget);
64
+ const actions = [];
65
+ if (elsewhere.length > 0 && target !== "node") {
66
+ actions.push(
67
+ ` - ${elsewhere.map((c) => CONFIG_KEY[c]).join(", ")}: build for \`node\` and run \`theokit start\`,`,
68
+ ` which applies ${elsewhere.length === 1 ? "it" : "them"}; or remove ${elsewhere.length === 1 ? "it" : "them"} so the file states what runs.`
69
+ );
70
+ } else if (elsewhere.length > 0) {
71
+ actions.push(
72
+ ` - ${elsewhere.map((c) => CONFIG_KEY[c]).join(", ")}: remove ${elsewhere.length === 1 ? "it" : "them"} so the file states what runs.`
73
+ );
74
+ }
75
+ if (nowhere.length > 0) {
76
+ actions.push(
77
+ ` - ${nowhere.map((c) => CONFIG_KEY[c]).join(", ")}: no production target applies ${nowhere.length === 1 ? "this" : "these"} today`,
78
+ ` (usetheokit/theokit#409) -- terminate it in front of the app, or remove it.`
79
+ );
80
+ }
81
+ return [
82
+ ` ! ${String(dropped.length)} configuration ${one ? "key is" : "keys are"} validated and NOT applied on \`${target}\`:`,
83
+ list,
84
+ ` The handler this target emits never reads ${one ? "it" : "them"}, so the deployed app`,
85
+ ` behaves as if ${one ? "the key were" : "the keys were"} absent.`,
86
+ ` What to do:`,
87
+ ...actions,
88
+ ` Tracked: usetheokit/theokit#410 (deploy targets), usetheokit/theokit#409 (cors).`
89
+ ].join("\n");
90
+ }
91
+ function warnUnappliedConfig(config, adapter, target, log) {
92
+ const dropped = findUnappliedConfig(config, adapter);
93
+ if (dropped.length === 0) return;
94
+ log(`
95
+ ${describeUnappliedConfig(target, dropped)}
96
+ `);
97
+ }
98
+ export {
99
+ CONFIG_CONCERNS,
100
+ describeUnappliedConfig,
101
+ findUnappliedConfig,
102
+ warnUnappliedConfig
103
+ };
104
+ //# sourceMappingURL=config-support-WQHQIJTA.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/adapters/config-support.ts"],"sourcesContent":["/**\n * Which configuration a deploy target's emitted handler actually applies.\n *\n * `theo.config.ts` validates `rateLimit`, `security.cors`, `security.csrf`,\n * `security.disallowed` and `serialization` for every target. Applying them is\n * the handler's job, and the six Web-standards adapters build `executeRoute`'s\n * context from a subset of its fields, so the rest fall back to hard-coded\n * defaults on a deployed app (usetheokit/theokit#410). `security.cors` was read\n * only by the dev server until #409 wired it into `theokit start`; the six Web\n * targets still drop it.\n *\n * This module does not fix that. It makes it **audible at build time**: a\n * config key that is parsed and then dropped is named, with the target that\n * drops it and the next action. Silence was the defect — an operator who\n * declares a rate limit and gets none has no reason to look.\n *\n * It warns rather than refuses, deliberately. Refusing would break every\n * deployment that declares `rateLimit` today, and the real fix — wiring a\n * limiter that needs a per-runtime client address — is not a build away\n * (`docs/program/journeys/j07-rate-limit.md` § Correction measured what it\n * costs). Forcing an operator to delete valid configuration in order to ship\n * would trade a silent gap for a loud one that also loses information.\n */\nimport type { TheoConfig } from '../config/schema.js'\n\nimport { nodeAdapter } from './node.js'\nimport type { ConfigConcern, DeployAdapter } from './types.js'\n\n/**\n * The closed set. A concern belongs here when it is (a) declarable in\n * `theo.config.ts` and (b) applied by a request handler rather than at build\n * time — a build-time key cannot be silently dropped by a runtime.\n */\nexport const CONFIG_CONCERNS = [\n 'rateLimit',\n 'cors',\n 'csrf',\n 'disallowed',\n 'serialization',\n 'plugins',\n 'securityHeaders',\n] as const satisfies readonly ConfigConcern[]\n\n/**\n * Does any production target apply this concern?\n *\n * DERIVED from what the `node` adapter declares, rather than listed. This was a hand-maintained\n * `APPLIED_BY_NO_TARGET` set holding `cors`, kept in step with `nodeAdapter.appliesConfig` by a\n * test — and #409, which taught `theokit start` to apply `cors`, emptied it. An empty hardcoded\n * set is not merely redundant: it makes the branch below provably unreachable, which the linter\n * says out loud (`sonarjs/no-empty-collection`).\n *\n * Deriving keeps the branch honest AND reachable: the moment a concern is added that `node` does\n * not apply, the advice stops claiming a target exists for it, with nothing to remember.\n */\nfunction appliedByNoTarget(concern: ConfigConcern): boolean {\n const applied = nodeAdapter.appliesConfig\n if (applied === undefined || applied === 'runtime-not-emitted-here') return true\n return !applied.includes(concern)\n}\n\n/** Where each concern lives in the config, for a message the operator can grep. */\nconst CONFIG_KEY: Record<ConfigConcern, string> = {\n rateLimit: 'rateLimit',\n cors: 'security.cors',\n csrf: 'security.csrf',\n disallowed: 'security.disallowed',\n serialization: 'serialization',\n plugins: 'plugins',\n securityHeaders: 'security.headers',\n}\n\nfunction isDeclared(config: TheoConfig, concern: ConfigConcern): boolean {\n const security = config.security\n switch (concern) {\n case 'rateLimit':\n return config.rateLimit !== undefined\n case 'cors':\n return security?.cors !== undefined\n case 'csrf':\n // `csrf` carries `.default('strict')` (config/schemas/security.ts:100) and\n // the deployed fallback is also `'strict'` (server/http/execute.ts:144).\n // A config that says `'strict'` therefore gets what it asked for, by\n // coincidence rather than by wiring -- reporting it dropped would be noise\n // over an identical outcome. Only a weaker setting is silently ignored.\n return security?.csrf !== undefined && security.csrf !== 'strict'\n case 'disallowed':\n return security?.disallowed !== undefined && security.disallowed.routes.length > 0\n case 'securityHeaders':\n return security?.headers !== undefined\n case 'serialization':\n // Same shape: `.default('json')` (config/schema.ts:147), and a target with\n // no transformer serializes as JSON. `'json'` is honoured by coincidence;\n // `'superjson'` is the case where the deployed app quietly disagrees with\n // the file.\n return config.serialization !== 'json'\n case 'plugins':\n return config.plugins !== undefined && config.plugins.length > 0\n }\n}\n\n/**\n * The concerns this config declares and this adapter does not apply.\n *\n * An adapter that emits no request handler of its own answers\n * `'runtime-not-emitted-here'` and is never reported against: it is not that\n * the configuration is dropped, it is that this build cannot know. Saying\n * nothing is the honest output, and it is a different fact from saying no.\n */\nexport function findUnappliedConfig(\n config: TheoConfig,\n adapter: Pick<DeployAdapter, 'appliesConfig'>,\n): ConfigConcern[] {\n const applied = adapter.appliesConfig ?? []\n if (applied === 'runtime-not-emitted-here') return []\n return CONFIG_CONCERNS.filter(\n (concern) => isDeclared(config, concern) && !applied.includes(concern),\n )\n}\n\n/**\n * The build-time message. Empty string when nothing was dropped, so the caller\n * neither branches nor prints a header over an empty list.\n */\nexport function describeUnappliedConfig(target: string, dropped: readonly ConfigConcern[]): string {\n if (dropped.length === 0) return ''\n const one = dropped.length === 1\n const list = dropped.map((concern) => ` - ${CONFIG_KEY[concern]}`).join('\\n')\n const elsewhere = dropped.filter((concern) => !appliedByNoTarget(concern))\n const nowhere = dropped.filter(appliedByNoTarget)\n\n // The advice has to change with the target, or it degenerates. Building for\n // `node` with only `security.cors` dropped once produced \"deploy to `node`,\n // which applies all of the above except security.cors\" -- an instruction to\n // do what you are already doing, about the one key it then excepts.\n const actions: string[] = []\n if (elsewhere.length > 0 && target !== 'node') {\n actions.push(\n ` - ${elsewhere.map((c) => CONFIG_KEY[c]).join(', ')}: build for \\`node\\` and run \\`theokit start\\`,`,\n ` which applies ${elsewhere.length === 1 ? 'it' : 'them'}; or remove ${elsewhere.length === 1 ? 'it' : 'them'} so the file states what runs.`,\n )\n } else if (elsewhere.length > 0) {\n actions.push(\n ` - ${elsewhere.map((c) => CONFIG_KEY[c]).join(', ')}: remove ${elsewhere.length === 1 ? 'it' : 'them'} so the file states what runs.`,\n )\n }\n if (nowhere.length > 0) {\n actions.push(\n ` - ${nowhere.map((c) => CONFIG_KEY[c]).join(', ')}: no production target applies ${nowhere.length === 1 ? 'this' : 'these'} today`,\n ` (usetheokit/theokit#409) -- terminate it in front of the app, or remove it.`,\n )\n }\n\n return [\n ` ! ${String(dropped.length)} configuration ${one ? 'key is' : 'keys are'} validated and NOT applied on \\`${target}\\`:`,\n list,\n ` The handler this target emits never reads ${one ? 'it' : 'them'}, so the deployed app`,\n ` behaves as if ${one ? 'the key were' : 'the keys were'} absent.`,\n ` What to do:`,\n ...actions,\n ` Tracked: usetheokit/theokit#410 (deploy targets), usetheokit/theokit#409 (cors).`,\n ].join('\\n')\n}\n\n/**\n * Emit the warning, if there is one. The sink is injected so the behaviour is\n * exercisable without driving a whole build: the alternative was a caller that\n * only a full `theokit build` could reach, which in practice means a caller\n * nothing tests.\n */\nexport function warnUnappliedConfig(\n config: TheoConfig,\n adapter: Pick<DeployAdapter, 'appliesConfig'>,\n target: string,\n log: (message: string) => void,\n): void {\n const dropped = findUnappliedConfig(config, adapter)\n if (dropped.length === 0) return\n log(`\\n${describeUnappliedConfig(target, dropped)}\\n`)\n}\n"],"mappings":"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","names":[]}
@@ -104,4 +104,4 @@ declare function enforceCsrf(req: IncomingMessage, mode: CsrfMode, logger?: Csrf
104
104
  reason?: string;
105
105
  };
106
106
 
107
- export { CSRF_WARN_CODE as C, type DisallowedConfig as D, CSRF_WARN_DOCS_URL as a, type CsrfLogger as b, type CsrfMode as c, type CsrfWarnPayload as d, enforceCsrf as e, validateCsrfRequest as f, matchDisallowed as m, validateCsrf as v };
107
+ export { type CsrfMode as C, type DisallowedConfig as D, CSRF_WARN_CODE as a, CSRF_WARN_DOCS_URL as b, type CsrfLogger as c, type CsrfWarnPayload as d, enforceCsrf as e, validateCsrfRequest as f, matchDisallowed as m, validateCsrf as v };