@clerk/ui 1.30.8-canary.v20260824165645 → 1.30.8

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 (171) hide show
  1. package/dist/ClerkUI.js +2 -2
  2. package/dist/hooks/useProtectCheckRunner.js +9 -12
  3. package/dist/hooks/useProtectCheckRunner.js.map +1 -1
  4. package/dist/index.js +1 -1
  5. package/dist/no-rhc/ClerkUI.js +2 -2
  6. package/dist/no-rhc/hooks/useProtectCheckRunner.js +4 -0
  7. package/dist/no-rhc/hooks/useProtectCheckRunner.js.map +1 -1
  8. package/dist/no-rhc/index.js +1 -1
  9. package/dist/server.js +1 -1
  10. package/dist/{ui-common_ui_1dbfe3_1.30.8-canary.v20260824165645.js → ui-common_ui_2bc187_1.30.8.js} +1 -1
  11. package/dist/{ui-common_ui_ade811_1.30.8-canary.v20260824165645.js → ui-common_ui_4ade33_1.30.8.js} +3 -3
  12. package/dist/{ui-common_ui_de77f5_1.30.8-canary.v20260824165645.js → ui-common_ui_7b3895_1.30.8.js} +3 -3
  13. package/dist/ui.browser.js +2 -2
  14. package/dist/ui.legacy.browser.js +1 -1
  15. package/dist/ui.shared.browser.js +2 -2
  16. package/package.json +4 -4
  17. /package/dist/{4424_ui_1dbfe3_1.30.8-canary.v20260824165645.js → 4424_ui_2bc187_1.30.8.js} +0 -0
  18. /package/dist/{4424_ui_ade811_1.30.8-canary.v20260824165645.js → 4424_ui_4ade33_1.30.8.js} +0 -0
  19. /package/dist/{4424_ui_de77f5_1.30.8-canary.v20260824165645.js → 4424_ui_7b3895_1.30.8.js} +0 -0
  20. /package/dist/{4718_ui_1dbfe3_1.30.8-canary.v20260824165645.js → 4718_ui_2bc187_1.30.8.js} +0 -0
  21. /package/dist/{4718_ui_ade811_1.30.8-canary.v20260824165645.js → 4718_ui_4ade33_1.30.8.js} +0 -0
  22. /package/dist/{4718_ui_de77f5_1.30.8-canary.v20260824165645.js → 4718_ui_7b3895_1.30.8.js} +0 -0
  23. /package/dist/{6678_ui_1dbfe3_1.30.8-canary.v20260824165645.js → 6678_ui_2bc187_1.30.8.js} +0 -0
  24. /package/dist/{6678_ui_ade811_1.30.8-canary.v20260824165645.js → 6678_ui_4ade33_1.30.8.js} +0 -0
  25. /package/dist/{6678_ui_de77f5_1.30.8-canary.v20260824165645.js → 6678_ui_7b3895_1.30.8.js} +0 -0
  26. /package/dist/{7574_ui_1dbfe3_1.30.8-canary.v20260824165645.js → 7574_ui_2bc187_1.30.8.js} +0 -0
  27. /package/dist/{7574_ui_ade811_1.30.8-canary.v20260824165645.js → 7574_ui_4ade33_1.30.8.js} +0 -0
  28. /package/dist/{7574_ui_de77f5_1.30.8-canary.v20260824165645.js → 7574_ui_7b3895_1.30.8.js} +0 -0
  29. /package/dist/{8316_ui_1dbfe3_1.30.8-canary.v20260824165645.js → 8316_ui_2bc187_1.30.8.js} +0 -0
  30. /package/dist/{8316_ui_ade811_1.30.8-canary.v20260824165645.js → 8316_ui_4ade33_1.30.8.js} +0 -0
  31. /package/dist/{8316_ui_de77f5_1.30.8-canary.v20260824165645.js → 8316_ui_7b3895_1.30.8.js} +0 -0
  32. /package/dist/{8746_ui_1dbfe3_1.30.8-canary.v20260824165645.js → 8746_ui_2bc187_1.30.8.js} +0 -0
  33. /package/dist/{8746_ui_ade811_1.30.8-canary.v20260824165645.js → 8746_ui_4ade33_1.30.8.js} +0 -0
  34. /package/dist/{8746_ui_de77f5_1.30.8-canary.v20260824165645.js → 8746_ui_7b3895_1.30.8.js} +0 -0
  35. /package/dist/{9419_ui_1dbfe3_1.30.8-canary.v20260824165645.js → 9419_ui_2bc187_1.30.8.js} +0 -0
  36. /package/dist/{9419_ui_ade811_1.30.8-canary.v20260824165645.js → 9419_ui_4ade33_1.30.8.js} +0 -0
  37. /package/dist/{9419_ui_de77f5_1.30.8-canary.v20260824165645.js → 9419_ui_7b3895_1.30.8.js} +0 -0
  38. /package/dist/{980_ui_1dbfe3_1.30.8-canary.v20260824165645.js → 980_ui_2bc187_1.30.8.js} +0 -0
  39. /package/dist/{980_ui_ade811_1.30.8-canary.v20260824165645.js → 980_ui_4ade33_1.30.8.js} +0 -0
  40. /package/dist/{980_ui_de77f5_1.30.8-canary.v20260824165645.js → 980_ui_7b3895_1.30.8.js} +0 -0
  41. /package/dist/{apiKeys_ui_1dbfe3_1.30.8-canary.v20260824165645.js → apiKeys_ui_2bc187_1.30.8.js} +0 -0
  42. /package/dist/{apiKeys_ui_ade811_1.30.8-canary.v20260824165645.js → apiKeys_ui_4ade33_1.30.8.js} +0 -0
  43. /package/dist/{apiKeys_ui_de77f5_1.30.8-canary.v20260824165645.js → apiKeys_ui_7b3895_1.30.8.js} +0 -0
  44. /package/dist/{blankcaptcha_ui_1dbfe3_1.30.8-canary.v20260824165645.js → blankcaptcha_ui_2bc187_1.30.8.js} +0 -0
  45. /package/dist/{blankcaptcha_ui_ade811_1.30.8-canary.v20260824165645.js → blankcaptcha_ui_4ade33_1.30.8.js} +0 -0
  46. /package/dist/{blankcaptcha_ui_de77f5_1.30.8-canary.v20260824165645.js → blankcaptcha_ui_7b3895_1.30.8.js} +0 -0
  47. /package/dist/{checkout_ui_1dbfe3_1.30.8-canary.v20260824165645.js → checkout_ui_2bc187_1.30.8.js} +0 -0
  48. /package/dist/{checkout_ui_ade811_1.30.8-canary.v20260824165645.js → checkout_ui_4ade33_1.30.8.js} +0 -0
  49. /package/dist/{checkout_ui_de77f5_1.30.8-canary.v20260824165645.js → checkout_ui_7b3895_1.30.8.js} +0 -0
  50. /package/dist/{configureSSO_ui_1dbfe3_1.30.8-canary.v20260824165645.js → configureSSO_ui_2bc187_1.30.8.js} +0 -0
  51. /package/dist/{configureSSO_ui_ade811_1.30.8-canary.v20260824165645.js → configureSSO_ui_4ade33_1.30.8.js} +0 -0
  52. /package/dist/{configureSSO_ui_de77f5_1.30.8-canary.v20260824165645.js → configureSSO_ui_7b3895_1.30.8.js} +0 -0
  53. /package/dist/{copy-api-key-modal_ui_1dbfe3_1.30.8-canary.v20260824165645.js → copy-api-key-modal_ui_2bc187_1.30.8.js} +0 -0
  54. /package/dist/{copy-api-key-modal_ui_ade811_1.30.8-canary.v20260824165645.js → copy-api-key-modal_ui_4ade33_1.30.8.js} +0 -0
  55. /package/dist/{copy-api-key-modal_ui_de77f5_1.30.8-canary.v20260824165645.js → copy-api-key-modal_ui_7b3895_1.30.8.js} +0 -0
  56. /package/dist/{createorganization_ui_1dbfe3_1.30.8-canary.v20260824165645.js → createorganization_ui_2bc187_1.30.8.js} +0 -0
  57. /package/dist/{createorganization_ui_ade811_1.30.8-canary.v20260824165645.js → createorganization_ui_4ade33_1.30.8.js} +0 -0
  58. /package/dist/{createorganization_ui_de77f5_1.30.8-canary.v20260824165645.js → createorganization_ui_7b3895_1.30.8.js} +0 -0
  59. /package/dist/{credit-history-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → credit-history-page_ui_2bc187_1.30.8.js} +0 -0
  60. /package/dist/{credit-history-page_ui_ade811_1.30.8-canary.v20260824165645.js → credit-history-page_ui_4ade33_1.30.8.js} +0 -0
  61. /package/dist/{credit-history-page_ui_de77f5_1.30.8-canary.v20260824165645.js → credit-history-page_ui_7b3895_1.30.8.js} +0 -0
  62. /package/dist/{enableOrganizationsPrompt_ui_1dbfe3_1.30.8-canary.v20260824165645.js → enableOrganizationsPrompt_ui_2bc187_1.30.8.js} +0 -0
  63. /package/dist/{enableOrganizationsPrompt_ui_ade811_1.30.8-canary.v20260824165645.js → enableOrganizationsPrompt_ui_4ade33_1.30.8.js} +0 -0
  64. /package/dist/{enableOrganizationsPrompt_ui_de77f5_1.30.8-canary.v20260824165645.js → enableOrganizationsPrompt_ui_7b3895_1.30.8.js} +0 -0
  65. /package/dist/{framework_ui_1dbfe3_1.30.8-canary.v20260824165645.js → framework_ui_2bc187_1.30.8.js} +0 -0
  66. /package/dist/{framework_ui_ade811_1.30.8-canary.v20260824165645.js → framework_ui_4ade33_1.30.8.js} +0 -0
  67. /package/dist/{impersonationfab_ui_1dbfe3_1.30.8-canary.v20260824165645.js → impersonationfab_ui_2bc187_1.30.8.js} +0 -0
  68. /package/dist/{impersonationfab_ui_ade811_1.30.8-canary.v20260824165645.js → impersonationfab_ui_4ade33_1.30.8.js} +0 -0
  69. /package/dist/{impersonationfab_ui_de77f5_1.30.8-canary.v20260824165645.js → impersonationfab_ui_7b3895_1.30.8.js} +0 -0
  70. /package/dist/{invitemembers_ui_1dbfe3_1.30.8-canary.v20260824165645.js → invitemembers_ui_2bc187_1.30.8.js} +0 -0
  71. /package/dist/{invitemembers_ui_ade811_1.30.8-canary.v20260824165645.js → invitemembers_ui_4ade33_1.30.8.js} +0 -0
  72. /package/dist/{invitemembers_ui_de77f5_1.30.8-canary.v20260824165645.js → invitemembers_ui_7b3895_1.30.8.js} +0 -0
  73. /package/dist/{keylessPrompt_ui_1dbfe3_1.30.8-canary.v20260824165645.js → keylessPrompt_ui_2bc187_1.30.8.js} +0 -0
  74. /package/dist/{keylessPrompt_ui_ade811_1.30.8-canary.v20260824165645.js → keylessPrompt_ui_4ade33_1.30.8.js} +0 -0
  75. /package/dist/{keylessPrompt_ui_de77f5_1.30.8-canary.v20260824165645.js → keylessPrompt_ui_7b3895_1.30.8.js} +0 -0
  76. /package/dist/{oauthConsent_ui_1dbfe3_1.30.8-canary.v20260824165645.js → oauthConsent_ui_2bc187_1.30.8.js} +0 -0
  77. /package/dist/{oauthConsent_ui_ade811_1.30.8-canary.v20260824165645.js → oauthConsent_ui_4ade33_1.30.8.js} +0 -0
  78. /package/dist/{oauthConsent_ui_de77f5_1.30.8-canary.v20260824165645.js → oauthConsent_ui_7b3895_1.30.8.js} +0 -0
  79. /package/dist/{onetap_ui_1dbfe3_1.30.8-canary.v20260824165645.js → onetap_ui_2bc187_1.30.8.js} +0 -0
  80. /package/dist/{onetap_ui_ade811_1.30.8-canary.v20260824165645.js → onetap_ui_4ade33_1.30.8.js} +0 -0
  81. /package/dist/{onetap_ui_de77f5_1.30.8-canary.v20260824165645.js → onetap_ui_7b3895_1.30.8.js} +0 -0
  82. /package/dist/{op-api-keys-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → op-api-keys-page_ui_2bc187_1.30.8.js} +0 -0
  83. /package/dist/{op-api-keys-page_ui_ade811_1.30.8-canary.v20260824165645.js → op-api-keys-page_ui_4ade33_1.30.8.js} +0 -0
  84. /package/dist/{op-api-keys-page_ui_de77f5_1.30.8-canary.v20260824165645.js → op-api-keys-page_ui_7b3895_1.30.8.js} +0 -0
  85. /package/dist/{op-billing-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → op-billing-page_ui_2bc187_1.30.8.js} +0 -0
  86. /package/dist/{op-billing-page_ui_ade811_1.30.8-canary.v20260824165645.js → op-billing-page_ui_4ade33_1.30.8.js} +0 -0
  87. /package/dist/{op-billing-page_ui_de77f5_1.30.8-canary.v20260824165645.js → op-billing-page_ui_7b3895_1.30.8.js} +0 -0
  88. /package/dist/{op-plans-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → op-plans-page_ui_2bc187_1.30.8.js} +0 -0
  89. /package/dist/{op-plans-page_ui_ade811_1.30.8-canary.v20260824165645.js → op-plans-page_ui_4ade33_1.30.8.js} +0 -0
  90. /package/dist/{op-plans-page_ui_de77f5_1.30.8-canary.v20260824165645.js → op-plans-page_ui_7b3895_1.30.8.js} +0 -0
  91. /package/dist/{op-security-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → op-security-page_ui_2bc187_1.30.8.js} +0 -0
  92. /package/dist/{op-security-page_ui_ade811_1.30.8-canary.v20260824165645.js → op-security-page_ui_4ade33_1.30.8.js} +0 -0
  93. /package/dist/{op-security-page_ui_de77f5_1.30.8-canary.v20260824165645.js → op-security-page_ui_7b3895_1.30.8.js} +0 -0
  94. /package/dist/{organizationlist_ui_1dbfe3_1.30.8-canary.v20260824165645.js → organizationlist_ui_2bc187_1.30.8.js} +0 -0
  95. /package/dist/{organizationlist_ui_ade811_1.30.8-canary.v20260824165645.js → organizationlist_ui_4ade33_1.30.8.js} +0 -0
  96. /package/dist/{organizationlist_ui_de77f5_1.30.8-canary.v20260824165645.js → organizationlist_ui_7b3895_1.30.8.js} +0 -0
  97. /package/dist/{organizationprofile_ui_1dbfe3_1.30.8-canary.v20260824165645.js → organizationprofile_ui_2bc187_1.30.8.js} +0 -0
  98. /package/dist/{organizationprofile_ui_ade811_1.30.8-canary.v20260824165645.js → organizationprofile_ui_4ade33_1.30.8.js} +0 -0
  99. /package/dist/{organizationprofile_ui_de77f5_1.30.8-canary.v20260824165645.js → organizationprofile_ui_7b3895_1.30.8.js} +0 -0
  100. /package/dist/{organizationswitcher_ui_1dbfe3_1.30.8-canary.v20260824165645.js → organizationswitcher_ui_2bc187_1.30.8.js} +0 -0
  101. /package/dist/{organizationswitcher_ui_ade811_1.30.8-canary.v20260824165645.js → organizationswitcher_ui_4ade33_1.30.8.js} +0 -0
  102. /package/dist/{organizationswitcher_ui_de77f5_1.30.8-canary.v20260824165645.js → organizationswitcher_ui_7b3895_1.30.8.js} +0 -0
  103. /package/dist/{payment-attempt-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → payment-attempt-page_ui_2bc187_1.30.8.js} +0 -0
  104. /package/dist/{payment-attempt-page_ui_ade811_1.30.8-canary.v20260824165645.js → payment-attempt-page_ui_4ade33_1.30.8.js} +0 -0
  105. /package/dist/{payment-attempt-page_ui_de77f5_1.30.8-canary.v20260824165645.js → payment-attempt-page_ui_7b3895_1.30.8.js} +0 -0
  106. /package/dist/{planDetails_ui_1dbfe3_1.30.8-canary.v20260824165645.js → planDetails_ui_2bc187_1.30.8.js} +0 -0
  107. /package/dist/{planDetails_ui_ade811_1.30.8-canary.v20260824165645.js → planDetails_ui_4ade33_1.30.8.js} +0 -0
  108. /package/dist/{planDetails_ui_de77f5_1.30.8-canary.v20260824165645.js → planDetails_ui_7b3895_1.30.8.js} +0 -0
  109. /package/dist/{prefetchorganizationlist_ui_1dbfe3_1.30.8-canary.v20260824165645.js → prefetchorganizationlist_ui_2bc187_1.30.8.js} +0 -0
  110. /package/dist/{prefetchorganizationlist_ui_ade811_1.30.8-canary.v20260824165645.js → prefetchorganizationlist_ui_4ade33_1.30.8.js} +0 -0
  111. /package/dist/{prefetchorganizationlist_ui_de77f5_1.30.8-canary.v20260824165645.js → prefetchorganizationlist_ui_7b3895_1.30.8.js} +0 -0
  112. /package/dist/{pricingTable_ui_1dbfe3_1.30.8-canary.v20260824165645.js → pricingTable_ui_2bc187_1.30.8.js} +0 -0
  113. /package/dist/{pricingTable_ui_ade811_1.30.8-canary.v20260824165645.js → pricingTable_ui_4ade33_1.30.8.js} +0 -0
  114. /package/dist/{pricingTable_ui_de77f5_1.30.8-canary.v20260824165645.js → pricingTable_ui_7b3895_1.30.8.js} +0 -0
  115. /package/dist/{revoke-api-key-modal_ui_1dbfe3_1.30.8-canary.v20260824165645.js → revoke-api-key-modal_ui_2bc187_1.30.8.js} +0 -0
  116. /package/dist/{revoke-api-key-modal_ui_ade811_1.30.8-canary.v20260824165645.js → revoke-api-key-modal_ui_4ade33_1.30.8.js} +0 -0
  117. /package/dist/{revoke-api-key-modal_ui_de77f5_1.30.8-canary.v20260824165645.js → revoke-api-key-modal_ui_7b3895_1.30.8.js} +0 -0
  118. /package/dist/{sessionTasks_ui_1dbfe3_1.30.8-canary.v20260824165645.js → sessionTasks_ui_2bc187_1.30.8.js} +0 -0
  119. /package/dist/{sessionTasks_ui_ade811_1.30.8-canary.v20260824165645.js → sessionTasks_ui_4ade33_1.30.8.js} +0 -0
  120. /package/dist/{sessionTasks_ui_de77f5_1.30.8-canary.v20260824165645.js → sessionTasks_ui_7b3895_1.30.8.js} +0 -0
  121. /package/dist/{signin_ui_1dbfe3_1.30.8-canary.v20260824165645.js → signin_ui_2bc187_1.30.8.js} +0 -0
  122. /package/dist/{signin_ui_ade811_1.30.8-canary.v20260824165645.js → signin_ui_4ade33_1.30.8.js} +0 -0
  123. /package/dist/{signin_ui_de77f5_1.30.8-canary.v20260824165645.js → signin_ui_7b3895_1.30.8.js} +0 -0
  124. /package/dist/{signup_ui_1dbfe3_1.30.8-canary.v20260824165645.js → signup_ui_2bc187_1.30.8.js} +0 -0
  125. /package/dist/{signup_ui_ade811_1.30.8-canary.v20260824165645.js → signup_ui_4ade33_1.30.8.js} +0 -0
  126. /package/dist/{signup_ui_de77f5_1.30.8-canary.v20260824165645.js → signup_ui_7b3895_1.30.8.js} +0 -0
  127. /package/dist/{statement-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → statement-page_ui_2bc187_1.30.8.js} +0 -0
  128. /package/dist/{statement-page_ui_ade811_1.30.8-canary.v20260824165645.js → statement-page_ui_4ade33_1.30.8.js} +0 -0
  129. /package/dist/{statement-page_ui_de77f5_1.30.8-canary.v20260824165645.js → statement-page_ui_7b3895_1.30.8.js} +0 -0
  130. /package/dist/{subscriptionDetails_ui_1dbfe3_1.30.8-canary.v20260824165645.js → subscriptionDetails_ui_2bc187_1.30.8.js} +0 -0
  131. /package/dist/{subscriptionDetails_ui_ade811_1.30.8-canary.v20260824165645.js → subscriptionDetails_ui_4ade33_1.30.8.js} +0 -0
  132. /package/dist/{subscriptionDetails_ui_de77f5_1.30.8-canary.v20260824165645.js → subscriptionDetails_ui_7b3895_1.30.8.js} +0 -0
  133. /package/dist/{taskChooseOrganization_ui_1dbfe3_1.30.8-canary.v20260824165645.js → taskChooseOrganization_ui_2bc187_1.30.8.js} +0 -0
  134. /package/dist/{taskChooseOrganization_ui_ade811_1.30.8-canary.v20260824165645.js → taskChooseOrganization_ui_4ade33_1.30.8.js} +0 -0
  135. /package/dist/{taskChooseOrganization_ui_de77f5_1.30.8-canary.v20260824165645.js → taskChooseOrganization_ui_7b3895_1.30.8.js} +0 -0
  136. /package/dist/{taskResetPassword_ui_1dbfe3_1.30.8-canary.v20260824165645.js → taskResetPassword_ui_2bc187_1.30.8.js} +0 -0
  137. /package/dist/{taskResetPassword_ui_ade811_1.30.8-canary.v20260824165645.js → taskResetPassword_ui_4ade33_1.30.8.js} +0 -0
  138. /package/dist/{taskResetPassword_ui_de77f5_1.30.8-canary.v20260824165645.js → taskResetPassword_ui_7b3895_1.30.8.js} +0 -0
  139. /package/dist/{taskSetupMFA_ui_1dbfe3_1.30.8-canary.v20260824165645.js → taskSetupMFA_ui_2bc187_1.30.8.js} +0 -0
  140. /package/dist/{taskSetupMFA_ui_ade811_1.30.8-canary.v20260824165645.js → taskSetupMFA_ui_4ade33_1.30.8.js} +0 -0
  141. /package/dist/{taskSetupMFA_ui_de77f5_1.30.8-canary.v20260824165645.js → taskSetupMFA_ui_7b3895_1.30.8.js} +0 -0
  142. /package/dist/{up-api-keys-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → up-api-keys-page_ui_2bc187_1.30.8.js} +0 -0
  143. /package/dist/{up-api-keys-page_ui_ade811_1.30.8-canary.v20260824165645.js → up-api-keys-page_ui_4ade33_1.30.8.js} +0 -0
  144. /package/dist/{up-api-keys-page_ui_de77f5_1.30.8-canary.v20260824165645.js → up-api-keys-page_ui_7b3895_1.30.8.js} +0 -0
  145. /package/dist/{up-billing-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → up-billing-page_ui_2bc187_1.30.8.js} +0 -0
  146. /package/dist/{up-billing-page_ui_ade811_1.30.8-canary.v20260824165645.js → up-billing-page_ui_4ade33_1.30.8.js} +0 -0
  147. /package/dist/{up-billing-page_ui_de77f5_1.30.8-canary.v20260824165645.js → up-billing-page_ui_7b3895_1.30.8.js} +0 -0
  148. /package/dist/{up-plans-page_ui_1dbfe3_1.30.8-canary.v20260824165645.js → up-plans-page_ui_2bc187_1.30.8.js} +0 -0
  149. /package/dist/{up-plans-page_ui_ade811_1.30.8-canary.v20260824165645.js → up-plans-page_ui_4ade33_1.30.8.js} +0 -0
  150. /package/dist/{up-plans-page_ui_de77f5_1.30.8-canary.v20260824165645.js → up-plans-page_ui_7b3895_1.30.8.js} +0 -0
  151. /package/dist/{useravatar_ui_1dbfe3_1.30.8-canary.v20260824165645.js → useravatar_ui_2bc187_1.30.8.js} +0 -0
  152. /package/dist/{useravatar_ui_ade811_1.30.8-canary.v20260824165645.js → useravatar_ui_4ade33_1.30.8.js} +0 -0
  153. /package/dist/{useravatar_ui_de77f5_1.30.8-canary.v20260824165645.js → useravatar_ui_7b3895_1.30.8.js} +0 -0
  154. /package/dist/{userbutton_ui_1dbfe3_1.30.8-canary.v20260824165645.js → userbutton_ui_2bc187_1.30.8.js} +0 -0
  155. /package/dist/{userbutton_ui_ade811_1.30.8-canary.v20260824165645.js → userbutton_ui_4ade33_1.30.8.js} +0 -0
  156. /package/dist/{userbutton_ui_de77f5_1.30.8-canary.v20260824165645.js → userbutton_ui_7b3895_1.30.8.js} +0 -0
  157. /package/dist/{userprofile_ui_1dbfe3_1.30.8-canary.v20260824165645.js → userprofile_ui_2bc187_1.30.8.js} +0 -0
  158. /package/dist/{userprofile_ui_ade811_1.30.8-canary.v20260824165645.js → userprofile_ui_4ade33_1.30.8.js} +0 -0
  159. /package/dist/{userprofile_ui_de77f5_1.30.8-canary.v20260824165645.js → userprofile_ui_7b3895_1.30.8.js} +0 -0
  160. /package/dist/{userverification_ui_1dbfe3_1.30.8-canary.v20260824165645.js → userverification_ui_2bc187_1.30.8.js} +0 -0
  161. /package/dist/{userverification_ui_ade811_1.30.8-canary.v20260824165645.js → userverification_ui_4ade33_1.30.8.js} +0 -0
  162. /package/dist/{userverification_ui_de77f5_1.30.8-canary.v20260824165645.js → userverification_ui_7b3895_1.30.8.js} +0 -0
  163. /package/dist/{vendors_ui_1dbfe3_1.30.8-canary.v20260824165645.js → vendors_ui_2bc187_1.30.8.js} +0 -0
  164. /package/dist/{vendors_ui_ade811_1.30.8-canary.v20260824165645.js → vendors_ui_4ade33_1.30.8.js} +0 -0
  165. /package/dist/{vendors_ui_de77f5_1.30.8-canary.v20260824165645.js → vendors_ui_7b3895_1.30.8.js} +0 -0
  166. /package/dist/{waitlist_ui_1dbfe3_1.30.8-canary.v20260824165645.js → waitlist_ui_2bc187_1.30.8.js} +0 -0
  167. /package/dist/{waitlist_ui_ade811_1.30.8-canary.v20260824165645.js → waitlist_ui_4ade33_1.30.8.js} +0 -0
  168. /package/dist/{waitlist_ui_de77f5_1.30.8-canary.v20260824165645.js → waitlist_ui_7b3895_1.30.8.js} +0 -0
  169. /package/dist/{web3-solana-wallet-buttons_ui_1dbfe3_1.30.8-canary.v20260824165645.js → web3-solana-wallet-buttons_ui_2bc187_1.30.8.js} +0 -0
  170. /package/dist/{web3-solana-wallet-buttons_ui_ade811_1.30.8-canary.v20260824165645.js → web3-solana-wallet-buttons_ui_4ade33_1.30.8.js} +0 -0
  171. /package/dist/{web3-solana-wallet-buttons_ui_de77f5_1.30.8-canary.v20260824165645.js → web3-solana-wallet-buttons_ui_7b3895_1.30.8.js} +0 -0
package/dist/ClerkUI.js CHANGED
@@ -22,8 +22,8 @@ import { isVersionAtLeast, parseVersion } from "@clerk/shared/versionCheck";
22
22
  * @public
23
23
  */
24
24
  var ClerkUI = class ClerkUI {
25
- static version = "1.30.8-canary.v20260824165645";
26
- version = "1.30.8-canary.v20260824165645";
25
+ static version = "1.30.8";
26
+ version = "1.30.8";
27
27
  #componentRenderer;
28
28
  /**
29
29
  * Creates a new `ClerkUI` instance and mounts the internal component renderer.
@@ -1,8 +1,10 @@
1
+ import { useEnvironment } from "../contexts/EnvironmentContext.js";
1
2
  import { useCardState } from "../elements/contexts/index.js";
2
3
  import { handleError } from "../utils/errorHandler.js";
3
4
  import { ClerkRuntimeError, isClerkAPIResponseError } from "@clerk/shared/error";
4
5
  import React from "react";
5
6
  import { ERROR_CODES } from "@clerk/shared/internal/clerk-js/constants";
7
+ import { useClerk } from "@clerk/shared/react";
6
8
  import { flushSync } from "react-dom";
7
9
 
8
10
  //#region src/hooks/useProtectCheckRunner.ts
@@ -15,8 +17,6 @@ import { flushSync } from "react-dom";
15
17
  * being decided with the clerk_go team; this cap is the defensive floor until that lands.
16
18
  */
17
19
  const MAX_EXPIRED_RELOADS = 2;
18
- /** Upper bound on how long we wait for the challenge SDK to settle before failing loud. */
19
- const PROTECT_CHECK_SCRIPT_TIMEOUT_MS = 6e4;
20
20
  /**
21
21
  * Shared driver for the `<SignInProtectCheck />` and `<SignUpProtectCheck />` cards. Both run the
22
22
  * exact same lifecycle — load + execute the Protect SDK, submit the proof token, continue the flow
@@ -27,6 +27,9 @@ const PROTECT_CHECK_SCRIPT_TIMEOUT_MS = 6e4;
27
27
  */
28
28
  function useProtectCheckRunner(params) {
29
29
  const card = useCardState();
30
+ const loaderTimeoutMs = useClerk().__internal_protectChallengeLoadTimeoutMs;
31
+ const instanceTimeoutMs = useEnvironment().protectConfig?.challenge_load_timeout_ms;
32
+ const loadTimeoutMs = loaderTimeoutMs ?? instanceTimeoutMs;
30
33
  const reportError = (err) => {
31
34
  try {
32
35
  handleError(err, [], card.setError);
@@ -105,18 +108,13 @@ function useProtectCheckRunner(params) {
105
108
  isRunningRef.current = true;
106
109
  setIsRunning(true);
107
110
  const runChallenge = async () => {
108
- let timeoutId;
109
111
  try {
110
112
  const { executeProtectCheck } = await import("@clerk/shared/internal/clerk-js/protectCheck");
111
- const proofToken = await Promise.race([executeProtectCheck(protectCheck, container, {
113
+ const proofToken = await executeProtectCheck(protectCheck, container, {
112
114
  signal: abortController.signal,
113
- setWidgetVisible
114
- }), new Promise((_, reject) => {
115
- timeoutId = setTimeout(() => {
116
- abortController.abort();
117
- reject(new ClerkRuntimeError("Protect verification timed out", { code: ERROR_CODES.PROTECT_CHECK_TIMED_OUT }));
118
- }, PROTECT_CHECK_SCRIPT_TIMEOUT_MS);
119
- })]);
115
+ setWidgetVisible,
116
+ loadTimeoutMs
117
+ });
120
118
  if (cancelled) return;
121
119
  let updatedResource;
122
120
  try {
@@ -137,7 +135,6 @@ function useProtectCheckRunner(params) {
137
135
  if (cancelled) return;
138
136
  reportError(err);
139
137
  } finally {
140
- if (timeoutId) clearTimeout(timeoutId);
141
138
  if (!cancelled) {
142
139
  isRunningRef.current = false;
143
140
  setIsRunning(false);
@@ -1 +1 @@
1
- {"version":3,"file":"useProtectCheckRunner.js","names":[],"sources":["../../src/hooks/useProtectCheckRunner.ts"],"sourcesContent":["import { ClerkRuntimeError, isClerkAPIResponseError } from '@clerk/shared/error';\nimport { ERROR_CODES } from '@clerk/shared/internal/clerk-js/constants';\nimport type { ProtectCheckResource } from '@clerk/shared/types';\nimport React from 'react';\nimport { flushSync } from 'react-dom';\n\nimport { useCardState } from '@/ui/elements/contexts';\nimport { handleError } from '@/ui/utils/errorHandler';\n\n/**\n * A plain GET reload does not re-mint a protect_check challenge server-side, so an expired\n * challenge would otherwise reload → still expired → reload again, forever. Cap the attempts\n * and surface an error instead of spinning silently.\n *\n * NOTE: who re-mints an expired challenge on read (FAPI vs. re-running the gated step) is still\n * being decided with the clerk_go team; this cap is the defensive floor until that lands.\n */\nconst MAX_EXPIRED_RELOADS = 2;\n\n/** Upper bound on how long we wait for the challenge SDK to settle before failing loud. */\nconst PROTECT_CHECK_SCRIPT_TIMEOUT_MS = 60_000;\n\nexport interface ProtectCheckRunnerParams<TResource> {\n /**\n * Reads the current protect_check off the resource. Called fresh on each effect run because\n * `fromJSON` mints a new object on every resource update — we key the effect on the token, not\n * this reference, so an unrelated refresh doesn't restart the challenge under the user.\n */\n getProtectCheck: () => ProtectCheckResource | null | undefined;\n /** Returns the live resource, used to route after a reload (which mutates it in place). */\n getResource: () => TResource;\n /** Reloads the underlying resource (GET) to pick up fresh server state. */\n reload: () => Promise<unknown>;\n /** Submits the proof token; resolves to the updated resource. */\n submitProtectCheck: (params: { proofToken: string }) => Promise<TResource>;\n /**\n * Continues the flow once the gate clears (or a chained challenge / already-resolved is\n * detected). Receives the resource to route on (the `submitProtectCheck` result, or the live\n * resource after a reload) and must finalize (`setActive`) the `complete` case itself.\n * `isCancelled` lets the continuation bail if the component unmounted mid-await.\n */\n onResolved: (resource: TResource, isCancelled: () => boolean) => Promise<unknown>;\n}\n\nexport interface ProtectCheckRunner {\n containerRef: React.MutableRefObject<HTMLDivElement | null>;\n isRunning: boolean;\n /**\n * Whether the challenge script has signalled (via the `setWidgetVisible` init callback) that\n * it is showing a widget in the container. While true, the widget owns the progress UI —\n * callers should hide their own spinner and give the container layout space.\n */\n isWidgetVisible: boolean;\n /** Whether the card is currently showing a (recoverable) error. */\n hasError: boolean;\n /** Clears the error and re-runs the challenge from scratch. */\n retry: () => void;\n}\n\n/**\n * Shared driver for the `<SignInProtectCheck />` and `<SignUpProtectCheck />` cards. Both run the\n * exact same lifecycle — load + execute the Protect SDK, submit the proof token, continue the flow\n * — so the abort/cancel/expiry/timeout/no-RHC handling lives here once instead of being duplicated\n * (and drifting) across the two components.\n *\n * Must be called from within a `CardStateProvider`.\n */\nexport function useProtectCheckRunner<TResource>(params: ProtectCheckRunnerParams<TResource>): ProtectCheckRunner {\n const card = useCardState();\n\n // `handleError` re-throws what it does not recognise, and this runner awaits caller code that\n // raises plain errors (a transient fetch failure, an OAuth continuation that did not complete).\n const reportError = (err: any) => {\n try {\n handleError(err, [], card.setError);\n } catch {\n card.setError('Unable to complete action at this time. If the problem persists please contact support.');\n }\n };\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n const isRunningRef = React.useRef(false);\n const reloadCountRef = React.useRef(0);\n const [isRunning, setIsRunning] = React.useState(false);\n const [isWidgetVisible, setIsWidgetVisibleState] = React.useState(false);\n const [retryNonce, setRetryNonce] = React.useState(0);\n\n // Tracks real unmount, distinct from the per-run `cancelled` flag below. Clearing `protectCheck`\n // (e.g. an expired-challenge reload that advances the flow) flips the token dependency and\n // re-runs/cancels the main effect — but that re-run is exactly our cue to route, so the routing\n // must key on actual unmount, not on the effect's cancel flag.\n const mountedRef = React.useRef(true);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n // Keep the latest callbacks without re-running the effect when the caller re-renders.\n const paramsRef = React.useRef(params);\n paramsRef.current = params;\n\n const token = params.getProtectCheck()?.token;\n\n React.useEffect(() => {\n const { getProtectCheck, getResource, reload, submitProtectCheck, onResolved } = paramsRef.current;\n const protectCheck = getProtectCheck();\n if (!protectCheck || isRunningRef.current) {\n return;\n }\n\n const abortController = new AbortController();\n let cancelled = false;\n // Routing after the gate clears must survive the effect re-run that\n // clearing `protectCheck` triggers — that re-run is our cue to route, not a\n // reason to bail. So the onResolved paths below key on REAL unmount, not the\n // effect's per-run `cancelled` flag (which the re-run's cleanup sets). Same\n // rationale the expired-reload path already relies on above.\n const isUnmounted = () => !mountedRef.current;\n\n const cleanup = () => {\n cancelled = true;\n abortController.abort();\n // Reset the guard so the next mount / token change / retry can re-run; this is what makes\n // chained challenges work correctly across re-renders.\n isRunningRef.current = false;\n };\n\n const failWith = (code: string, message: string) => {\n isRunningRef.current = false;\n setIsRunning(false);\n handleError(new ClerkRuntimeError(message, { code }), [], card.setError);\n };\n\n // The script owns the widget-visibility decision: it receives this callback in its init\n // payload (as `setWidgetVisible`) and calls it right before revealing UI in the container,\n // and again with `false` once its widget is done. flushSync so the returned promise only\n // resolves after the change is committed to the DOM — the caller's spinner is genuinely\n // gone when the script reveals its widget, with no frame of overlap (same guarantee\n // BaseRouter relies on flushSync for). Scoped to THIS run: the abort contract is\n // best-effort, so a zombie script from a timed-out, retried, or superseded run can still\n // call it late — those signals must not flip visibility under the active run.\n const setWidgetVisible = (visible: boolean): Promise<void> => {\n if (cancelled || abortController.signal.aborted || !mountedRef.current) {\n return Promise.resolve();\n }\n flushSync(() => setIsWidgetVisibleState(visible));\n return Promise.resolve();\n };\n\n // Fail closed in no-RHC builds (chrome extension / clerk.no-rhc.js): the gate requires a\n // remote `import(sdk_url)` we must not perform there. This guard MUST live in the component\n // layer — `executeProtectCheck` is in `@clerk/shared`, compiled once with the flag hard-coded\n // `false`, so a guard there would never trip.\n if (__BUILD_DISABLE_RHC__) {\n failWith(\n ERROR_CODES.PROTECT_CHECK_UNSUPPORTED_ENVIRONMENT,\n 'Protect verification is not supported in this environment',\n );\n return;\n }\n\n // Expired challenge: reload once to pick up a fresh challenge if the server minted one, but\n // cap the attempts (see MAX_EXPIRED_RELOADS) so a server that returns the same expired\n // challenge on read can't spin us forever.\n if (protectCheck.expiresAt !== undefined && protectCheck.expiresAt < Date.now()) {\n if (reloadCountRef.current >= MAX_EXPIRED_RELOADS) {\n failWith(ERROR_CODES.PROTECT_CHECK_TIMED_OUT, 'Protect verification expired');\n return;\n }\n reloadCountRef.current += 1;\n isRunningRef.current = true;\n setIsRunning(true);\n void (async () => {\n try {\n await reload();\n if (!mountedRef.current) {\n return;\n }\n const refreshed = getProtectCheck();\n const stillExpired = !!refreshed && refreshed.expiresAt !== undefined && refreshed.expiresAt < Date.now();\n if (stillExpired) {\n // The server didn't re-mint on read. Don't sit on a spinner — fail loud so the user\n // gets a retry instead of an indefinite wait.\n failWith(ERROR_CODES.PROTECT_CHECK_TIMED_OUT, 'Protect verification expired');\n } else if (!refreshed) {\n // The reload cleared the gate or completed the flow. Route on the refreshed live\n // resource so the flow continues (and a completed sign-in still gets `setActive`)\n // instead of the route guard bouncing the user back to flow start. Keyed on mount (not\n // `cancelled`): clearing protectCheck re-runs/cancels this effect, and that re-run is\n // our signal to route — it must not abort the routing.\n await onResolved(getResource(), () => !mountedRef.current);\n }\n // Otherwise the server re-minted a fresh, non-expired challenge whose new token\n // re-triggers this effect (keyed on the token), which then runs it.\n } catch (err: any) {\n if (mountedRef.current) {\n reportError(err);\n }\n } finally {\n if (mountedRef.current) {\n isRunningRef.current = false;\n setIsRunning(false);\n }\n }\n })();\n return cleanup;\n }\n\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n // This run owns the container outright: drop anything a previous run left behind (a solved or\n // errored widget) so the spinner covers the load phase and a re-rendering SDK can't stack a\n // second widget under a stale one. Reset visibility in the same breath — the container is\n // empty by construction here, and waiting on the observer callback would leave the state\n // stale for a scheduling-dependent window (especially on the MutationObserver fallback).\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n setIsWidgetVisibleState(false);\n\n isRunningRef.current = true;\n setIsRunning(true);\n\n const runChallenge = async () => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n try {\n // Load the Protect SDK loader lazily, gated on the same compile-time flag as the\n // fail-closed guard above. In no-RHC builds `__BUILD_DISABLE_RHC__` is `true`, so this\n // branch (and the dynamic `import()` below it) is dead-code-eliminated — the loader and\n // its remote `import(sdk_url)` are tree-shaken out of those bundles entirely rather than\n // merely shipped-but-unused.\n if (__BUILD_DISABLE_RHC__) {\n return;\n }\n const { executeProtectCheck } = await import('@clerk/shared/internal/clerk-js/protectCheck');\n const proofToken = await Promise.race([\n executeProtectCheck(protectCheck, container, { signal: abortController.signal, setWidgetVisible }),\n new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n // Stop the (possibly hung) SDK and surface a retryable timeout error.\n abortController.abort();\n reject(\n new ClerkRuntimeError('Protect verification timed out', {\n code: ERROR_CODES.PROTECT_CHECK_TIMED_OUT,\n }),\n );\n }, PROTECT_CHECK_SCRIPT_TIMEOUT_MS);\n }),\n ]);\n if (cancelled) {\n return;\n }\n\n let updatedResource: TResource;\n try {\n updatedResource = await submitProtectCheck({ proofToken });\n } catch (err) {\n if (cancelled) {\n return;\n }\n // `protect_check_already_resolved` is retry-safe: the server's state has already moved\n // past this gate. Reload to clear the stale local protectCheck, then continue routing on\n // the refreshed live resource.\n if (isClerkAPIResponseError(err) && err.errors?.[0]?.code === ERROR_CODES.PROTECT_CHECK_ALREADY_RESOLVED) {\n await reload();\n if (isUnmounted()) {\n return;\n }\n await onResolved(getResource(), isUnmounted);\n return;\n }\n throw err;\n }\n if (isUnmounted()) {\n return;\n }\n await onResolved(updatedResource, isUnmounted);\n } catch (err: any) {\n if (cancelled) {\n return;\n }\n reportError(err);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n if (!cancelled) {\n isRunningRef.current = false;\n setIsRunning(false);\n }\n }\n };\n\n void runChallenge();\n return cleanup;\n // Keyed on the challenge token (a primitive) rather than the protectCheck object: an unrelated\n // resource refresh keeps the same token and must NOT restart the challenge, while a genuine\n // chained challenge carries a new token and re-runs. `retryNonce` re-runs on manual retry.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [token, retryNonce]);\n\n const retry = React.useCallback(() => {\n card.setError('');\n reloadCountRef.current = 0;\n isRunningRef.current = false;\n setRetryNonce(n => n + 1);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { containerRef, isRunning, isWidgetVisible, hasError: !!card.error, retry };\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"useProtectCheckRunner.js","names":[],"sources":["../../src/hooks/useProtectCheckRunner.ts"],"sourcesContent":["import { ClerkRuntimeError, isClerkAPIResponseError } from '@clerk/shared/error';\nimport { ERROR_CODES } from '@clerk/shared/internal/clerk-js/constants';\nimport { useClerk } from '@clerk/shared/react';\nimport type { ProtectCheckResource } from '@clerk/shared/types';\nimport React from 'react';\nimport { flushSync } from 'react-dom';\n\nimport { useEnvironment } from '@/ui/contexts/EnvironmentContext';\nimport { useCardState } from '@/ui/elements/contexts';\nimport { handleError } from '@/ui/utils/errorHandler';\n\n/**\n * A plain GET reload does not re-mint a protect_check challenge server-side, so an expired\n * challenge would otherwise reload → still expired → reload again, forever. Cap the attempts\n * and surface an error instead of spinning silently.\n *\n * NOTE: who re-mints an expired challenge on read (FAPI vs. re-running the gated step) is still\n * being decided with the clerk_go team; this cap is the defensive floor until that lands.\n */\nconst MAX_EXPIRED_RELOADS = 2;\n\nexport interface ProtectCheckRunnerParams<TResource> {\n /**\n * Reads the current protect_check off the resource. Called fresh on each effect run because\n * `fromJSON` mints a new object on every resource update — we key the effect on the token, not\n * this reference, so an unrelated refresh doesn't restart the challenge under the user.\n */\n getProtectCheck: () => ProtectCheckResource | null | undefined;\n /** Returns the live resource, used to route after a reload (which mutates it in place). */\n getResource: () => TResource;\n /** Reloads the underlying resource (GET) to pick up fresh server state. */\n reload: () => Promise<unknown>;\n /** Submits the proof token; resolves to the updated resource. */\n submitProtectCheck: (params: { proofToken: string }) => Promise<TResource>;\n /**\n * Continues the flow once the gate clears (or a chained challenge / already-resolved is\n * detected). Receives the resource to route on (the `submitProtectCheck` result, or the live\n * resource after a reload) and must finalize (`setActive`) the `complete` case itself.\n * `isCancelled` lets the continuation bail if the component unmounted mid-await.\n */\n onResolved: (resource: TResource, isCancelled: () => boolean) => Promise<unknown>;\n}\n\nexport interface ProtectCheckRunner {\n containerRef: React.MutableRefObject<HTMLDivElement | null>;\n isRunning: boolean;\n /**\n * Whether the challenge script has signalled (via the `setWidgetVisible` init callback) that\n * it is showing a widget in the container. While true, the widget owns the progress UI —\n * callers should hide their own spinner and give the container layout space.\n */\n isWidgetVisible: boolean;\n /** Whether the card is currently showing a (recoverable) error. */\n hasError: boolean;\n /** Clears the error and re-runs the challenge from scratch. */\n retry: () => void;\n}\n\n/**\n * Shared driver for the `<SignInProtectCheck />` and `<SignUpProtectCheck />` cards. Both run the\n * exact same lifecycle — load + execute the Protect SDK, submit the proof token, continue the flow\n * — so the abort/cancel/expiry/timeout/no-RHC handling lives here once instead of being duplicated\n * (and drifting) across the two components.\n *\n * Must be called from within a `CardStateProvider`.\n */\nexport function useProtectCheckRunner<TResource>(params: ProtectCheckRunnerParams<TResource>): ProtectCheckRunner {\n const card = useCardState();\n\n // Override for the module-LOAD bound only (see `executeProtectCheck`), resolved loader first\n // and instance second: a loader being rolled out gradually can carry its own value without\n // changing anything for browsers still on the loader it replaces. Undefined at both levels\n // leaves the SDK default in force. Read here rather than inside the effect so the effect keeps\n // depending on primitives.\n // Older clerk-js versions omit this getter; undefined preserves the instance/default fallback.\n const loaderTimeoutMs = useClerk().__internal_protectChallengeLoadTimeoutMs;\n const instanceTimeoutMs = useEnvironment().protectConfig?.challenge_load_timeout_ms;\n const loadTimeoutMs = loaderTimeoutMs ?? instanceTimeoutMs;\n\n // `handleError` re-throws what it does not recognise, and this runner awaits caller code that\n // raises plain errors (a transient fetch failure, an OAuth continuation that did not complete).\n const reportError = (err: any) => {\n try {\n handleError(err, [], card.setError);\n } catch {\n card.setError('Unable to complete action at this time. If the problem persists please contact support.');\n }\n };\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n const isRunningRef = React.useRef(false);\n const reloadCountRef = React.useRef(0);\n const [isRunning, setIsRunning] = React.useState(false);\n const [isWidgetVisible, setIsWidgetVisibleState] = React.useState(false);\n const [retryNonce, setRetryNonce] = React.useState(0);\n\n // Tracks real unmount, distinct from the per-run `cancelled` flag below. Clearing `protectCheck`\n // (e.g. an expired-challenge reload that advances the flow) flips the token dependency and\n // re-runs/cancels the main effect — but that re-run is exactly our cue to route, so the routing\n // must key on actual unmount, not on the effect's cancel flag.\n const mountedRef = React.useRef(true);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n // Keep the latest callbacks without re-running the effect when the caller re-renders.\n const paramsRef = React.useRef(params);\n paramsRef.current = params;\n\n const token = params.getProtectCheck()?.token;\n\n React.useEffect(() => {\n const { getProtectCheck, getResource, reload, submitProtectCheck, onResolved } = paramsRef.current;\n const protectCheck = getProtectCheck();\n if (!protectCheck || isRunningRef.current) {\n return;\n }\n\n const abortController = new AbortController();\n let cancelled = false;\n // Routing after the gate clears must survive the effect re-run that\n // clearing `protectCheck` triggers — that re-run is our cue to route, not a\n // reason to bail. So the onResolved paths below key on REAL unmount, not the\n // effect's per-run `cancelled` flag (which the re-run's cleanup sets). Same\n // rationale the expired-reload path already relies on above.\n const isUnmounted = () => !mountedRef.current;\n\n const cleanup = () => {\n cancelled = true;\n abortController.abort();\n // Reset the guard so the next mount / token change / retry can re-run; this is what makes\n // chained challenges work correctly across re-renders.\n isRunningRef.current = false;\n };\n\n const failWith = (code: string, message: string) => {\n isRunningRef.current = false;\n setIsRunning(false);\n handleError(new ClerkRuntimeError(message, { code }), [], card.setError);\n };\n\n // The script owns the widget-visibility decision: it receives this callback in its init\n // payload (as `setWidgetVisible`) and calls it right before revealing UI in the container,\n // and again with `false` once its widget is done. flushSync so the returned promise only\n // resolves after the change is committed to the DOM — the caller's spinner is genuinely\n // gone when the script reveals its widget, with no frame of overlap (same guarantee\n // BaseRouter relies on flushSync for). Scoped to THIS run: the abort contract is\n // best-effort, so a zombie script from a timed-out, retried, or superseded run can still\n // call it late — those signals must not flip visibility under the active run.\n const setWidgetVisible = (visible: boolean): Promise<void> => {\n if (cancelled || abortController.signal.aborted || !mountedRef.current) {\n return Promise.resolve();\n }\n flushSync(() => setIsWidgetVisibleState(visible));\n return Promise.resolve();\n };\n\n // Fail closed in no-RHC builds (chrome extension / clerk.no-rhc.js): the gate requires a\n // remote `import(sdk_url)` we must not perform there. This guard MUST live in the component\n // layer — `executeProtectCheck` is in `@clerk/shared`, compiled once with the flag hard-coded\n // `false`, so a guard there would never trip.\n if (__BUILD_DISABLE_RHC__) {\n failWith(\n ERROR_CODES.PROTECT_CHECK_UNSUPPORTED_ENVIRONMENT,\n 'Protect verification is not supported in this environment',\n );\n return;\n }\n\n // Expired challenge: reload once to pick up a fresh challenge if the server minted one, but\n // cap the attempts (see MAX_EXPIRED_RELOADS) so a server that returns the same expired\n // challenge on read can't spin us forever.\n if (protectCheck.expiresAt !== undefined && protectCheck.expiresAt < Date.now()) {\n if (reloadCountRef.current >= MAX_EXPIRED_RELOADS) {\n failWith(ERROR_CODES.PROTECT_CHECK_TIMED_OUT, 'Protect verification expired');\n return;\n }\n reloadCountRef.current += 1;\n isRunningRef.current = true;\n setIsRunning(true);\n void (async () => {\n try {\n await reload();\n if (!mountedRef.current) {\n return;\n }\n const refreshed = getProtectCheck();\n const stillExpired = !!refreshed && refreshed.expiresAt !== undefined && refreshed.expiresAt < Date.now();\n if (stillExpired) {\n // The server didn't re-mint on read. Don't sit on a spinner — fail loud so the user\n // gets a retry instead of an indefinite wait.\n failWith(ERROR_CODES.PROTECT_CHECK_TIMED_OUT, 'Protect verification expired');\n } else if (!refreshed) {\n // The reload cleared the gate or completed the flow. Route on the refreshed live\n // resource so the flow continues (and a completed sign-in still gets `setActive`)\n // instead of the route guard bouncing the user back to flow start. Keyed on mount (not\n // `cancelled`): clearing protectCheck re-runs/cancels this effect, and that re-run is\n // our signal to route — it must not abort the routing.\n await onResolved(getResource(), () => !mountedRef.current);\n }\n // Otherwise the server re-minted a fresh, non-expired challenge whose new token\n // re-triggers this effect (keyed on the token), which then runs it.\n } catch (err: any) {\n if (mountedRef.current) {\n reportError(err);\n }\n } finally {\n if (mountedRef.current) {\n isRunningRef.current = false;\n setIsRunning(false);\n }\n }\n })();\n return cleanup;\n }\n\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n // This run owns the container outright: drop anything a previous run left behind (a solved or\n // errored widget) so the spinner covers the load phase and a re-rendering SDK can't stack a\n // second widget under a stale one. Reset visibility in the same breath — the container is\n // empty by construction here, and waiting on the observer callback would leave the state\n // stale for a scheduling-dependent window (especially on the MutationObserver fallback).\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n setIsWidgetVisibleState(false);\n\n isRunningRef.current = true;\n setIsRunning(true);\n\n const runChallenge = async () => {\n try {\n // Load the Protect SDK loader lazily, gated on the same compile-time flag as the\n // fail-closed guard above. In no-RHC builds `__BUILD_DISABLE_RHC__` is `true`, so this\n // branch (and the dynamic `import()` below it) is dead-code-eliminated — the loader and\n // its remote `import(sdk_url)` are tree-shaken out of those bundles entirely rather than\n // merely shipped-but-unused.\n if (__BUILD_DISABLE_RHC__) {\n return;\n }\n const { executeProtectCheck } = await import('@clerk/shared/internal/clerk-js/protectCheck');\n // Deliberately unraced. `executeProtectCheck` bounds LOADING the challenge module and\n // nothing after it: once control passes to the challenge, the challenge owns its own\n // deadline. We cannot know an honest duration for it — the challenge type is chosen\n // server-side, per decision, long after this bundle shipped, and its work may be waiting\n // on a person or moving a server-chosen number of bytes over a link we know nothing\n // about. The wall that used to be here aborted valid challenges and reported them to the\n // user as a timeout, and since a re-run restarts the work from the beginning, retrying\n // could never win on any connection slow enough to trip it in the first place.\n const proofToken = await executeProtectCheck(protectCheck, container, {\n signal: abortController.signal,\n setWidgetVisible,\n loadTimeoutMs,\n });\n if (cancelled) {\n return;\n }\n\n let updatedResource: TResource;\n try {\n updatedResource = await submitProtectCheck({ proofToken });\n } catch (err) {\n if (cancelled) {\n return;\n }\n // `protect_check_already_resolved` is retry-safe: the server's state has already moved\n // past this gate. Reload to clear the stale local protectCheck, then continue routing on\n // the refreshed live resource.\n if (isClerkAPIResponseError(err) && err.errors?.[0]?.code === ERROR_CODES.PROTECT_CHECK_ALREADY_RESOLVED) {\n await reload();\n if (isUnmounted()) {\n return;\n }\n await onResolved(getResource(), isUnmounted);\n return;\n }\n throw err;\n }\n if (isUnmounted()) {\n return;\n }\n await onResolved(updatedResource, isUnmounted);\n } catch (err: any) {\n if (cancelled) {\n return;\n }\n reportError(err);\n } finally {\n if (!cancelled) {\n isRunningRef.current = false;\n setIsRunning(false);\n }\n }\n };\n\n void runChallenge();\n return cleanup;\n // Keyed on the challenge token (a primitive) rather than the protectCheck object: an unrelated\n // resource refresh keeps the same token and must NOT restart the challenge, while a genuine\n // chained challenge carries a new token and re-runs. `retryNonce` re-runs on manual retry.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [token, retryNonce]);\n\n const retry = React.useCallback(() => {\n card.setError('');\n reloadCountRef.current = 0;\n isRunningRef.current = false;\n setRetryNonce(n => n + 1);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { containerRef, isRunning, isWidgetVisible, hasError: !!card.error, retry };\n}\n"],"mappings":"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"}
package/dist/index.js CHANGED
@@ -17,7 +17,7 @@ import { ClerkUI } from "./ClerkUI.js";
17
17
  */
18
18
  const ui = {
19
19
  __brand: UI_BRAND,
20
- version: "1.30.8-canary.v20260824165645",
20
+ version: "1.30.8",
21
21
  ClerkUI
22
22
  };
23
23
 
@@ -22,8 +22,8 @@ import { isVersionAtLeast, parseVersion } from "@clerk/shared/versionCheck";
22
22
  * @public
23
23
  */
24
24
  var ClerkUI = class ClerkUI {
25
- static version = "1.30.8-canary.v20260824165645";
26
- version = "1.30.8-canary.v20260824165645";
25
+ static version = "1.30.8";
26
+ version = "1.30.8";
27
27
  #componentRenderer;
28
28
  /**
29
29
  * Creates a new `ClerkUI` instance and mounts the internal component renderer.
@@ -1,8 +1,10 @@
1
+ import { useEnvironment } from "../contexts/EnvironmentContext.js";
1
2
  import { useCardState } from "../elements/contexts/index.js";
2
3
  import { handleError } from "../utils/errorHandler.js";
3
4
  import { ClerkRuntimeError, isClerkAPIResponseError } from "@clerk/shared/error";
4
5
  import React from "react";
5
6
  import { ERROR_CODES } from "@clerk/shared/internal/clerk-js/constants";
7
+ import { useClerk } from "@clerk/shared/react";
6
8
  import { flushSync } from "react-dom";
7
9
 
8
10
  //#region src/hooks/useProtectCheckRunner.ts
@@ -16,6 +18,8 @@ import { flushSync } from "react-dom";
16
18
  */
17
19
  function useProtectCheckRunner(params) {
18
20
  const card = useCardState();
21
+ useClerk().__internal_protectChallengeLoadTimeoutMs;
22
+ useEnvironment().protectConfig?.challenge_load_timeout_ms;
19
23
  const containerRef = React.useRef(null);
20
24
  const isRunningRef = React.useRef(false);
21
25
  const reloadCountRef = React.useRef(0);
@@ -1 +1 @@
1
- {"version":3,"file":"useProtectCheckRunner.js","names":[],"sources":["../../../src/hooks/useProtectCheckRunner.ts"],"sourcesContent":["import { ClerkRuntimeError, isClerkAPIResponseError } from '@clerk/shared/error';\nimport { ERROR_CODES } from '@clerk/shared/internal/clerk-js/constants';\nimport type { ProtectCheckResource } from '@clerk/shared/types';\nimport React from 'react';\nimport { flushSync } from 'react-dom';\n\nimport { useCardState } from '@/ui/elements/contexts';\nimport { handleError } from '@/ui/utils/errorHandler';\n\n/**\n * A plain GET reload does not re-mint a protect_check challenge server-side, so an expired\n * challenge would otherwise reload → still expired → reload again, forever. Cap the attempts\n * and surface an error instead of spinning silently.\n *\n * NOTE: who re-mints an expired challenge on read (FAPI vs. re-running the gated step) is still\n * being decided with the clerk_go team; this cap is the defensive floor until that lands.\n */\nconst MAX_EXPIRED_RELOADS = 2;\n\n/** Upper bound on how long we wait for the challenge SDK to settle before failing loud. */\nconst PROTECT_CHECK_SCRIPT_TIMEOUT_MS = 60_000;\n\nexport interface ProtectCheckRunnerParams<TResource> {\n /**\n * Reads the current protect_check off the resource. Called fresh on each effect run because\n * `fromJSON` mints a new object on every resource update — we key the effect on the token, not\n * this reference, so an unrelated refresh doesn't restart the challenge under the user.\n */\n getProtectCheck: () => ProtectCheckResource | null | undefined;\n /** Returns the live resource, used to route after a reload (which mutates it in place). */\n getResource: () => TResource;\n /** Reloads the underlying resource (GET) to pick up fresh server state. */\n reload: () => Promise<unknown>;\n /** Submits the proof token; resolves to the updated resource. */\n submitProtectCheck: (params: { proofToken: string }) => Promise<TResource>;\n /**\n * Continues the flow once the gate clears (or a chained challenge / already-resolved is\n * detected). Receives the resource to route on (the `submitProtectCheck` result, or the live\n * resource after a reload) and must finalize (`setActive`) the `complete` case itself.\n * `isCancelled` lets the continuation bail if the component unmounted mid-await.\n */\n onResolved: (resource: TResource, isCancelled: () => boolean) => Promise<unknown>;\n}\n\nexport interface ProtectCheckRunner {\n containerRef: React.MutableRefObject<HTMLDivElement | null>;\n isRunning: boolean;\n /**\n * Whether the challenge script has signalled (via the `setWidgetVisible` init callback) that\n * it is showing a widget in the container. While true, the widget owns the progress UI —\n * callers should hide their own spinner and give the container layout space.\n */\n isWidgetVisible: boolean;\n /** Whether the card is currently showing a (recoverable) error. */\n hasError: boolean;\n /** Clears the error and re-runs the challenge from scratch. */\n retry: () => void;\n}\n\n/**\n * Shared driver for the `<SignInProtectCheck />` and `<SignUpProtectCheck />` cards. Both run the\n * exact same lifecycle — load + execute the Protect SDK, submit the proof token, continue the flow\n * — so the abort/cancel/expiry/timeout/no-RHC handling lives here once instead of being duplicated\n * (and drifting) across the two components.\n *\n * Must be called from within a `CardStateProvider`.\n */\nexport function useProtectCheckRunner<TResource>(params: ProtectCheckRunnerParams<TResource>): ProtectCheckRunner {\n const card = useCardState();\n\n // `handleError` re-throws what it does not recognise, and this runner awaits caller code that\n // raises plain errors (a transient fetch failure, an OAuth continuation that did not complete).\n const reportError = (err: any) => {\n try {\n handleError(err, [], card.setError);\n } catch {\n card.setError('Unable to complete action at this time. If the problem persists please contact support.');\n }\n };\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n const isRunningRef = React.useRef(false);\n const reloadCountRef = React.useRef(0);\n const [isRunning, setIsRunning] = React.useState(false);\n const [isWidgetVisible, setIsWidgetVisibleState] = React.useState(false);\n const [retryNonce, setRetryNonce] = React.useState(0);\n\n // Tracks real unmount, distinct from the per-run `cancelled` flag below. Clearing `protectCheck`\n // (e.g. an expired-challenge reload that advances the flow) flips the token dependency and\n // re-runs/cancels the main effect — but that re-run is exactly our cue to route, so the routing\n // must key on actual unmount, not on the effect's cancel flag.\n const mountedRef = React.useRef(true);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n // Keep the latest callbacks without re-running the effect when the caller re-renders.\n const paramsRef = React.useRef(params);\n paramsRef.current = params;\n\n const token = params.getProtectCheck()?.token;\n\n React.useEffect(() => {\n const { getProtectCheck, getResource, reload, submitProtectCheck, onResolved } = paramsRef.current;\n const protectCheck = getProtectCheck();\n if (!protectCheck || isRunningRef.current) {\n return;\n }\n\n const abortController = new AbortController();\n let cancelled = false;\n // Routing after the gate clears must survive the effect re-run that\n // clearing `protectCheck` triggers — that re-run is our cue to route, not a\n // reason to bail. So the onResolved paths below key on REAL unmount, not the\n // effect's per-run `cancelled` flag (which the re-run's cleanup sets). Same\n // rationale the expired-reload path already relies on above.\n const isUnmounted = () => !mountedRef.current;\n\n const cleanup = () => {\n cancelled = true;\n abortController.abort();\n // Reset the guard so the next mount / token change / retry can re-run; this is what makes\n // chained challenges work correctly across re-renders.\n isRunningRef.current = false;\n };\n\n const failWith = (code: string, message: string) => {\n isRunningRef.current = false;\n setIsRunning(false);\n handleError(new ClerkRuntimeError(message, { code }), [], card.setError);\n };\n\n // The script owns the widget-visibility decision: it receives this callback in its init\n // payload (as `setWidgetVisible`) and calls it right before revealing UI in the container,\n // and again with `false` once its widget is done. flushSync so the returned promise only\n // resolves after the change is committed to the DOM — the caller's spinner is genuinely\n // gone when the script reveals its widget, with no frame of overlap (same guarantee\n // BaseRouter relies on flushSync for). Scoped to THIS run: the abort contract is\n // best-effort, so a zombie script from a timed-out, retried, or superseded run can still\n // call it late — those signals must not flip visibility under the active run.\n const setWidgetVisible = (visible: boolean): Promise<void> => {\n if (cancelled || abortController.signal.aborted || !mountedRef.current) {\n return Promise.resolve();\n }\n flushSync(() => setIsWidgetVisibleState(visible));\n return Promise.resolve();\n };\n\n // Fail closed in no-RHC builds (chrome extension / clerk.no-rhc.js): the gate requires a\n // remote `import(sdk_url)` we must not perform there. This guard MUST live in the component\n // layer — `executeProtectCheck` is in `@clerk/shared`, compiled once with the flag hard-coded\n // `false`, so a guard there would never trip.\n if (__BUILD_DISABLE_RHC__) {\n failWith(\n ERROR_CODES.PROTECT_CHECK_UNSUPPORTED_ENVIRONMENT,\n 'Protect verification is not supported in this environment',\n );\n return;\n }\n\n // Expired challenge: reload once to pick up a fresh challenge if the server minted one, but\n // cap the attempts (see MAX_EXPIRED_RELOADS) so a server that returns the same expired\n // challenge on read can't spin us forever.\n if (protectCheck.expiresAt !== undefined && protectCheck.expiresAt < Date.now()) {\n if (reloadCountRef.current >= MAX_EXPIRED_RELOADS) {\n failWith(ERROR_CODES.PROTECT_CHECK_TIMED_OUT, 'Protect verification expired');\n return;\n }\n reloadCountRef.current += 1;\n isRunningRef.current = true;\n setIsRunning(true);\n void (async () => {\n try {\n await reload();\n if (!mountedRef.current) {\n return;\n }\n const refreshed = getProtectCheck();\n const stillExpired = !!refreshed && refreshed.expiresAt !== undefined && refreshed.expiresAt < Date.now();\n if (stillExpired) {\n // The server didn't re-mint on read. Don't sit on a spinner — fail loud so the user\n // gets a retry instead of an indefinite wait.\n failWith(ERROR_CODES.PROTECT_CHECK_TIMED_OUT, 'Protect verification expired');\n } else if (!refreshed) {\n // The reload cleared the gate or completed the flow. Route on the refreshed live\n // resource so the flow continues (and a completed sign-in still gets `setActive`)\n // instead of the route guard bouncing the user back to flow start. Keyed on mount (not\n // `cancelled`): clearing protectCheck re-runs/cancels this effect, and that re-run is\n // our signal to route — it must not abort the routing.\n await onResolved(getResource(), () => !mountedRef.current);\n }\n // Otherwise the server re-minted a fresh, non-expired challenge whose new token\n // re-triggers this effect (keyed on the token), which then runs it.\n } catch (err: any) {\n if (mountedRef.current) {\n reportError(err);\n }\n } finally {\n if (mountedRef.current) {\n isRunningRef.current = false;\n setIsRunning(false);\n }\n }\n })();\n return cleanup;\n }\n\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n // This run owns the container outright: drop anything a previous run left behind (a solved or\n // errored widget) so the spinner covers the load phase and a re-rendering SDK can't stack a\n // second widget under a stale one. Reset visibility in the same breath — the container is\n // empty by construction here, and waiting on the observer callback would leave the state\n // stale for a scheduling-dependent window (especially on the MutationObserver fallback).\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n setIsWidgetVisibleState(false);\n\n isRunningRef.current = true;\n setIsRunning(true);\n\n const runChallenge = async () => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n try {\n // Load the Protect SDK loader lazily, gated on the same compile-time flag as the\n // fail-closed guard above. In no-RHC builds `__BUILD_DISABLE_RHC__` is `true`, so this\n // branch (and the dynamic `import()` below it) is dead-code-eliminated — the loader and\n // its remote `import(sdk_url)` are tree-shaken out of those bundles entirely rather than\n // merely shipped-but-unused.\n if (__BUILD_DISABLE_RHC__) {\n return;\n }\n const { executeProtectCheck } = await import('@clerk/shared/internal/clerk-js/protectCheck');\n const proofToken = await Promise.race([\n executeProtectCheck(protectCheck, container, { signal: abortController.signal, setWidgetVisible }),\n new Promise<never>((_, reject) => {\n timeoutId = setTimeout(() => {\n // Stop the (possibly hung) SDK and surface a retryable timeout error.\n abortController.abort();\n reject(\n new ClerkRuntimeError('Protect verification timed out', {\n code: ERROR_CODES.PROTECT_CHECK_TIMED_OUT,\n }),\n );\n }, PROTECT_CHECK_SCRIPT_TIMEOUT_MS);\n }),\n ]);\n if (cancelled) {\n return;\n }\n\n let updatedResource: TResource;\n try {\n updatedResource = await submitProtectCheck({ proofToken });\n } catch (err) {\n if (cancelled) {\n return;\n }\n // `protect_check_already_resolved` is retry-safe: the server's state has already moved\n // past this gate. Reload to clear the stale local protectCheck, then continue routing on\n // the refreshed live resource.\n if (isClerkAPIResponseError(err) && err.errors?.[0]?.code === ERROR_CODES.PROTECT_CHECK_ALREADY_RESOLVED) {\n await reload();\n if (isUnmounted()) {\n return;\n }\n await onResolved(getResource(), isUnmounted);\n return;\n }\n throw err;\n }\n if (isUnmounted()) {\n return;\n }\n await onResolved(updatedResource, isUnmounted);\n } catch (err: any) {\n if (cancelled) {\n return;\n }\n reportError(err);\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n if (!cancelled) {\n isRunningRef.current = false;\n setIsRunning(false);\n }\n }\n };\n\n void runChallenge();\n return cleanup;\n // Keyed on the challenge token (a primitive) rather than the protectCheck object: an unrelated\n // resource refresh keeps the same token and must NOT restart the challenge, while a genuine\n // chained challenge carries a new token and re-runs. `retryNonce` re-runs on manual retry.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [token, retryNonce]);\n\n const retry = React.useCallback(() => {\n card.setError('');\n reloadCountRef.current = 0;\n isRunningRef.current = false;\n setRetryNonce(n => n + 1);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { containerRef, isRunning, isWidgetVisible, hasError: !!card.error, retry };\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAmEA,SAAgB,sBAAiC,QAAiE;CAChH,MAAM,OAAO,aAAa;CAY1B,MAAM,eAAe,MAAM,OAA8B,IAAI;CAC7D,MAAM,eAAe,MAAM,OAAO,KAAK;CACvC,MAAM,iBAAiB,MAAM,OAAO,CAAC;CACrC,MAAM,CAAC,WAAW,gBAAgB,MAAM,SAAS,KAAK;CACtD,MAAM,CAAC,iBAAiB,2BAA2B,MAAM,SAAS,KAAK;CACvE,MAAM,CAAC,YAAY,iBAAiB,MAAM,SAAS,CAAC;CAMpD,MAAM,aAAa,MAAM,OAAO,IAAI;CACpC,MAAM,gBAAgB;EACpB,WAAW,UAAU;EACrB,aAAa;GACX,WAAW,UAAU;EACvB;CACF,GAAG,CAAC,CAAC;CAGL,MAAM,YAAY,MAAM,OAAO,MAAM;CACrC,UAAU,UAAU;CAEpB,MAAM,QAAQ,OAAO,gBAAgB,CAAC,EAAE;CAExC,MAAM,gBAAgB;EACpB,MAAM,EAAE,iBAAiB,aAAa,QAAQ,oBAAoB,eAAe,UAAU;EAE3F,IAAI,CADiB,gBACL,KAAK,aAAa,SAChC;EAGsB,IAAI,gBAAgB;EAiB5C,MAAM,YAAY,MAAc,YAAoB;GAClD,aAAa,UAAU;GACvB,aAAa,KAAK;GAClB,YAAY,IAAI,kBAAkB,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,QAAQ;EACzE;EAuBE,SACE,YAAY,uCACZ,2DACF;CAiJJ,GAAG,CAAC,OAAO,UAAU,CAAC;CAEtB,MAAM,QAAQ,MAAM,kBAAkB;EACpC,KAAK,SAAS,EAAE;EAChB,eAAe,UAAU;EACzB,aAAa,UAAU;EACvB,eAAc,MAAK,IAAI,CAAC;CAE1B,GAAG,CAAC,CAAC;CAEL,OAAO;EAAE;EAAc;EAAW;EAAiB,UAAU,CAAC,CAAC,KAAK;EAAO;CAAM;AACnF"}
1
+ {"version":3,"file":"useProtectCheckRunner.js","names":[],"sources":["../../../src/hooks/useProtectCheckRunner.ts"],"sourcesContent":["import { ClerkRuntimeError, isClerkAPIResponseError } from '@clerk/shared/error';\nimport { ERROR_CODES } from '@clerk/shared/internal/clerk-js/constants';\nimport { useClerk } from '@clerk/shared/react';\nimport type { ProtectCheckResource } from '@clerk/shared/types';\nimport React from 'react';\nimport { flushSync } from 'react-dom';\n\nimport { useEnvironment } from '@/ui/contexts/EnvironmentContext';\nimport { useCardState } from '@/ui/elements/contexts';\nimport { handleError } from '@/ui/utils/errorHandler';\n\n/**\n * A plain GET reload does not re-mint a protect_check challenge server-side, so an expired\n * challenge would otherwise reload → still expired → reload again, forever. Cap the attempts\n * and surface an error instead of spinning silently.\n *\n * NOTE: who re-mints an expired challenge on read (FAPI vs. re-running the gated step) is still\n * being decided with the clerk_go team; this cap is the defensive floor until that lands.\n */\nconst MAX_EXPIRED_RELOADS = 2;\n\nexport interface ProtectCheckRunnerParams<TResource> {\n /**\n * Reads the current protect_check off the resource. Called fresh on each effect run because\n * `fromJSON` mints a new object on every resource update — we key the effect on the token, not\n * this reference, so an unrelated refresh doesn't restart the challenge under the user.\n */\n getProtectCheck: () => ProtectCheckResource | null | undefined;\n /** Returns the live resource, used to route after a reload (which mutates it in place). */\n getResource: () => TResource;\n /** Reloads the underlying resource (GET) to pick up fresh server state. */\n reload: () => Promise<unknown>;\n /** Submits the proof token; resolves to the updated resource. */\n submitProtectCheck: (params: { proofToken: string }) => Promise<TResource>;\n /**\n * Continues the flow once the gate clears (or a chained challenge / already-resolved is\n * detected). Receives the resource to route on (the `submitProtectCheck` result, or the live\n * resource after a reload) and must finalize (`setActive`) the `complete` case itself.\n * `isCancelled` lets the continuation bail if the component unmounted mid-await.\n */\n onResolved: (resource: TResource, isCancelled: () => boolean) => Promise<unknown>;\n}\n\nexport interface ProtectCheckRunner {\n containerRef: React.MutableRefObject<HTMLDivElement | null>;\n isRunning: boolean;\n /**\n * Whether the challenge script has signalled (via the `setWidgetVisible` init callback) that\n * it is showing a widget in the container. While true, the widget owns the progress UI —\n * callers should hide their own spinner and give the container layout space.\n */\n isWidgetVisible: boolean;\n /** Whether the card is currently showing a (recoverable) error. */\n hasError: boolean;\n /** Clears the error and re-runs the challenge from scratch. */\n retry: () => void;\n}\n\n/**\n * Shared driver for the `<SignInProtectCheck />` and `<SignUpProtectCheck />` cards. Both run the\n * exact same lifecycle — load + execute the Protect SDK, submit the proof token, continue the flow\n * — so the abort/cancel/expiry/timeout/no-RHC handling lives here once instead of being duplicated\n * (and drifting) across the two components.\n *\n * Must be called from within a `CardStateProvider`.\n */\nexport function useProtectCheckRunner<TResource>(params: ProtectCheckRunnerParams<TResource>): ProtectCheckRunner {\n const card = useCardState();\n\n // Override for the module-LOAD bound only (see `executeProtectCheck`), resolved loader first\n // and instance second: a loader being rolled out gradually can carry its own value without\n // changing anything for browsers still on the loader it replaces. Undefined at both levels\n // leaves the SDK default in force. Read here rather than inside the effect so the effect keeps\n // depending on primitives.\n // Older clerk-js versions omit this getter; undefined preserves the instance/default fallback.\n const loaderTimeoutMs = useClerk().__internal_protectChallengeLoadTimeoutMs;\n const instanceTimeoutMs = useEnvironment().protectConfig?.challenge_load_timeout_ms;\n const loadTimeoutMs = loaderTimeoutMs ?? instanceTimeoutMs;\n\n // `handleError` re-throws what it does not recognise, and this runner awaits caller code that\n // raises plain errors (a transient fetch failure, an OAuth continuation that did not complete).\n const reportError = (err: any) => {\n try {\n handleError(err, [], card.setError);\n } catch {\n card.setError('Unable to complete action at this time. If the problem persists please contact support.');\n }\n };\n\n const containerRef = React.useRef<HTMLDivElement | null>(null);\n const isRunningRef = React.useRef(false);\n const reloadCountRef = React.useRef(0);\n const [isRunning, setIsRunning] = React.useState(false);\n const [isWidgetVisible, setIsWidgetVisibleState] = React.useState(false);\n const [retryNonce, setRetryNonce] = React.useState(0);\n\n // Tracks real unmount, distinct from the per-run `cancelled` flag below. Clearing `protectCheck`\n // (e.g. an expired-challenge reload that advances the flow) flips the token dependency and\n // re-runs/cancels the main effect — but that re-run is exactly our cue to route, so the routing\n // must key on actual unmount, not on the effect's cancel flag.\n const mountedRef = React.useRef(true);\n React.useEffect(() => {\n mountedRef.current = true;\n return () => {\n mountedRef.current = false;\n };\n }, []);\n\n // Keep the latest callbacks without re-running the effect when the caller re-renders.\n const paramsRef = React.useRef(params);\n paramsRef.current = params;\n\n const token = params.getProtectCheck()?.token;\n\n React.useEffect(() => {\n const { getProtectCheck, getResource, reload, submitProtectCheck, onResolved } = paramsRef.current;\n const protectCheck = getProtectCheck();\n if (!protectCheck || isRunningRef.current) {\n return;\n }\n\n const abortController = new AbortController();\n let cancelled = false;\n // Routing after the gate clears must survive the effect re-run that\n // clearing `protectCheck` triggers — that re-run is our cue to route, not a\n // reason to bail. So the onResolved paths below key on REAL unmount, not the\n // effect's per-run `cancelled` flag (which the re-run's cleanup sets). Same\n // rationale the expired-reload path already relies on above.\n const isUnmounted = () => !mountedRef.current;\n\n const cleanup = () => {\n cancelled = true;\n abortController.abort();\n // Reset the guard so the next mount / token change / retry can re-run; this is what makes\n // chained challenges work correctly across re-renders.\n isRunningRef.current = false;\n };\n\n const failWith = (code: string, message: string) => {\n isRunningRef.current = false;\n setIsRunning(false);\n handleError(new ClerkRuntimeError(message, { code }), [], card.setError);\n };\n\n // The script owns the widget-visibility decision: it receives this callback in its init\n // payload (as `setWidgetVisible`) and calls it right before revealing UI in the container,\n // and again with `false` once its widget is done. flushSync so the returned promise only\n // resolves after the change is committed to the DOM — the caller's spinner is genuinely\n // gone when the script reveals its widget, with no frame of overlap (same guarantee\n // BaseRouter relies on flushSync for). Scoped to THIS run: the abort contract is\n // best-effort, so a zombie script from a timed-out, retried, or superseded run can still\n // call it late — those signals must not flip visibility under the active run.\n const setWidgetVisible = (visible: boolean): Promise<void> => {\n if (cancelled || abortController.signal.aborted || !mountedRef.current) {\n return Promise.resolve();\n }\n flushSync(() => setIsWidgetVisibleState(visible));\n return Promise.resolve();\n };\n\n // Fail closed in no-RHC builds (chrome extension / clerk.no-rhc.js): the gate requires a\n // remote `import(sdk_url)` we must not perform there. This guard MUST live in the component\n // layer — `executeProtectCheck` is in `@clerk/shared`, compiled once with the flag hard-coded\n // `false`, so a guard there would never trip.\n if (__BUILD_DISABLE_RHC__) {\n failWith(\n ERROR_CODES.PROTECT_CHECK_UNSUPPORTED_ENVIRONMENT,\n 'Protect verification is not supported in this environment',\n );\n return;\n }\n\n // Expired challenge: reload once to pick up a fresh challenge if the server minted one, but\n // cap the attempts (see MAX_EXPIRED_RELOADS) so a server that returns the same expired\n // challenge on read can't spin us forever.\n if (protectCheck.expiresAt !== undefined && protectCheck.expiresAt < Date.now()) {\n if (reloadCountRef.current >= MAX_EXPIRED_RELOADS) {\n failWith(ERROR_CODES.PROTECT_CHECK_TIMED_OUT, 'Protect verification expired');\n return;\n }\n reloadCountRef.current += 1;\n isRunningRef.current = true;\n setIsRunning(true);\n void (async () => {\n try {\n await reload();\n if (!mountedRef.current) {\n return;\n }\n const refreshed = getProtectCheck();\n const stillExpired = !!refreshed && refreshed.expiresAt !== undefined && refreshed.expiresAt < Date.now();\n if (stillExpired) {\n // The server didn't re-mint on read. Don't sit on a spinner — fail loud so the user\n // gets a retry instead of an indefinite wait.\n failWith(ERROR_CODES.PROTECT_CHECK_TIMED_OUT, 'Protect verification expired');\n } else if (!refreshed) {\n // The reload cleared the gate or completed the flow. Route on the refreshed live\n // resource so the flow continues (and a completed sign-in still gets `setActive`)\n // instead of the route guard bouncing the user back to flow start. Keyed on mount (not\n // `cancelled`): clearing protectCheck re-runs/cancels this effect, and that re-run is\n // our signal to route — it must not abort the routing.\n await onResolved(getResource(), () => !mountedRef.current);\n }\n // Otherwise the server re-minted a fresh, non-expired challenge whose new token\n // re-triggers this effect (keyed on the token), which then runs it.\n } catch (err: any) {\n if (mountedRef.current) {\n reportError(err);\n }\n } finally {\n if (mountedRef.current) {\n isRunningRef.current = false;\n setIsRunning(false);\n }\n }\n })();\n return cleanup;\n }\n\n const container = containerRef.current;\n if (!container) {\n return;\n }\n\n // This run owns the container outright: drop anything a previous run left behind (a solved or\n // errored widget) so the spinner covers the load phase and a re-rendering SDK can't stack a\n // second widget under a stale one. Reset visibility in the same breath — the container is\n // empty by construction here, and waiting on the observer callback would leave the state\n // stale for a scheduling-dependent window (especially on the MutationObserver fallback).\n while (container.firstChild) {\n container.removeChild(container.firstChild);\n }\n setIsWidgetVisibleState(false);\n\n isRunningRef.current = true;\n setIsRunning(true);\n\n const runChallenge = async () => {\n try {\n // Load the Protect SDK loader lazily, gated on the same compile-time flag as the\n // fail-closed guard above. In no-RHC builds `__BUILD_DISABLE_RHC__` is `true`, so this\n // branch (and the dynamic `import()` below it) is dead-code-eliminated — the loader and\n // its remote `import(sdk_url)` are tree-shaken out of those bundles entirely rather than\n // merely shipped-but-unused.\n if (__BUILD_DISABLE_RHC__) {\n return;\n }\n const { executeProtectCheck } = await import('@clerk/shared/internal/clerk-js/protectCheck');\n // Deliberately unraced. `executeProtectCheck` bounds LOADING the challenge module and\n // nothing after it: once control passes to the challenge, the challenge owns its own\n // deadline. We cannot know an honest duration for it — the challenge type is chosen\n // server-side, per decision, long after this bundle shipped, and its work may be waiting\n // on a person or moving a server-chosen number of bytes over a link we know nothing\n // about. The wall that used to be here aborted valid challenges and reported them to the\n // user as a timeout, and since a re-run restarts the work from the beginning, retrying\n // could never win on any connection slow enough to trip it in the first place.\n const proofToken = await executeProtectCheck(protectCheck, container, {\n signal: abortController.signal,\n setWidgetVisible,\n loadTimeoutMs,\n });\n if (cancelled) {\n return;\n }\n\n let updatedResource: TResource;\n try {\n updatedResource = await submitProtectCheck({ proofToken });\n } catch (err) {\n if (cancelled) {\n return;\n }\n // `protect_check_already_resolved` is retry-safe: the server's state has already moved\n // past this gate. Reload to clear the stale local protectCheck, then continue routing on\n // the refreshed live resource.\n if (isClerkAPIResponseError(err) && err.errors?.[0]?.code === ERROR_CODES.PROTECT_CHECK_ALREADY_RESOLVED) {\n await reload();\n if (isUnmounted()) {\n return;\n }\n await onResolved(getResource(), isUnmounted);\n return;\n }\n throw err;\n }\n if (isUnmounted()) {\n return;\n }\n await onResolved(updatedResource, isUnmounted);\n } catch (err: any) {\n if (cancelled) {\n return;\n }\n reportError(err);\n } finally {\n if (!cancelled) {\n isRunningRef.current = false;\n setIsRunning(false);\n }\n }\n };\n\n void runChallenge();\n return cleanup;\n // Keyed on the challenge token (a primitive) rather than the protectCheck object: an unrelated\n // resource refresh keeps the same token and must NOT restart the challenge, while a genuine\n // chained challenge carries a new token and re-runs. `retryNonce` re-runs on manual retry.\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [token, retryNonce]);\n\n const retry = React.useCallback(() => {\n card.setError('');\n reloadCountRef.current = 0;\n isRunningRef.current = false;\n setRetryNonce(n => n + 1);\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, []);\n\n return { containerRef, isRunning, isWidgetVisible, hasError: !!card.error, retry };\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;AAkEA,SAAgB,sBAAiC,QAAiE;CAChH,MAAM,OAAO,aAAa;CAQF,SAAS,CAAC,CAAC;CACT,eAAe,CAAC,CAAC,eAAe;CAa1D,MAAM,eAAe,MAAM,OAA8B,IAAI;CAC7D,MAAM,eAAe,MAAM,OAAO,KAAK;CACvC,MAAM,iBAAiB,MAAM,OAAO,CAAC;CACrC,MAAM,CAAC,WAAW,gBAAgB,MAAM,SAAS,KAAK;CACtD,MAAM,CAAC,iBAAiB,2BAA2B,MAAM,SAAS,KAAK;CACvE,MAAM,CAAC,YAAY,iBAAiB,MAAM,SAAS,CAAC;CAMpD,MAAM,aAAa,MAAM,OAAO,IAAI;CACpC,MAAM,gBAAgB;EACpB,WAAW,UAAU;EACrB,aAAa;GACX,WAAW,UAAU;EACvB;CACF,GAAG,CAAC,CAAC;CAGL,MAAM,YAAY,MAAM,OAAO,MAAM;CACrC,UAAU,UAAU;CAEpB,MAAM,QAAQ,OAAO,gBAAgB,CAAC,EAAE;CAExC,MAAM,gBAAgB;EACpB,MAAM,EAAE,iBAAiB,aAAa,QAAQ,oBAAoB,eAAe,UAAU;EAE3F,IAAI,CADiB,gBACL,KAAK,aAAa,SAChC;EAGsB,IAAI,gBAAgB;EAiB5C,MAAM,YAAY,MAAc,YAAoB;GAClD,aAAa,UAAU;GACvB,aAAa,KAAK;GAClB,YAAY,IAAI,kBAAkB,SAAS,EAAE,KAAK,CAAC,GAAG,CAAC,GAAG,KAAK,QAAQ;EACzE;EAuBE,SACE,YAAY,uCACZ,2DACF;CA4IJ,GAAG,CAAC,OAAO,UAAU,CAAC;CAEtB,MAAM,QAAQ,MAAM,kBAAkB;EACpC,KAAK,SAAS,EAAE;EAChB,eAAe,UAAU;EACzB,aAAa,UAAU;EACvB,eAAc,MAAK,IAAI,CAAC;CAE1B,GAAG,CAAC,CAAC;CAEL,OAAO;EAAE;EAAc;EAAW;EAAiB,UAAU,CAAC,CAAC,KAAK;EAAO;CAAM;AACnF"}
@@ -17,7 +17,7 @@ import { ClerkUI } from "./ClerkUI.js";
17
17
  */
18
18
  const ui = {
19
19
  __brand: UI_BRAND,
20
- version: "1.30.8-canary.v20260824165645",
20
+ version: "1.30.8",
21
21
  ClerkUI
22
22
  };
23
23
 
package/dist/server.js CHANGED
@@ -22,7 +22,7 @@ import { ClerkUI } from "./ClerkUI.js";
22
22
  */
23
23
  const ui = {
24
24
  __brand: UI_BRAND,
25
- version: "1.30.8-canary.v20260824165645",
25
+ version: "1.30.8",
26
26
  ClerkUI
27
27
  };
28
28