raffel 0.2.3 → 1.0.0-next.f81d4db

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 (590) hide show
  1. package/dist/adapters/grpc.d.ts.map +1 -1
  2. package/dist/adapters/grpc.js +1 -15
  3. package/dist/adapters/grpc.js.map +1 -1
  4. package/dist/adapters/http.d.ts +6 -0
  5. package/dist/adapters/http.d.ts.map +1 -1
  6. package/dist/adapters/http.js +53 -86
  7. package/dist/adapters/http.js.map +1 -1
  8. package/dist/adapters/index.d.ts +0 -2
  9. package/dist/adapters/index.d.ts.map +1 -1
  10. package/dist/adapters/index.js +0 -2
  11. package/dist/adapters/index.js.map +1 -1
  12. package/dist/adapters/tcp.d.ts +16 -0
  13. package/dist/adapters/tcp.d.ts.map +1 -1
  14. package/dist/adapters/tcp.js +85 -34
  15. package/dist/adapters/tcp.js.map +1 -1
  16. package/dist/adapters/websocket.d.ts.map +1 -1
  17. package/dist/adapters/websocket.js +1 -14
  18. package/dist/adapters/websocket.js.map +1 -1
  19. package/dist/cache/drivers/index.d.ts +0 -1
  20. package/dist/cache/drivers/index.d.ts.map +1 -1
  21. package/dist/cache/drivers/index.js +0 -1
  22. package/dist/cache/drivers/index.js.map +1 -1
  23. package/dist/cache/factory.d.ts +2 -9
  24. package/dist/cache/factory.d.ts.map +1 -1
  25. package/dist/cache/factory.js +1 -19
  26. package/dist/cache/factory.js.map +1 -1
  27. package/dist/cache/index.d.ts +2 -7
  28. package/dist/cache/index.d.ts.map +1 -1
  29. package/dist/cache/index.js +1 -6
  30. package/dist/cache/index.js.map +1 -1
  31. package/dist/cache/types.d.ts +1 -32
  32. package/dist/cache/types.d.ts.map +1 -1
  33. package/dist/core/event-delivery.d.ts.map +1 -1
  34. package/dist/core/event-delivery.js +5 -3
  35. package/dist/core/event-delivery.js.map +1 -1
  36. package/dist/core/index.d.ts +1 -1
  37. package/dist/core/index.d.ts.map +1 -1
  38. package/dist/core/registry.d.ts +3 -3
  39. package/dist/core/registry.d.ts.map +1 -1
  40. package/dist/core/registry.js +30 -8
  41. package/dist/core/registry.js.map +1 -1
  42. package/dist/core/router.d.ts.map +1 -1
  43. package/dist/core/router.js +5 -4
  44. package/dist/core/router.js.map +1 -1
  45. package/dist/docs/generators/code-samples.d.ts +32 -0
  46. package/dist/docs/generators/code-samples.d.ts.map +1 -0
  47. package/dist/docs/generators/code-samples.js +322 -0
  48. package/dist/docs/generators/code-samples.js.map +1 -0
  49. package/dist/docs/generators/errors-types.d.ts +2 -2
  50. package/dist/docs/generators/errors-types.js +2 -2
  51. package/dist/docs/generators/http-generator.d.ts +10 -0
  52. package/dist/docs/generators/http-generator.d.ts.map +1 -1
  53. package/dist/docs/generators/http-generator.js +100 -3
  54. package/dist/docs/generators/http-generator.js.map +1 -1
  55. package/dist/docs/generators/usd-generator.d.ts +31 -1
  56. package/dist/docs/generators/usd-generator.d.ts.map +1 -1
  57. package/dist/docs/generators/usd-generator.js +19 -1
  58. package/dist/docs/generators/usd-generator.js.map +1 -1
  59. package/dist/docs/generators/websocket-generator.d.ts.map +1 -1
  60. package/dist/docs/generators/websocket-generator.js +6 -4
  61. package/dist/docs/generators/websocket-generator.js.map +1 -1
  62. package/dist/docs/ui/html-builder.d.ts.map +1 -1
  63. package/dist/docs/ui/html-builder.js +260 -54
  64. package/dist/docs/ui/html-builder.js.map +1 -1
  65. package/dist/docs/ui/styles.d.ts.map +1 -1
  66. package/dist/docs/ui/styles.js +240 -30
  67. package/dist/docs/ui/styles.js.map +1 -1
  68. package/dist/docs/ui/types.d.ts +15 -1
  69. package/dist/docs/ui/types.d.ts.map +1 -1
  70. package/dist/docs/usd-middleware.d.ts +32 -7
  71. package/dist/docs/usd-middleware.d.ts.map +1 -1
  72. package/dist/docs/usd-middleware.js +5 -1
  73. package/dist/docs/usd-middleware.js.map +1 -1
  74. package/dist/dx/index.d.ts +2 -0
  75. package/dist/dx/index.d.ts.map +1 -1
  76. package/dist/dx/index.js +1 -0
  77. package/dist/dx/index.js.map +1 -1
  78. package/dist/dx/logging/index.d.ts.map +1 -1
  79. package/dist/dx/logging/index.js +5 -3
  80. package/dist/dx/logging/index.js.map +1 -1
  81. package/dist/dx/scenarios.d.ts +26 -0
  82. package/dist/dx/scenarios.d.ts.map +1 -0
  83. package/dist/dx/scenarios.js +109 -0
  84. package/dist/dx/scenarios.js.map +1 -0
  85. package/dist/errors/codes.d.ts +1 -1
  86. package/dist/errors/codes.js +1 -1
  87. package/dist/graphql/adapter.js +1 -1
  88. package/dist/http/index.d.ts +2 -0
  89. package/dist/http/index.d.ts.map +1 -1
  90. package/dist/http/index.js +4 -0
  91. package/dist/http/index.js.map +1 -1
  92. package/dist/http/openapi-ui.d.ts +174 -0
  93. package/dist/http/openapi-ui.d.ts.map +1 -0
  94. package/dist/http/openapi-ui.js +221 -0
  95. package/dist/http/openapi-ui.js.map +1 -0
  96. package/dist/http/serve.d.ts +14 -0
  97. package/dist/http/serve.d.ts.map +1 -1
  98. package/dist/http/serve.js +8 -1
  99. package/dist/http/serve.js.map +1 -1
  100. package/dist/index.d.ts +17 -10
  101. package/dist/index.d.ts.map +1 -1
  102. package/dist/index.js +12 -6
  103. package/dist/index.js.map +1 -1
  104. package/dist/mcp/cli.d.ts +2 -1
  105. package/dist/mcp/cli.d.ts.map +1 -1
  106. package/dist/mcp/cli.js +30 -7
  107. package/dist/mcp/cli.js.map +1 -1
  108. package/dist/mcp/docs/adapters.d.ts.map +1 -1
  109. package/dist/mcp/docs/adapters.js +1 -117
  110. package/dist/mcp/docs/adapters.js.map +1 -1
  111. package/dist/mcp/docs/index.d.ts +0 -1
  112. package/dist/mcp/docs/index.d.ts.map +1 -1
  113. package/dist/mcp/docs/index.js +0 -1
  114. package/dist/mcp/docs/index.js.map +1 -1
  115. package/dist/mcp/docs/interceptors.d.ts.map +1 -1
  116. package/dist/mcp/docs/interceptors.js +272 -1
  117. package/dist/mcp/docs/interceptors.js.map +1 -1
  118. package/dist/mcp/docs/patterns.js +1 -1
  119. package/dist/mcp/prompts/index.d.ts.map +1 -1
  120. package/dist/mcp/prompts/index.js +147 -22
  121. package/dist/mcp/prompts/index.js.map +1 -1
  122. package/dist/mcp/resources/index.d.ts.map +1 -1
  123. package/dist/mcp/resources/index.js +508 -10
  124. package/dist/mcp/resources/index.js.map +1 -1
  125. package/dist/mcp/server.js +1 -1
  126. package/dist/mcp/server.js.map +1 -1
  127. package/dist/mcp/tools/definitions.d.ts +2 -0
  128. package/dist/mcp/tools/definitions.d.ts.map +1 -1
  129. package/dist/mcp/tools/definitions.js +149 -1
  130. package/dist/mcp/tools/definitions.js.map +1 -1
  131. package/dist/mcp/tools/handlers.d.ts.map +1 -1
  132. package/dist/mcp/tools/handlers.js +828 -44
  133. package/dist/mcp/tools/handlers.js.map +1 -1
  134. package/dist/mcp/types.d.ts +1 -1
  135. package/dist/mcp/types.d.ts.map +1 -1
  136. package/dist/metrics/interceptor.d.ts.map +1 -1
  137. package/dist/metrics/interceptor.js +10 -2
  138. package/dist/metrics/interceptor.js.map +1 -1
  139. package/dist/middleware/interceptors/cache.d.ts +1 -1
  140. package/dist/middleware/interceptors/cache.d.ts.map +1 -1
  141. package/dist/middleware/interceptors/cache.js +4 -2
  142. package/dist/middleware/interceptors/cache.js.map +1 -1
  143. package/dist/middleware/interceptors/envelope.d.ts.map +1 -1
  144. package/dist/middleware/interceptors/envelope.js +12 -14
  145. package/dist/middleware/interceptors/envelope.js.map +1 -1
  146. package/dist/middleware/interceptors/logging.d.ts.map +1 -1
  147. package/dist/middleware/interceptors/logging.js +11 -6
  148. package/dist/middleware/interceptors/logging.js.map +1 -1
  149. package/dist/middleware/session/drivers/memory.d.ts +36 -0
  150. package/dist/middleware/session/drivers/memory.d.ts.map +1 -0
  151. package/dist/middleware/session/drivers/memory.js +82 -0
  152. package/dist/middleware/session/drivers/memory.js.map +1 -0
  153. package/dist/middleware/session/drivers/redis.d.ts +58 -0
  154. package/dist/middleware/session/drivers/redis.d.ts.map +1 -0
  155. package/dist/middleware/session/drivers/redis.js +70 -0
  156. package/dist/middleware/session/drivers/redis.js.map +1 -0
  157. package/dist/middleware/session/drivers/s3db.d.ts +65 -0
  158. package/dist/middleware/session/drivers/s3db.d.ts.map +1 -0
  159. package/dist/middleware/session/drivers/s3db.js +98 -0
  160. package/dist/middleware/session/drivers/s3db.js.map +1 -0
  161. package/dist/middleware/session/index.d.ts +47 -0
  162. package/dist/middleware/session/index.d.ts.map +1 -0
  163. package/dist/middleware/session/index.js +46 -0
  164. package/dist/middleware/session/index.js.map +1 -0
  165. package/dist/middleware/session/interceptor.d.ts +42 -0
  166. package/dist/middleware/session/interceptor.d.ts.map +1 -0
  167. package/dist/middleware/session/interceptor.js +264 -0
  168. package/dist/middleware/session/interceptor.js.map +1 -0
  169. package/dist/middleware/session/types.d.ts +116 -0
  170. package/dist/middleware/session/types.d.ts.map +1 -0
  171. package/dist/middleware/session/types.js +9 -0
  172. package/dist/middleware/session/types.js.map +1 -0
  173. package/dist/proxy/connect-tunnel.d.ts +50 -0
  174. package/dist/proxy/connect-tunnel.d.ts.map +1 -0
  175. package/dist/proxy/connect-tunnel.js +163 -0
  176. package/dist/proxy/connect-tunnel.js.map +1 -0
  177. package/dist/proxy/http-forward.d.ts +48 -0
  178. package/dist/proxy/http-forward.d.ts.map +1 -0
  179. package/dist/proxy/http-forward.js +160 -0
  180. package/dist/proxy/http-forward.js.map +1 -0
  181. package/dist/proxy/index.d.ts +19 -0
  182. package/dist/proxy/index.d.ts.map +1 -0
  183. package/dist/proxy/index.js +14 -0
  184. package/dist/proxy/index.js.map +1 -0
  185. package/dist/proxy/socks5.d.ts +22 -0
  186. package/dist/proxy/socks5.d.ts.map +1 -0
  187. package/dist/proxy/socks5.js +307 -0
  188. package/dist/proxy/socks5.js.map +1 -0
  189. package/dist/proxy/transparent.d.ts +40 -0
  190. package/dist/proxy/transparent.d.ts.map +1 -0
  191. package/dist/proxy/transparent.js +144 -0
  192. package/dist/proxy/transparent.js.map +1 -0
  193. package/dist/proxy/types.d.ts +32 -0
  194. package/dist/proxy/types.d.ts.map +1 -0
  195. package/dist/proxy/types.js +5 -0
  196. package/dist/proxy/types.js.map +1 -0
  197. package/dist/proxy/utils/auth.d.ts +31 -0
  198. package/dist/proxy/utils/auth.d.ts.map +1 -0
  199. package/dist/proxy/utils/auth.js +69 -0
  200. package/dist/proxy/utils/auth.js.map +1 -0
  201. package/dist/proxy/utils/hop-headers.d.ts +13 -0
  202. package/dist/proxy/utils/hop-headers.d.ts.map +1 -0
  203. package/dist/proxy/utils/hop-headers.js +38 -0
  204. package/dist/proxy/utils/hop-headers.js.map +1 -0
  205. package/dist/proxy/utils/pipe.d.ts +22 -0
  206. package/dist/proxy/utils/pipe.d.ts.map +1 -0
  207. package/dist/proxy/utils/pipe.js +60 -0
  208. package/dist/proxy/utils/pipe.js.map +1 -0
  209. package/dist/rate-limit/factory.d.ts.map +1 -1
  210. package/dist/rate-limit/factory.js +30 -6
  211. package/dist/rate-limit/factory.js.map +1 -1
  212. package/dist/server/builder/config-preview.d.ts +34 -0
  213. package/dist/server/builder/config-preview.d.ts.map +1 -0
  214. package/dist/server/builder/config-preview.js +95 -0
  215. package/dist/server/builder/config-preview.js.map +1 -0
  216. package/dist/server/builder/lifecycle-utils.d.ts +11 -0
  217. package/dist/server/builder/lifecycle-utils.d.ts.map +1 -0
  218. package/dist/server/builder/lifecycle-utils.js +32 -0
  219. package/dist/server/builder/lifecycle-utils.js.map +1 -0
  220. package/dist/server/builder/lifecycle.d.ts +86 -0
  221. package/dist/server/builder/lifecycle.d.ts.map +1 -0
  222. package/dist/server/builder/lifecycle.js +738 -0
  223. package/dist/server/builder/lifecycle.js.map +1 -0
  224. package/dist/server/builder/single-port-utils.d.ts +27 -0
  225. package/dist/server/builder/single-port-utils.d.ts.map +1 -0
  226. package/dist/server/builder/single-port-utils.js +170 -0
  227. package/dist/server/builder/single-port-utils.js.map +1 -0
  228. package/dist/server/builder.d.ts.map +1 -1
  229. package/dist/server/builder.js +446 -601
  230. package/dist/server/builder.js.map +1 -1
  231. package/dist/server/discovery-bootstrap.d.ts +21 -0
  232. package/dist/server/discovery-bootstrap.d.ts.map +1 -0
  233. package/dist/server/discovery-bootstrap.js +39 -0
  234. package/dist/server/discovery-bootstrap.js.map +1 -0
  235. package/dist/server/errors.d.ts.map +1 -1
  236. package/dist/server/errors.js +1 -33
  237. package/dist/server/errors.js.map +1 -1
  238. package/dist/server/front-door.d.ts +34 -0
  239. package/dist/server/front-door.d.ts.map +1 -0
  240. package/dist/server/front-door.js +238 -0
  241. package/dist/server/front-door.js.map +1 -0
  242. package/dist/server/fs-routes/types.d.ts +6 -0
  243. package/dist/server/fs-routes/types.d.ts.map +1 -1
  244. package/dist/server/handler-builders.d.ts +22 -4
  245. package/dist/server/handler-builders.d.ts.map +1 -1
  246. package/dist/server/handler-builders.js +37 -14
  247. package/dist/server/handler-builders.js.map +1 -1
  248. package/dist/server/index.d.ts +4 -1
  249. package/dist/server/index.d.ts.map +1 -1
  250. package/dist/server/index.js +2 -0
  251. package/dist/server/index.js.map +1 -1
  252. package/dist/server/interceptor-utils.d.ts +8 -0
  253. package/dist/server/interceptor-utils.d.ts.map +1 -0
  254. package/dist/server/interceptor-utils.js +23 -0
  255. package/dist/server/interceptor-utils.js.map +1 -0
  256. package/dist/server/port-binding.d.ts +44 -0
  257. package/dist/server/port-binding.d.ts.map +1 -0
  258. package/dist/server/port-binding.js +94 -0
  259. package/dist/server/port-binding.js.map +1 -0
  260. package/dist/server/protocol-aliases.d.ts +56 -0
  261. package/dist/server/protocol-aliases.d.ts.map +1 -0
  262. package/dist/server/protocol-aliases.js +47 -0
  263. package/dist/server/protocol-aliases.js.map +1 -0
  264. package/dist/server/protocol-config.d.ts +17 -1
  265. package/dist/server/protocol-config.d.ts.map +1 -1
  266. package/dist/server/protocol-config.js +116 -9
  267. package/dist/server/protocol-config.js.map +1 -1
  268. package/dist/server/resource-builder.js +3 -3
  269. package/dist/server/resource-builder.js.map +1 -1
  270. package/dist/server/rest-middleware.d.ts.map +1 -1
  271. package/dist/server/rest-middleware.js +1 -15
  272. package/dist/server/rest-middleware.js.map +1 -1
  273. package/dist/server/router-module.d.ts.map +1 -1
  274. package/dist/server/router-module.js +22 -99
  275. package/dist/server/router-module.js.map +1 -1
  276. package/dist/server/shared-context.d.ts.map +1 -1
  277. package/dist/server/shared-context.js +3 -1
  278. package/dist/server/shared-context.js.map +1 -1
  279. package/dist/server/single-port/dispatcher.d.ts +10 -0
  280. package/dist/server/single-port/dispatcher.d.ts.map +1 -0
  281. package/dist/server/single-port/dispatcher.js +188 -0
  282. package/dist/server/single-port/dispatcher.js.map +1 -0
  283. package/dist/server/single-port/index.d.ts +4 -0
  284. package/dist/server/single-port/index.d.ts.map +1 -0
  285. package/dist/server/single-port/index.js +3 -0
  286. package/dist/server/single-port/index.js.map +1 -0
  287. package/dist/server/single-port/registry.d.ts +19 -0
  288. package/dist/server/single-port/registry.d.ts.map +1 -0
  289. package/dist/server/single-port/registry.js +24 -0
  290. package/dist/server/single-port/registry.js.map +1 -0
  291. package/dist/server/single-port/types.d.ts +46 -0
  292. package/dist/server/single-port/types.d.ts.map +1 -0
  293. package/dist/server/single-port/types.js +2 -0
  294. package/dist/server/single-port/types.js.map +1 -0
  295. package/dist/server/telemetry-bootstrap.d.ts +38 -0
  296. package/dist/server/telemetry-bootstrap.d.ts.map +1 -0
  297. package/dist/server/telemetry-bootstrap.js +115 -0
  298. package/dist/server/telemetry-bootstrap.js.map +1 -0
  299. package/dist/server/types.d.ts +422 -21
  300. package/dist/server/types.d.ts.map +1 -1
  301. package/dist/testing/echo-protection.d.ts +30 -0
  302. package/dist/testing/echo-protection.d.ts.map +1 -0
  303. package/dist/testing/echo-protection.js +158 -0
  304. package/dist/testing/echo-protection.js.map +1 -0
  305. package/dist/testing/index.d.ts +344 -0
  306. package/dist/testing/index.d.ts.map +1 -0
  307. package/dist/testing/index.js +1072 -0
  308. package/dist/testing/index.js.map +1 -0
  309. package/dist/testing/mock-dns-server.d.ts +31 -0
  310. package/dist/testing/mock-dns-server.d.ts.map +1 -0
  311. package/dist/testing/mock-dns-server.js +247 -0
  312. package/dist/testing/mock-dns-server.js.map +1 -0
  313. package/dist/testing/mock-hls-server.d.ts +85 -0
  314. package/dist/testing/mock-hls-server.d.ts.map +1 -0
  315. package/dist/testing/mock-hls-server.js +252 -0
  316. package/dist/testing/mock-hls-server.js.map +1 -0
  317. package/dist/testing/mock-proxy-server.d.ts +78 -0
  318. package/dist/testing/mock-proxy-server.d.ts.map +1 -0
  319. package/dist/testing/mock-proxy-server.js +277 -0
  320. package/dist/testing/mock-proxy-server.js.map +1 -0
  321. package/dist/testing/mock-sse-server.d.ts +56 -0
  322. package/dist/testing/mock-sse-server.d.ts.map +1 -0
  323. package/dist/testing/mock-sse-server.js +206 -0
  324. package/dist/testing/mock-sse-server.js.map +1 -0
  325. package/dist/testing/proxy-certs.d.ts +9 -0
  326. package/dist/testing/proxy-certs.d.ts.map +1 -0
  327. package/dist/testing/proxy-certs.js +2 -0
  328. package/dist/testing/proxy-certs.js.map +1 -0
  329. package/dist/testing/service-suite.d.ts +47 -0
  330. package/dist/testing/service-suite.d.ts.map +1 -0
  331. package/dist/testing/service-suite.js +82 -0
  332. package/dist/testing/service-suite.js.map +1 -0
  333. package/dist/testing/service-types.d.ts +32 -0
  334. package/dist/testing/service-types.d.ts.map +1 -0
  335. package/dist/testing/service-types.js +2 -0
  336. package/dist/testing/service-types.js.map +1 -0
  337. package/dist/ui/core/event-delivery.d.ts.map +1 -1
  338. package/dist/ui/core/index.d.ts +1 -1
  339. package/dist/ui/core/index.d.ts.map +1 -1
  340. package/dist/ui/core/registry.d.ts +3 -3
  341. package/dist/ui/core/registry.d.ts.map +1 -1
  342. package/dist/ui/core/router.d.ts.map +1 -1
  343. package/dist/ui/docs/generators/code-samples.d.ts +32 -0
  344. package/dist/ui/docs/generators/code-samples.d.ts.map +1 -0
  345. package/dist/ui/docs/generators/errors-types.d.ts +2 -2
  346. package/dist/ui/docs/generators/http-generator.d.ts +10 -0
  347. package/dist/ui/docs/generators/http-generator.d.ts.map +1 -1
  348. package/dist/ui/docs/generators/usd-generator.d.ts +31 -1
  349. package/dist/ui/docs/generators/usd-generator.d.ts.map +1 -1
  350. package/dist/ui/docs/generators/websocket-generator.d.ts.map +1 -1
  351. package/dist/ui/docs/ui/html-builder.d.ts.map +1 -1
  352. package/dist/ui/docs/ui/styles.d.ts.map +1 -1
  353. package/dist/ui/docs/ui/types.d.ts +15 -1
  354. package/dist/ui/docs/ui/types.d.ts.map +1 -1
  355. package/dist/ui/docs/usd-middleware.d.ts +32 -7
  356. package/dist/ui/docs/usd-middleware.d.ts.map +1 -1
  357. package/dist/ui/errors/codes.d.ts +1 -1
  358. package/dist/ui/server/fs-routes/types.d.ts +6 -0
  359. package/dist/ui/server/fs-routes/types.d.ts.map +1 -1
  360. package/dist/ui/usd/index.d.ts +1 -1
  361. package/dist/ui/usd/index.d.ts.map +1 -1
  362. package/dist/ui/usd/spec/types.d.ts +91 -0
  363. package/dist/ui/usd/spec/types.d.ts.map +1 -1
  364. package/dist/usd/index.d.ts +1 -1
  365. package/dist/usd/index.d.ts.map +1 -1
  366. package/dist/usd/index.js.map +1 -1
  367. package/dist/usd/spec/types.d.ts +91 -0
  368. package/dist/usd/spec/types.d.ts.map +1 -1
  369. package/dist/usd/spec/types.js.map +1 -1
  370. package/dist/utils/certs.d.ts +30 -0
  371. package/dist/utils/certs.d.ts.map +1 -0
  372. package/dist/utils/certs.js +230 -0
  373. package/dist/utils/certs.js.map +1 -0
  374. package/dist/utils/context-utils.d.ts +11 -0
  375. package/dist/utils/context-utils.d.ts.map +1 -0
  376. package/dist/utils/context-utils.js +24 -0
  377. package/dist/utils/context-utils.js.map +1 -0
  378. package/package.json +11 -2
  379. package/dist/adapters/grpc.int.test.d.ts +0 -5
  380. package/dist/adapters/grpc.int.test.d.ts.map +0 -1
  381. package/dist/adapters/grpc.int.test.js +0 -168
  382. package/dist/adapters/grpc.int.test.js.map +0 -1
  383. package/dist/adapters/http.int.test.d.ts +0 -5
  384. package/dist/adapters/http.int.test.d.ts.map +0 -1
  385. package/dist/adapters/http.int.test.js +0 -396
  386. package/dist/adapters/http.int.test.js.map +0 -1
  387. package/dist/adapters/jsonrpc.int.test.d.ts +0 -5
  388. package/dist/adapters/jsonrpc.int.test.d.ts.map +0 -1
  389. package/dist/adapters/jsonrpc.int.test.js +0 -640
  390. package/dist/adapters/jsonrpc.int.test.js.map +0 -1
  391. package/dist/adapters/s3db/adapter.d.ts +0 -105
  392. package/dist/adapters/s3db/adapter.d.ts.map +0 -1
  393. package/dist/adapters/s3db/adapter.js +0 -536
  394. package/dist/adapters/s3db/adapter.js.map +0 -1
  395. package/dist/adapters/s3db/index.d.ts +0 -20
  396. package/dist/adapters/s3db/index.d.ts.map +0 -1
  397. package/dist/adapters/s3db/index.js +0 -25
  398. package/dist/adapters/s3db/index.js.map +0 -1
  399. package/dist/adapters/s3db/s3db.int.test.d.ts +0 -5
  400. package/dist/adapters/s3db/s3db.int.test.d.ts.map +0 -1
  401. package/dist/adapters/s3db/s3db.int.test.js +0 -472
  402. package/dist/adapters/s3db/s3db.int.test.js.map +0 -1
  403. package/dist/adapters/s3db/types.d.ts +0 -277
  404. package/dist/adapters/s3db/types.d.ts.map +0 -1
  405. package/dist/adapters/s3db/types.js +0 -7
  406. package/dist/adapters/s3db/types.js.map +0 -1
  407. package/dist/adapters/s3db/utils/etag.d.ts +0 -65
  408. package/dist/adapters/s3db/utils/etag.d.ts.map +0 -1
  409. package/dist/adapters/s3db/utils/etag.js +0 -99
  410. package/dist/adapters/s3db/utils/etag.js.map +0 -1
  411. package/dist/adapters/s3db/utils/guards.d.ts +0 -121
  412. package/dist/adapters/s3db/utils/guards.d.ts.map +0 -1
  413. package/dist/adapters/s3db/utils/guards.js +0 -169
  414. package/dist/adapters/s3db/utils/guards.js.map +0 -1
  415. package/dist/adapters/s3db/utils/index.d.ts +0 -9
  416. package/dist/adapters/s3db/utils/index.d.ts.map +0 -1
  417. package/dist/adapters/s3db/utils/index.js +0 -10
  418. package/dist/adapters/s3db/utils/index.js.map +0 -1
  419. package/dist/adapters/s3db/utils/populate.d.ts +0 -89
  420. package/dist/adapters/s3db/utils/populate.d.ts.map +0 -1
  421. package/dist/adapters/s3db/utils/populate.js +0 -165
  422. package/dist/adapters/s3db/utils/populate.js.map +0 -1
  423. package/dist/adapters/tcp.int.test.d.ts +0 -5
  424. package/dist/adapters/tcp.int.test.d.ts.map +0 -1
  425. package/dist/adapters/tcp.int.test.js +0 -379
  426. package/dist/adapters/tcp.int.test.js.map +0 -1
  427. package/dist/adapters/udp.int.test.d.ts +0 -5
  428. package/dist/adapters/udp.int.test.d.ts.map +0 -1
  429. package/dist/adapters/udp.int.test.js +0 -397
  430. package/dist/adapters/udp.int.test.js.map +0 -1
  431. package/dist/adapters/websocket.int.test.d.ts +0 -5
  432. package/dist/adapters/websocket.int.test.d.ts.map +0 -1
  433. package/dist/adapters/websocket.int.test.js +0 -383
  434. package/dist/adapters/websocket.int.test.js.map +0 -1
  435. package/dist/cache/drivers/memory.int.test.d.ts +0 -5
  436. package/dist/cache/drivers/memory.int.test.d.ts.map +0 -1
  437. package/dist/cache/drivers/memory.int.test.js +0 -241
  438. package/dist/cache/drivers/memory.int.test.js.map +0 -1
  439. package/dist/cache/drivers/s3db.d.ts +0 -78
  440. package/dist/cache/drivers/s3db.d.ts.map +0 -1
  441. package/dist/cache/drivers/s3db.js +0 -216
  442. package/dist/cache/drivers/s3db.js.map +0 -1
  443. package/dist/channels/channel-manager.int.test.d.ts +0 -5
  444. package/dist/channels/channel-manager.int.test.d.ts.map +0 -1
  445. package/dist/channels/channel-manager.int.test.js +0 -378
  446. package/dist/channels/channel-manager.int.test.js.map +0 -1
  447. package/dist/core/ctx-call.int.test.d.ts +0 -7
  448. package/dist/core/ctx-call.int.test.d.ts.map +0 -1
  449. package/dist/core/ctx-call.int.test.js +0 -263
  450. package/dist/core/ctx-call.int.test.js.map +0 -1
  451. package/dist/core/registry.unit.test.d.ts +0 -2
  452. package/dist/core/registry.unit.test.d.ts.map +0 -1
  453. package/dist/core/registry.unit.test.js +0 -133
  454. package/dist/core/registry.unit.test.js.map +0 -1
  455. package/dist/core/router.int.test.d.ts +0 -2
  456. package/dist/core/router.int.test.d.ts.map +0 -1
  457. package/dist/core/router.int.test.js +0 -368
  458. package/dist/core/router.int.test.js.map +0 -1
  459. package/dist/docs/generators/generators.int.test.d.ts +0 -2
  460. package/dist/docs/generators/generators.int.test.d.ts.map +0 -1
  461. package/dist/docs/generators/generators.int.test.js +0 -105
  462. package/dist/docs/generators/generators.int.test.js.map +0 -1
  463. package/dist/docs/openapi/generator.int.test.d.ts +0 -5
  464. package/dist/docs/openapi/generator.int.test.d.ts.map +0 -1
  465. package/dist/docs/openapi/generator.int.test.js +0 -260
  466. package/dist/docs/openapi/generator.int.test.js.map +0 -1
  467. package/dist/dx/health/health.int.test.d.ts +0 -5
  468. package/dist/dx/health/health.int.test.d.ts.map +0 -1
  469. package/dist/dx/health/health.int.test.js +0 -249
  470. package/dist/dx/health/health.int.test.js.map +0 -1
  471. package/dist/dx/logging/http-logging.int.test.d.ts +0 -5
  472. package/dist/dx/logging/http-logging.int.test.d.ts.map +0 -1
  473. package/dist/dx/logging/http-logging.int.test.js +0 -319
  474. package/dist/dx/logging/http-logging.int.test.js.map +0 -1
  475. package/dist/errors/factories.unit.test.d.ts +0 -7
  476. package/dist/errors/factories.unit.test.d.ts.map +0 -1
  477. package/dist/errors/factories.unit.test.js +0 -358
  478. package/dist/errors/factories.unit.test.js.map +0 -1
  479. package/dist/graphql/graphql.int.test.d.ts +0 -10
  480. package/dist/graphql/graphql.int.test.d.ts.map +0 -1
  481. package/dist/graphql/graphql.int.test.js +0 -698
  482. package/dist/graphql/graphql.int.test.js.map +0 -1
  483. package/dist/graphql/schema-generator.int.test.d.ts +0 -5
  484. package/dist/graphql/schema-generator.int.test.d.ts.map +0 -1
  485. package/dist/graphql/schema-generator.int.test.js +0 -51
  486. package/dist/graphql/schema-generator.int.test.js.map +0 -1
  487. package/dist/http/http.int.test.d.ts +0 -7
  488. package/dist/http/http.int.test.d.ts.map +0 -1
  489. package/dist/http/http.int.test.js +0 -605
  490. package/dist/http/http.int.test.js.map +0 -1
  491. package/dist/http/session-redis.int.test.d.ts +0 -8
  492. package/dist/http/session-redis.int.test.d.ts.map +0 -1
  493. package/dist/http/session-redis.int.test.js +0 -492
  494. package/dist/http/session-redis.int.test.js.map +0 -1
  495. package/dist/metrics/metrics.int.test.d.ts +0 -5
  496. package/dist/metrics/metrics.int.test.d.ts.map +0 -1
  497. package/dist/metrics/metrics.int.test.js +0 -288
  498. package/dist/metrics/metrics.int.test.js.map +0 -1
  499. package/dist/middleware/auth/oauth2.int.test.d.ts +0 -2
  500. package/dist/middleware/auth/oauth2.int.test.d.ts.map +0 -1
  501. package/dist/middleware/auth/oauth2.int.test.js +0 -714
  502. package/dist/middleware/auth/oauth2.int.test.js.map +0 -1
  503. package/dist/middleware/auth.int.test.d.ts +0 -5
  504. package/dist/middleware/auth.int.test.d.ts.map +0 -1
  505. package/dist/middleware/auth.int.test.js +0 -366
  506. package/dist/middleware/auth.int.test.js.map +0 -1
  507. package/dist/middleware/compose.int.test.d.ts +0 -7
  508. package/dist/middleware/compose.int.test.d.ts.map +0 -1
  509. package/dist/middleware/compose.int.test.js +0 -238
  510. package/dist/middleware/compose.int.test.js.map +0 -1
  511. package/dist/middleware/interceptors/bulkhead.int.test.d.ts +0 -5
  512. package/dist/middleware/interceptors/bulkhead.int.test.d.ts.map +0 -1
  513. package/dist/middleware/interceptors/bulkhead.int.test.js +0 -263
  514. package/dist/middleware/interceptors/bulkhead.int.test.js.map +0 -1
  515. package/dist/middleware/interceptors/cache.int.test.d.ts +0 -5
  516. package/dist/middleware/interceptors/cache.int.test.d.ts.map +0 -1
  517. package/dist/middleware/interceptors/cache.int.test.js +0 -470
  518. package/dist/middleware/interceptors/cache.int.test.js.map +0 -1
  519. package/dist/middleware/interceptors/circuit-breaker.int.test.d.ts +0 -5
  520. package/dist/middleware/interceptors/circuit-breaker.int.test.d.ts.map +0 -1
  521. package/dist/middleware/interceptors/circuit-breaker.int.test.js +0 -253
  522. package/dist/middleware/interceptors/circuit-breaker.int.test.js.map +0 -1
  523. package/dist/middleware/interceptors/envelope.int.test.d.ts +0 -5
  524. package/dist/middleware/interceptors/envelope.int.test.d.ts.map +0 -1
  525. package/dist/middleware/interceptors/envelope.int.test.js +0 -409
  526. package/dist/middleware/interceptors/envelope.int.test.js.map +0 -1
  527. package/dist/middleware/interceptors/fallback.int.test.d.ts +0 -5
  528. package/dist/middleware/interceptors/fallback.int.test.d.ts.map +0 -1
  529. package/dist/middleware/interceptors/fallback.int.test.js +0 -211
  530. package/dist/middleware/interceptors/fallback.int.test.js.map +0 -1
  531. package/dist/middleware/interceptors/logging.int.test.d.ts +0 -5
  532. package/dist/middleware/interceptors/logging.int.test.d.ts.map +0 -1
  533. package/dist/middleware/interceptors/logging.int.test.js +0 -144
  534. package/dist/middleware/interceptors/logging.int.test.js.map +0 -1
  535. package/dist/middleware/interceptors/rate-limit.int.test.d.ts +0 -5
  536. package/dist/middleware/interceptors/rate-limit.int.test.d.ts.map +0 -1
  537. package/dist/middleware/interceptors/rate-limit.int.test.js +0 -221
  538. package/dist/middleware/interceptors/rate-limit.int.test.js.map +0 -1
  539. package/dist/middleware/interceptors/request-id.int.test.d.ts +0 -5
  540. package/dist/middleware/interceptors/request-id.int.test.d.ts.map +0 -1
  541. package/dist/middleware/interceptors/request-id.int.test.js +0 -136
  542. package/dist/middleware/interceptors/request-id.int.test.js.map +0 -1
  543. package/dist/middleware/interceptors/retry.int.test.d.ts +0 -5
  544. package/dist/middleware/interceptors/retry.int.test.d.ts.map +0 -1
  545. package/dist/middleware/interceptors/retry.int.test.js +0 -534
  546. package/dist/middleware/interceptors/retry.int.test.js.map +0 -1
  547. package/dist/middleware/interceptors/timeout.int.test.d.ts +0 -5
  548. package/dist/middleware/interceptors/timeout.int.test.d.ts.map +0 -1
  549. package/dist/middleware/interceptors/timeout.int.test.js +0 -228
  550. package/dist/middleware/interceptors/timeout.int.test.js.map +0 -1
  551. package/dist/rate-limit/drivers/drivers.int.test.d.ts +0 -7
  552. package/dist/rate-limit/drivers/drivers.int.test.d.ts.map +0 -1
  553. package/dist/rate-limit/drivers/drivers.int.test.js +0 -466
  554. package/dist/rate-limit/drivers/drivers.int.test.js.map +0 -1
  555. package/dist/server/builder.int.test.d.ts +0 -7
  556. package/dist/server/builder.int.test.d.ts.map +0 -1
  557. package/dist/server/builder.int.test.js +0 -455
  558. package/dist/server/builder.int.test.js.map +0 -1
  559. package/dist/server/fs-routes/loader.int.test.d.ts +0 -5
  560. package/dist/server/fs-routes/loader.int.test.d.ts.map +0 -1
  561. package/dist/server/fs-routes/loader.int.test.js +0 -48
  562. package/dist/server/fs-routes/loader.int.test.js.map +0 -1
  563. package/dist/server/hooks.int.test.d.ts +0 -7
  564. package/dist/server/hooks.int.test.d.ts.map +0 -1
  565. package/dist/server/hooks.int.test.js +0 -564
  566. package/dist/server/hooks.int.test.js.map +0 -1
  567. package/dist/server/route-discovery.int.test.d.ts +0 -5
  568. package/dist/server/route-discovery.int.test.d.ts.map +0 -1
  569. package/dist/server/route-discovery.int.test.js +0 -49
  570. package/dist/server/route-discovery.int.test.js.map +0 -1
  571. package/dist/stream/raffel-stream.int.test.d.ts +0 -2
  572. package/dist/stream/raffel-stream.int.test.d.ts.map +0 -1
  573. package/dist/stream/raffel-stream.int.test.js +0 -265
  574. package/dist/stream/raffel-stream.int.test.js.map +0 -1
  575. package/dist/tracing/tracing.int.test.d.ts +0 -5
  576. package/dist/tracing/tracing.int.test.d.ts.map +0 -1
  577. package/dist/tracing/tracing.int.test.js +0 -412
  578. package/dist/tracing/tracing.int.test.js.map +0 -1
  579. package/dist/usd/usd.int.test.d.ts +0 -10
  580. package/dist/usd/usd.int.test.d.ts.map +0 -1
  581. package/dist/usd/usd.int.test.js +0 -719
  582. package/dist/usd/usd.int.test.js.map +0 -1
  583. package/dist/validation/multi-validator.int.test.d.ts +0 -7
  584. package/dist/validation/multi-validator.int.test.d.ts.map +0 -1
  585. package/dist/validation/multi-validator.int.test.js +0 -808
  586. package/dist/validation/multi-validator.int.test.js.map +0 -1
  587. package/dist/validation/schema.int.test.d.ts +0 -5
  588. package/dist/validation/schema.int.test.d.ts.map +0 -1
  589. package/dist/validation/schema.int.test.js +0 -340
  590. package/dist/validation/schema.int.test.js.map +0 -1
@@ -127,6 +127,14 @@ function formatError(e) {
127
127
  }
128
128
  return md;
129
129
  }
130
+ function toTitleCase(input) {
131
+ return input
132
+ .replace(/[-_]/g, ' ')
133
+ .split(' ')
134
+ .filter(Boolean)
135
+ .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
136
+ .join(' ');
137
+ }
130
138
  // === Tool Handlers ===
131
139
  export const handlers = {
132
140
  // === Documentation Tools ===
@@ -268,9 +276,22 @@ export const handlers = {
268
276
  serverChain += ` .use(createAuthMiddleware({\n`;
269
277
  serverChain += ` strategy: createBearerStrategy({\n`;
270
278
  serverChain += ` validate: async (token) => {\n`;
271
- serverChain += ` // TODO: Implement token validation\n`;
272
- serverChain += ` const user = await verifyToken(token)\n`;
273
- serverChain += ` return user ? { authenticated: true, principal: user } : { authenticated: false }\n`;
279
+ serverChain += ` const tokenValue = String(token || '').trim()\n`;
280
+ serverChain += ` if (!tokenValue) return { authenticated: false }\n`;
281
+ serverChain += `\n`;
282
+ serverChain += ` const allowedTokens = new Set(\n`;
283
+ serverChain += ` (process.env.RAFFEL_BEARER_TOKENS || 'dev-token')\n`;
284
+ serverChain += ` .split(',')\n`;
285
+ serverChain += ` .map((t) => t.trim())\n`;
286
+ serverChain += ` .filter(Boolean)\n`;
287
+ serverChain += ` )\n`;
288
+ serverChain += `\n`;
289
+ serverChain += ` if (!allowedTokens.has(tokenValue)) return { authenticated: false }\n`;
290
+ serverChain += `\n`;
291
+ serverChain += ` return {\n`;
292
+ serverChain += ` authenticated: true,\n`;
293
+ serverChain += ` principal: { id: tokenValue, roles: ['user'] },\n`;
294
+ serverChain += ` }\n`;
274
295
  serverChain += ` }\n`;
275
296
  serverChain += ` })\n`;
276
297
  serverChain += ` }))\n\n`;
@@ -443,10 +464,21 @@ export const handlers = {
443
464
  code += ` throw new RaffelError('UNAUTHENTICATED', 'Login required')\n`;
444
465
  code += ` }\n\n`;
445
466
  }
446
- code += ` // TODO: Implement handler logic\n`;
467
+ code += ` // Replace with your business logic\n`;
447
468
  code += ` return {\n`;
448
469
  for (const field of outputFields) {
449
- code += ` ${field.name}: undefined, // TODO\n`;
470
+ const defaultValue = field.type === 'number'
471
+ ? '0'
472
+ : field.type === 'boolean'
473
+ ? 'false'
474
+ : field.type === 'array'
475
+ ? '[]'
476
+ : field.type === 'object'
477
+ ? '{}'
478
+ : field.type === 'date'
479
+ ? `new Date().toISOString()`
480
+ : `''`;
481
+ code += ` ${field.name}: ${defaultValue},\n`;
450
482
  }
451
483
  if (outputFields.length === 0) {
452
484
  code += ` success: true\n`;
@@ -473,9 +505,15 @@ export const handlers = {
473
505
  code += ` // ${description}\n`;
474
506
  code += ` .handler(async function* (input, ctx) {\n`;
475
507
  code += ` // Server streams data to client\n`;
508
+ code += ` let index = 0\n`;
476
509
  code += ` while (!ctx.signal.aborted) {\n`;
477
- code += ` // TODO: Get data to stream\n`;
478
- code += ` const data: ${dataType} = await getData()\n`;
510
+ code += ` const dataPayload = {\n`;
511
+ code += ` index,\n`;
512
+ code += ` timestamp: new Date().toISOString(),\n`;
513
+ code += ` value: Math.floor(Math.random() * 1000)\n`;
514
+ code += ` } as unknown as ${dataType}\n`;
515
+ code += ` index += 1\n`;
516
+ code += ` const data: ${dataType} = dataPayload\n`;
479
517
  code += ` yield data\n`;
480
518
  code += `\n`;
481
519
  code += ` // Optional: Wait between chunks\n`;
@@ -492,8 +530,13 @@ export const handlers = {
492
530
  code += ` const results = []\n`;
493
531
  code += `\n`;
494
532
  code += ` for await (const chunk of inputStream) {\n`;
495
- code += ` // TODO: Process each chunk from client\n`;
496
- code += ` results.push(await processChunk(chunk))\n`;
533
+ code += ` const normalized =\n`;
534
+ code += ` typeof chunk === 'string' ? chunk : JSON.stringify(chunk)\n`;
535
+ code += ` const entry = {\n`;
536
+ code += ` payload: normalized,\n`;
537
+ code += ` receivedAt: new Date().toISOString()\n`;
538
+ code += ` }\n`;
539
+ code += ` results.push(entry)\n`;
497
540
  code += ` }\n`;
498
541
  code += `\n`;
499
542
  code += ` // Return final result\n`;
@@ -511,8 +554,12 @@ export const handlers = {
511
554
  code += ` // Process incoming stream in background\n`;
512
555
  code += ` ;(async () => {\n`;
513
556
  code += ` for await (const chunk of inputStream) {\n`;
514
- code += ` // TODO: Process and respond\n`;
515
- code += ` const response = await process(chunk)\n`;
557
+ code += ` const normalized =\n`;
558
+ code += ` typeof chunk === 'string' ? chunk.toUpperCase() : JSON.stringify(chunk)\n`;
559
+ code += ` const response = {\n`;
560
+ code += ` payload: normalized,\n`;
561
+ code += ` receivedAt: new Date().toISOString()\n`;
562
+ code += ` }\n`;
516
563
  code += ` output.write(response)\n`;
517
564
  code += ` }\n`;
518
565
  code += ` output.end()\n`;
@@ -555,8 +602,13 @@ export const handlers = {
555
602
  if (delivery === 'at-least-once') {
556
603
  code += ` .handler(async (payload, ctx, ack) => {\n`;
557
604
  code += ` try {\n`;
558
- code += ` // TODO: Process the event\n`;
559
- code += ` await processEvent(payload)\n`;
605
+ code += ` const handled = {\n`;
606
+ code += ` processed: true,\n`;
607
+ code += ` id: crypto.randomUUID?.() || String(Date.now()),\n`;
608
+ code += ` at: new Date().toISOString(),\n`;
609
+ code += ` payload\n`;
610
+ code += ` }\n`;
611
+ code += ` console.log('Event processed', handled)\n`;
560
612
  code += `\n`;
561
613
  code += ` // Acknowledge successful processing\n`;
562
614
  code += ` ack()\n`;
@@ -569,8 +621,12 @@ export const handlers = {
569
621
  }
570
622
  else {
571
623
  code += ` .handler(async (payload, ctx) => {\n`;
572
- code += ` // TODO: Process the event (fire-and-forget)\n`;
573
- code += ` await processEvent(payload)\n`;
624
+ code += ` const handled = {\n`;
625
+ code += ` processed: true,\n`;
626
+ code += ` at: new Date().toISOString(),\n`;
627
+ code += ` payload\n`;
628
+ code += ` }\n`;
629
+ code += ` console.log('Fire-and-forget event handled', handled)\n`;
574
630
  code += ` })\n`;
575
631
  }
576
632
  let md = `# Event: ${name}\n\n`;
@@ -599,33 +655,58 @@ export const handlers = {
599
655
  switch (type) {
600
656
  case 'auth-bearer':
601
657
  imports += 'createAuthMiddleware, createBearerStrategy';
602
- code = `.use(createAuthMiddleware({
603
- strategy: createBearerStrategy({
604
- validate: async (token) => {
605
- // TODO: Implement token validation
606
- const user = await verifyToken(token)
607
- return user
608
- ? { authenticated: true, principal: user }
609
- : { authenticated: false }
610
- }
611
- })
612
- }))`;
658
+ code = `.use(createAuthMiddleware({\n`;
659
+ code += ` strategy: createBearerStrategy({\n`;
660
+ code += ` validate: async (token) => {\n`;
661
+ code += ` const tokenValue = String(token || '').trim()\n`;
662
+ code += ` if (!tokenValue) {\n`;
663
+ code += ` return { authenticated: false }\n`;
664
+ code += ` }\n`;
665
+ code += `\n`;
666
+ code += ` const allowedTokens = new Set(\n`;
667
+ code += ` (process.env.RAFFEL_BEARER_TOKENS || 'dev-token')\n`;
668
+ code += ` .split(',')\n`;
669
+ code += ` .map((item) => item.trim())\n`;
670
+ code += ` .filter(Boolean)\n`;
671
+ code += ` )\n`;
672
+ code += `\n`;
673
+ code += ` if (!allowedTokens.has(tokenValue)) {\n`;
674
+ code += ` return { authenticated: false }\n`;
675
+ code += ` }\n`;
676
+ code += `\n`;
677
+ code += ` return {\n`;
678
+ code += ` authenticated: true,\n`;
679
+ code += ` principal: { id: tokenValue, roles: ['user'] }\n`;
680
+ code += ` }\n`;
681
+ code += ` }\n`;
682
+ code += ` })\n`;
683
+ code += `}))`;
613
684
  break;
614
685
  case 'auth-apikey':
615
686
  imports += 'createAuthMiddleware, createApiKeyStrategy';
616
- code = `.use(createAuthMiddleware({
617
- strategy: createApiKeyStrategy({
618
- validate: async (key) => {
619
- // TODO: Implement API key validation
620
- const app = await db.apiKeys.findByKey(key)
621
- return app
622
- ? { authenticated: true, principal: app }
623
- : { authenticated: false }
624
- },
625
- extractFrom: 'header',
626
- headerName: 'X-API-Key'
627
- })
628
- }))`;
687
+ code = `.use(createAuthMiddleware({\n`;
688
+ code += ` strategy: createApiKeyStrategy({\n`;
689
+ code += ` validate: async (key) => {\n`;
690
+ code += ` const keyValue = String(key || '').trim()\n`;
691
+ code += ` if (!keyValue) {\n`;
692
+ code += ` return { authenticated: false }\n`;
693
+ code += ` }\n`;
694
+ code += `\n`;
695
+ code += ` const allowedKeys = new Set(\n`;
696
+ code += ` (process.env.RAFFEL_API_KEYS || '')\n`;
697
+ code += ` .split(',')\n`;
698
+ code += ` .map((item) => item.trim())\n`;
699
+ code += ` .filter(Boolean)\n`;
700
+ code += ` )\n`;
701
+ code += `\n`;
702
+ code += ` return allowedKeys.has(keyValue)\n`;
703
+ code += ` ? { authenticated: true, principal: { id: keyValue, source: 'api-key' } }\n`;
704
+ code += ` : { authenticated: false }\n`;
705
+ code += ` },\n`;
706
+ code += ` extractFrom: 'header',\n`;
707
+ code += ` headerName: 'X-API-Key'\n`;
708
+ code += ` })\n`;
709
+ code += `}))`;
629
710
  break;
630
711
  case 'rate-limit':
631
712
  imports += 'createRateLimitInterceptor';
@@ -742,14 +823,349 @@ const tracer = createTracer({
742
823
  md += '```\n';
743
824
  return text(md);
744
825
  },
826
+ raffel_project_blueprint: async (args) => {
827
+ const projectName = String(args.projectName || 'raffel-service');
828
+ const architecture = String(args.architecture || 'api');
829
+ const includeAuth = Boolean(args.includeAuth);
830
+ const includeDatabase = Boolean(args.includeDatabase);
831
+ const includeRealtime = Boolean(args.includeRealtime);
832
+ const includeObservability = Boolean(args.includeObservability);
833
+ const safeName = projectName.replace(/[^a-z0-9-]/gi, '-');
834
+ let structure = `src/\n`;
835
+ structure += `├─ ${safeName}.ts\n`;
836
+ structure += `├─ config/\n`;
837
+ structure += `│ ├─ env.ts\n`;
838
+ structure += `│ ├─ middleware.ts\n`;
839
+ structure += `│ └─ features.ts\n`;
840
+ structure += `├─ modules/\n`;
841
+ structure += `│ ├─ health/\n`;
842
+ structure += `│ ├─ users/\n`;
843
+ structure += `│ └─ <business-domain>/\n`;
844
+ structure += `├─ plugins/\n`;
845
+ structure += `│ ├─ middleware/\n`;
846
+ structure += `│ │ ├─ auth.ts\n`;
847
+ structure += `│ │ ├─ errors.ts\n`;
848
+ structure += `│ │ └─ observability.ts\n`;
849
+ structure += `│ └─ resolvers/\n`;
850
+ structure += `├─ lib/\n`;
851
+ structure += `│ ├─ logger.ts\n`;
852
+ structure += `│ ├─ errors.ts\n`;
853
+ structure += `│ └─ bootstrap.ts\n`;
854
+ structure += `├─ bootstrap/\n`;
855
+ structure += `│ ├─ dependencies.ts\n`;
856
+ structure += `│ └─ container.ts\n`;
857
+ if (includeRealtime) {
858
+ structure += `├─ services/\n`;
859
+ structure += `│ ├─ streaming/\n`;
860
+ structure += `│ │ ├─ channels.ts\n`;
861
+ structure += `│ │ └─ topics.ts\n`;
862
+ structure += `│ └─ events/\n`;
863
+ structure += `│ ├─ publisher.ts\n`;
864
+ structure += `│ └─ consumer.ts\n`;
865
+ }
866
+ structure += `└─ index.ts\n`;
867
+ let setupPlan = '';
868
+ setupPlan += `1) Create core server entry in \`src/index.ts\` with \`createServer()\`.\n`;
869
+ setupPlan += `2) Add environment loading from \`src/config/env.ts\`.\n`;
870
+ setupPlan += `3) Build shared middleware stack in \`src/plugins/middleware.ts\`.\n`;
871
+ setupPlan += `4) Register domain modules from \`src/modules/\`.\n`;
872
+ setupPlan += `5) Add integrations (database, cache, streams, observability).\n`;
873
+ setupPlan += `6) Add tests for one happy path and one error path per module.\n`;
874
+ let starterCode = `import { createServer } from 'raffel'\n`;
875
+ starterCode += `import { createRouterModule } from 'raffel'\n`;
876
+ starterCode += `import { createServerConfig } from './config/env.js'\n`;
877
+ starterCode += `import { errorMiddleware, loggerMiddleware } from './plugins/middleware/index.js'\n`;
878
+ starterCode += `import { createHealthModule } from './modules/health/index.js'\n\n`;
879
+ starterCode += `const config = createServerConfig()\n`;
880
+ starterCode += `const server = createServer({\n`;
881
+ starterCode += ` port: config.port,\n`;
882
+ starterCode += ` logLevel: config.logLevel,\n`;
883
+ starterCode += `})\n`;
884
+ starterCode += `\n`;
885
+ starterCode += `server.use(errorMiddleware()).use(loggerMiddleware())\n`;
886
+ starterCode += `server.mount('/', createHealthModule())\n`;
887
+ starterCode += `\n`;
888
+ starterCode += `await server.start()\n`;
889
+ starterCode += `console.log('${safeName} running at ' + 'http://localhost:' + config.port)\n`;
890
+ const featureChecklist = [
891
+ includeAuth ? '- [ ] Add bearer and API key strategy in `src/plugins/middleware/auth.ts`' : '',
892
+ includeDatabase
893
+ ? '- [ ] Add Prisma schema + migration scripts'
894
+ : '- [ ] Start with in-memory repositories and add DB later',
895
+ architecture === 'realtime'
896
+ ? '- [ ] Add WebSocket adapter and event bus in `src/services/streaming`'
897
+ : '',
898
+ architecture === 'microservice'
899
+ ? '- [ ] Add queue-based integrations and explicit service boundaries'
900
+ : '',
901
+ includeObservability
902
+ ? '- [ ] Add metrics/tracing and alerting hooks before first release'
903
+ : '- [ ] Add basic logs and health checks in phase 2',
904
+ ].filter(Boolean);
905
+ let md = `# Project Blueprint: ${projectName}\n\n`;
906
+ md += `**Architecture:** ${architecture}\n`;
907
+ md += `**Goal:** Teach-first scaffold with practical Raffel defaults.\n\n`;
908
+ md += `## Recommended directory structure\n\n`;
909
+ md += '```text\n';
910
+ md += `${structure}\n`;
911
+ md += '```\n\n';
912
+ md += `## Migration path\n\n`;
913
+ md += `${setupPlan}\n\n`;
914
+ md += `## Starter entrypoint\n\n`;
915
+ md += '```typescript\n';
916
+ md += starterCode;
917
+ md += '```\n\n';
918
+ md += `## Feature checklist\n\n`;
919
+ for (const item of featureChecklist) {
920
+ md += `${item}\n`;
921
+ }
922
+ md += '\n';
923
+ md += `## Suggested next commands\n\n`;
924
+ md += `- npx raffel-mcp --category architecture\n`;
925
+ md += `- Use \`raffel_create_module\` for \`src/modules\` boundaries\n`;
926
+ md += `- Use \`raffel_runtime_config\` with profile \`development\` for defaults\n`;
927
+ return text(md);
928
+ },
929
+ raffel_api_endpoint_blueprint: async (args) => {
930
+ const resourceName = String(args.resourceName || 'resource');
931
+ const includeAuth = Boolean(args.includeAuth);
932
+ const includeSearch = Boolean(args.includeSearch);
933
+ const includeBulk = Boolean(args.includeBulk);
934
+ const includeStreaming = Boolean(args.includeStreaming);
935
+ const withEvents = Boolean(args.withEvents);
936
+ const safeResource = resourceName.replace(/[^a-zA-Z0-9_]/g, '_');
937
+ const singular = safeResource.replace(/s$/, '');
938
+ const moduleName = `${singular}Module`;
939
+ const moduleFile = `${singular}.ts`;
940
+ const title = toTitleCase(safeResource);
941
+ let procedures = [
942
+ `.list(params): paginated list`,
943
+ `.get({ id })`,
944
+ `.create(input)`,
945
+ `.update({ id, ...input })`,
946
+ `.delete({ id })`,
947
+ ];
948
+ if (includeSearch) {
949
+ procedures.push('.search({ query, filters, page, pageSize })');
950
+ }
951
+ if (includeBulk) {
952
+ procedures.push('.bulkCreate(input[])');
953
+ procedures.push('.bulkDelete(ids[])');
954
+ }
955
+ if (withEvents) {
956
+ procedures.push('.onCreated / .onUpdated / .onDeleted events');
957
+ }
958
+ if (includeStreaming) {
959
+ procedures.push('.stream("liveUpdates")');
960
+ }
961
+ let routeTree = `# ${title} Module\n\n`;
962
+ routeTree += `\nsrc/modules/${safeResource}/${moduleFile}\n`;
963
+ routeTree += `\n`;
964
+ routeTree += `## Procedure ideas\n\n`;
965
+ for (const p of procedures) {
966
+ routeTree += `- ${resourceName}${p}\n`;
967
+ }
968
+ routeTree += '\n';
969
+ let moduleCode = `import { createRouterModule, z, RaffelError } from 'raffel'\n\n`;
970
+ moduleCode += `const ${toTitleCase(singular).replace(/ /g, '')}Input = z.object({\n`;
971
+ moduleCode += ` id: z.string().optional(),\n`;
972
+ moduleCode += ` name: z.string(),\n`;
973
+ moduleCode += `})\n\n`;
974
+ moduleCode += `export const ${moduleName} = createRouterModule()\n`;
975
+ moduleCode += ` .procedure('list')\n`;
976
+ moduleCode += ` .input(z.object({ page: z.number().int().min(1).default(1), pageSize: z.number().int().min(1).max(100).default(20) }))\n`;
977
+ moduleCode += ` .handler(async () => ({ items: [], page: 1, pageSize: 20, total: 0 }))\n`;
978
+ moduleCode += `\n`;
979
+ moduleCode += ` .procedure('get')\n`;
980
+ moduleCode += ` .input(z.object({ id: z.string() }))\n`;
981
+ moduleCode += ` .handler(async ({ id }) => {\n`;
982
+ moduleCode += ` const item = null\n`;
983
+ moduleCode += ` if (!item) throw new RaffelError('NOT_FOUND', \`\${id} not found\`)\n`;
984
+ moduleCode += ` return item\n`;
985
+ moduleCode += ` })\n\n`;
986
+ moduleCode += ` .procedure('create')\n`;
987
+ moduleCode += ` .input(${toTitleCase(singular).replace(/ /g, '')}Input)\n`;
988
+ moduleCode += ` .handler(async (input) => ({ id: 'id', ...input }))\n`;
989
+ if (includeAuth) {
990
+ moduleCode += ` // protect with auth middleware in mount or procedure\n`;
991
+ }
992
+ let md = `# API Endpoint Blueprint: ${title}\n\n`;
993
+ md += `**Resource:** ${resourceName}\n`;
994
+ md += `**Suggested protection:** ${includeAuth ? 'Mutations protected' : 'Optional auth'}\n\n`;
995
+ md += `## Procedures to generate\n\n`;
996
+ md += `${routeTree}\n\n`;
997
+ md += `## Module starter\n\n`;
998
+ md += '```typescript\n';
999
+ md += moduleCode;
1000
+ md += '```\n\n';
1001
+ md += `## Suggested mount\n\n`;
1002
+ md += `\`\`\`typescript\n`;
1003
+ md += `import { ${moduleName} } from './modules/${safeResource}/${moduleFile.replace('.ts', '')}'\n`;
1004
+ md += `\n`;
1005
+ md += `server.mount('/${safeResource}', ${moduleName})\n`;
1006
+ md += `\`\`\`\n\n`;
1007
+ if (includeStreaming) {
1008
+ md += `## Streaming extension\n\n`;
1009
+ md += `Add stream in the same module or a dedicated stream module:\n\n`;
1010
+ md += '```typescript\n';
1011
+ md += `server.stream('${safeResource}.live')\n`;
1012
+ md += ` .handler(async function* () {\n`;
1013
+ md += ` while (true) {\n`;
1014
+ md += ` yield { type: 'heartbeat', now: new Date().toISOString() }\n`;
1015
+ md += ` await new Promise((resolve) => setTimeout(resolve, 1000))\n`;
1016
+ md += ` }\n`;
1017
+ md += ` })\n`;
1018
+ md += '```\n\n';
1019
+ }
1020
+ if (withEvents) {
1021
+ md += `## Events to wire\n\n`;
1022
+ md += `- ${safeResource}.created\n`;
1023
+ md += `- ${safeResource}.updated\n`;
1024
+ md += `- ${safeResource}.deleted\n`;
1025
+ md += `\n`;
1026
+ }
1027
+ md += `## Suggested tests\n\n`;
1028
+ md += `- List + pagination\n`;
1029
+ md += `- Get not found path\n`;
1030
+ md += `- Create validation errors\n`;
1031
+ md += `- Delete idempotency checks\n`;
1032
+ if (includeAuth) {
1033
+ md += `- Unauthorized on create/update/delete\n`;
1034
+ }
1035
+ return text(md);
1036
+ },
1037
+ raffel_runtime_config: async (args) => {
1038
+ const profile = String(args.profile || 'production');
1039
+ const includeSecurity = Boolean(args.includeSecurity);
1040
+ const includeMonitoring = Boolean(args.includeMonitoring);
1041
+ const includeResilience = Boolean(args.includeResilience);
1042
+ const baseEnv = [
1043
+ '# Environment',
1044
+ 'NODE_ENV=' + profile.toUpperCase(),
1045
+ 'PORT=3000',
1046
+ 'LOG_LEVEL=info',
1047
+ 'CORS_ORIGINS=*',
1048
+ '',
1049
+ '# Feature flags',
1050
+ 'ENABLE_METRICS=' + (includeMonitoring ? 'true' : 'false'),
1051
+ 'ENABLE_TRACING=' + (includeMonitoring ? 'true' : 'false'),
1052
+ includeSecurity ? 'ENABLE_RATE_LIMIT=true' : 'ENABLE_RATE_LIMIT=false',
1053
+ includeResilience ? 'ENABLE_RESILIENCE=true' : 'ENABLE_RESILIENCE=false',
1054
+ ];
1055
+ const env = baseEnv.join('\n');
1056
+ const setup = [];
1057
+ const security = [];
1058
+ const observability = [];
1059
+ if (profile === 'production') {
1060
+ setup.push('set "trust proxy" equivalent for reverse proxies');
1061
+ setup.push('prefer structured logs + correlation IDs');
1062
+ if (includeSecurity) {
1063
+ security.push('.use(createAuthMiddleware(...))');
1064
+ security.push('Use RAFFEL_BEARER_TOKENS + RAFFEL_API_KEYS');
1065
+ }
1066
+ }
1067
+ if (profile === 'staging') {
1068
+ setup.push('mirror production middleware, relaxed sampling');
1069
+ setup.push('keep debug headers disabled');
1070
+ }
1071
+ if (profile === 'development') {
1072
+ setup.push('enable debug logs and stack traces');
1073
+ setup.push('disable strict security checks where local dev needs speed');
1074
+ if (includeMonitoring) {
1075
+ setup.push('start metrics endpoint but hide from external traffic');
1076
+ }
1077
+ }
1078
+ if (includeMonitoring) {
1079
+ observability.push('Metrics endpoint with Prometheus registry');
1080
+ observability.push('OpenTelemetry exporter for tracing');
1081
+ observability.push('Request/response timing at middleware boundary');
1082
+ }
1083
+ if (includeResilience) {
1084
+ setup.push('Use timeout interceptor globally (1-5s by endpoint)');
1085
+ setup.push('Enable retry + circuit breaker for downstream calls');
1086
+ setup.push('Standardize idempotency keys for unsafe operations');
1087
+ }
1088
+ const profileChecklist = setup.map((item) => `- [ ] ${item}`).join('\n');
1089
+ const securityList = security.map((item) => `- ${item}`).join('\n');
1090
+ const monitorList = observability.map((item) => `- ${item}`).join('\n');
1091
+ let md = `# Runtime configuration for ${toTitleCase(profile)} profile\n\n`;
1092
+ md += `## \`.env.example\`\n\n`;
1093
+ md += '```env\n';
1094
+ md += `${env}\n`;
1095
+ md += '```\n\n';
1096
+ md += `## Setup checklist\n\n${profileChecklist}\n\n`;
1097
+ if (includeSecurity) {
1098
+ md += `## Security\n\n${securityList || '- [ ] Configure auth middleware'}\n\n`;
1099
+ }
1100
+ if (includeMonitoring) {
1101
+ md += `## Monitoring\n\n${monitorList}\n\n`;
1102
+ }
1103
+ md += `## Recommended middleware order\n\n`;
1104
+ md += `1. logger\n`;
1105
+ if (includeSecurity) {
1106
+ md += `2. errorBoundary\n`;
1107
+ md += `3. auth (before protected procedures)\n`;
1108
+ }
1109
+ else {
1110
+ md += `2. errorBoundary\n`;
1111
+ }
1112
+ md += `4. validation\n`;
1113
+ md += `5. metrics/tracing\n`;
1114
+ if (includeResilience) {
1115
+ md += `6. timeout / retry / circuit-breaker\n`;
1116
+ }
1117
+ md += `\n`;
1118
+ md += `## Snippet\n\n`;
1119
+ md += '```typescript\n';
1120
+ md += `import { createServer } from 'raffel'\n`;
1121
+ md += `const profile = process.env.NODE_ENV || '${profile}'\n`;
1122
+ md += `const server = createServer({\n`;
1123
+ md += ` port: Number(process.env.PORT || 3000),\n`;
1124
+ md += ` logLevel: process.env.LOG_LEVEL || 'info',\n`;
1125
+ md += `})\n`;
1126
+ if (includeMonitoring) {
1127
+ md += `\n`;
1128
+ md += `// Metrics and tracing\n`;
1129
+ md += `// import { createMetricRegistry, createMetricsInterceptor } from 'raffel'\n`;
1130
+ md += `// createMetricRegistry\n`;
1131
+ md += `// server.use(createMetricsInterceptor({ registry: metrics }))\n`;
1132
+ }
1133
+ if (includeResilience) {
1134
+ md += `\n`;
1135
+ md += `// Resilience defaults for downstream calls\n`;
1136
+ md += `// server.use(createRateLimitInterceptor({ windowMs: 60000, maxRequests: 120 }))\n`;
1137
+ md += `// server.use(timeout({ ms: 30000 }))\n`;
1138
+ }
1139
+ md += `\n`;
1140
+ md += `await server.start()\n`;
1141
+ md += `console.log('Server running in ${profile}')\n`;
1142
+ md += '```\n';
1143
+ return text(md);
1144
+ },
745
1145
  raffel_create_module: async (args) => {
746
1146
  const name = String(args.name || 'myModule');
747
1147
  const procedures = args.procedures || [];
748
1148
  const withMiddleware = args.withMiddleware || [];
749
1149
  let code = `// src/modules/${name}.ts\n`;
750
- code += `import { createRouterModule } from 'raffel'\n`;
1150
+ code += `import { createRouterModule, RaffelError } from 'raffel'\n`;
1151
+ code += `import { z } from 'zod'\n`;
1152
+ const moduleClassName = `${name.charAt(0).toUpperCase() + name.slice(1)}`;
1153
+ const needsCreateInput = procedures.some((proc) => proc.method === 'create');
1154
+ const needsUpdateInput = procedures.some((proc) => proc.method === 'update');
1155
+ if (needsCreateInput) {
1156
+ code += `\nconst Create${moduleClassName}Input = z.object({\n`;
1157
+ code += ` data: z.record(z.unknown())\n`;
1158
+ code += `})\n`;
1159
+ }
1160
+ if (needsUpdateInput) {
1161
+ code += `\nconst Update${moduleClassName}Input = z.object({\n`;
1162
+ code += ` id: z.string(),\n`;
1163
+ code += ` data: z.record(z.unknown())\n`;
1164
+ code += `})\n`;
1165
+ }
751
1166
  if (withMiddleware.length > 0) {
752
- code += `// TODO: Import middleware\n`;
1167
+ code += `\n`;
1168
+ code += `// Add needed middleware imports in your codebase\n`;
753
1169
  }
754
1170
  code += `\nexport const ${name}Module = createRouterModule()\n`;
755
1171
  if (withMiddleware.length > 0) {
@@ -769,7 +1185,9 @@ const tracer = createTracer({
769
1185
  switch (method) {
770
1186
  case 'list':
771
1187
  code += ` .handler(async (input, ctx) => {\n`;
772
- code += ` // TODO: Return list of items\n`;
1188
+ code += ` if (!ctx.db?.${name}?.findMany) {\n`;
1189
+ code += ` return []\n`;
1190
+ code += ` }\n`;
773
1191
  code += ` return await ctx.db.${name}.findMany()\n`;
774
1192
  code += ` })\n\n`;
775
1193
  break;
@@ -802,8 +1220,13 @@ const tracer = createTracer({
802
1220
  break;
803
1221
  default:
804
1222
  code += ` .handler(async (input, ctx) => {\n`;
805
- code += ` // TODO: Implement\n`;
806
- code += ` return {}\n`;
1223
+ code += ` if (!ctx.auth?.authenticated) {\n`;
1224
+ code += ` throw new RaffelError('UNAUTHENTICATED', 'Authentication required')\n`;
1225
+ code += ` }\n`;
1226
+ code += ` return {\n`;
1227
+ code += ` input,\n`;
1228
+ code += ` receivedAt: new Date().toISOString()\n`;
1229
+ code += ` }\n`;
807
1230
  code += ` })\n\n`;
808
1231
  }
809
1232
  }
@@ -849,6 +1272,367 @@ const tracer = createTracer({
849
1272
  }
850
1273
  return text(md);
851
1274
  },
1275
+ raffel_implement_auth: async (args) => {
1276
+ const method = String(args.method || '');
1277
+ const provider = String(args.provider || 'google');
1278
+ const withSession = Boolean(args.withSession ?? true);
1279
+ const storage = String(args.storage || 'database');
1280
+ if (!method)
1281
+ return error('method is required');
1282
+ switch (method) {
1283
+ case 'bearer-jwt': {
1284
+ let md = `# Implementing Bearer JWT Authentication\n\n`;
1285
+ md += `JWT tokens are self-contained — no DB lookup needed to validate them. ` +
1286
+ `The server signs tokens on login and verifies signatures on each request.\n\n`;
1287
+ md += `## When to use\n- REST APIs / RPC services consumed by mobile or SPA clients\n` +
1288
+ `- Microservices that need stateless auth\n- Anywhere you can't use cookies (e.g. CLI, mobile)\n\n`;
1289
+ md += `## Step 1 — Install\n\`\`\`bash\npnpm add jsonwebtoken @types/jsonwebtoken bcrypt @types/bcrypt\n\`\`\`\n\n`;
1290
+ md += `## Step 2 — Environment variables\n\`\`\`bash\nJWT_SECRET=at-least-32-char-random-secret # openssl rand -base64 32\nJWT_EXPIRES_IN=1h\n\`\`\`\n\n`;
1291
+ md += `## Step 3 — Auth module (src/modules/auth.ts)\n\`\`\`typescript\n`;
1292
+ md += `import { createBearerStrategy, createAuthMiddleware, requireAuth, RaffelError } from 'raffel'\n`;
1293
+ md += `import jwt from 'jsonwebtoken'\nimport bcrypt from 'bcrypt'\n\n`;
1294
+ md += `const SECRET = process.env.JWT_SECRET!\n\n`;
1295
+ md += `export const bearerStrategy = createBearerStrategy({\n`;
1296
+ md += ` verify: async (token) => {\n`;
1297
+ md += ` try {\n`;
1298
+ md += ` const payload = jwt.verify(token, SECRET) as jwt.JwtPayload\n`;
1299
+ md += ` return { authenticated: true, principal: payload.sub!, claims: payload }\n`;
1300
+ md += ` } catch {\n`;
1301
+ md += ` return null // expired or tampered\n`;
1302
+ md += ` }\n`;
1303
+ md += ` },\n`;
1304
+ md += `})\n\n`;
1305
+ md += `export const authMiddleware = createAuthMiddleware({\n`;
1306
+ md += ` strategies: [bearerStrategy],\n`;
1307
+ md += ` publicProcedures: ['auth.login', 'auth.register', 'health.check'],\n`;
1308
+ md += `})\n\n`;
1309
+ md += `// Procedures\n`;
1310
+ md += `export function registerAuthProcedures(server: ReturnType<typeof createServer>) {\n`;
1311
+ md += ` server.procedure('auth.login').handler(async ({ email, password }) => {\n`;
1312
+ md += ` const user = await db.users.findByEmail(email)\n`;
1313
+ md += ` if (!user || !(await bcrypt.compare(password, user.passwordHash)))\n`;
1314
+ md += ` throw new RaffelError('UNAUTHENTICATED', 'Invalid credentials')\n\n`;
1315
+ md += ` const token = jwt.sign(\n`;
1316
+ md += ` { sub: user.id, email: user.email, roles: user.roles },\n`;
1317
+ md += ` SECRET,\n`;
1318
+ md += ` { expiresIn: process.env.JWT_EXPIRES_IN || '1h' }\n`;
1319
+ md += ` )\n`;
1320
+ md += ` return { token, expiresIn: 3600 }\n`;
1321
+ md += ` })\n\n`;
1322
+ md += ` server.procedure('users.me').handler(async (_input, ctx) => {\n`;
1323
+ md += ` requireAuth(ctx)\n`;
1324
+ md += ` return { userId: ctx.auth!.principal, email: ctx.auth!.claims?.email }\n`;
1325
+ md += ` })\n`;
1326
+ md += `}\n\`\`\`\n\n`;
1327
+ md += `## Step 4 — Server setup (src/server.ts)\n\`\`\`typescript\n`;
1328
+ md += `import { createServer } from 'raffel'\nimport { authMiddleware, registerAuthProcedures } from './modules/auth'\n\n`;
1329
+ md += `const server = createServer({ port: 3000 })\nserver.use(authMiddleware)\nregisterAuthProcedures(server)\nawait server.start()\n\`\`\`\n\n`;
1330
+ md += `## Step 5 — Test\n\`\`\`bash\n`;
1331
+ md += `# Login\ncurl -X POST http://localhost:3000/auth/login \\\n -H 'Content-Type: application/json' \\\n -d '{"email":"alice@example.com","password":"secret"}'\n# → {"token":"eyJ..."}\n\n`;
1332
+ md += `# Use the token\ncurl http://localhost:3000/users/me \\\n -H 'Authorization: Bearer eyJ...'\n\`\`\`\n\n`;
1333
+ md += `## Token refresh pattern\n\`\`\`typescript\n`;
1334
+ md += `// Issue short-lived access token + long-lived refresh token\nconst accessToken = jwt.sign({ sub: user.id }, SECRET, { expiresIn: '15m' })\nconst refreshToken = jwt.sign({ sub: user.id, type: 'refresh' }, SECRET, { expiresIn: '7d' })\n// Store refreshToken in httpOnly cookie or DB\n\`\`\`\n`;
1335
+ return text(md);
1336
+ }
1337
+ case 'api-key': {
1338
+ let md = `# Implementing API Key Authentication\n\n`;
1339
+ md += `API keys are long-lived credentials for machine-to-machine (M2M) access. ` +
1340
+ `Never expose private API keys — they should only be used server-side or in trusted clients.\n\n`;
1341
+ md += `## When to use\n- SDKs / CLI tools / server-to-server integrations\n` +
1342
+ `- Public APIs where OAuth2 is overkill\n- Webhooks that need signed requests\n\n`;
1343
+ if (storage === 'env') {
1344
+ md += `## Setup (env-var storage — simpler, no DB)\n\n`;
1345
+ md += `### Step 1 — Environment variable\n\`\`\`bash\nRAFFEL_API_KEYS=key-abc123,key-xyz789 # comma-separated\n\`\`\`\n\n`;
1346
+ md += `### Step 2 — Auth module\n\`\`\`typescript\n`;
1347
+ md += `import { createApiKeyStrategy, createAuthMiddleware } from 'raffel'\n\n`;
1348
+ md += `const allowed = new Set(\n`;
1349
+ md += ` (process.env.RAFFEL_API_KEYS || '').split(',').map((k) => k.trim()).filter(Boolean)\n`;
1350
+ md += `)\n\n`;
1351
+ md += `export const apiKeyStrategy = createApiKeyStrategy({\n`;
1352
+ md += ` validate: async (key) =>\n`;
1353
+ md += ` allowed.has(key) ? { authenticated: true, principal: key } : null,\n`;
1354
+ md += ` extractFrom: 'header',\n`;
1355
+ md += ` headerName: 'X-API-Key',\n`;
1356
+ md += `})\n\n`;
1357
+ md += `export const authMiddleware = createAuthMiddleware({ strategies: [apiKeyStrategy] })\n\`\`\`\n\n`;
1358
+ }
1359
+ else {
1360
+ md += `## Setup (database storage)\n\n`;
1361
+ md += `### Step 1 — Database schema\n\`\`\`sql\nCREATE TABLE api_keys (\n`;
1362
+ md += ` id UUID PRIMARY KEY DEFAULT gen_random_uuid(),\n`;
1363
+ md += ` owner_id UUID NOT NULL REFERENCES users(id),\n`;
1364
+ md += ` key_hash TEXT NOT NULL UNIQUE, -- SHA-256 of the key\n`;
1365
+ md += ` name TEXT, -- human label\n`;
1366
+ md += ` scopes TEXT[] DEFAULT '{}',\n`;
1367
+ md += ` last_used TIMESTAMPTZ,\n`;
1368
+ md += ` revoked_at TIMESTAMPTZ,\n`;
1369
+ md += ` created_at TIMESTAMPTZ DEFAULT now()\n`;
1370
+ md += `);\n\`\`\`\n\n`;
1371
+ md += `### Step 2 — Key generation helper\n\`\`\`typescript\n`;
1372
+ md += `import { createHash, randomBytes } from 'crypto'\n\n`;
1373
+ md += `export function generateApiKey() {\n`;
1374
+ md += ` const raw = 'rfl_' + randomBytes(32).toString('hex')\n`;
1375
+ md += ` const hash = createHash('sha256').update(raw).digest('hex')\n`;
1376
+ md += ` return { raw, hash } // store hash, return raw once to user\n`;
1377
+ md += `}\n\`\`\`\n\n`;
1378
+ md += `### Step 3 — Auth module\n\`\`\`typescript\n`;
1379
+ md += `import { createApiKeyStrategy, createAuthMiddleware } from 'raffel'\nimport { createHash } from 'crypto'\n\n`;
1380
+ md += `export const apiKeyStrategy = createApiKeyStrategy({\n`;
1381
+ md += ` validate: async (key) => {\n`;
1382
+ md += ` const hash = createHash('sha256').update(key).digest('hex')\n`;
1383
+ md += ` const record = await db.apiKeys.findUnique({ where: { keyHash: hash } })\n`;
1384
+ md += ` if (!record || record.revokedAt) return null\n`;
1385
+ md += ` // optionally update last_used\n`;
1386
+ md += ` await db.apiKeys.update({ where: { id: record.id }, data: { lastUsed: new Date() } })\n`;
1387
+ md += ` return { authenticated: true, principal: record.ownerId, claims: { keyId: record.id, scopes: record.scopes } }\n`;
1388
+ md += ` },\n`;
1389
+ md += ` headerName: 'X-API-Key',\n`;
1390
+ md += `})\n\n`;
1391
+ md += `export const authMiddleware = createAuthMiddleware({ strategies: [apiKeyStrategy] })\n\`\`\`\n\n`;
1392
+ md += `### Step 4 — Key management procedures\n\`\`\`typescript\n`;
1393
+ md += `server.procedure('apiKeys.create').handler(async ({ name, scopes }, ctx) => {\n`;
1394
+ md += ` requireAuth(ctx)\n`;
1395
+ md += ` const { raw, hash } = generateApiKey()\n`;
1396
+ md += ` await db.apiKeys.create({ data: { ownerId: ctx.auth!.principal, keyHash: hash, name, scopes } })\n`;
1397
+ md += ` return { key: raw } // show ONCE, never again\n`;
1398
+ md += `})\n\n`;
1399
+ md += `server.procedure('apiKeys.revoke').handler(async ({ id }, ctx) => {\n`;
1400
+ md += ` requireAuth(ctx)\n`;
1401
+ md += ` await db.apiKeys.update({ where: { id, ownerId: ctx.auth!.principal }, data: { revokedAt: new Date() } })\n`;
1402
+ md += ` return { revoked: true }\n`;
1403
+ md += `})\n\`\`\`\n\n`;
1404
+ }
1405
+ md += `## Test\n\`\`\`bash\ncurl http://localhost:3000/items \\\n -H 'X-API-Key: rfl_abc123'\n\`\`\`\n`;
1406
+ return text(md);
1407
+ }
1408
+ case 'oauth2': {
1409
+ const prov = provider || 'google';
1410
+ const envPrefix = prov.toUpperCase();
1411
+ const provCap = prov.charAt(0).toUpperCase() + prov.slice(1);
1412
+ let md = `# Implementing OAuth2 Social Login (${provCap})\n\n`;
1413
+ md += `OAuth2 lets users log in with existing accounts (${provCap}, GitHub, etc.) without a password. ` +
1414
+ `You redirect → they approve → you get an access token + user info.\n\n`;
1415
+ md += `## When to use\n- Web apps where users are humans\n- You want "Login with ${provCap}"\n- Reduce signup friction\n\n`;
1416
+ md += `## Step 1 — Create OAuth2 app on ${provCap}\n`;
1417
+ if (prov === 'google') {
1418
+ md += `1. Go to https://console.cloud.google.com/apis/credentials\n`;
1419
+ md += `2. Create → OAuth 2.0 Client ID → Web application\n`;
1420
+ md += `3. Authorized redirect URI: \`http://localhost:3000/auth/callback\`\n`;
1421
+ md += `4. Copy Client ID and Secret\n\n`;
1422
+ }
1423
+ else if (prov === 'github') {
1424
+ md += `1. Go to https://github.com/settings/applications/new\n`;
1425
+ md += `2. Homepage URL: \`http://localhost:3000\`\n`;
1426
+ md += `3. Authorization callback URL: \`http://localhost:3000/auth/callback\`\n`;
1427
+ md += `4. Copy Client ID and Secret\n\n`;
1428
+ }
1429
+ else {
1430
+ md += `1. Create an OAuth2 app in ${provCap}'s developer console\n`;
1431
+ md += `2. Set redirect URI: \`http://localhost:3000/auth/callback\`\n`;
1432
+ md += `3. Copy Client ID and Secret\n\n`;
1433
+ }
1434
+ md += `## Step 2 — Environment variables\n\`\`\`bash\n`;
1435
+ md += `${envPrefix}_CLIENT_ID=your-client-id\n${envPrefix}_CLIENT_SECRET=your-client-secret\n`;
1436
+ if (withSession)
1437
+ md += `SESSION_SECRET=random-32-char-string\n`;
1438
+ md += `\`\`\`\n\n`;
1439
+ md += `## Step 3 — Auth module (src/modules/auth.ts)\n\`\`\`typescript\n`;
1440
+ md += `import { createServer, createAuthMiddleware, createOAuth2Strategy, generateState, RaffelError } from 'raffel'\n`;
1441
+ if (withSession)
1442
+ md += `import { createSessionInterceptor } from 'raffel'\n`;
1443
+ md += `\n`;
1444
+ md += `export const ${prov}Auth = createOAuth2Strategy({\n`;
1445
+ md += ` provider: '${prov}',\n`;
1446
+ md += ` clientId: process.env.${envPrefix}_CLIENT_ID!,\n`;
1447
+ md += ` clientSecret: process.env.${envPrefix}_CLIENT_SECRET!,\n`;
1448
+ md += ` redirectUri: 'http://localhost:3000/auth/callback',\n`;
1449
+ md += ` scopes: ${prov === 'google' ? "['openid', 'email', 'profile']" : "['read:user', 'user:email']"},\n`;
1450
+ md += `})\n\n`;
1451
+ md += `export function registerAuthProcedures(server: ReturnType<typeof createServer>) {\n`;
1452
+ md += ` // Step A: redirect user to ${provCap}\n`;
1453
+ md += ` server.procedure('auth.authorize').handler(async (_input, ctx) => {\n`;
1454
+ md += ` const state = generateState()\n`;
1455
+ if (withSession) {
1456
+ md += ` ctx.session.data.oauthState = state\n ctx.session.touch()\n`;
1457
+ }
1458
+ else {
1459
+ md += ` // store state in a short-lived cookie or cache\n`;
1460
+ }
1461
+ md += ` return { redirect: ${prov}Auth.getAuthorizationUrl({ state }) }\n`;
1462
+ md += ` })\n\n`;
1463
+ md += ` // Step B: handle redirect back from ${provCap}\n`;
1464
+ md += ` server.procedure('auth.callback').handler(async ({ code, state }, ctx) => {\n`;
1465
+ if (withSession) {
1466
+ md += ` if (state !== ctx.session.data.oauthState)\n`;
1467
+ md += ` throw new RaffelError('INVALID_ARGUMENT', 'Invalid state — possible CSRF')\n`;
1468
+ }
1469
+ md += ` const tokens = await ${prov}Auth.exchangeCode(String(code))\n`;
1470
+ md += ` const userInfo = await ${prov}Auth.getUserInfo(tokens.accessToken)\n`;
1471
+ md += ` // upsert user in your DB\n`;
1472
+ md += ` const user = await db.users.upsert({\n`;
1473
+ md += ` where: { email: userInfo.email },\n`;
1474
+ md += ` create: { email: userInfo.email, name: userInfo.name, provider: '${prov}' },\n`;
1475
+ md += ` update: { name: userInfo.name },\n`;
1476
+ md += ` })\n`;
1477
+ if (withSession) {
1478
+ md += ` ctx.session.data.userId = user.id\n ctx.session.data.oauthState = undefined\n ctx.session.touch()\n`;
1479
+ }
1480
+ md += ` return { ok: true, user: { id: user.id, email: user.email } }\n`;
1481
+ md += ` })\n\n`;
1482
+ md += ` server.procedure('auth.me').handler(async (_input, ctx) => {\n`;
1483
+ if (withSession) {
1484
+ md += ` if (!ctx.session.data.userId) throw new RaffelError('UNAUTHENTICATED', 'Not logged in')\n`;
1485
+ md += ` return db.users.findById(ctx.session.data.userId)\n`;
1486
+ }
1487
+ else {
1488
+ md += ` // check your session/token here\n return { ok: true }\n`;
1489
+ }
1490
+ md += ` })\n}\n\`\`\`\n\n`;
1491
+ md += `## Step 4 — Server setup\n\`\`\`typescript\n`;
1492
+ md += `import { createServer } from 'raffel'\n`;
1493
+ if (withSession)
1494
+ md += `import { createSessionInterceptor } from 'raffel'\n`;
1495
+ md += `import { registerAuthProcedures } from './modules/auth'\n\n`;
1496
+ md += `const server = createServer({ port: 3000 })\n`;
1497
+ if (withSession) {
1498
+ md += `server.use(createSessionInterceptor({\n driver: 'memory', // use redis in prod\n ttl: 3600,\n secret: process.env.SESSION_SECRET,\n}))\n`;
1499
+ }
1500
+ md += `registerAuthProcedures(server)\nawait server.start()\n\`\`\`\n\n`;
1501
+ md += `## Flow diagram\n\`\`\`\nClient → POST /auth/authorize → {redirect: "${prov}.com/oauth?state=..."}\nClient → browser opens ${provCap} → user approves\n${provCap} → GET /auth/callback?code=...&state=...\nServer → exchange code → get userInfo → store in session → return ok\nClient → GET /auth/me → {id, email}\n\`\`\`\n`;
1502
+ return text(md);
1503
+ }
1504
+ case 'oidc': {
1505
+ const prov = provider || 'google';
1506
+ const envPrefix = prov.toUpperCase();
1507
+ let md = `# Implementing OIDC Authentication\n\n`;
1508
+ md += `OIDC (OpenID Connect) extends OAuth2 with an ID token — a signed JWT containing user claims. ` +
1509
+ `The library auto-discovers endpoints from \`/.well-known/openid-configuration\`.\n\n`;
1510
+ md += `## When to use\n- Enterprise SSO (Okta, Auth0, Azure AD, Keycloak)\n` +
1511
+ `- When you need to validate user identity (not just "who has access")\n` +
1512
+ `- When the provider supports OIDC (all major ones do)\n\n`;
1513
+ md += `## Step 1 — Environment variables\n\`\`\`bash\n`;
1514
+ md += `${envPrefix}_CLIENT_ID=your-client-id\n${envPrefix}_CLIENT_SECRET=your-client-secret\n`;
1515
+ md += `${envPrefix}_ISSUER=https://accounts.google.com # or your IdP URL\n`;
1516
+ if (withSession)
1517
+ md += `SESSION_SECRET=random-32-char-string\n`;
1518
+ md += `\`\`\`\n\n`;
1519
+ md += `## Step 2 — Auth module\n\`\`\`typescript\n`;
1520
+ md += `import { createServer, createAuthMiddleware, createOIDCStrategy, generateState, RaffelError } from 'raffel'\n\n`;
1521
+ md += `export const oidcStrategy = createOIDCStrategy({\n`;
1522
+ md += ` issuer: process.env.${envPrefix}_ISSUER!,\n`;
1523
+ md += ` clientId: process.env.${envPrefix}_CLIENT_ID!,\n`;
1524
+ md += ` clientSecret: process.env.${envPrefix}_CLIENT_SECRET!,\n`;
1525
+ md += ` redirectUri: 'http://localhost:3000/auth/callback',\n`;
1526
+ md += ` // issuer auto-discovers: authorizationEndpoint, tokenEndpoint, jwksUri\n`;
1527
+ md += `})\n\n`;
1528
+ md += `export function registerAuthProcedures(server: ReturnType<typeof createServer>) {\n`;
1529
+ md += ` server.procedure('auth.authorize').handler(async (_input, ctx) => {\n`;
1530
+ md += ` const state = generateState()\n`;
1531
+ md += ` const nonce = generateState() // prevents replay attacks\n`;
1532
+ if (withSession) {
1533
+ md += ` ctx.session.data.oauthState = state\n`;
1534
+ md += ` ctx.session.data.nonce = nonce\n`;
1535
+ md += ` ctx.session.touch()\n`;
1536
+ }
1537
+ md += ` return { redirect: oidcStrategy.getAuthorizationUrl({ state, nonce }) }\n`;
1538
+ md += ` })\n\n`;
1539
+ md += ` server.procedure('auth.callback').handler(async ({ code, state }, ctx) => {\n`;
1540
+ if (withSession) {
1541
+ md += ` if (state !== ctx.session.data.oauthState)\n`;
1542
+ md += ` throw new RaffelError('INVALID_ARGUMENT', 'Invalid state — possible CSRF')\n`;
1543
+ }
1544
+ md += ` // exchangeCode validates the ID token signature, expiry, nonce, and audience\n`;
1545
+ md += ` const tokens = await oidcStrategy.exchangeCode(String(code))\n`;
1546
+ md += ` const claims = tokens.idTokenClaims // { sub, email, name, nonce, ... }\n`;
1547
+ if (withSession) {
1548
+ md += ` if (claims.nonce !== ctx.session.data.nonce)\n`;
1549
+ md += ` throw new RaffelError('INVALID_ARGUMENT', 'Nonce mismatch')\n`;
1550
+ }
1551
+ md += ` const user = await db.users.upsert({\n`;
1552
+ md += ` where: { email: claims.email },\n`;
1553
+ md += ` create: { email: claims.email, name: claims.name, sub: claims.sub },\n`;
1554
+ md += ` update: { name: claims.name },\n`;
1555
+ md += ` })\n`;
1556
+ if (withSession) {
1557
+ md += ` ctx.session.data.userId = user.id\n ctx.session.touch()\n`;
1558
+ }
1559
+ md += ` return { ok: true, user: { id: user.id, email: user.email } }\n`;
1560
+ md += ` })\n`;
1561
+ md += `}\n\`\`\`\n\n`;
1562
+ md += `## Key difference vs OAuth2\n`;
1563
+ md += `| | OAuth2 | OIDC |\n|---|---|---|\n`;
1564
+ md += `| Returns | access_token | access_token + **id_token** |\n`;
1565
+ md += `| User info | extra HTTP call to /userinfo | embedded in id_token (JWT) |\n`;
1566
+ md += `| Signature | server checks with userinfo EP | server verifies JWT against JWKS |\n`;
1567
+ md += `| Use when | social login with limited claims | enterprise SSO, need verified identity |\n`;
1568
+ return text(md);
1569
+ }
1570
+ case 'session': {
1571
+ let md = `# Implementing Session-Based Authentication\n\n`;
1572
+ md += `Sessions store auth state server-side (memory + custom stores like Redis) and give the client ` +
1573
+ `an opaque cookie. Nothing sensitive leaves the server.\n\n`;
1574
+ md += `## When to use\n- Traditional web apps with cookie-based auth\n` +
1575
+ `- When you need to revoke access instantly (just delete the session)\n` +
1576
+ `- After OAuth2/OIDC to persist the authenticated user across requests\n\n`;
1577
+ md += `## Step 1 — Install (for Redis in production)\n\`\`\`bash\npnpm add redis\n\`\`\`\n\n`;
1578
+ md += `## Step 2 — Environment variables\n\`\`\`bash\nSESSION_SECRET=random-32-char-string # openssl rand -base64 32\nREDIS_URL=redis://localhost:6379 # production only\n\`\`\`\n\n`;
1579
+ md += `## Step 3 — Server setup\n\`\`\`typescript\n`;
1580
+ md += `import { createServer, createSessionInterceptor, RaffelError } from 'raffel'\nimport bcrypt from 'bcrypt'\n\n`;
1581
+ md += `const server = createServer({ port: 3000 })\n\n`;
1582
+ md += `// Development: in-memory (lost on restart)\nserver.use(createSessionInterceptor({\n driver: 'memory',\n ttl: 3600,\n secret: process.env.SESSION_SECRET,\n cookie: { name: 'sid', httpOnly: true, sameSite: 'lax' },\n}))\n\n`;
1583
+ md += `// Production: switch to Redis\n// import { createRedisSessionDriver } from 'raffel'\n// import { createClient } from 'redis'\n// const redis = createClient({ url: process.env.REDIS_URL })\n// await redis.connect()\n// server.use(createSessionInterceptor({\n// driver: createRedisSessionDriver({ client: redis }),\n// ttl: 7200, rolling: true,\n// secret: process.env.SESSION_SECRET,\n// }))\n\n`;
1584
+ md += `server.procedure('auth.login').handler(async ({ email, password }, ctx) => {\n`;
1585
+ md += ` const user = await db.users.findByEmail(email)\n`;
1586
+ md += ` if (!user || !(await bcrypt.compare(password, user.passwordHash)))\n`;
1587
+ md += ` throw new RaffelError('UNAUTHENTICATED', 'Invalid credentials')\n`;
1588
+ md += ` await ctx.session.regenerate() // prevent session fixation\n`;
1589
+ md += ` ctx.session.data.userId = user.id\n`;
1590
+ md += ` ctx.session.data.roles = user.roles\n`;
1591
+ md += ` ctx.session.touch()\n`;
1592
+ md += ` return { ok: true }\n`;
1593
+ md += `})\n\n`;
1594
+ md += `server.procedure('auth.me').handler(async (_input, ctx) => {\n`;
1595
+ md += ` if (!ctx.session.data.userId) throw new RaffelError('UNAUTHENTICATED', 'Not logged in')\n`;
1596
+ md += ` return db.users.findById(ctx.session.data.userId)\n`;
1597
+ md += `})\n\n`;
1598
+ md += `server.procedure('auth.logout').handler(async (_input, ctx) => {\n`;
1599
+ md += ` await ctx.session.destroy() // removes from store + clears cookie\n`;
1600
+ md += ` return { ok: true }\n`;
1601
+ md += `})\n\n`;
1602
+ md += `await server.start()\n\`\`\`\n\n`;
1603
+ md += `## Session API reference\n`;
1604
+ md += `| Method | What it does |\n|--------|-------------|\n`;
1605
+ md += `| \`ctx.session.data.key = value\` + \`touch()\` | Store data and mark dirty |\n`;
1606
+ md += `| \`ctx.session.data.key\` | Read stored value |\n`;
1607
+ md += `| \`ctx.session.destroy()\` | Delete session + clear cookie |\n`;
1608
+ md += `| \`ctx.session.regenerate()\` | New session ID (call after login) |\n`;
1609
+ md += `| \`ctx.session.id\` | Current session ID |\n`;
1610
+ return text(md);
1611
+ }
1612
+ case 'combined': {
1613
+ let md = `# Combined Auth: JWT + API Key + Sessions\n\n`;
1614
+ md += `Use multiple strategies simultaneously — Raffel tries them in order and uses the first that succeeds.\n\n`;
1615
+ md += `## Typical setup for a full-stack API\n\`\`\`typescript\n`;
1616
+ md += `import {\n createServer,\n createAuthMiddleware,\n createBearerStrategy,\n createApiKeyStrategy,\n createSessionInterceptor,\n requireAuth,\n} from 'raffel'\nimport jwt from 'jsonwebtoken'\n\n`;
1617
+ md += `// Strategy 1: JWT Bearer (for SPA/mobile clients)\nconst bearer = createBearerStrategy({\n verify: async (token) => {\n try {\n const p = jwt.verify(token, process.env.JWT_SECRET!) as jwt.JwtPayload\n return { authenticated: true, principal: p.sub!, claims: p }\n } catch { return null }\n },\n})\n\n`;
1618
+ md += `// Strategy 2: API Key (for server-to-server)\nconst apiKey = createApiKeyStrategy({\n validate: async (key) => {\n const record = await db.apiKeys.findByHash(sha256(key))\n if (!record || record.revokedAt) return null\n return { authenticated: true, principal: record.ownerId, claims: { source: 'api-key' } }\n },\n})\n\n`;
1619
+ md += `const server = createServer({ port: 3000 })\n\n`;
1620
+ md += `// Sessions (for OAuth2 callback state persistence)\nserver.use(createSessionInterceptor({ driver: 'memory', ttl: 3600 }))\n\n`;
1621
+ md += `// Auth: try bearer → then api-key → then unauthenticated\nserver.use(createAuthMiddleware({\n strategies: [bearer, apiKey],\n publicProcedures: ['auth.login', 'auth.authorize', 'auth.callback', 'health.check'],\n}))\n\n`;
1622
+ md += `// Protected procedure works for both JWT users and API key clients\nserver.procedure('users.list').handler(async (_input, ctx) => {\n requireAuth(ctx)\n const source = ctx.auth!.claims?.source || 'jwt'\n return { users: [], authenticatedVia: source }\n})\n\`\`\`\n\n`;
1623
+ md += `## Strategy selection guide\n`;
1624
+ md += `| Client type | Best strategy |\n|-------------|---------------|\n`;
1625
+ md += `| Browser SPA | Bearer JWT or Sessions |\n`;
1626
+ md += `| Mobile app | Bearer JWT |\n`;
1627
+ md += `| Server-to-server | API Key |\n`;
1628
+ md += `| CLI tool | API Key or Bearer JWT |\n`;
1629
+ md += `| OAuth2 callback | Sessions (state storage) |\n`;
1630
+ return text(md);
1631
+ }
1632
+ default:
1633
+ return error(`Unknown method "${method}". Valid: bearer-jwt, api-key, oauth2, oidc, session, combined`);
1634
+ }
1635
+ },
852
1636
  raffel_version: async (args) => {
853
1637
  const checkCompatibility = Boolean(args.checkCompatibility);
854
1638
  let md = `# Raffel Version Information\n\n`;