@frontmcp/ui 0.5.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 (393) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +438 -0
  3. package/package.json +147 -0
  4. package/src/adapters/index.d.ts +10 -0
  5. package/src/adapters/index.js +18 -0
  6. package/src/adapters/index.js.map +1 -0
  7. package/src/adapters/platform-meta.d.ts +165 -0
  8. package/src/adapters/platform-meta.js +310 -0
  9. package/src/adapters/platform-meta.js.map +1 -0
  10. package/src/base-template/bridge.d.ts +89 -0
  11. package/src/base-template/bridge.js +452 -0
  12. package/src/base-template/bridge.js.map +1 -0
  13. package/src/base-template/default-base-template.d.ts +91 -0
  14. package/src/base-template/default-base-template.js +435 -0
  15. package/src/base-template/default-base-template.js.map +1 -0
  16. package/src/base-template/index.d.ts +14 -0
  17. package/src/base-template/index.js +30 -0
  18. package/src/base-template/index.js.map +1 -0
  19. package/src/base-template/polyfills.d.ts +30 -0
  20. package/src/base-template/polyfills.js +190 -0
  21. package/src/base-template/polyfills.js.map +1 -0
  22. package/src/base-template/theme-styles.d.ts +73 -0
  23. package/src/base-template/theme-styles.js +95 -0
  24. package/src/base-template/theme-styles.js.map +1 -0
  25. package/src/bridge/adapters/base-adapter.d.ts +103 -0
  26. package/src/bridge/adapters/base-adapter.js +314 -0
  27. package/src/bridge/adapters/base-adapter.js.map +1 -0
  28. package/src/bridge/adapters/claude.adapter.d.ts +66 -0
  29. package/src/bridge/adapters/claude.adapter.js +145 -0
  30. package/src/bridge/adapters/claude.adapter.js.map +1 -0
  31. package/src/bridge/adapters/ext-apps.adapter.d.ts +142 -0
  32. package/src/bridge/adapters/ext-apps.adapter.js +416 -0
  33. package/src/bridge/adapters/ext-apps.adapter.js.map +1 -0
  34. package/src/bridge/adapters/gemini.adapter.d.ts +63 -0
  35. package/src/bridge/adapters/gemini.adapter.js +160 -0
  36. package/src/bridge/adapters/gemini.adapter.js.map +1 -0
  37. package/src/bridge/adapters/generic.adapter.d.ts +55 -0
  38. package/src/bridge/adapters/generic.adapter.js +108 -0
  39. package/src/bridge/adapters/generic.adapter.js.map +1 -0
  40. package/src/bridge/adapters/index.d.ts +25 -0
  41. package/src/bridge/adapters/index.js +65 -0
  42. package/src/bridge/adapters/index.js.map +1 -0
  43. package/src/bridge/adapters/openai.adapter.d.ts +64 -0
  44. package/src/bridge/adapters/openai.adapter.js +194 -0
  45. package/src/bridge/adapters/openai.adapter.js.map +1 -0
  46. package/src/bridge/core/adapter-registry.d.ts +121 -0
  47. package/src/bridge/core/adapter-registry.js +271 -0
  48. package/src/bridge/core/adapter-registry.js.map +1 -0
  49. package/src/bridge/core/bridge-factory.d.ts +198 -0
  50. package/src/bridge/core/bridge-factory.js +428 -0
  51. package/src/bridge/core/bridge-factory.js.map +1 -0
  52. package/src/bridge/core/index.d.ts +9 -0
  53. package/src/bridge/core/index.js +22 -0
  54. package/src/bridge/core/index.js.map +1 -0
  55. package/src/bridge/index.d.ts +61 -0
  56. package/src/bridge/index.js +94 -0
  57. package/src/bridge/index.js.map +1 -0
  58. package/src/bridge/runtime/iife-generator.d.ts +61 -0
  59. package/src/bridge/runtime/iife-generator.js +940 -0
  60. package/src/bridge/runtime/iife-generator.js.map +1 -0
  61. package/src/bridge/runtime/index.d.ts +8 -0
  62. package/src/bridge/runtime/index.js +16 -0
  63. package/src/bridge/runtime/index.js.map +1 -0
  64. package/src/bridge/types.d.ts +385 -0
  65. package/src/bridge/types.js +11 -0
  66. package/src/bridge/types.js.map +1 -0
  67. package/src/build/cdn-resources.d.ts +140 -0
  68. package/src/build/cdn-resources.js +314 -0
  69. package/src/build/cdn-resources.js.map +1 -0
  70. package/src/build/index.d.ts +294 -0
  71. package/src/build/index.js +325 -0
  72. package/src/build/index.js.map +1 -0
  73. package/src/build/widget-manifest.d.ts +212 -0
  74. package/src/build/widget-manifest.js +652 -0
  75. package/src/build/widget-manifest.js.map +1 -0
  76. package/src/bundler/bundler.d.ts +110 -0
  77. package/src/bundler/bundler.js +432 -0
  78. package/src/bundler/bundler.js.map +1 -0
  79. package/src/bundler/cache.d.ts +172 -0
  80. package/src/bundler/cache.js +250 -0
  81. package/src/bundler/cache.js.map +1 -0
  82. package/src/bundler/index.d.ts +41 -0
  83. package/src/bundler/index.js +73 -0
  84. package/src/bundler/index.js.map +1 -0
  85. package/src/bundler/sandbox/enclave-adapter.d.ts +120 -0
  86. package/src/bundler/sandbox/enclave-adapter.js +339 -0
  87. package/src/bundler/sandbox/enclave-adapter.js.map +1 -0
  88. package/src/bundler/sandbox/executor.d.ts +13 -0
  89. package/src/bundler/sandbox/executor.js +22 -0
  90. package/src/bundler/sandbox/executor.js.map +1 -0
  91. package/src/bundler/sandbox/policy.d.ts +61 -0
  92. package/src/bundler/sandbox/policy.js +238 -0
  93. package/src/bundler/sandbox/policy.js.map +1 -0
  94. package/src/bundler/types.d.ts +347 -0
  95. package/src/bundler/types.js +132 -0
  96. package/src/bundler/types.js.map +1 -0
  97. package/src/components/alert.d.ts +71 -0
  98. package/src/components/alert.js +189 -0
  99. package/src/components/alert.js.map +1 -0
  100. package/src/components/alert.schema.d.ts +114 -0
  101. package/src/components/alert.schema.js +105 -0
  102. package/src/components/alert.schema.js.map +1 -0
  103. package/src/components/avatar.d.ts +76 -0
  104. package/src/components/avatar.js +176 -0
  105. package/src/components/avatar.js.map +1 -0
  106. package/src/components/avatar.schema.d.ts +169 -0
  107. package/src/components/avatar.schema.js +103 -0
  108. package/src/components/avatar.schema.js.map +1 -0
  109. package/src/components/badge.d.ts +70 -0
  110. package/src/components/badge.js +149 -0
  111. package/src/components/badge.js.map +1 -0
  112. package/src/components/badge.schema.d.ts +109 -0
  113. package/src/components/badge.schema.js +96 -0
  114. package/src/components/badge.schema.js.map +1 -0
  115. package/src/components/button.d.ts +111 -0
  116. package/src/components/button.js +336 -0
  117. package/src/components/button.js.map +1 -0
  118. package/src/components/button.schema.d.ts +148 -0
  119. package/src/components/button.schema.js +121 -0
  120. package/src/components/button.schema.js.map +1 -0
  121. package/src/components/card.d.ts +60 -0
  122. package/src/components/card.js +117 -0
  123. package/src/components/card.js.map +1 -0
  124. package/src/components/card.schema.d.ts +113 -0
  125. package/src/components/card.schema.js +98 -0
  126. package/src/components/card.schema.js.map +1 -0
  127. package/src/components/form.d.ts +239 -0
  128. package/src/components/form.js +420 -0
  129. package/src/components/form.js.map +1 -0
  130. package/src/components/form.schema.d.ts +441 -0
  131. package/src/components/form.schema.js +406 -0
  132. package/src/components/form.schema.js.map +1 -0
  133. package/src/components/index.d.ts +29 -0
  134. package/src/components/index.js +98 -0
  135. package/src/components/index.js.map +1 -0
  136. package/src/components/list.d.ts +127 -0
  137. package/src/components/list.js +279 -0
  138. package/src/components/list.js.map +1 -0
  139. package/src/components/list.schema.d.ts +134 -0
  140. package/src/components/list.schema.js +168 -0
  141. package/src/components/list.schema.js.map +1 -0
  142. package/src/components/modal.d.ts +111 -0
  143. package/src/components/modal.js +260 -0
  144. package/src/components/modal.js.map +1 -0
  145. package/src/components/modal.schema.d.ts +186 -0
  146. package/src/components/modal.schema.js +167 -0
  147. package/src/components/modal.schema.js.map +1 -0
  148. package/src/components/table.d.ts +105 -0
  149. package/src/components/table.js +283 -0
  150. package/src/components/table.js.map +1 -0
  151. package/src/components/table.schema.d.ts +159 -0
  152. package/src/components/table.schema.js +173 -0
  153. package/src/components/table.schema.js.map +1 -0
  154. package/src/handlebars/helpers.d.ts +348 -0
  155. package/src/handlebars/helpers.js +605 -0
  156. package/src/handlebars/helpers.js.map +1 -0
  157. package/src/handlebars/index.d.ts +193 -0
  158. package/src/handlebars/index.js +350 -0
  159. package/src/handlebars/index.js.map +1 -0
  160. package/src/index.d.ts +50 -0
  161. package/src/index.js +192 -0
  162. package/src/index.js.map +1 -0
  163. package/src/layouts/base.d.ts +88 -0
  164. package/src/layouts/base.js +227 -0
  165. package/src/layouts/base.js.map +1 -0
  166. package/src/layouts/index.d.ts +7 -0
  167. package/src/layouts/index.js +25 -0
  168. package/src/layouts/index.js.map +1 -0
  169. package/src/layouts/presets.d.ts +133 -0
  170. package/src/layouts/presets.js +277 -0
  171. package/src/layouts/presets.js.map +1 -0
  172. package/src/pages/consent.d.ts +116 -0
  173. package/src/pages/consent.js +218 -0
  174. package/src/pages/consent.js.map +1 -0
  175. package/src/pages/error.d.ts +100 -0
  176. package/src/pages/error.js +263 -0
  177. package/src/pages/error.js.map +1 -0
  178. package/src/pages/index.d.ts +8 -0
  179. package/src/pages/index.js +27 -0
  180. package/src/pages/index.js.map +1 -0
  181. package/src/react/Alert.d.ts +101 -0
  182. package/src/react/Alert.js +51 -0
  183. package/src/react/Alert.js.map +1 -0
  184. package/src/react/Badge.d.ts +100 -0
  185. package/src/react/Badge.js +55 -0
  186. package/src/react/Badge.js.map +1 -0
  187. package/src/react/Button.d.ts +108 -0
  188. package/src/react/Button.js +52 -0
  189. package/src/react/Button.js.map +1 -0
  190. package/src/react/Card.d.ts +103 -0
  191. package/src/react/Card.js +55 -0
  192. package/src/react/Card.js.map +1 -0
  193. package/src/react/hooks/context.d.ts +178 -0
  194. package/src/react/hooks/context.js +287 -0
  195. package/src/react/hooks/context.js.map +1 -0
  196. package/src/react/hooks/index.d.ts +41 -0
  197. package/src/react/hooks/index.js +61 -0
  198. package/src/react/hooks/index.js.map +1 -0
  199. package/src/react/hooks/tools.d.ts +283 -0
  200. package/src/react/hooks/tools.js +465 -0
  201. package/src/react/hooks/tools.js.map +1 -0
  202. package/src/react/index.d.ts +80 -0
  203. package/src/react/index.js +113 -0
  204. package/src/react/index.js.map +1 -0
  205. package/src/react/types.d.ts +105 -0
  206. package/src/react/types.js +12 -0
  207. package/src/react/types.js.map +1 -0
  208. package/src/react/utils.d.ts +42 -0
  209. package/src/react/utils.js +99 -0
  210. package/src/react/utils.js.map +1 -0
  211. package/src/registry/index.d.ts +45 -0
  212. package/src/registry/index.js +67 -0
  213. package/src/registry/index.js.map +1 -0
  214. package/src/registry/render-template.d.ts +86 -0
  215. package/src/registry/render-template.js +239 -0
  216. package/src/registry/render-template.js.map +1 -0
  217. package/src/registry/tool-ui.registry.d.ts +260 -0
  218. package/src/registry/tool-ui.registry.js +438 -0
  219. package/src/registry/tool-ui.registry.js.map +1 -0
  220. package/src/registry/uri-utils.d.ts +55 -0
  221. package/src/registry/uri-utils.js +97 -0
  222. package/src/registry/uri-utils.js.map +1 -0
  223. package/src/render/index.d.ts +7 -0
  224. package/src/render/index.js +14 -0
  225. package/src/render/index.js.map +1 -0
  226. package/src/render/prerender.d.ts +56 -0
  227. package/src/render/prerender.js +98 -0
  228. package/src/render/prerender.js.map +1 -0
  229. package/src/renderers/cache.d.ts +144 -0
  230. package/src/renderers/cache.js +240 -0
  231. package/src/renderers/cache.js.map +1 -0
  232. package/src/renderers/html.renderer.d.ts +122 -0
  233. package/src/renderers/html.renderer.js +204 -0
  234. package/src/renderers/html.renderer.js.map +1 -0
  235. package/src/renderers/index.d.ts +35 -0
  236. package/src/renderers/index.js +70 -0
  237. package/src/renderers/index.js.map +1 -0
  238. package/src/renderers/mdx.renderer.d.ts +119 -0
  239. package/src/renderers/mdx.renderer.js +305 -0
  240. package/src/renderers/mdx.renderer.js.map +1 -0
  241. package/src/renderers/react.renderer.d.ts +95 -0
  242. package/src/renderers/react.renderer.js +260 -0
  243. package/src/renderers/react.renderer.js.map +1 -0
  244. package/src/renderers/registry.d.ts +133 -0
  245. package/src/renderers/registry.js +232 -0
  246. package/src/renderers/registry.js.map +1 -0
  247. package/src/renderers/types.d.ts +341 -0
  248. package/src/renderers/types.js +9 -0
  249. package/src/renderers/types.js.map +1 -0
  250. package/src/renderers/utils/detect.d.ts +106 -0
  251. package/src/renderers/utils/detect.js +267 -0
  252. package/src/renderers/utils/detect.js.map +1 -0
  253. package/src/renderers/utils/hash.d.ts +39 -0
  254. package/src/renderers/utils/hash.js +75 -0
  255. package/src/renderers/utils/hash.js.map +1 -0
  256. package/src/renderers/utils/index.d.ts +8 -0
  257. package/src/renderers/utils/index.js +28 -0
  258. package/src/renderers/utils/index.js.map +1 -0
  259. package/src/renderers/utils/transpiler.d.ts +88 -0
  260. package/src/renderers/utils/transpiler.js +215 -0
  261. package/src/renderers/utils/transpiler.js.map +1 -0
  262. package/src/runtime/adapters/html.adapter.d.ts +58 -0
  263. package/src/runtime/adapters/html.adapter.js +131 -0
  264. package/src/runtime/adapters/html.adapter.js.map +1 -0
  265. package/src/runtime/adapters/index.d.ts +25 -0
  266. package/src/runtime/adapters/index.js +54 -0
  267. package/src/runtime/adapters/index.js.map +1 -0
  268. package/src/runtime/adapters/mdx.adapter.d.ts +72 -0
  269. package/src/runtime/adapters/mdx.adapter.js +241 -0
  270. package/src/runtime/adapters/mdx.adapter.js.map +1 -0
  271. package/src/runtime/adapters/react.adapter.d.ts +69 -0
  272. package/src/runtime/adapters/react.adapter.js +245 -0
  273. package/src/runtime/adapters/react.adapter.js.map +1 -0
  274. package/src/runtime/adapters/types.d.ts +94 -0
  275. package/src/runtime/adapters/types.js +11 -0
  276. package/src/runtime/adapters/types.js.map +1 -0
  277. package/src/runtime/csp.d.ts +37 -0
  278. package/src/runtime/csp.js +140 -0
  279. package/src/runtime/csp.js.map +1 -0
  280. package/src/runtime/index.d.ts +16 -0
  281. package/src/runtime/index.js +72 -0
  282. package/src/runtime/index.js.map +1 -0
  283. package/src/runtime/mcp-bridge.d.ts +100 -0
  284. package/src/runtime/mcp-bridge.js +581 -0
  285. package/src/runtime/mcp-bridge.js.map +1 -0
  286. package/src/runtime/renderer-runtime.d.ts +132 -0
  287. package/src/runtime/renderer-runtime.js +389 -0
  288. package/src/runtime/renderer-runtime.js.map +1 -0
  289. package/src/runtime/sanitizer.d.ts +171 -0
  290. package/src/runtime/sanitizer.js +318 -0
  291. package/src/runtime/sanitizer.js.map +1 -0
  292. package/src/runtime/types.d.ts +414 -0
  293. package/src/runtime/types.js +12 -0
  294. package/src/runtime/types.js.map +1 -0
  295. package/src/runtime/wrapper.d.ts +375 -0
  296. package/src/runtime/wrapper.js +1793 -0
  297. package/src/runtime/wrapper.js.map +1 -0
  298. package/src/styles/index.d.ts +7 -0
  299. package/src/styles/index.js +11 -0
  300. package/src/styles/index.js.map +1 -0
  301. package/src/styles/variants.d.ts +50 -0
  302. package/src/styles/variants.js +175 -0
  303. package/src/styles/variants.js.map +1 -0
  304. package/src/theme/cdn.d.ts +194 -0
  305. package/src/theme/cdn.js +375 -0
  306. package/src/theme/cdn.js.map +1 -0
  307. package/src/theme/index.d.ts +17 -0
  308. package/src/theme/index.js +57 -0
  309. package/src/theme/index.js.map +1 -0
  310. package/src/theme/platforms.d.ts +106 -0
  311. package/src/theme/platforms.js +161 -0
  312. package/src/theme/platforms.js.map +1 -0
  313. package/src/theme/presets/github-openai.d.ts +49 -0
  314. package/src/theme/presets/github-openai.js +189 -0
  315. package/src/theme/presets/github-openai.js.map +1 -0
  316. package/src/theme/presets/index.d.ts +10 -0
  317. package/src/theme/presets/index.js +17 -0
  318. package/src/theme/presets/index.js.map +1 -0
  319. package/src/theme/theme.d.ts +395 -0
  320. package/src/theme/theme.js +332 -0
  321. package/src/theme/theme.js.map +1 -0
  322. package/src/tool-template/builder.d.ts +212 -0
  323. package/src/tool-template/builder.js +397 -0
  324. package/src/tool-template/builder.js.map +1 -0
  325. package/src/tool-template/index.d.ts +15 -0
  326. package/src/tool-template/index.js +38 -0
  327. package/src/tool-template/index.js.map +1 -0
  328. package/src/types/index.d.ts +13 -0
  329. package/src/types/index.js +26 -0
  330. package/src/types/index.js.map +1 -0
  331. package/src/types/ui-config.d.ts +357 -0
  332. package/src/types/ui-config.js +12 -0
  333. package/src/types/ui-config.js.map +1 -0
  334. package/src/types/ui-runtime.d.ts +965 -0
  335. package/src/types/ui-runtime.js +117 -0
  336. package/src/types/ui-runtime.js.map +1 -0
  337. package/src/validation/error-box.d.ts +55 -0
  338. package/src/validation/error-box.js +75 -0
  339. package/src/validation/error-box.js.map +1 -0
  340. package/src/validation/index.d.ts +12 -0
  341. package/src/validation/index.js +21 -0
  342. package/src/validation/index.js.map +1 -0
  343. package/src/validation/wrapper.d.ts +96 -0
  344. package/src/validation/wrapper.js +117 -0
  345. package/src/validation/wrapper.js.map +1 -0
  346. package/src/web-components/core/attribute-parser.d.ts +85 -0
  347. package/src/web-components/core/attribute-parser.js +189 -0
  348. package/src/web-components/core/attribute-parser.js.map +1 -0
  349. package/src/web-components/core/base-element.d.ts +197 -0
  350. package/src/web-components/core/base-element.js +289 -0
  351. package/src/web-components/core/base-element.js.map +1 -0
  352. package/src/web-components/core/index.d.ts +8 -0
  353. package/src/web-components/core/index.js +18 -0
  354. package/src/web-components/core/index.js.map +1 -0
  355. package/src/web-components/elements/fmcp-alert.d.ts +45 -0
  356. package/src/web-components/elements/fmcp-alert.js +93 -0
  357. package/src/web-components/elements/fmcp-alert.js.map +1 -0
  358. package/src/web-components/elements/fmcp-badge.d.ts +46 -0
  359. package/src/web-components/elements/fmcp-badge.js +99 -0
  360. package/src/web-components/elements/fmcp-badge.js.map +1 -0
  361. package/src/web-components/elements/fmcp-button.d.ts +124 -0
  362. package/src/web-components/elements/fmcp-button.js +233 -0
  363. package/src/web-components/elements/fmcp-button.js.map +1 -0
  364. package/src/web-components/elements/fmcp-card.d.ts +52 -0
  365. package/src/web-components/elements/fmcp-card.js +115 -0
  366. package/src/web-components/elements/fmcp-card.js.map +1 -0
  367. package/src/web-components/elements/fmcp-input.d.ts +95 -0
  368. package/src/web-components/elements/fmcp-input.js +248 -0
  369. package/src/web-components/elements/fmcp-input.js.map +1 -0
  370. package/src/web-components/elements/fmcp-select.d.ts +99 -0
  371. package/src/web-components/elements/fmcp-select.js +243 -0
  372. package/src/web-components/elements/fmcp-select.js.map +1 -0
  373. package/src/web-components/elements/index.d.ts +12 -0
  374. package/src/web-components/elements/index.js +34 -0
  375. package/src/web-components/elements/index.js.map +1 -0
  376. package/src/web-components/index.d.ts +49 -0
  377. package/src/web-components/index.js +75 -0
  378. package/src/web-components/index.js.map +1 -0
  379. package/src/web-components/register.d.ts +56 -0
  380. package/src/web-components/register.js +80 -0
  381. package/src/web-components/register.js.map +1 -0
  382. package/src/web-components/types.d.ts +121 -0
  383. package/src/web-components/types.js +25 -0
  384. package/src/web-components/types.js.map +1 -0
  385. package/src/widgets/index.d.ts +7 -0
  386. package/src/widgets/index.js +24 -0
  387. package/src/widgets/index.js.map +1 -0
  388. package/src/widgets/progress.d.ts +132 -0
  389. package/src/widgets/progress.js +303 -0
  390. package/src/widgets/progress.js.map +1 -0
  391. package/src/widgets/resource.d.ts +162 -0
  392. package/src/widgets/resource.js +340 -0
  393. package/src/widgets/resource.js.map +1 -0
@@ -0,0 +1,218 @@
1
+ "use strict";
2
+ /**
3
+ * OAuth Consent Page Template
4
+ *
5
+ * OAuth/OpenID Connect consent page for authorization flows.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.consentPage = consentPage;
9
+ exports.consentSuccessPage = consentSuccessPage;
10
+ exports.consentDeniedPage = consentDeniedPage;
11
+ const layouts_1 = require("../layouts");
12
+ const button_1 = require("../components/button");
13
+ const list_1 = require("../components/list");
14
+ const form_1 = require("../components/form");
15
+ const alert_1 = require("../components/alert");
16
+ const base_1 = require("../layouts/base");
17
+ // ============================================
18
+ // Consent Page Builder
19
+ // ============================================
20
+ /**
21
+ * Build an OAuth consent page
22
+ */
23
+ function consentPage(options) {
24
+ const { client, user, permissions, approveUrl, denyUrl, csrfToken, state, redirectUri, responseType, nonce, codeChallenge, codeChallengeMethod, error, layout = {}, warningMessage, allowScopeSelection = false, approveText = 'Allow', denyText = 'Deny', } = options;
25
+ // Error alert
26
+ const errorAlert = error ? (0, alert_1.alert)(error, { variant: 'danger', dismissible: true }) : '';
27
+ // Warning for unverified apps
28
+ const unverifiedWarning = !client.verified
29
+ ? (0, alert_1.alert)(warningMessage || 'This application has not been verified. Only authorize applications you trust.', {
30
+ variant: 'warning',
31
+ title: 'Unverified Application',
32
+ })
33
+ : '';
34
+ // Client header
35
+ const clientHeader = `
36
+ <div class="text-center mb-6">
37
+ ${client.icon
38
+ ? `<img src="${(0, base_1.escapeHtml)(client.icon)}" alt="${(0, base_1.escapeHtml)(client.name)}" class="w-16 h-16 rounded-xl mx-auto mb-4 shadow-md">`
39
+ : `<div class="inline-flex items-center justify-center w-16 h-16 rounded-xl bg-gradient-to-br from-primary to-secondary text-white font-bold text-2xl mx-auto mb-4 shadow-md">
40
+ ${(0, base_1.escapeHtml)(client.name.charAt(0).toUpperCase())}
41
+ </div>`}
42
+ <h1 class="text-xl font-bold text-text-primary">
43
+ ${client.verified
44
+ ? `<span class="inline-flex items-center gap-1">
45
+ ${(0, base_1.escapeHtml)(client.name)}
46
+ <svg class="w-5 h-5 text-primary" fill="currentColor" viewBox="0 0 20 20">
47
+ <path fill-rule="evenodd" d="M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"/>
48
+ </svg>
49
+ </span>`
50
+ : (0, base_1.escapeHtml)(client.name)}
51
+ </h1>
52
+ <p class="text-text-secondary mt-1">wants to access your account</p>
53
+ </div>
54
+ `;
55
+ // User info section
56
+ const userSection = user
57
+ ? `
58
+ <div class="flex items-center gap-3 p-4 bg-gray-50 rounded-lg mb-6">
59
+ ${user.avatar
60
+ ? `<img src="${(0, base_1.escapeHtml)(user.avatar)}" class="w-12 h-12 rounded-full">`
61
+ : `<div class="w-12 h-12 rounded-full bg-primary text-white flex items-center justify-center font-semibold text-lg">
62
+ ${(0, base_1.escapeHtml)((user.name || user.email || 'U').charAt(0).toUpperCase())}
63
+ </div>`}
64
+ <div class="flex-1 min-w-0">
65
+ ${user.name ? `<div class="font-medium text-text-primary truncate">${(0, base_1.escapeHtml)(user.name)}</div>` : ''}
66
+ ${user.email ? `<div class="text-sm text-text-secondary truncate">${(0, base_1.escapeHtml)(user.email)}</div>` : ''}
67
+ </div>
68
+ <a href="/login?prompt=select_account" class="text-sm text-primary hover:text-primary/80">
69
+ Switch account
70
+ </a>
71
+ </div>
72
+ `
73
+ : '';
74
+ // Permissions section
75
+ const permissionsSection = `
76
+ <div class="mb-6">
77
+ <h3 class="font-medium text-text-primary mb-3">This will allow ${(0, base_1.escapeHtml)(client.name)} to:</h3>
78
+ ${(0, list_1.permissionList)(permissions, {
79
+ checkable: allowScopeSelection,
80
+ inputName: 'scope',
81
+ })}
82
+ </div>
83
+ `;
84
+ // Hidden form fields
85
+ const hiddenFields = [
86
+ csrfToken ? (0, form_1.csrfInput)(csrfToken) : '',
87
+ state ? (0, form_1.hiddenInput)('state', state) : '',
88
+ redirectUri ? (0, form_1.hiddenInput)('redirect_uri', redirectUri) : '',
89
+ responseType ? (0, form_1.hiddenInput)('response_type', responseType) : '',
90
+ nonce ? (0, form_1.hiddenInput)('nonce', nonce) : '',
91
+ codeChallenge ? (0, form_1.hiddenInput)('code_challenge', codeChallenge) : '',
92
+ codeChallengeMethod ? (0, form_1.hiddenInput)('code_challenge_method', codeChallengeMethod) : '',
93
+ (0, form_1.hiddenInput)('client_id', client.clientId),
94
+ // Include all scopes if not selectable
95
+ !allowScopeSelection ? permissions.map((p) => (0, form_1.hiddenInput)('scope[]', p.scope)).join('\n') : '',
96
+ ]
97
+ .filter(Boolean)
98
+ .join('\n');
99
+ // Action buttons
100
+ const actionsHtml = `
101
+ <div class="flex gap-3 pt-4">
102
+ <form action="${(0, base_1.escapeHtml)(denyUrl || approveUrl)}" method="post" class="flex-1">
103
+ ${hiddenFields}
104
+ <input type="hidden" name="action" value="deny">
105
+ ${(0, button_1.outlineButton)(denyText, { type: 'submit', fullWidth: true })}
106
+ </form>
107
+ <form action="${(0, base_1.escapeHtml)(approveUrl)}" method="post" class="flex-1">
108
+ ${hiddenFields}
109
+ <input type="hidden" name="action" value="approve">
110
+ ${(0, button_1.primaryButton)(approveText, { type: 'submit', fullWidth: true })}
111
+ </form>
112
+ </div>
113
+ `;
114
+ // Privacy/Terms links
115
+ const linksHtml = client.privacyUrl || client.termsUrl || client.websiteUrl
116
+ ? `
117
+ <div class="text-center text-xs text-text-secondary mt-6 space-x-3">
118
+ ${client.websiteUrl
119
+ ? `<a href="${(0, base_1.escapeHtml)(client.websiteUrl)}" target="_blank" rel="noopener" class="hover:text-primary">Website</a>`
120
+ : ''}
121
+ ${client.privacyUrl
122
+ ? `<a href="${(0, base_1.escapeHtml)(client.privacyUrl)}" target="_blank" rel="noopener" class="hover:text-primary">Privacy Policy</a>`
123
+ : ''}
124
+ ${client.termsUrl
125
+ ? `<a href="${(0, base_1.escapeHtml)(client.termsUrl)}" target="_blank" rel="noopener" class="hover:text-primary">Terms of Service</a>`
126
+ : ''}
127
+ </div>
128
+ `
129
+ : '';
130
+ // Combine all content
131
+ const content = `
132
+ ${errorAlert}
133
+ ${unverifiedWarning}
134
+ ${clientHeader}
135
+ ${userSection}
136
+ ${permissionsSection}
137
+ ${actionsHtml}
138
+ ${linksHtml}
139
+ `;
140
+ return (0, layouts_1.consentLayout)(content, {
141
+ title: `Authorize ${client.name}`,
142
+ clientName: client.name,
143
+ clientIcon: client.icon,
144
+ userInfo: user,
145
+ ...layout,
146
+ });
147
+ }
148
+ /**
149
+ * Build a consent success page
150
+ */
151
+ function consentSuccessPage(options) {
152
+ const { client, redirectUrl, autoRedirectDelay = 3000, layout = {} } = options;
153
+ const redirectScript = redirectUrl && autoRedirectDelay > 0
154
+ ? `
155
+ <script>
156
+ setTimeout(() => {
157
+ window.location.href = '${(0, base_1.escapeHtml)(redirectUrl)}';
158
+ }, ${autoRedirectDelay});
159
+ </script>
160
+ `
161
+ : '';
162
+ const content = `
163
+ <div class="text-center">
164
+ <div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-success/10 mb-6">
165
+ <svg class="w-8 h-8 text-success" fill="none" stroke="currentColor" viewBox="0 0 24 24">
166
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"/>
167
+ </svg>
168
+ </div>
169
+ <h1 class="text-2xl font-bold text-text-primary mb-2">Authorization Successful</h1>
170
+ <p class="text-text-secondary mb-4">
171
+ You have authorized <strong>${(0, base_1.escapeHtml)(client.name)}</strong> to access your account.
172
+ </p>
173
+ ${redirectUrl
174
+ ? `<p class="text-sm text-text-secondary">Redirecting you back to ${(0, base_1.escapeHtml)(client.name)}...</p>`
175
+ : ''}
176
+ </div>
177
+ ${redirectScript}
178
+ `;
179
+ return (0, layouts_1.consentLayout)(content, {
180
+ title: 'Authorization Successful',
181
+ clientName: client.name,
182
+ clientIcon: client.icon,
183
+ ...layout,
184
+ });
185
+ }
186
+ /**
187
+ * Build a consent denied page
188
+ */
189
+ function consentDeniedPage(options) {
190
+ const { client, redirectUrl, layout = {} } = options;
191
+ const content = `
192
+ <div class="text-center">
193
+ <div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-gray-100 mb-6">
194
+ <svg class="w-8 h-8 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
195
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"/>
196
+ </svg>
197
+ </div>
198
+ <h1 class="text-2xl font-bold text-text-primary mb-2">Authorization Denied</h1>
199
+ <p class="text-text-secondary mb-6">
200
+ You denied <strong>${(0, base_1.escapeHtml)(client.name)}</strong> access to your account.
201
+ </p>
202
+ ${redirectUrl
203
+ ? `
204
+ <a href="${(0, base_1.escapeHtml)(redirectUrl)}" class="inline-block px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors">
205
+ Return to ${(0, base_1.escapeHtml)(client.name)}
206
+ </a>
207
+ `
208
+ : ''}
209
+ </div>
210
+ `;
211
+ return (0, layouts_1.consentLayout)(content, {
212
+ title: 'Authorization Denied',
213
+ clientName: client.name,
214
+ clientIcon: client.icon,
215
+ ...layout,
216
+ });
217
+ }
218
+ //# sourceMappingURL=consent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"consent.js","sourceRoot":"","sources":["../../../src/pages/consent.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * OAuth Consent Page Template\n *\n * OAuth/OpenID Connect consent page for authorization flows.\n */\n\nimport { consentLayout, type ConsentLayoutOptions } from '../layouts';\nimport { primaryButton, outlineButton, dangerButton } from '../components/button';\nimport { permissionList, type PermissionItem } from '../components/list';\nimport { form, formActions, csrfInput, hiddenInput } from '../components/form';\nimport { alert } from '../components/alert';\nimport { escapeHtml } from '../layouts/base';\n\n// ============================================\n// Consent Page Types\n// ============================================\n\n/**\n * Client/Application information\n */\nexport interface ClientInfo {\n /** Client ID */\n clientId: string;\n /** Client name */\n name: string;\n /** Client icon/logo URL */\n icon?: string;\n /** Client website URL */\n websiteUrl?: string;\n /** Privacy policy URL */\n privacyUrl?: string;\n /** Terms of service URL */\n termsUrl?: string;\n /** Verified client badge */\n verified?: boolean;\n}\n\n/**\n * User information\n */\nexport interface UserInfo {\n /** User ID */\n id?: string;\n /** User name */\n name?: string;\n /** User email */\n email?: string;\n /** Avatar URL */\n avatar?: string;\n}\n\n/**\n * Consent page options\n */\nexport interface ConsentPageOptions {\n /** Client/App requesting authorization */\n client: ClientInfo;\n /** Current user info */\n user?: UserInfo;\n /** Requested permissions/scopes */\n permissions: PermissionItem[];\n /** Form action URL for approval */\n approveUrl: string;\n /** Form action URL for denial (optional, uses approveUrl if not provided) */\n denyUrl?: string;\n /** CSRF token */\n csrfToken?: string;\n /** OAuth state parameter */\n state?: string;\n /** Redirect URI */\n redirectUri?: string;\n /** Response type */\n responseType?: string;\n /** Nonce */\n nonce?: string;\n /** Code challenge */\n codeChallenge?: string;\n /** Code challenge method */\n codeChallengeMethod?: string;\n /** Error message */\n error?: string;\n /** Layout options */\n layout?: Partial<ConsentLayoutOptions>;\n /** Custom warning message */\n warningMessage?: string;\n /** Allow partial scope selection */\n allowScopeSelection?: boolean;\n /** Custom approve button text */\n approveText?: string;\n /** Custom deny button text */\n denyText?: string;\n}\n\n// ============================================\n// Consent Page Builder\n// ============================================\n\n/**\n * Build an OAuth consent page\n */\nexport function consentPage(options: ConsentPageOptions): string {\n const {\n client,\n user,\n permissions,\n approveUrl,\n denyUrl,\n csrfToken,\n state,\n redirectUri,\n responseType,\n nonce,\n codeChallenge,\n codeChallengeMethod,\n error,\n layout = {},\n warningMessage,\n allowScopeSelection = false,\n approveText = 'Allow',\n denyText = 'Deny',\n } = options;\n\n // Error alert\n const errorAlert = error ? alert(error, { variant: 'danger', dismissible: true }) : '';\n\n // Warning for unverified apps\n const unverifiedWarning = !client.verified\n ? alert(warningMessage || 'This application has not been verified. Only authorize applications you trust.', {\n variant: 'warning',\n title: 'Unverified Application',\n })\n : '';\n\n // Client header\n const clientHeader = `\n <div class=\"text-center mb-6\">\n ${\n client.icon\n ? `<img src=\"${escapeHtml(client.icon)}\" alt=\"${escapeHtml(\n client.name,\n )}\" class=\"w-16 h-16 rounded-xl mx-auto mb-4 shadow-md\">`\n : `<div class=\"inline-flex items-center justify-center w-16 h-16 rounded-xl bg-gradient-to-br from-primary to-secondary text-white font-bold text-2xl mx-auto mb-4 shadow-md\">\n ${escapeHtml(client.name.charAt(0).toUpperCase())}\n </div>`\n }\n <h1 class=\"text-xl font-bold text-text-primary\">\n ${\n client.verified\n ? `<span class=\"inline-flex items-center gap-1\">\n ${escapeHtml(client.name)}\n <svg class=\"w-5 h-5 text-primary\" fill=\"currentColor\" viewBox=\"0 0 20 20\">\n <path fill-rule=\"evenodd\" d=\"M6.267 3.455a3.066 3.066 0 001.745-.723 3.066 3.066 0 013.976 0 3.066 3.066 0 001.745.723 3.066 3.066 0 012.812 2.812c.051.643.304 1.254.723 1.745a3.066 3.066 0 010 3.976 3.066 3.066 0 00-.723 1.745 3.066 3.066 0 01-2.812 2.812 3.066 3.066 0 00-1.745.723 3.066 3.066 0 01-3.976 0 3.066 3.066 0 00-1.745-.723 3.066 3.066 0 01-2.812-2.812 3.066 3.066 0 00-.723-1.745 3.066 3.066 0 010-3.976 3.066 3.066 0 00.723-1.745 3.066 3.066 0 012.812-2.812zm7.44 5.252a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z\" clip-rule=\"evenodd\"/>\n </svg>\n </span>`\n : escapeHtml(client.name)\n }\n </h1>\n <p class=\"text-text-secondary mt-1\">wants to access your account</p>\n </div>\n `;\n\n // User info section\n const userSection = user\n ? `\n <div class=\"flex items-center gap-3 p-4 bg-gray-50 rounded-lg mb-6\">\n ${\n user.avatar\n ? `<img src=\"${escapeHtml(user.avatar)}\" class=\"w-12 h-12 rounded-full\">`\n : `<div class=\"w-12 h-12 rounded-full bg-primary text-white flex items-center justify-center font-semibold text-lg\">\n ${escapeHtml((user.name || user.email || 'U').charAt(0).toUpperCase())}\n </div>`\n }\n <div class=\"flex-1 min-w-0\">\n ${user.name ? `<div class=\"font-medium text-text-primary truncate\">${escapeHtml(user.name)}</div>` : ''}\n ${user.email ? `<div class=\"text-sm text-text-secondary truncate\">${escapeHtml(user.email)}</div>` : ''}\n </div>\n <a href=\"/login?prompt=select_account\" class=\"text-sm text-primary hover:text-primary/80\">\n Switch account\n </a>\n </div>\n `\n : '';\n\n // Permissions section\n const permissionsSection = `\n <div class=\"mb-6\">\n <h3 class=\"font-medium text-text-primary mb-3\">This will allow ${escapeHtml(client.name)} to:</h3>\n ${permissionList(permissions, {\n checkable: allowScopeSelection,\n inputName: 'scope',\n })}\n </div>\n `;\n\n // Hidden form fields\n const hiddenFields = [\n csrfToken ? csrfInput(csrfToken) : '',\n state ? hiddenInput('state', state) : '',\n redirectUri ? hiddenInput('redirect_uri', redirectUri) : '',\n responseType ? hiddenInput('response_type', responseType) : '',\n nonce ? hiddenInput('nonce', nonce) : '',\n codeChallenge ? hiddenInput('code_challenge', codeChallenge) : '',\n codeChallengeMethod ? hiddenInput('code_challenge_method', codeChallengeMethod) : '',\n hiddenInput('client_id', client.clientId),\n // Include all scopes if not selectable\n !allowScopeSelection ? permissions.map((p) => hiddenInput('scope[]', p.scope)).join('\\n') : '',\n ]\n .filter(Boolean)\n .join('\\n');\n\n // Action buttons\n const actionsHtml = `\n <div class=\"flex gap-3 pt-4\">\n <form action=\"${escapeHtml(denyUrl || approveUrl)}\" method=\"post\" class=\"flex-1\">\n ${hiddenFields}\n <input type=\"hidden\" name=\"action\" value=\"deny\">\n ${outlineButton(denyText, { type: 'submit', fullWidth: true })}\n </form>\n <form action=\"${escapeHtml(approveUrl)}\" method=\"post\" class=\"flex-1\">\n ${hiddenFields}\n <input type=\"hidden\" name=\"action\" value=\"approve\">\n ${primaryButton(approveText, { type: 'submit', fullWidth: true })}\n </form>\n </div>\n `;\n\n // Privacy/Terms links\n const linksHtml =\n client.privacyUrl || client.termsUrl || client.websiteUrl\n ? `\n <div class=\"text-center text-xs text-text-secondary mt-6 space-x-3\">\n ${\n client.websiteUrl\n ? `<a href=\"${escapeHtml(\n client.websiteUrl,\n )}\" target=\"_blank\" rel=\"noopener\" class=\"hover:text-primary\">Website</a>`\n : ''\n }\n ${\n client.privacyUrl\n ? `<a href=\"${escapeHtml(\n client.privacyUrl,\n )}\" target=\"_blank\" rel=\"noopener\" class=\"hover:text-primary\">Privacy Policy</a>`\n : ''\n }\n ${\n client.termsUrl\n ? `<a href=\"${escapeHtml(\n client.termsUrl,\n )}\" target=\"_blank\" rel=\"noopener\" class=\"hover:text-primary\">Terms of Service</a>`\n : ''\n }\n </div>\n `\n : '';\n\n // Combine all content\n const content = `\n ${errorAlert}\n ${unverifiedWarning}\n ${clientHeader}\n ${userSection}\n ${permissionsSection}\n ${actionsHtml}\n ${linksHtml}\n `;\n\n return consentLayout(content, {\n title: `Authorize ${client.name}`,\n clientName: client.name,\n clientIcon: client.icon,\n userInfo: user,\n ...layout,\n });\n}\n\n// ============================================\n// Consent Success Page\n// ============================================\n\n/**\n * Consent success page options\n */\nexport interface ConsentSuccessOptions {\n /** Client info */\n client: ClientInfo;\n /** Redirect URL */\n redirectUrl?: string;\n /** Auto redirect delay (ms) */\n autoRedirectDelay?: number;\n /** Layout options */\n layout?: Partial<ConsentLayoutOptions>;\n}\n\n/**\n * Build a consent success page\n */\nexport function consentSuccessPage(options: ConsentSuccessOptions): string {\n const { client, redirectUrl, autoRedirectDelay = 3000, layout = {} } = options;\n\n const redirectScript =\n redirectUrl && autoRedirectDelay > 0\n ? `\n <script>\n setTimeout(() => {\n window.location.href = '${escapeHtml(redirectUrl)}';\n }, ${autoRedirectDelay});\n </script>\n `\n : '';\n\n const content = `\n <div class=\"text-center\">\n <div class=\"inline-flex items-center justify-center w-16 h-16 rounded-full bg-success/10 mb-6\">\n <svg class=\"w-8 h-8 text-success\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M5 13l4 4L19 7\"/>\n </svg>\n </div>\n <h1 class=\"text-2xl font-bold text-text-primary mb-2\">Authorization Successful</h1>\n <p class=\"text-text-secondary mb-4\">\n You have authorized <strong>${escapeHtml(client.name)}</strong> to access your account.\n </p>\n ${\n redirectUrl\n ? `<p class=\"text-sm text-text-secondary\">Redirecting you back to ${escapeHtml(client.name)}...</p>`\n : ''\n }\n </div>\n ${redirectScript}\n `;\n\n return consentLayout(content, {\n title: 'Authorization Successful',\n clientName: client.name,\n clientIcon: client.icon,\n ...layout,\n });\n}\n\n// ============================================\n// Consent Denied Page\n// ============================================\n\n/**\n * Consent denied page options\n */\nexport interface ConsentDeniedOptions {\n /** Client info */\n client: ClientInfo;\n /** Redirect URL */\n redirectUrl?: string;\n /** Layout options */\n layout?: Partial<ConsentLayoutOptions>;\n}\n\n/**\n * Build a consent denied page\n */\nexport function consentDeniedPage(options: ConsentDeniedOptions): string {\n const { client, redirectUrl, layout = {} } = options;\n\n const content = `\n <div class=\"text-center\">\n <div class=\"inline-flex items-center justify-center w-16 h-16 rounded-full bg-gray-100 mb-6\">\n <svg class=\"w-8 h-8 text-gray-500\" fill=\"none\" stroke=\"currentColor\" viewBox=\"0 0 24 24\">\n <path stroke-linecap=\"round\" stroke-linejoin=\"round\" stroke-width=\"2\" d=\"M6 18L18 6M6 6l12 12\"/>\n </svg>\n </div>\n <h1 class=\"text-2xl font-bold text-text-primary mb-2\">Authorization Denied</h1>\n <p class=\"text-text-secondary mb-6\">\n You denied <strong>${escapeHtml(client.name)}</strong> access to your account.\n </p>\n ${\n redirectUrl\n ? `\n <a href=\"${escapeHtml(\n redirectUrl,\n )}\" class=\"inline-block px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors\">\n Return to ${escapeHtml(client.name)}\n </a>\n `\n : ''\n }\n </div>\n `;\n\n return consentLayout(content, {\n title: 'Authorization Denied',\n clientName: client.name,\n clientIcon: client.icon,\n ...layout,\n });\n}\n"]}
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Error Page Templates
3
+ *
4
+ * Various error page templates (404, 500, etc.)
5
+ */
6
+ import { type ErrorLayoutOptions } from '../layouts';
7
+ /**
8
+ * Error page options
9
+ */
10
+ export interface ErrorPageOptions {
11
+ /** Error code (404, 500, etc.) */
12
+ code?: string | number;
13
+ /** Error title */
14
+ title?: string;
15
+ /** Error message */
16
+ message?: string;
17
+ /** Detailed error (for development) */
18
+ details?: string;
19
+ /** Show stack trace (development only) */
20
+ showStack?: boolean;
21
+ /** Stack trace */
22
+ stack?: string;
23
+ /** Show retry button */
24
+ showRetry?: boolean;
25
+ /** Retry URL */
26
+ retryUrl?: string;
27
+ /** Show home button */
28
+ showHome?: boolean;
29
+ /** Home URL */
30
+ homeUrl?: string;
31
+ /** Show back button */
32
+ showBack?: boolean;
33
+ /** Custom actions HTML */
34
+ actions?: string;
35
+ /** Layout options */
36
+ layout?: Partial<ErrorLayoutOptions>;
37
+ /** Request ID (for support) */
38
+ requestId?: string;
39
+ }
40
+ /**
41
+ * Build a generic error page
42
+ */
43
+ export declare function errorPage(options: ErrorPageOptions): string;
44
+ /**
45
+ * 404 Not Found page
46
+ */
47
+ export declare function notFoundPage(options?: Partial<ErrorPageOptions>): string;
48
+ /**
49
+ * 403 Forbidden page
50
+ */
51
+ export declare function forbiddenPage(options?: Partial<ErrorPageOptions>): string;
52
+ /**
53
+ * 401 Unauthorized page
54
+ */
55
+ export declare function unauthorizedPage(options?: Partial<ErrorPageOptions> & {
56
+ loginUrl?: string;
57
+ }): string;
58
+ /**
59
+ * 500 Internal Server Error page
60
+ */
61
+ export declare function serverErrorPage(options?: Partial<ErrorPageOptions>): string;
62
+ /**
63
+ * 503 Service Unavailable page
64
+ */
65
+ export declare function maintenancePage(options?: Partial<ErrorPageOptions> & {
66
+ estimatedTime?: string;
67
+ }): string;
68
+ /**
69
+ * 429 Rate Limit page
70
+ */
71
+ export declare function rateLimitPage(options?: Partial<ErrorPageOptions> & {
72
+ retryAfter?: number;
73
+ }): string;
74
+ /**
75
+ * Offline page
76
+ */
77
+ export declare function offlinePage(options?: Partial<ErrorPageOptions>): string;
78
+ /**
79
+ * Session expired page
80
+ */
81
+ export declare function sessionExpiredPage(options?: Partial<ErrorPageOptions> & {
82
+ loginUrl?: string;
83
+ }): string;
84
+ /**
85
+ * OAuth error page options
86
+ */
87
+ export interface OAuthErrorPageOptions extends Partial<ErrorPageOptions> {
88
+ /** OAuth error code */
89
+ errorCode?: string;
90
+ /** OAuth error description */
91
+ errorDescription?: string;
92
+ /** Redirect URI */
93
+ redirectUri?: string;
94
+ /** Client name */
95
+ clientName?: string;
96
+ }
97
+ /**
98
+ * OAuth error page
99
+ */
100
+ export declare function oauthErrorPage(options: OAuthErrorPageOptions): string;
@@ -0,0 +1,263 @@
1
+ "use strict";
2
+ /**
3
+ * Error Page Templates
4
+ *
5
+ * Various error page templates (404, 500, etc.)
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.errorPage = errorPage;
9
+ exports.notFoundPage = notFoundPage;
10
+ exports.forbiddenPage = forbiddenPage;
11
+ exports.unauthorizedPage = unauthorizedPage;
12
+ exports.serverErrorPage = serverErrorPage;
13
+ exports.maintenancePage = maintenancePage;
14
+ exports.rateLimitPage = rateLimitPage;
15
+ exports.offlinePage = offlinePage;
16
+ exports.sessionExpiredPage = sessionExpiredPage;
17
+ exports.oauthErrorPage = oauthErrorPage;
18
+ const layouts_1 = require("../layouts");
19
+ const base_1 = require("../layouts/base");
20
+ // ============================================
21
+ // Error Page Builder
22
+ // ============================================
23
+ /**
24
+ * Build a generic error page
25
+ */
26
+ function errorPage(options) {
27
+ const { code, title = 'Something went wrong', message, details, showStack = false, stack, showRetry = true, retryUrl, showHome = true, homeUrl = '/', showBack = false, actions, layout = {}, requestId, } = options;
28
+ // Details section (for development)
29
+ const detailsHtml = details || (showStack && stack)
30
+ ? `
31
+ <div class="mt-8 text-left">
32
+ ${details
33
+ ? `
34
+ <div class="p-4 bg-gray-50 rounded-lg text-sm text-text-secondary mb-4">
35
+ <strong class="text-text-primary">Details:</strong>
36
+ <p class="mt-1">${(0, base_1.escapeHtml)(details)}</p>
37
+ </div>
38
+ `
39
+ : ''}
40
+ ${showStack && stack
41
+ ? `
42
+ <details class="p-4 bg-gray-900 rounded-lg text-sm">
43
+ <summary class="text-gray-300 cursor-pointer hover:text-white">Stack Trace</summary>
44
+ <pre class="mt-2 text-xs text-gray-400 overflow-x-auto whitespace-pre-wrap">${(0, base_1.escapeHtml)(stack)}</pre>
45
+ </details>
46
+ `
47
+ : ''}
48
+ </div>
49
+ `
50
+ : '';
51
+ // Request ID for support
52
+ const requestIdHtml = requestId
53
+ ? `
54
+ <p class="text-xs text-text-secondary mt-6">
55
+ Request ID: <code class="px-1.5 py-0.5 bg-gray-100 rounded text-xs">${(0, base_1.escapeHtml)(requestId)}</code>
56
+ </p>
57
+ `
58
+ : '';
59
+ // Custom actions or default buttons are handled by errorLayout
60
+ const content = `
61
+ ${detailsHtml}
62
+ ${actions || ''}
63
+ ${requestIdHtml}
64
+ `;
65
+ return (0, layouts_1.errorLayout)(content, {
66
+ title: `${code ? `Error ${code} - ` : ''}${title}`,
67
+ errorCode: code?.toString(),
68
+ errorTitle: title,
69
+ errorMessage: message,
70
+ showRetry,
71
+ retryUrl,
72
+ showHome,
73
+ homeUrl,
74
+ ...layout,
75
+ });
76
+ }
77
+ // ============================================
78
+ // Specific Error Pages
79
+ // ============================================
80
+ /**
81
+ * 404 Not Found page
82
+ */
83
+ function notFoundPage(options = {}) {
84
+ return errorPage({
85
+ code: 404,
86
+ title: 'Page Not Found',
87
+ message: "The page you're looking for doesn't exist or has been moved.",
88
+ showRetry: false,
89
+ ...options,
90
+ });
91
+ }
92
+ /**
93
+ * 403 Forbidden page
94
+ */
95
+ function forbiddenPage(options = {}) {
96
+ return errorPage({
97
+ code: 403,
98
+ title: 'Access Denied',
99
+ message: "You don't have permission to access this resource.",
100
+ showRetry: false,
101
+ ...options,
102
+ });
103
+ }
104
+ /**
105
+ * 401 Unauthorized page
106
+ */
107
+ function unauthorizedPage(options = {}) {
108
+ const { loginUrl = '/login', ...rest } = options;
109
+ return errorPage({
110
+ code: 401,
111
+ title: 'Authentication Required',
112
+ message: 'Please sign in to access this resource.',
113
+ showRetry: false,
114
+ showHome: false,
115
+ actions: `
116
+ <div class="flex justify-center mt-8">
117
+ <a href="${(0, base_1.escapeHtml)(loginUrl)}" class="px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors">
118
+ Sign In
119
+ </a>
120
+ </div>
121
+ `,
122
+ ...rest,
123
+ });
124
+ }
125
+ /**
126
+ * 500 Internal Server Error page
127
+ */
128
+ function serverErrorPage(options = {}) {
129
+ return errorPage({
130
+ code: 500,
131
+ title: 'Server Error',
132
+ message: "We're having trouble processing your request. Please try again later.",
133
+ showRetry: true,
134
+ ...options,
135
+ });
136
+ }
137
+ /**
138
+ * 503 Service Unavailable page
139
+ */
140
+ function maintenancePage(options = {}) {
141
+ const { estimatedTime, ...rest } = options;
142
+ const timeMessage = estimatedTime
143
+ ? `We expect to be back by ${(0, base_1.escapeHtml)(estimatedTime)}.`
144
+ : "We'll be back shortly.";
145
+ return errorPage({
146
+ code: 503,
147
+ title: 'Under Maintenance',
148
+ message: `We're currently performing scheduled maintenance. ${timeMessage}`,
149
+ showRetry: true,
150
+ showHome: false,
151
+ ...rest,
152
+ });
153
+ }
154
+ /**
155
+ * 429 Rate Limit page
156
+ */
157
+ function rateLimitPage(options = {}) {
158
+ const { retryAfter, ...rest } = options;
159
+ const retryMessage = retryAfter
160
+ ? `Please wait ${retryAfter} seconds before trying again.`
161
+ : 'Please wait a moment before trying again.';
162
+ return errorPage({
163
+ code: 429,
164
+ title: 'Too Many Requests',
165
+ message: `You've made too many requests. ${retryMessage}`,
166
+ showRetry: true,
167
+ showHome: true,
168
+ ...rest,
169
+ });
170
+ }
171
+ /**
172
+ * Offline page
173
+ */
174
+ function offlinePage(options = {}) {
175
+ return errorPage({
176
+ title: "You're Offline",
177
+ message: 'Please check your internet connection and try again.',
178
+ showRetry: true,
179
+ showHome: false,
180
+ ...options,
181
+ layout: {
182
+ ...options.layout,
183
+ },
184
+ });
185
+ }
186
+ /**
187
+ * Session expired page
188
+ */
189
+ function sessionExpiredPage(options = {}) {
190
+ const { loginUrl = '/login', ...rest } = options;
191
+ return errorPage({
192
+ title: 'Session Expired',
193
+ message: 'Your session has expired. Please sign in again to continue.',
194
+ showRetry: false,
195
+ showHome: false,
196
+ actions: `
197
+ <div class="flex justify-center mt-8">
198
+ <a href="${(0, base_1.escapeHtml)(loginUrl)}" class="px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors">
199
+ Sign In Again
200
+ </a>
201
+ </div>
202
+ `,
203
+ ...rest,
204
+ });
205
+ }
206
+ /**
207
+ * OAuth error page
208
+ */
209
+ function oauthErrorPage(options) {
210
+ const { errorCode, errorDescription, redirectUri, clientName, ...rest } = options;
211
+ // Map OAuth error codes to user-friendly messages
212
+ const errorMessages = {
213
+ invalid_request: {
214
+ title: 'Invalid Request',
215
+ message: 'The authorization request is missing required parameters or is malformed.',
216
+ },
217
+ unauthorized_client: {
218
+ title: 'Unauthorized Client',
219
+ message: 'The client is not authorized to request an authorization code.',
220
+ },
221
+ access_denied: {
222
+ title: 'Access Denied',
223
+ message: 'The resource owner denied the authorization request.',
224
+ },
225
+ unsupported_response_type: {
226
+ title: 'Unsupported Response Type',
227
+ message: 'The authorization server does not support the requested response type.',
228
+ },
229
+ invalid_scope: {
230
+ title: 'Invalid Scope',
231
+ message: 'The requested scope is invalid, unknown, or malformed.',
232
+ },
233
+ server_error: {
234
+ title: 'Server Error',
235
+ message: 'The authorization server encountered an unexpected error.',
236
+ },
237
+ temporarily_unavailable: {
238
+ title: 'Temporarily Unavailable',
239
+ message: 'The authorization server is temporarily unavailable. Please try again later.',
240
+ },
241
+ };
242
+ const errorInfo = errorCode && errorMessages[errorCode]
243
+ ? errorMessages[errorCode]
244
+ : { title: 'Authorization Error', message: errorDescription || 'An error occurred during authorization.' };
245
+ const clientMessage = clientName ? ` while connecting to ${(0, base_1.escapeHtml)(clientName)}` : '';
246
+ const redirectAction = redirectUri
247
+ ? `
248
+ <a href="${(0, base_1.escapeHtml)(redirectUri)}" class="px-6 py-3 bg-gray-100 hover:bg-gray-200 text-text-primary font-medium rounded-lg transition-colors">
249
+ Return to ${clientName ? (0, base_1.escapeHtml)(clientName) : 'Application'}
250
+ </a>
251
+ `
252
+ : '';
253
+ return errorPage({
254
+ title: errorInfo.title,
255
+ message: `${errorInfo.message}${clientMessage}`,
256
+ details: errorCode && errorDescription ? `Error: ${errorCode}\n${errorDescription}` : undefined,
257
+ showRetry: errorCode === 'server_error' || errorCode === 'temporarily_unavailable',
258
+ showHome: true,
259
+ actions: redirectAction ? `<div class="flex justify-center gap-4 mt-8">${redirectAction}</div>` : undefined,
260
+ ...rest,
261
+ });
262
+ }
263
+ //# sourceMappingURL=error.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error.js","sourceRoot":"","sources":["../../../src/pages/error.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Error Page Templates\n *\n * Various error page templates (404, 500, etc.)\n */\n\nimport { errorLayout, type ErrorLayoutOptions } from '../layouts';\nimport { escapeHtml } from '../layouts/base';\n\n// ============================================\n// Error Page Types\n// ============================================\n\n/**\n * Error page options\n */\nexport interface ErrorPageOptions {\n /** Error code (404, 500, etc.) */\n code?: string | number;\n /** Error title */\n title?: string;\n /** Error message */\n message?: string;\n /** Detailed error (for development) */\n details?: string;\n /** Show stack trace (development only) */\n showStack?: boolean;\n /** Stack trace */\n stack?: string;\n /** Show retry button */\n showRetry?: boolean;\n /** Retry URL */\n retryUrl?: string;\n /** Show home button */\n showHome?: boolean;\n /** Home URL */\n homeUrl?: string;\n /** Show back button */\n showBack?: boolean;\n /** Custom actions HTML */\n actions?: string;\n /** Layout options */\n layout?: Partial<ErrorLayoutOptions>;\n /** Request ID (for support) */\n requestId?: string;\n}\n\n// ============================================\n// Error Page Builder\n// ============================================\n\n/**\n * Build a generic error page\n */\nexport function errorPage(options: ErrorPageOptions): string {\n const {\n code,\n title = 'Something went wrong',\n message,\n details,\n showStack = false,\n stack,\n showRetry = true,\n retryUrl,\n showHome = true,\n homeUrl = '/',\n showBack = false,\n actions,\n layout = {},\n requestId,\n } = options;\n\n // Details section (for development)\n const detailsHtml =\n details || (showStack && stack)\n ? `\n <div class=\"mt-8 text-left\">\n ${\n details\n ? `\n <div class=\"p-4 bg-gray-50 rounded-lg text-sm text-text-secondary mb-4\">\n <strong class=\"text-text-primary\">Details:</strong>\n <p class=\"mt-1\">${escapeHtml(details)}</p>\n </div>\n `\n : ''\n }\n ${\n showStack && stack\n ? `\n <details class=\"p-4 bg-gray-900 rounded-lg text-sm\">\n <summary class=\"text-gray-300 cursor-pointer hover:text-white\">Stack Trace</summary>\n <pre class=\"mt-2 text-xs text-gray-400 overflow-x-auto whitespace-pre-wrap\">${escapeHtml(stack)}</pre>\n </details>\n `\n : ''\n }\n </div>\n `\n : '';\n\n // Request ID for support\n const requestIdHtml = requestId\n ? `\n <p class=\"text-xs text-text-secondary mt-6\">\n Request ID: <code class=\"px-1.5 py-0.5 bg-gray-100 rounded text-xs\">${escapeHtml(requestId)}</code>\n </p>\n `\n : '';\n\n // Custom actions or default buttons are handled by errorLayout\n const content = `\n ${detailsHtml}\n ${actions || ''}\n ${requestIdHtml}\n `;\n\n return errorLayout(content, {\n title: `${code ? `Error ${code} - ` : ''}${title}`,\n errorCode: code?.toString(),\n errorTitle: title,\n errorMessage: message,\n showRetry,\n retryUrl,\n showHome,\n homeUrl,\n ...layout,\n });\n}\n\n// ============================================\n// Specific Error Pages\n// ============================================\n\n/**\n * 404 Not Found page\n */\nexport function notFoundPage(options: Partial<ErrorPageOptions> = {}): string {\n return errorPage({\n code: 404,\n title: 'Page Not Found',\n message: \"The page you're looking for doesn't exist or has been moved.\",\n showRetry: false,\n ...options,\n });\n}\n\n/**\n * 403 Forbidden page\n */\nexport function forbiddenPage(options: Partial<ErrorPageOptions> = {}): string {\n return errorPage({\n code: 403,\n title: 'Access Denied',\n message: \"You don't have permission to access this resource.\",\n showRetry: false,\n ...options,\n });\n}\n\n/**\n * 401 Unauthorized page\n */\nexport function unauthorizedPage(options: Partial<ErrorPageOptions> & { loginUrl?: string } = {}): string {\n const { loginUrl = '/login', ...rest } = options;\n\n return errorPage({\n code: 401,\n title: 'Authentication Required',\n message: 'Please sign in to access this resource.',\n showRetry: false,\n showHome: false,\n actions: `\n <div class=\"flex justify-center mt-8\">\n <a href=\"${escapeHtml(\n loginUrl,\n )}\" class=\"px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors\">\n Sign In\n </a>\n </div>\n `,\n ...rest,\n });\n}\n\n/**\n * 500 Internal Server Error page\n */\nexport function serverErrorPage(options: Partial<ErrorPageOptions> = {}): string {\n return errorPage({\n code: 500,\n title: 'Server Error',\n message: \"We're having trouble processing your request. Please try again later.\",\n showRetry: true,\n ...options,\n });\n}\n\n/**\n * 503 Service Unavailable page\n */\nexport function maintenancePage(options: Partial<ErrorPageOptions> & { estimatedTime?: string } = {}): string {\n const { estimatedTime, ...rest } = options;\n\n const timeMessage = estimatedTime\n ? `We expect to be back by ${escapeHtml(estimatedTime)}.`\n : \"We'll be back shortly.\";\n\n return errorPage({\n code: 503,\n title: 'Under Maintenance',\n message: `We're currently performing scheduled maintenance. ${timeMessage}`,\n showRetry: true,\n showHome: false,\n ...rest,\n });\n}\n\n/**\n * 429 Rate Limit page\n */\nexport function rateLimitPage(options: Partial<ErrorPageOptions> & { retryAfter?: number } = {}): string {\n const { retryAfter, ...rest } = options;\n\n const retryMessage = retryAfter\n ? `Please wait ${retryAfter} seconds before trying again.`\n : 'Please wait a moment before trying again.';\n\n return errorPage({\n code: 429,\n title: 'Too Many Requests',\n message: `You've made too many requests. ${retryMessage}`,\n showRetry: true,\n showHome: true,\n ...rest,\n });\n}\n\n/**\n * Offline page\n */\nexport function offlinePage(options: Partial<ErrorPageOptions> = {}): string {\n return errorPage({\n title: \"You're Offline\",\n message: 'Please check your internet connection and try again.',\n showRetry: true,\n showHome: false,\n ...options,\n layout: {\n ...options.layout,\n },\n });\n}\n\n/**\n * Session expired page\n */\nexport function sessionExpiredPage(options: Partial<ErrorPageOptions> & { loginUrl?: string } = {}): string {\n const { loginUrl = '/login', ...rest } = options;\n\n return errorPage({\n title: 'Session Expired',\n message: 'Your session has expired. Please sign in again to continue.',\n showRetry: false,\n showHome: false,\n actions: `\n <div class=\"flex justify-center mt-8\">\n <a href=\"${escapeHtml(\n loginUrl,\n )}\" class=\"px-6 py-3 bg-primary hover:bg-primary/90 text-white font-medium rounded-lg transition-colors\">\n Sign In Again\n </a>\n </div>\n `,\n ...rest,\n });\n}\n\n// ============================================\n// OAuth Error Pages\n// ============================================\n\n/**\n * OAuth error page options\n */\nexport interface OAuthErrorPageOptions extends Partial<ErrorPageOptions> {\n /** OAuth error code */\n errorCode?: string;\n /** OAuth error description */\n errorDescription?: string;\n /** Redirect URI */\n redirectUri?: string;\n /** Client name */\n clientName?: string;\n}\n\n/**\n * OAuth error page\n */\nexport function oauthErrorPage(options: OAuthErrorPageOptions): string {\n const { errorCode, errorDescription, redirectUri, clientName, ...rest } = options;\n\n // Map OAuth error codes to user-friendly messages\n const errorMessages: Record<string, { title: string; message: string }> = {\n invalid_request: {\n title: 'Invalid Request',\n message: 'The authorization request is missing required parameters or is malformed.',\n },\n unauthorized_client: {\n title: 'Unauthorized Client',\n message: 'The client is not authorized to request an authorization code.',\n },\n access_denied: {\n title: 'Access Denied',\n message: 'The resource owner denied the authorization request.',\n },\n unsupported_response_type: {\n title: 'Unsupported Response Type',\n message: 'The authorization server does not support the requested response type.',\n },\n invalid_scope: {\n title: 'Invalid Scope',\n message: 'The requested scope is invalid, unknown, or malformed.',\n },\n server_error: {\n title: 'Server Error',\n message: 'The authorization server encountered an unexpected error.',\n },\n temporarily_unavailable: {\n title: 'Temporarily Unavailable',\n message: 'The authorization server is temporarily unavailable. Please try again later.',\n },\n };\n\n const errorInfo =\n errorCode && errorMessages[errorCode]\n ? errorMessages[errorCode]\n : { title: 'Authorization Error', message: errorDescription || 'An error occurred during authorization.' };\n\n const clientMessage = clientName ? ` while connecting to ${escapeHtml(clientName)}` : '';\n\n const redirectAction = redirectUri\n ? `\n <a href=\"${escapeHtml(\n redirectUri,\n )}\" class=\"px-6 py-3 bg-gray-100 hover:bg-gray-200 text-text-primary font-medium rounded-lg transition-colors\">\n Return to ${clientName ? escapeHtml(clientName) : 'Application'}\n </a>\n `\n : '';\n\n return errorPage({\n title: errorInfo.title,\n message: `${errorInfo.message}${clientMessage}`,\n details: errorCode && errorDescription ? `Error: ${errorCode}\\n${errorDescription}` : undefined,\n showRetry: errorCode === 'server_error' || errorCode === 'temporarily_unavailable',\n showHome: true,\n actions: redirectAction ? `<div class=\"flex justify-center gap-4 mt-8\">${redirectAction}</div>` : undefined,\n ...rest,\n });\n}\n"]}