@atproto/oauth-provider 0.3.1 → 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 (404) hide show
  1. package/.linguirc +57 -0
  2. package/CHANGELOG.md +29 -0
  3. package/LICENSE.txt +1 -1
  4. package/dist/account/account-manager.d.ts +17 -3
  5. package/dist/account/account-manager.d.ts.map +1 -1
  6. package/dist/account/account-manager.js +102 -8
  7. package/dist/account/account-manager.js.map +1 -1
  8. package/dist/account/account-store.d.ts +81 -15
  9. package/dist/account/account-store.d.ts.map +1 -1
  10. package/dist/account/account-store.js +70 -19
  11. package/dist/account/account-store.js.map +1 -1
  12. package/dist/account/sign-in-data.d.ts +28 -0
  13. package/dist/account/sign-in-data.d.ts.map +1 -0
  14. package/dist/account/sign-in-data.js +16 -0
  15. package/dist/account/sign-in-data.js.map +1 -0
  16. package/dist/account/sign-up-data.d.ts +26 -0
  17. package/dist/account/sign-up-data.d.ts.map +1 -0
  18. package/dist/account/sign-up-data.js +11 -0
  19. package/dist/account/sign-up-data.js.map +1 -0
  20. package/dist/assets/app/bundle-manifest.json +598 -6
  21. package/dist/assets/app/index-ItwwtJ8r.js +36 -0
  22. package/dist/assets/app/index-ItwwtJ8r.js.map +1 -0
  23. package/dist/assets/app/main-B_dNxQo_.js +4 -0
  24. package/dist/assets/app/main-B_dNxQo_.js.map +1 -0
  25. package/dist/assets/app/main-CSatvmRR.css +3 -0
  26. package/dist/assets/app/main-CSatvmRR.js +306 -0
  27. package/dist/assets/app/main-CSatvmRR.js.map +1 -0
  28. package/dist/assets/app/messages-BQeltXSF.js +4 -0
  29. package/dist/assets/app/messages-BQeltXSF.js.map +1 -0
  30. package/dist/assets/app/messages-BQkEhfjg.js +4 -0
  31. package/dist/assets/app/messages-BQkEhfjg.js.map +1 -0
  32. package/dist/assets/app/messages-BUjKj_UJ.js +4 -0
  33. package/dist/assets/app/messages-BUjKj_UJ.js.map +1 -0
  34. package/dist/assets/app/messages-BWIQa8fO.js +4 -0
  35. package/dist/assets/app/messages-BWIQa8fO.js.map +1 -0
  36. package/dist/assets/app/messages-BaNVb0bp.js +4 -0
  37. package/dist/assets/app/messages-BaNVb0bp.js.map +1 -0
  38. package/dist/assets/app/messages-BaizVXcF.js +4 -0
  39. package/dist/assets/app/messages-BaizVXcF.js.map +1 -0
  40. package/dist/assets/app/messages-BfoClA1Y.js +4 -0
  41. package/dist/assets/app/messages-BfoClA1Y.js.map +1 -0
  42. package/dist/assets/app/messages-BsKGDZnC.js +4 -0
  43. package/dist/assets/app/messages-BsKGDZnC.js.map +1 -0
  44. package/dist/assets/app/messages-Bu-TJhml.js +4 -0
  45. package/dist/assets/app/messages-Bu-TJhml.js.map +1 -0
  46. package/dist/assets/app/messages-BvOKnBQk.js +4 -0
  47. package/dist/assets/app/messages-BvOKnBQk.js.map +1 -0
  48. package/dist/assets/app/messages-BxDzCiWz.js +4 -0
  49. package/dist/assets/app/messages-BxDzCiWz.js.map +1 -0
  50. package/dist/assets/app/messages-CDgFOy4S.js +4 -0
  51. package/dist/assets/app/messages-CDgFOy4S.js.map +1 -0
  52. package/dist/assets/app/messages-CLbTz0o9.js +4 -0
  53. package/dist/assets/app/messages-CLbTz0o9.js.map +1 -0
  54. package/dist/assets/app/messages-CNwSh0t7.js +4 -0
  55. package/dist/assets/app/messages-CNwSh0t7.js.map +1 -0
  56. package/dist/assets/app/messages-CSMNJ6P8.js +4 -0
  57. package/dist/assets/app/messages-CSMNJ6P8.js.map +1 -0
  58. package/dist/assets/app/messages-CZQUw3mp.js +4 -0
  59. package/dist/assets/app/messages-CZQUw3mp.js.map +1 -0
  60. package/dist/assets/app/messages-CZT41oVp.js +4 -0
  61. package/dist/assets/app/messages-CZT41oVp.js.map +1 -0
  62. package/dist/assets/app/messages-C_b-d3t8.js +4 -0
  63. package/dist/assets/app/messages-C_b-d3t8.js.map +1 -0
  64. package/dist/assets/app/messages-C_u3MTc2.js +4 -0
  65. package/dist/assets/app/messages-C_u3MTc2.js.map +1 -0
  66. package/dist/assets/app/messages-Cn8nHZic.js +4 -0
  67. package/dist/assets/app/messages-Cn8nHZic.js.map +1 -0
  68. package/dist/assets/app/messages-CtDywJUm.js +4 -0
  69. package/dist/assets/app/messages-CtDywJUm.js.map +1 -0
  70. package/dist/assets/app/messages-CurtIjBF.js +4 -0
  71. package/dist/assets/app/messages-CurtIjBF.js.map +1 -0
  72. package/dist/assets/app/messages-Cv6zIbaP.js +4 -0
  73. package/dist/assets/app/messages-Cv6zIbaP.js.map +1 -0
  74. package/dist/assets/app/messages-D1eLQuPE.js +4 -0
  75. package/dist/assets/app/messages-D1eLQuPE.js.map +1 -0
  76. package/dist/assets/app/messages-D8vHEaYW.js +4 -0
  77. package/dist/assets/app/messages-D8vHEaYW.js.map +1 -0
  78. package/dist/assets/app/messages-DJ1Q4GeC.js +4 -0
  79. package/dist/assets/app/messages-DJ1Q4GeC.js.map +1 -0
  80. package/dist/assets/app/messages-DRL3exqd.js +4 -0
  81. package/dist/assets/app/messages-DRL3exqd.js.map +1 -0
  82. package/dist/assets/app/messages-DWLPQRTp.js +4 -0
  83. package/dist/assets/app/messages-DWLPQRTp.js.map +1 -0
  84. package/dist/assets/app/messages-DjVaE9YE.js +4 -0
  85. package/dist/assets/app/messages-DjVaE9YE.js.map +1 -0
  86. package/dist/assets/app/messages-DqpMfFJR.js +4 -0
  87. package/dist/assets/app/messages-DqpMfFJR.js.map +1 -0
  88. package/dist/assets/app/messages-ETjhJBEN.js +4 -0
  89. package/dist/assets/app/messages-ETjhJBEN.js.map +1 -0
  90. package/dist/assets/app/messages-EUKrgrGn.js +4 -0
  91. package/dist/assets/app/messages-EUKrgrGn.js.map +1 -0
  92. package/dist/assets/app/messages-QQrOUcPW.js +4 -0
  93. package/dist/assets/app/messages-QQrOUcPW.js.map +1 -0
  94. package/dist/assets/app/messages-e2QGqFL6.js +4 -0
  95. package/dist/assets/app/messages-e2QGqFL6.js.map +1 -0
  96. package/dist/assets/app/messages-p61py7gD.js +4 -0
  97. package/dist/assets/app/messages-p61py7gD.js.map +1 -0
  98. package/dist/assets/asset.d.ts +1 -0
  99. package/dist/assets/asset.d.ts.map +1 -1
  100. package/dist/assets/assets-middleware.d.ts.map +1 -1
  101. package/dist/assets/assets-middleware.js +12 -7
  102. package/dist/assets/assets-middleware.js.map +1 -1
  103. package/dist/assets/index.d.ts +3 -2
  104. package/dist/assets/index.d.ts.map +1 -1
  105. package/dist/assets/index.js +13 -1
  106. package/dist/assets/index.js.map +1 -1
  107. package/dist/client/client-store.d.ts +3 -3
  108. package/dist/client/client-store.d.ts.map +1 -1
  109. package/dist/client/client-store.js +6 -5
  110. package/dist/client/client-store.js.map +1 -1
  111. package/dist/device/device-manager.d.ts +12 -13
  112. package/dist/device/device-manager.d.ts.map +1 -1
  113. package/dist/device/device-manager.js +5 -3
  114. package/dist/device/device-manager.js.map +1 -1
  115. package/dist/device/device-store.d.ts +3 -3
  116. package/dist/device/device-store.d.ts.map +1 -1
  117. package/dist/device/device-store.js +10 -9
  118. package/dist/device/device-store.js.map +1 -1
  119. package/dist/dpop/dpop-manager.d.ts +15 -7
  120. package/dist/dpop/dpop-manager.d.ts.map +1 -1
  121. package/dist/dpop/dpop-manager.js +17 -3
  122. package/dist/dpop/dpop-manager.js.map +1 -1
  123. package/dist/dpop/dpop-nonce.d.ts +11 -5
  124. package/dist/dpop/dpop-nonce.d.ts.map +1 -1
  125. package/dist/dpop/dpop-nonce.js +47 -38
  126. package/dist/dpop/dpop-nonce.js.map +1 -1
  127. package/dist/errors/handle-unavailable-error.d.ts +11 -0
  128. package/dist/errors/handle-unavailable-error.d.ts.map +1 -0
  129. package/dist/errors/handle-unavailable-error.js +19 -0
  130. package/dist/errors/handle-unavailable-error.js.map +1 -0
  131. package/dist/errors/invalid-request-error.d.ts +6 -8
  132. package/dist/errors/invalid-request-error.d.ts.map +1 -1
  133. package/dist/errors/invalid-request-error.js +10 -8
  134. package/dist/errors/invalid-request-error.js.map +1 -1
  135. package/dist/lib/csp/index.d.ts +18 -0
  136. package/dist/lib/csp/index.d.ts.map +1 -0
  137. package/dist/lib/csp/index.js +72 -0
  138. package/dist/lib/csp/index.js.map +1 -0
  139. package/dist/lib/hcaptcha.d.ts +177 -0
  140. package/dist/lib/hcaptcha.d.ts.map +1 -0
  141. package/dist/lib/hcaptcha.js +155 -0
  142. package/dist/lib/hcaptcha.js.map +1 -0
  143. package/dist/lib/html/build-document.d.ts +11 -3
  144. package/dist/lib/html/build-document.d.ts.map +1 -1
  145. package/dist/lib/html/build-document.js +51 -15
  146. package/dist/lib/html/build-document.js.map +1 -1
  147. package/dist/lib/http/middleware.d.ts.map +1 -1
  148. package/dist/lib/http/middleware.js +4 -1
  149. package/dist/lib/http/middleware.js.map +1 -1
  150. package/dist/lib/http/request.d.ts +18 -3
  151. package/dist/lib/http/request.d.ts.map +1 -1
  152. package/dist/lib/http/request.js +56 -23
  153. package/dist/lib/http/request.js.map +1 -1
  154. package/dist/lib/http/response.d.ts +4 -2
  155. package/dist/lib/http/response.d.ts.map +1 -1
  156. package/dist/lib/http/response.js +23 -5
  157. package/dist/lib/http/response.js.map +1 -1
  158. package/dist/lib/locale.d.ts +15 -0
  159. package/dist/lib/locale.d.ts.map +1 -0
  160. package/dist/lib/locale.js +17 -0
  161. package/dist/lib/locale.js.map +1 -0
  162. package/dist/lib/util/function.d.ts +2 -2
  163. package/dist/lib/util/function.d.ts.map +1 -1
  164. package/dist/lib/util/function.js.map +1 -1
  165. package/dist/lib/util/type.d.ts +88 -1
  166. package/dist/lib/util/type.d.ts.map +1 -1
  167. package/dist/lib/util/type.js +41 -0
  168. package/dist/lib/util/type.js.map +1 -1
  169. package/dist/metadata/build-metadata.d.ts +2 -2
  170. package/dist/metadata/build-metadata.d.ts.map +1 -1
  171. package/dist/metadata/build-metadata.js.map +1 -1
  172. package/dist/oauth-errors.d.ts +1 -0
  173. package/dist/oauth-errors.d.ts.map +1 -1
  174. package/dist/oauth-errors.js +3 -1
  175. package/dist/oauth-errors.js.map +1 -1
  176. package/dist/oauth-hooks.d.ts +60 -3
  177. package/dist/oauth-hooks.d.ts.map +1 -1
  178. package/dist/oauth-hooks.js +3 -3
  179. package/dist/oauth-hooks.js.map +1 -1
  180. package/dist/oauth-provider.d.ts +28 -22
  181. package/dist/oauth-provider.d.ts.map +1 -1
  182. package/dist/oauth-provider.js +212 -211
  183. package/dist/oauth-provider.js.map +1 -1
  184. package/dist/oauth-verifier.d.ts +1 -1
  185. package/dist/oauth-verifier.d.ts.map +1 -1
  186. package/dist/oauth-verifier.js +2 -1
  187. package/dist/oauth-verifier.js.map +1 -1
  188. package/dist/output/build-authorize-data.d.ts +0 -1
  189. package/dist/output/build-authorize-data.d.ts.map +1 -1
  190. package/dist/output/build-authorize-data.js +0 -1
  191. package/dist/output/build-authorize-data.js.map +1 -1
  192. package/dist/output/build-customization-data.d.ts +232 -0
  193. package/dist/output/build-customization-data.d.ts.map +1 -0
  194. package/dist/output/build-customization-data.js +145 -0
  195. package/dist/output/build-customization-data.js.map +1 -0
  196. package/dist/output/output-manager.d.ts +16 -9
  197. package/dist/output/output-manager.d.ts.map +1 -1
  198. package/dist/output/output-manager.js +78 -42
  199. package/dist/output/output-manager.js.map +1 -1
  200. package/dist/output/send-authorize-redirect.d.ts +9 -6
  201. package/dist/output/send-authorize-redirect.d.ts.map +1 -1
  202. package/dist/output/send-authorize-redirect.js +20 -14
  203. package/dist/output/send-authorize-redirect.js.map +1 -1
  204. package/dist/output/send-web-page.d.ts +7 -2
  205. package/dist/output/send-web-page.d.ts.map +1 -1
  206. package/dist/output/send-web-page.js +37 -21
  207. package/dist/output/send-web-page.js.map +1 -1
  208. package/dist/request/request-manager.d.ts +1 -1
  209. package/dist/request/request-manager.d.ts.map +1 -1
  210. package/dist/request/request-manager.js +4 -4
  211. package/dist/request/request-manager.js.map +1 -1
  212. package/dist/request/request-store.d.ts +3 -3
  213. package/dist/request/request-store.d.ts.map +1 -1
  214. package/dist/request/request-store.js +11 -10
  215. package/dist/request/request-store.js.map +1 -1
  216. package/dist/token/token-store.d.ts +4 -4
  217. package/dist/token/token-store.d.ts.map +1 -1
  218. package/dist/token/token-store.js +13 -12
  219. package/dist/token/token-store.js.map +1 -1
  220. package/package.json +46 -21
  221. package/rollup.config.js +61 -17
  222. package/src/account/account-manager.ts +159 -8
  223. package/src/account/account-store.ts +127 -32
  224. package/src/account/sign-in-data.ts +15 -0
  225. package/src/account/sign-up-data.ts +11 -0
  226. package/src/assets/app/app.tsx +31 -16
  227. package/src/assets/app/backend-data.ts +15 -60
  228. package/src/assets/app/backend-types.ts +66 -0
  229. package/src/assets/app/components/forms/button-toggle-visibility.tsx +43 -0
  230. package/src/assets/app/components/forms/button.tsx +60 -0
  231. package/src/assets/app/components/forms/fieldset.tsx +55 -0
  232. package/src/assets/app/components/forms/form-card-async.tsx +103 -0
  233. package/src/assets/app/components/forms/form-card.tsx +49 -0
  234. package/src/assets/app/components/forms/input-checkbox.tsx +73 -0
  235. package/src/assets/app/components/forms/input-container.tsx +107 -0
  236. package/src/assets/app/components/forms/input-email-address.tsx +66 -0
  237. package/src/assets/app/components/forms/input-new-password.tsx +62 -0
  238. package/src/assets/app/components/forms/input-password.tsx +88 -0
  239. package/src/assets/app/components/forms/input-text.tsx +76 -0
  240. package/src/assets/app/components/forms/input-token.tsx +94 -0
  241. package/src/assets/app/components/forms/wizard-card.tsx +116 -0
  242. package/src/assets/app/components/layouts/layout-title-page.tsx +77 -0
  243. package/src/assets/app/components/layouts/layout-welcome.tsx +73 -0
  244. package/src/assets/app/components/utils/account-identifier.tsx +23 -0
  245. package/src/assets/app/components/utils/account-image.tsx +33 -0
  246. package/src/assets/app/components/utils/admonition.tsx +52 -0
  247. package/src/assets/app/components/utils/client-name.tsx +45 -0
  248. package/src/assets/app/components/utils/error-card.tsx +93 -0
  249. package/src/assets/app/components/utils/error-message.tsx +62 -0
  250. package/src/assets/app/components/utils/help-card.tsx +46 -0
  251. package/src/assets/app/components/utils/icons.tsx +88 -0
  252. package/src/assets/app/components/utils/link-anchor.tsx +28 -0
  253. package/src/assets/app/components/utils/link-title.tsx +26 -0
  254. package/src/assets/app/components/utils/multi-lang-string.tsx +56 -0
  255. package/src/assets/app/components/utils/password-strength-label.tsx +37 -0
  256. package/src/assets/app/components/utils/password-strength-meter.tsx +58 -0
  257. package/src/assets/app/components/{url-viewer.tsx → utils/url-viewer.tsx} +9 -6
  258. package/src/assets/app/hooks/use-api.ts +128 -55
  259. package/src/assets/app/hooks/use-async-action.ts +120 -0
  260. package/src/assets/app/hooks/use-browser-color-scheme.ts +31 -0
  261. package/src/assets/app/hooks/use-csrf-token.ts +1 -1
  262. package/src/assets/app/hooks/use-random-string.ts +37 -0
  263. package/src/assets/app/hooks/use-stepper.ts +87 -0
  264. package/src/assets/app/index.html +182 -0
  265. package/src/assets/app/lib/api.ts +248 -79
  266. package/src/assets/app/lib/clsx.ts +5 -8
  267. package/src/assets/app/lib/json-client.ts +94 -0
  268. package/src/assets/app/lib/password.ts +98 -0
  269. package/src/assets/app/lib/ref.ts +17 -0
  270. package/src/assets/app/locales/an/messages.po +492 -0
  271. package/src/assets/app/locales/ast/messages.po +492 -0
  272. package/src/assets/app/locales/ca/messages.po +492 -0
  273. package/src/assets/app/locales/da/messages.po +492 -0
  274. package/src/assets/app/locales/de/messages.po +492 -0
  275. package/src/assets/app/locales/el/messages.po +492 -0
  276. package/src/assets/app/locales/en/messages.po +492 -0
  277. package/src/assets/app/locales/en-GB/messages.po +492 -0
  278. package/src/assets/app/locales/es/messages.po +492 -0
  279. package/src/assets/app/locales/eu/messages.po +492 -0
  280. package/src/assets/app/locales/fi/messages.po +492 -0
  281. package/src/assets/app/locales/fr/messages.po +492 -0
  282. package/src/assets/app/locales/ga/messages.po +492 -0
  283. package/src/assets/app/locales/gl/messages.po +492 -0
  284. package/src/assets/app/locales/hi/messages.po +492 -0
  285. package/src/assets/app/locales/hu/messages.po +492 -0
  286. package/src/assets/app/locales/ia/messages.po +492 -0
  287. package/src/assets/app/locales/id/messages.po +492 -0
  288. package/src/assets/app/locales/it/messages.po +492 -0
  289. package/src/assets/app/locales/ja/messages.po +492 -0
  290. package/src/assets/app/locales/km/messages.po +492 -0
  291. package/src/assets/app/locales/ko/messages.po +492 -0
  292. package/src/assets/app/locales/load.ts +8 -0
  293. package/src/assets/app/locales/locale-context.ts +19 -0
  294. package/src/assets/app/locales/locale-provider.tsx +112 -0
  295. package/src/assets/app/locales/locale-selector.tsx +58 -0
  296. package/src/assets/app/locales/locales.ts +168 -0
  297. package/src/assets/app/locales/ne/messages.po +492 -0
  298. package/src/assets/app/locales/nl/messages.po +492 -0
  299. package/src/assets/app/locales/pl/messages.po +492 -0
  300. package/src/assets/app/locales/pt-BR/messages.po +492 -0
  301. package/src/assets/app/locales/ro/messages.po +492 -0
  302. package/src/assets/app/locales/ru/messages.po +492 -0
  303. package/src/assets/app/locales/sv/messages.po +492 -0
  304. package/src/assets/app/locales/th/messages.po +492 -0
  305. package/src/assets/app/locales/tr/messages.po +492 -0
  306. package/src/assets/app/locales/uk/messages.po +492 -0
  307. package/src/assets/app/locales/vi/messages.po +492 -0
  308. package/src/assets/app/locales/zh-CN/messages.po +492 -0
  309. package/src/assets/app/locales/zh-HK/messages.po +492 -0
  310. package/src/assets/app/locales/zh-TW/messages.po +492 -0
  311. package/src/assets/app/main.css +23 -2
  312. package/src/assets/app/main.tsx +24 -8
  313. package/src/assets/app/views/authorize/accept/accept-form.tsx +150 -0
  314. package/src/assets/app/views/authorize/accept/accept-view.tsx +70 -0
  315. package/src/assets/app/views/authorize/authorize-view.tsx +180 -0
  316. package/src/assets/app/views/authorize/reset-password/reset-password-confirm-form.tsx +88 -0
  317. package/src/assets/app/views/authorize/reset-password/reset-password-request-form.tsx +80 -0
  318. package/src/assets/app/views/authorize/reset-password/reset-password-view.tsx +127 -0
  319. package/src/assets/app/views/authorize/sign-in/sign-in-form.tsx +244 -0
  320. package/src/assets/app/views/authorize/sign-in/sign-in-picker.tsx +116 -0
  321. package/src/assets/app/views/authorize/sign-in/sign-in-view.tsx +145 -0
  322. package/src/assets/app/views/authorize/sign-up/sign-up-account-form.tsx +140 -0
  323. package/src/assets/app/views/authorize/sign-up/sign-up-disclaimer.tsx +51 -0
  324. package/src/assets/app/views/authorize/sign-up/sign-up-handle-form.tsx +289 -0
  325. package/src/assets/app/views/authorize/sign-up/sign-up-hcaptcha-form.tsx +108 -0
  326. package/src/assets/app/views/authorize/sign-up/sign-up-view.tsx +158 -0
  327. package/src/assets/app/views/authorize/welcome/welcome-view.tsx +56 -0
  328. package/src/assets/app/views/error/error-view.tsx +31 -0
  329. package/src/assets/asset.ts +1 -0
  330. package/src/assets/assets-middleware.ts +13 -8
  331. package/src/assets/index.ts +15 -2
  332. package/src/client/client-store.ts +10 -12
  333. package/src/device/device-manager.ts +14 -15
  334. package/src/device/device-store.ts +9 -15
  335. package/src/dpop/dpop-manager.ts +20 -8
  336. package/src/dpop/dpop-nonce.ts +58 -40
  337. package/src/errors/handle-unavailable-error.ts +18 -0
  338. package/src/errors/invalid-request-error.ts +10 -8
  339. package/src/lib/csp/index.ts +98 -0
  340. package/src/lib/hcaptcha.ts +182 -0
  341. package/src/lib/html/build-document.ts +60 -16
  342. package/src/lib/http/middleware.ts +4 -3
  343. package/src/lib/http/request.ts +81 -28
  344. package/src/lib/http/response.ts +22 -9
  345. package/src/lib/locale.ts +21 -0
  346. package/src/lib/util/function.ts +0 -3
  347. package/src/lib/util/type.ts +130 -1
  348. package/src/metadata/build-metadata.ts +2 -1
  349. package/src/oauth-errors.ts +1 -0
  350. package/src/oauth-hooks.ts +69 -3
  351. package/src/oauth-provider.ts +410 -315
  352. package/src/oauth-verifier.ts +3 -1
  353. package/src/output/build-authorize-data.ts +1 -3
  354. package/src/output/build-customization-data.ts +189 -0
  355. package/src/output/output-manager.ts +111 -48
  356. package/src/output/send-authorize-redirect.ts +43 -36
  357. package/src/output/send-web-page.ts +40 -26
  358. package/src/request/request-manager.ts +4 -4
  359. package/src/request/request-store.ts +12 -16
  360. package/src/token/token-store.ts +14 -18
  361. package/tailwind.config.js +5 -0
  362. package/tsconfig.backend.tsbuildinfo +1 -1
  363. package/tsconfig.frontend.tsbuildinfo +1 -1
  364. package/tsconfig.tools.tsbuildinfo +1 -1
  365. package/vite.config.mjs +16 -0
  366. package/.postcssrc.yml +0 -3
  367. package/dist/assets/app/main.css +0 -3
  368. package/dist/assets/app/main.js +0 -20
  369. package/dist/assets/app/main.js.map +0 -1
  370. package/dist/output/customization.d.ts +0 -27
  371. package/dist/output/customization.d.ts.map +0 -1
  372. package/dist/output/customization.js +0 -88
  373. package/dist/output/customization.js.map +0 -1
  374. package/src/assets/app/components/accept-form.tsx +0 -137
  375. package/src/assets/app/components/account-identifier.tsx +0 -18
  376. package/src/assets/app/components/account-picker.tsx +0 -127
  377. package/src/assets/app/components/button.tsx +0 -34
  378. package/src/assets/app/components/client-name.tsx +0 -37
  379. package/src/assets/app/components/fieldset.tsx +0 -26
  380. package/src/assets/app/components/form-card.tsx +0 -47
  381. package/src/assets/app/components/help-card.tsx +0 -42
  382. package/src/assets/app/components/icons/alert-icon.tsx +0 -5
  383. package/src/assets/app/components/icons/at-symbol-icon.tsx +0 -5
  384. package/src/assets/app/components/icons/caret-right-icon.tsx +0 -5
  385. package/src/assets/app/components/icons/lock-icon.tsx +0 -5
  386. package/src/assets/app/components/icons/token-icon.tsx +0 -5
  387. package/src/assets/app/components/icons/util.tsx +0 -17
  388. package/src/assets/app/components/info-card.tsx +0 -45
  389. package/src/assets/app/components/input-checkbox.tsx +0 -47
  390. package/src/assets/app/components/input-container.tsx +0 -37
  391. package/src/assets/app/components/input-layout.tsx +0 -47
  392. package/src/assets/app/components/input-text.tsx +0 -69
  393. package/src/assets/app/components/layout-title-page.tsx +0 -60
  394. package/src/assets/app/components/layout-welcome.tsx +0 -74
  395. package/src/assets/app/components/sign-in-form.tsx +0 -337
  396. package/src/assets/app/components/sign-up-account-form.tsx +0 -194
  397. package/src/assets/app/components/sign-up-disclaimer.tsx +0 -44
  398. package/src/assets/app/views/accept-view.tsx +0 -55
  399. package/src/assets/app/views/authorize-view.tsx +0 -106
  400. package/src/assets/app/views/error-view.tsx +0 -36
  401. package/src/assets/app/views/sign-in-view.tsx +0 -111
  402. package/src/assets/app/views/sign-up-view.tsx +0 -86
  403. package/src/assets/app/views/welcome-view.tsx +0 -54
  404. package/src/output/customization.ts +0 -118
@@ -0,0 +1,120 @@
1
+ import {
2
+ ForwardedRef,
3
+ useCallback,
4
+ useEffect,
5
+ useImperativeHandle,
6
+ useRef,
7
+ useState,
8
+ } from 'react'
9
+
10
+ export type AsyncActionController = {
11
+ reset: () => void
12
+ }
13
+
14
+ export type UseAsyncActionOptions = {
15
+ ref?: ForwardedRef<AsyncActionController>
16
+ onLoading?: (loading: boolean) => void
17
+ onError?: (error: Error | undefined) => void
18
+ }
19
+
20
+ export function useAsyncAction(
21
+ fn: (signal: AbortSignal) => void | PromiseLike<void>,
22
+ { ref, onLoading, onError }: UseAsyncActionOptions = {},
23
+ ) {
24
+ const [loading, setLoading] = useState(false)
25
+ const [error, setError] = useState<Error | undefined>()
26
+
27
+ const doSetError = useCallback(
28
+ (error: Error | undefined) => {
29
+ setError(error)
30
+ onError?.(error)
31
+ },
32
+ [onError],
33
+ )
34
+
35
+ const doSetLoading = useCallback(
36
+ (loading: boolean) => {
37
+ setLoading(loading)
38
+ onLoading?.(loading)
39
+ },
40
+ [onLoading],
41
+ )
42
+
43
+ const controllerRef = useRef<AbortController>(null)
44
+
45
+ const resetRef = useRef<() => void>(null)
46
+ useEffect(() => {
47
+ resetRef.current = () => {
48
+ controllerRef.current?.abort()
49
+ controllerRef.current = null
50
+ doSetError(undefined)
51
+ doSetLoading(false)
52
+ }
53
+ return () => {
54
+ resetRef.current = null
55
+ }
56
+ }, [doSetError, doSetLoading])
57
+
58
+ useImperativeHandle(
59
+ ref,
60
+ (): AsyncActionController => ({
61
+ reset: () => resetRef.current?.(),
62
+ }),
63
+ [],
64
+ )
65
+
66
+ // Cancel pending action when unmounted
67
+ useEffect(() => {
68
+ return () => {
69
+ controllerRef.current?.abort()
70
+ controllerRef.current = null
71
+ }
72
+ }, [])
73
+
74
+ const run = useCallback(async (): Promise<void> => {
75
+ // Cancel previous run
76
+ controllerRef.current?.abort()
77
+
78
+ doSetLoading(true)
79
+ doSetError(undefined)
80
+
81
+ const controller = new AbortController()
82
+ const { signal } = controller
83
+
84
+ controllerRef.current = controller
85
+
86
+ try {
87
+ await fn(signal)
88
+ } catch (err) {
89
+ if (controller === controllerRef.current) {
90
+ doSetError(err instanceof Error ? err : new Error(String(err)))
91
+ } else {
92
+ if (!isAbortReason(signal, err)) {
93
+ console.warn('Async action error after abort', err)
94
+ }
95
+ }
96
+ } finally {
97
+ if (controller === controllerRef.current) {
98
+ controllerRef.current = null
99
+ doSetLoading(false)
100
+ }
101
+
102
+ controller.abort()
103
+ }
104
+ }, [fn, doSetLoading, doSetError])
105
+
106
+ return {
107
+ loading,
108
+ error,
109
+ run,
110
+ }
111
+ }
112
+
113
+ function isAbortReason(signal: AbortSignal, err: unknown): boolean {
114
+ return (
115
+ signal.aborted &&
116
+ (signal.reason === err ||
117
+ signal.reason === err?.['cause'] ||
118
+ (err instanceof DOMException && err.name === 'AbortError'))
119
+ )
120
+ }
@@ -0,0 +1,31 @@
1
+ import { useEffect, useState } from 'react'
2
+
3
+ const query =
4
+ typeof window === 'undefined'
5
+ ? null
6
+ : window.matchMedia('(prefers-color-scheme: dark)')
7
+
8
+ export function useBrowserColorScheme() {
9
+ const [theme, setTheme] = useState<'light' | 'dark'>(
10
+ query?.matches ? 'dark' : 'light',
11
+ )
12
+
13
+ useEffect(() => {
14
+ if (!query) return
15
+
16
+ const listener = () => {
17
+ setTheme(query.matches ? 'dark' : 'light')
18
+ }
19
+
20
+ query.addEventListener('change', listener)
21
+
22
+ return () => {
23
+ query.removeEventListener('change', listener)
24
+ }
25
+
26
+ // @NOTE "query" is a global constant and does not need to be part of the
27
+ // array bellow:
28
+ }, [])
29
+
30
+ return theme
31
+ }
@@ -1,4 +1,4 @@
1
- import { cookies } from '../cookies'
1
+ import { cookies } from '../cookies.ts'
2
2
 
3
3
  export function useCsrfToken(cookieName: string) {
4
4
  return cookies[cookieName]
@@ -0,0 +1,37 @@
1
+ import { useEffect, useState } from 'react'
2
+
3
+ export const UPPER = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
4
+ export const LOWER = UPPER.toLowerCase() as Lowercase<typeof UPPER>
5
+ export const DIGITS = '0123456789'
6
+
7
+ export const ALPHANUMERIC = `${UPPER}${LOWER}${DIGITS}` as const
8
+
9
+ export type UseRandomStringOptions = BuildRandomStringOptions & {
10
+ prefix?: string
11
+ suffix?: string
12
+ }
13
+
14
+ export function useRandomString(options?: UseRandomStringOptions) {
15
+ const [state, setState] = useState(() => buildRandomString(options))
16
+ useEffect(() => {
17
+ setState(buildRandomString(options))
18
+ }, [options?.length, options?.alphabet])
19
+
20
+ return `${options?.prefix ?? ''}${state}${options?.suffix ?? ''}`
21
+ }
22
+
23
+ type BuildRandomStringOptions = {
24
+ length?: number
25
+ alphabet?: string
26
+ }
27
+
28
+ function buildRandomString({
29
+ length = 16,
30
+ alphabet = ALPHANUMERIC,
31
+ }: BuildRandomStringOptions = {}) {
32
+ return Array.from({ length }, () => getRandomCharFrom(alphabet)).join('')
33
+ }
34
+
35
+ function getRandomCharFrom(alphabet: string) {
36
+ return alphabet.charAt((Math.random() * alphabet.length) | 0)
37
+ }
@@ -0,0 +1,87 @@
1
+ import { useCallback, useEffect, useState } from 'react'
2
+
3
+ export type DisabledStep = false | null | undefined
4
+ export type Step = {
5
+ invalid: boolean
6
+ }
7
+
8
+ const isEnabled = <S extends Step | DisabledStep>(
9
+ s: S,
10
+ ): s is S extends DisabledStep ? never : S => s != null && s !== false
11
+ const isRequired = <S extends Step | DisabledStep>(
12
+ s: S,
13
+ ): s is S extends DisabledStep ? never : S & { invalid: true } =>
14
+ isEnabled(s) && s.invalid === true
15
+ const isCompleted = <S extends Step | DisabledStep>(
16
+ s: S,
17
+ ): s is S extends DisabledStep ? S : S & { invalid: false } =>
18
+ !isEnabled(s) || s.invalid === false
19
+
20
+ export function useStepper<const S extends Step>(
21
+ steps: readonly (S | DisabledStep)[],
22
+ ) {
23
+ const firstIdx = steps.findIndex(isEnabled)
24
+ const lastIdx = steps.findLastIndex(isEnabled)
25
+ const requiredIdx = steps.findIndex(isRequired)
26
+
27
+ const [currentIdx, setCurrentIdx] = useState<number>(firstIdx)
28
+
29
+ const to = useCallback(
30
+ (idx: number) => {
31
+ if (idx !== -1 && steps[idx]) {
32
+ setCurrentIdx(idx)
33
+ return true
34
+ } else {
35
+ return false
36
+ }
37
+ },
38
+ [steps.map(isEnabled).join()],
39
+ )
40
+
41
+ const prevIdx = steps.findLastIndex((s, i) => isEnabled(s) && i < currentIdx)
42
+ const nextIdx = steps.findIndex((s, i) => isEnabled(s) && i > currentIdx)
43
+
44
+ const toFirst = useCallback(() => to(firstIdx), [to, firstIdx])
45
+ const toLast = useCallback(() => to(lastIdx), [to, lastIdx])
46
+ const toPrev = useCallback(() => to(prevIdx), [to, prevIdx])
47
+ const toNext = useCallback(() => to(nextIdx), [to, nextIdx])
48
+ const toRequired = useCallback(() => to(requiredIdx), [to, requiredIdx])
49
+
50
+ // Step number in user friendly terms (accounting for disabled steps)
51
+ const currentPosition =
52
+ currentIdx +
53
+ // use "1 indexed position" (for user friendliness):
54
+ 1 +
55
+ // Adjust the position by counting the number of disabled steps before the
56
+ // current step (if any):
57
+ steps.reduce(
58
+ (acc, s, i) => (i >= currentIdx || isEnabled(s) ? acc : acc - 1),
59
+ 0,
60
+ )
61
+
62
+ const count = steps.filter(isEnabled).length
63
+ const completed = steps.every(isCompleted)
64
+
65
+ const current =
66
+ currentIdx === -1 || !steps[currentIdx] ? undefined : steps[currentIdx]
67
+
68
+ // Fool-proof (reset current step in case the current step becomes disabled)
69
+ const broken = currentIdx === -1
70
+ useEffect(() => {
71
+ if (broken) toFirst()
72
+ }, [broken])
73
+
74
+ return {
75
+ current,
76
+ currentPosition,
77
+ count,
78
+ completed,
79
+ atFirst: currentPosition === 1,
80
+ atLast: currentPosition === count,
81
+ toFirst,
82
+ toLast,
83
+ toPrev,
84
+ toNext,
85
+ toRequired,
86
+ }
87
+ }
@@ -0,0 +1,182 @@
1
+ <!doctype html>
2
+ <html>
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <link rel="stylesheet" href="./main.css" />
7
+ <title>OAuth Provider</title>
8
+ </head>
9
+ <body>
10
+ <div id="root"></div>
11
+ <script>
12
+ /*
13
+ * This file's purpose is to provide a way to develop the UI without
14
+ * running a full featured OAuth server. It mocks the server responses and
15
+ * provides configuration data to the UI.
16
+ *
17
+ * This file is not part of the production build.
18
+ *
19
+ * Start the development server with the following command from the
20
+ * oauth-provider root:
21
+ *
22
+ * ```sh
23
+ * pnpm run start:ui
24
+ * ```
25
+ *
26
+ * Then open the browser at http://localhost:5173/
27
+ */
28
+ </script>
29
+ <style>
30
+ /*
31
+ * PDS branding configuration (colors), in R G B format.
32
+ *
33
+ * The variables here are meant to override the default values defined in
34
+ * main.css. These values are typically generated by the backend and
35
+ * injected into the HTML. The colors suffixed with "-c" denote the
36
+ * "contrast" color of the corresponding color name. These are also
37
+ * automatically generated by the backend from the branding colors.
38
+ *
39
+ * The default colors can be seen by commenting out a color name (and
40
+ * corresponding "-c" contrast color) below:
41
+ */
42
+ :root {
43
+ --color-brand: 10 122 255;
44
+ --color-brand-c: 255 255 255;
45
+ --color-error: 244 11 66;
46
+ --color-error-c: 255 255 255;
47
+ --color-warning: 251 86 7;
48
+ --color-warning-c: 255 255 255;
49
+ --color-success: 2 195 154;
50
+ --color-success-c: 0 0 0;
51
+ }
52
+ </style>
53
+ <script type="module">
54
+ /*
55
+ * PDS branding configuration
56
+ */
57
+
58
+ const name = 'Bluesky'
59
+ const links = [
60
+ {
61
+ title: { en: 'Home' },
62
+ href: 'https://bsky.social/',
63
+ rel: 'canonical', // prevents the login page from being indexed by search engines
64
+ },
65
+ {
66
+ title: { en: 'Terms of Service' },
67
+ href: 'https://bsky.social/about/support/tos',
68
+ rel: 'terms-of-service',
69
+ },
70
+ {
71
+ title: { en: 'Privacy Policy' },
72
+ href: 'https://bsky.social/about/support/privacy-policy',
73
+ rel: 'privacy-policy',
74
+ },
75
+ {
76
+ title: { en: 'Support' },
77
+ href: 'https://blueskyweb.zendesk.com/hc/en-us',
78
+ rel: 'help',
79
+ },
80
+ ]
81
+ const logo = `data:image/svg+xml,${encodeURIComponent('<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 320 286"><path fill="rgb(10,122,255)" d="M69.364 19.146c36.687 27.806 76.147 84.186 90.636 114.439 14.489-30.253 53.948-86.633 90.636-114.439C277.107-.917 320-16.44 320 32.957c0 9.865-5.603 82.875-8.889 94.729-11.423 41.208-53.045 51.719-90.071 45.357 64.719 11.12 81.182 47.953 45.627 84.785-80 82.874-106.667-44.333-106.667-44.333s-26.667 127.207-106.667 44.333c-35.555-36.832-19.092-73.665 45.627-84.785-37.026 6.362-78.648-4.149-90.071-45.357C5.603 115.832 0 42.822 0 32.957 0-16.44 42.893-.917 69.364 19.147Z" /></svg>')}`
82
+
83
+ // Provide a value here to test the "sing-in only" flow
84
+ const loginHint = undefined // 'alice.test'
85
+
86
+ // Use empty array to disable the "sing-up" flow, use a single value to
87
+ // disable the domain selector.
88
+ const availableUserDomains = ['.bsky.social', '.bsky.team']
89
+
90
+ // Use non empty string to enable hCaptcha during "sing-up" flow
91
+ const hcaptchaSiteKey = undefined
92
+
93
+ /*
94
+ * Client branding configuration
95
+ */
96
+
97
+ // Use an "http://" URL to test the "an app on your device" flow
98
+ const clientId = 'https://example.com/client.json'
99
+ const clientName = 'My App'
100
+ const clientPolicyUri = 'https://bsky.app'
101
+ const clientTosUri = 'https://bsky.app'
102
+ const clientLogoUri = 'https://bsky.app'
103
+
104
+ // Mock data
105
+
106
+ const requestUri = 'foo-bar'
107
+
108
+ document.cookie = `csrf-${requestUri}=xyz; path=/`
109
+
110
+ window.__customizationData = {
111
+ availableUserDomains,
112
+ inviteCodeRequired: false,
113
+ hcaptchaSiteKey,
114
+ name,
115
+ links,
116
+ logo,
117
+ }
118
+
119
+ window.__authorizeData = {
120
+ clientId: clientId,
121
+ clientMetadata: {
122
+ client_id: clientId,
123
+ client_name: clientName,
124
+ policy_uri: clientPolicyUri,
125
+ tos_uri: clientTosUri,
126
+ logo_uri: clientLogoUri,
127
+ },
128
+ clientTrusted: false,
129
+ requestUri,
130
+ loginHint,
131
+ newSessionsRequireConsent: true,
132
+ sessions: [],
133
+ scopeDetails: [
134
+ { scope: 'atproto' },
135
+ { scope: 'transition:generic' },
136
+ { scope: 'transition:chat.bsky' },
137
+ ],
138
+ }
139
+
140
+ const origFetch = window.fetch
141
+
142
+ async function mockFetch(...args) {
143
+ const [input, init] = args
144
+
145
+ if (typeof input === 'string' && init.method === 'POST') {
146
+ const url = new URL(input, window.location)
147
+ switch (url.pathname) {
148
+ case '/oauth/authorize/sign-up':
149
+ case '/oauth/authorize/sign-in':
150
+ return new Response(
151
+ JSON.stringify({
152
+ consentRequired: false,
153
+ account: {
154
+ sub: 'did:plc:123',
155
+ name: 'Alice',
156
+ email: 'alice@test.com',
157
+ email_verified: false,
158
+ preferred_username: 'alice.test',
159
+ picture: 'https://cat.com/cat.jpg',
160
+ },
161
+ }),
162
+ { status: 200 },
163
+ )
164
+ case '/oauth/authorize/verify-handle-availability':
165
+ case '/oauth/authorize/reset-password-request':
166
+ case '/oauth/authorize/reset-password-confirm':
167
+ return new Response(null, { status: 204 })
168
+ }
169
+ }
170
+
171
+ return origFetch.call(this, ...args)
172
+ }
173
+
174
+ Object.defineProperty(window, 'fetch', {
175
+ value: mockFetch,
176
+ writable: true,
177
+ configurable: true,
178
+ })
179
+ </script>
180
+ <script src="./main.tsx" type="module"></script>
181
+ </body>
182
+ </html>