@buoy-gg/clock 7.0.74 → 7.0.75
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.
- package/lib/commonjs/components/TokenSection.js +1 -1
- package/lib/commonjs/tokens/extract.js +1 -1
- package/lib/commonjs/tokens/tokenStore.js +1 -1
- package/lib/module/components/TokenSection.js +1 -1
- package/lib/module/tokens/extract.js +1 -1
- package/lib/module/tokens/tokenStore.js +1 -1
- package/lib/typescript/tokens/tokenStore.d.ts +7 -0
- package/lib/web/index.mjs +1 -1
- package/package.json +2 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TokenSection=TokenSection;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _clockMath=require("../engine/clockMath");var _useLiveClock=require("./useLiveClock");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const size=e=>(0,_clockMath.formatDuration)(Math.abs(e),{signed:false});function TokenSection({snapshot:e,run:o,openId:l,onToggle:i,isPro:n,onUpgrade:r}){const t=e.tokens;return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:t.tokens.length>1?"Sign-in tokens":"Sign-in token"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[t.tokens.map((s,a)=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(TokenRow,{token:s,snapshot:e,index:a,open:l===s.id,onPress:()=>i(s.id)}),l===s.id?(0,_jsxRuntime.jsx)(TokenDetail,{token:s,snapshot:e,run:n?o:()=>r("Sign-in token tests"),isPro:n}):null]},s.id)),t.tokens.length===0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.row,testID:"clock-token-empty",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.emptyText,children:t.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),(0,_jsxRuntime.jsx)(CheckNote,{check:t.check,tokens:t.tokens,snapshot:e,run:o}),t.tokens.length===0?(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:t.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function TokenRow({token:e,snapshot:o,index:l,open:i,onPress:n}){const{virtual:r}=(0,_useLiveClock.useLiveClock)(o,1e3);const t=e.expiresAt!==void 0?e.expiresAt-r:void 0;const s=e.neverExpires?"No expiry":t===void 0?"Unknown":t<=0?"Expired":size(t);const a=t!==void 0&&t<=0?styles.valueDanger:t!==void 0&&t<6e4?styles.valueWarning:null;return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:`clock-token-${l}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${t!==void 0&&t>0?`expires in ${s}`:s}`,accessibilityState:{expanded:i},activeOpacity:.6,onPress:n,style:styles.row,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,numberOfLines:1,children:e.label}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowRight,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.value,a],testID:`clock-token-${l}-left`,children:s}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:i?styles.chevronOpen:null,children:(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:16,color:_sharedUi.night.color.textTertiary})})]})]})}function TokenDetail({token:e,snapshot:o,run:l,isPro:i}){const{virtual:n,real:r}=(0,_useLiveClock.useLiveClock)(o,1e3);const t=detailLines(e,n,r);const s=e.expiresAt!==void 0&&e.expiresAt-n>1e4;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detail,testID:"clock-token-detail",children:[t.map(a=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.detailLine,a.tone==="warn"?styles.warn:null,a.tone==="bad"?styles.bad:null],children:a.text},a.text)),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.buttons,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.button,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!s,onPress:()=>l("jumpToTokenExpiry",{token:e.id})})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.button,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>l("failNextRequest",{token:e.id})})})]}),i?null:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.proLine,children:[(0,_jsxRuntime.jsx)(_sharedUi.ProBadge,{}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.hint,styles.proHint],children:"Jump to Expiry and Fail Next Request are part of Buoy Pro."})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.hint,children:s||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function detailLines(e,o,l){const i=[];if(e.expiresAt!==void 0){i.push({text:`Expires ${(0,_format.formatChipTime)(e.expiresAt)}`});if(e.lifetimeMs!==void 0&&e.lifetimeMs>0){i.push({text:`Lasts ${size(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`})}if(e.serverExpiresAt!==void 0){const n=e.expiresAt-o;const r=e.serverExpiresAt-l;if(Math.abs(n-r)>2e3){i.push({text:r>0?`The server still accepts it for ${size(r)}`:`The server stopped accepting it ${size(r)} ago`})}}}else if(!e.neverExpires){i.push({text:"The token doesn't say when it expires, and no login response did either."})}if(e.hint)i.push({text:e.formatLabel});if(e.issuedBy)i.push({text:`Issued by ${e.issuedBy}`});if(e.refresh?.expiresAt!==void 0){const n=e.refresh.expiresAt-o;i.push({text:n>0?`Refresh token expires in ${size(n)}`:"Refresh token expired"})}if(e.refreshes>0&&e.lastRefreshAt!==void 0){i.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${(0,_format.formatClockTime)(e.lastRefreshAt)}`})}i.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`});if(e.expiredSends>0){i.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"})}if(e.rejected>0){i.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"})}if(e.looping){i.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"})}return i}function CheckNote({check:e,tokens:o,snapshot:l,run:i}){const{virtual:n,real:r}=(0,_useLiveClock.useLiveClock)(l,1e3);if(!e)return null;const t=o.find(d=>d.id===e.tokenId);const{text:s,tone:a}=verdict(e,t,n,r);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.check,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.checkText,a==="good"?styles.good:null,a==="bad"?styles.bad:null,a==="warn"?styles.warn:null],testID:"clock-token-check",children:s}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>i("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function verdict(e,o,l,i){if(e.status==="loop"){return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"}}if(e.status==="refreshed"){const s=e.newIssuedBy?` by ${e.newIssuedBy}`:"";const a=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${size(e.newLifetimeMs)}`:"";const d=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed";const c=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${d} at ${(0,_format.formatClockTime)(e.refreshedAt??i)}${s}${a}.${c}`,tone:c?"warn":"good"}}const n=i-e.startedAt;const r=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(n>6e4){return{text:`No new token after ${size(n)}. The app may refresh on its next action, or not at all.${r}`,tone:"warn"}}if(e.kind==="401"){return e.forcedAt===void 0?{text:`The next request to ${o?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${r}`,tone:r?"warn":void 0}}const t=o?.expiresAt!==void 0?o.expiresAt-l:void 0;return t!==void 0&&t>0?{text:`Expires in ${size(t)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row},rowSubtitle:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:_sharedUi.night.color.warning},valueDanger:{color:_sharedUi.night.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row},detail:{paddingHorizontal:_sharedUi.night.rowPadH,paddingBottom:14,gap:4},detailLine:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:6},proLine:{flexDirection:"row",alignItems:"center",gap:8,marginTop:6},proHint:{marginTop:0,flexShrink:1},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:_sharedUi.night.labelInset},checkText:{flex:1,color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,lineHeight:18},checkDone:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.caption,fontWeight:"600"},good:{color:_sharedUi.night.color.accent},warn:{color:_sharedUi.night.color.warning},bad:{color:_sharedUi.night.color.danger}});
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.TokenSection=TokenSection;var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _clockMath=require("../engine/clockMath");var _useLiveClock=require("./useLiveClock");var _format=require("./format");var _jsxRuntime=require("react/jsx-runtime");const size=e=>(0,_clockMath.formatDuration)(Math.abs(e),{signed:false});function TokenSection({snapshot:e,run:o,openId:a,onToggle:t,isPro:n,onUpgrade:r}){const i=e.tokens;return(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{children:i.tokens.length>1?"Sign-in tokens":"Sign-in token"}),(0,_jsxRuntime.jsx)(_sharedUi.NightCard,{children:(0,_jsxRuntime.jsxs)(_sharedUi.NightRows,{children:[i.tokens.map((s,l)=>(0,_jsxRuntime.jsxs)(_reactNative.View,{children:[(0,_jsxRuntime.jsx)(TokenRow,{token:s,snapshot:e,index:l,open:a===s.id,onPress:()=>t(s.id)}),a===s.id?(0,_jsxRuntime.jsx)(TokenDetail,{token:s,snapshot:e,run:n?o:()=>r("Sign-in token tests"),isPro:n}):null]},s.id)),i.tokens.length===0?(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.row,testID:"clock-token-empty",children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.emptyText,children:i.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),(0,_jsxRuntime.jsx)(CheckNote,{check:i.check,tokens:i.tokens,snapshot:e,run:o}),i.tokens.length===0?(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{children:i.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function TokenRow({token:e,snapshot:o,index:a,open:t,onPress:n}){const{virtual:r}=(0,_useLiveClock.useLiveClock)(o,1e3);const i=e.expiresAt!==void 0?e.expiresAt-r:void 0;const s=e.neverExpires?"No expiry":i===void 0?"Unknown":i<=0?"Expired":size(i);const l=i!==void 0&&i<=0?styles.valueDanger:i!==void 0&&i<6e4?styles.valueWarning:null;return(0,_jsxRuntime.jsxs)(_reactNative.TouchableOpacity,{testID:`clock-token-${a}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${i!==void 0&&i>0?`expires in ${s}`:s}`,accessibilityState:{expanded:t},activeOpacity:.6,onPress:n,style:styles.row,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowText,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowTitle,numberOfLines:1,children:e.label}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.rowRight,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.value,l],testID:`clock-token-${a}-left`,children:s}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:t?styles.chevronOpen:null,children:(0,_jsxRuntime.jsx)(_sharedUi.ChevronRight,{size:16,color:_sharedUi.night.color.textTertiary})})]})]})}function TokenDetail({token:e,snapshot:o,run:a,isPro:t}){const{virtual:n,real:r}=(0,_useLiveClock.useLiveClock)(o,1e3);const i=detailLines(e,n,r);const s=e.expiresAt!==void 0&&e.expiresAt-n>1e4;return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.detail,testID:"clock-token-detail",children:[i.map(l=>(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.detailLine,l.tone==="warn"?styles.warn:null,l.tone==="bad"?styles.bad:null],children:l.text},l.text)),(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.buttons,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.button,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!s,onPress:()=>a("jumpToTokenExpiry",{token:e.id})})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.button,children:(0,_jsxRuntime.jsx)(_sharedUi.NightButton,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>a("failNextRequest",{token:e.id})})})]}),t?null:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.proLine,children:[(0,_jsxRuntime.jsx)(_sharedUi.ProBadge,{}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.hint,styles.proHint],children:"Jump to Expiry and Fail Next Request are part of Buoy Pro."})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.hint,children:s||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function detailLines(e,o,a){const t=[];if(e.expiresAt!==void 0){t.push({text:`Expires ${(0,_format.formatChipTime)(e.expiresAt)}`});if(e.lifetimeMs!==void 0&&e.lifetimeMs>0){t.push({text:`Lasts ${size(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`})}if(e.serverExpiresAt!==void 0){const n=e.expiresAt-o;const r=e.serverExpiresAt-a;if(Math.abs(n-r)>2e3){t.push({text:r>0?`The server still accepts it for ${size(r)}`:`The server stopped accepting it ${size(r)} ago`})}}}else if(!e.neverExpires){t.push({text:"The token doesn't say when it expires, and no login response did either."})}if(e.hint)t.push({text:e.formatLabel});if(e.issuedBy)t.push({text:`Issued by ${e.issuedBy}`});if(e.refresh?.expiresAt!==void 0){const n=e.refresh.expiresAt-o;t.push({text:n>0?`Refresh token expires in ${size(n)}`:"Refresh token expired"})}if(e.refreshes>0&&e.lastRefreshAt!==void 0){t.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${(0,_format.formatClockTime)(e.lastRefreshAt)}`})}t.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`});if(e.expiredSends>0){t.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"})}if(e.rejected>0){t.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"})}if(e.looping){t.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"})}return t}function CheckNote({check:e,tokens:o,snapshot:a,run:t}){const{virtual:n,real:r}=(0,_useLiveClock.useLiveClock)(a,1e3);if(!e)return null;const i=o.find(d=>d.id===e.tokenId);const{text:s,tone:l}=verdict(e,i,n,r);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.check,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:[styles.checkText,l==="good"?styles.good:null,l==="bad"?styles.bad:null,l==="warn"?styles.warn:null],testID:"clock-token-check",children:s}),(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>t("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function verdict(e,o,a,t){if(e.status==="loop"){return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"}}if(e.status==="refreshed"&&e.sameToken){return{text:`The app got the 401 and refreshed at ${(0,_format.formatClockTime)(e.refreshedAt??t)}. The refresh sent back the same token, and the retry worked.`,tone:"good"}}if(e.status==="refreshed"){const s=e.newIssuedBy?` by ${e.newIssuedBy}`:"";const l=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${size(e.newLifetimeMs)}`:"";const d=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed";const c=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${d} at ${(0,_format.formatClockTime)(e.refreshedAt??t)}${s}${l}.${c}`,tone:c?"warn":"good"}}const n=t-e.startedAt;const r=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(n>6e4){return{text:`No new token after ${size(n)}. The app may refresh on its next action, or not at all.${r}`,tone:"warn"}}if(e.kind==="401"){return e.forcedAt===void 0?{text:`The next request to ${o?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${r}`,tone:r?"warn":void 0}}const i=o?.expiresAt!==void 0?o.expiresAt-a:void 0;return i!==void 0&&i>0?{text:`Expires in ${size(i)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}const styles=_reactNative.StyleSheet.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:_sharedUi.night.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:_sharedUi.night.color.text,fontSize:_sharedUi.night.font.row},rowSubtitle:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:_sharedUi.night.color.warning},valueDanger:{color:_sharedUi.night.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.row},detail:{paddingHorizontal:_sharedUi.night.rowPadH,paddingBottom:14,gap:4},detailLine:{color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:_sharedUi.night.color.textTertiary,fontSize:_sharedUi.night.font.caption,marginTop:6},proLine:{flexDirection:"row",alignItems:"center",gap:8,marginTop:6},proHint:{marginTop:0,flexShrink:1},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:_sharedUi.night.labelInset},checkText:{flex:1,color:_sharedUi.night.color.textSecondary,fontSize:_sharedUi.night.font.caption,lineHeight:18},checkDone:{color:_sharedUi.night.color.accent,fontSize:_sharedUi.night.font.caption,fontWeight:"600"},good:{color:_sharedUi.night.color.accent},warn:{color:_sharedUi.night.color.warning},bad:{color:_sharedUi.night.color.danger}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.hostOf=hostOf;exports.originOf=originOf;exports.pathOf=pathOf;exports.tokensIssued=tokensIssued;exports.tokensUsed=tokensUsed;var _decode=require("./decode");function originOf(e){const t=/^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(e);return t?t[1].toLowerCase():null}function hostOf(e){const t=originOf(e);return t?t.replace(/^[a-z][a-z0-9+.-]*:\/\//,""):"unknown"}function pathOf(e){const t=e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i,"");const n=t.split(/[?#]/)[0]||"/";return n}function queryParams(e){const t=e.split("#")[0].split("?")[1];if(!t)return[];const n=[];for(const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.hostOf=hostOf;exports.originOf=originOf;exports.pathOf=pathOf;exports.tokensIssued=tokensIssued;exports.tokensUsed=tokensUsed;var _decode=require("./decode");function originOf(e){const t=/^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(e);return t?t[1].toLowerCase():null}function hostOf(e){const t=originOf(e);return t?t.replace(/^[a-z][a-z0-9+.-]*:\/\//,""):"unknown"}function pathOf(e){const t=e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i,"");const n=t.split(/[?#]/)[0]||"/";return n}function queryParams(e){const t=e.split("#")[0].split("?")[1];if(!t)return[];const n=[];for(const o of t.split("&")){const r=o.indexOf("=");if(r<=0)continue;try{n.push([decodeURIComponent(o.slice(0,r)),decodeURIComponent(o.slice(r+1))])}catch{}}return n}const TOKEN_NAME=/(token|jwt|session|auth|appcheck|api[-_]?key|apikey|credential|bearer)/i;const NOT_TOKEN_HEADERS=new Set(["authorization","cookie","dpop","idempotency-key","x-request-id","x-correlation-id","www-authenticate","proxy-authenticate","x-csrf-token","x-xsrf-token"]);const TOKEN_QUERY=new Set(["access_token","accesstoken","id_token","token","auth","auth_token","jwt","session","session_token"]);const SCHEMES=new Set(["bearer","token","jwt","dpop","oauth","firebase"]);function lowerKeys(e){const t={};if(!e)return t;for(const[n,o]of Object.entries(e)){if(typeof o==="string")t[n.toLowerCase()]=o;else if(Array.isArray(o))t[n.toLowerCase()]=o.join(", ")}return t}function parseCookieHeader(e){const t=[];for(const n of e.split(";")){const o=n.indexOf("=");if(o<=0)continue;t.push([n.slice(0,o).trim(),n.slice(o+1).trim()])}return t}function candidate(e,t,n){const o=(0,_decode.inspectToken)(e,n);if(!o)return null;if((0,_decode.isStructured)(o)||o.hint)return o;return t?o:null}function tokensUsed(e,t){const n=[];const o=lowerKeys(e.requestHeaders);const r=o.authorization;if(r){const s=/^(\S+)\s+(\S+)$/.exec(r.trim());const i=s?s[1]:void 0;const c=s?s[2]:r.trim();if(!i||SCHEMES.has(i.toLowerCase())){const u=candidate(c,true,t)??(i&&!/^(null|undefined)$/i.test(c)?{format:"opaque",formatLabel:"Opaque",claims:{}}:null);if(u){n.push({location:"authorization",name:"Authorization",scheme:i,fp:(0,_decode.fingerprint)(c),info:u})}}}for(const[s,i]of Object.entries(o)){if(NOT_TOKEN_HEADERS.has(s)||!TOKEN_NAME.test(s))continue;const c=i.replace(/^bearer\s+/i,"");const u=candidate(c,true,t);if(u)n.push({location:"header",name:s,fp:(0,_decode.fingerprint)(c),info:u})}if(o.cookie){for(const[s,i]of parseCookieHeader(o.cookie)){const c=candidate(i,TOKEN_NAME.test(s)||/^(sid|sess)/i.test(s),t);if(c)n.push({location:"cookie",name:s,fp:(0,_decode.fingerprint)(i),info:c})}}for(const[s,i]of queryParams(e.url)){const c=candidate(i,TOKEN_QUERY.has(s.toLowerCase()),t);if(c&&TOKEN_QUERY.has(s.toLowerCase())){n.push({location:"query",name:s,fp:(0,_decode.fingerprint)(i),info:c})}}return n}const ACCESS_KEYS=/^(access_?token|accesstoken|token|jwt|auth_?token|session_?token|sessiontoken)$/i;const ID_KEYS=/^(id_?token|idtoken)$/i;const REFRESH_KEYS=/^(refresh_?token|refreshtoken)$/i;const LIFETIME_KEYS=["expires_in","expiresIn","ExpiresIn","expires","ttl"];const ABSOLUTE_KEYS=["expires_at","expiresAt","ExpiresAt","expiration","Expiration","expiry","expirationTime","expiration_time","access_token_expires_at","accessTokenExpiresAt","accessTokenExpiry"];const REFRESH_LIFETIME_KEYS=["refresh_expires_in","refresh_token_expires_in","refreshTokenExpiresIn","refreshExpiresIn"];const REFRESH_ABSOLUTE_KEYS=["refresh_expires_at","refreshTokenExpiresAt","refresh_token_expires_at"];function parseBody(e){if(typeof e!=="string")return e;const t=e.trim();if(!(t.startsWith("{")||t.startsWith("[")))return null;try{return JSON.parse(t)}catch{return null}}function findTokens(e,t,n){if(t>4||!e||typeof e!=="object")return;if(Array.isArray(e)){for(const r of e.slice(0,5))findTokens(r,t+1,n);return}const o=e;for(const[r,s]of Object.entries(o)){if(typeof s==="string"&&(ACCESS_KEYS.test(r)||ID_KEYS.test(r)||REFRESH_KEYS.test(r))){n.push({key:r,value:s,holder:o})}else if(s&&typeof s==="object"){findTokens(s,t+1,n)}}}function roleOf(e){if(REFRESH_KEYS.test(e))return"refresh";if(ID_KEYS.test(e))return"id";if(/session/i.test(e))return"session";return"access"}function expiryIn(e,t,n,o,r){for(const s of t){const i=(0,_decode.lifetimeSeconds)(e[s]);if(i!==void 0){return{expiresAt:o+i*1e3,source:s,lifetimeMs:i*1e3}}}for(const s of n){const i=(0,_decode.absoluteTime)(e[s],r);if(i!==void 0)return{expiresAt:i,source:s}}return{}}function setCookieLines(e){const t=e["set-cookie"];if(!t)return[];return t.split(/,(?=\s*[A-Za-z0-9!#$%&'*+.^_`|~-]+=)/).map(n=>n.trim())}function tokensIssued(e,t){if(e.status===void 0||e.status>=400)return[];const n=`${e.method.toUpperCase()} ${pathOf(e.url)}`;const o=e.timestamp+(e.duration??0);const r=[];const s=parseBody(e.responseData);if(s){const c=[];findTokens(s,0,c);const u=new Map;for(const f of c.filter(a=>REFRESH_KEYS.test(a.key))){const a=(0,_decode.inspectToken)(f.value,t);if(!a)continue;const p=expiryIn(f.holder,REFRESH_LIFETIME_KEYS,REFRESH_ABSOLUTE_KEYS,o,t);u.set(f.holder,{fp:(0,_decode.fingerprint)(f.value),expiresAt:a.expiresAt??p.expiresAt,formatLabel:a.formatLabel})}for(const f of c){if(REFRESH_KEYS.test(f.key))continue;const a=(0,_decode.inspectToken)(f.value,t);if(!a)continue;const p=expiryIn(f.holder,LIFETIME_KEYS,ABSOLUTE_KEYS,o,t);r.push({fp:(0,_decode.fingerprint)(f.value),info:a,role:roleOf(f.key),expiresAt:p.expiresAt,expirySource:p.source,lifetimeMs:p.lifetimeMs,issuedBy:n,refresh:u.get(f.holder)})}}const i=lowerKeys(e.responseHeaders);for(const c of setCookieLines(i)){const[u,...f]=c.split(";");const a=u.indexOf("=");if(a<=0)continue;const p=u.slice(0,a).trim();const x=u.slice(a+1).trim();const l=candidate(x,TOKEN_NAME.test(p)||/^(sid|sess)/i.test(p),t);if(!l||x===""||x.toLowerCase()==="deleted")continue;let k;let d;let h;for(const y of f){const[A,...S]=y.split("=");const _=A.trim().toLowerCase();const m=S.join("=").trim();if(_==="max-age"&&/^-?\d+$/.test(m)){h=Number(m)*1e3;k=o+h;d="Max-Age"}else if(_==="expires"&&d!=="Max-Age"){const E=t(m);if(Number.isFinite(E)){k=E;d="Expires"}}}r.push({fp:(0,_decode.fingerprint)(x),info:l,role:"cookie",cookie:p,expiresAt:l.expiresAt??k,expirySource:l.expiresAt?l.expirySource:d,lifetimeMs:l.expiresAt?void 0:h,issuedBy:n})}return r}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.__ingestForTests=__ingestForTests;exports.__resetTokensForTests=__resetTokensForTests;exports.beginTokenCheck=beginTokenCheck;exports.clearTokenCheck=clearTokenCheck;exports.getTokenOrigin=getTokenOrigin;exports.getTokenReport=getTokenReport;exports.getTokenRow=getTokenRow;exports.isTokenWatchOn=isTokenWatchOn;exports.startTokenWatch=startTokenWatch;exports.subscribeTokens=subscribeTokens;exports.tokenAppNow=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _utils=require("@buoy-gg/shared-ui/utils");var _patches=require("../engine/patches");var _extract=require("./extract");const parseDate=e=>_patches.RealDate.parse(e);const LOOP_COUNT=4;const LOOP_WINDOW_MS=2e4;const MAX_ROWS=8;const MAX_HISTORY=8;const MAX_ISSUANCES=200;const MAX_SEEN_IDS=1e3;const rows=new Map;const issuances=new Map;const seenRequests=new Set;const seenResponses=new Set;const issuingEndpoints=new Set;const TOKEN_PATH=/(token|refresh|oauth|session|auth\/)/i;let check=null;let available=true;let unsubscribeNetwork=null;const listeners=new Set;let emitQueued=false;function emit(){if(emitQueued)return;emitQueued=true;Promise.resolve().then(()=>{emitQueued=false;listeners.forEach(e=>e())})}function subscribeTokens(e){listeners.add(e);return()=>{listeners.delete(e)}}function remember(e,t){if(e.has(t))return false;if(e.size>=MAX_SEEN_IDS){const s=e.values().next().value;if(s!==void 0)e.delete(s)}e.add(t);return true}function rowKey(e,t){return`${e}|${t.location}:${t.name.toLowerCase()}`}function expiryFor(e,t){const s=t?.lifetimeMs!==void 0&&t.expiresAt!==void 0;const
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.__ingestForTests=__ingestForTests;exports.__resetTokensForTests=__resetTokensForTests;exports.beginTokenCheck=beginTokenCheck;exports.clearTokenCheck=clearTokenCheck;exports.getTokenOrigin=getTokenOrigin;exports.getTokenReport=getTokenReport;exports.getTokenRow=getTokenRow;exports.isTokenWatchOn=isTokenWatchOn;exports.startTokenWatch=startTokenWatch;exports.subscribeTokens=subscribeTokens;exports.tokenAppNow=void 0;var _sharedUi=require("@buoy-gg/shared-ui");var _utils=require("@buoy-gg/shared-ui/utils");var _patches=require("../engine/patches");var _extract=require("./extract");const parseDate=e=>_patches.RealDate.parse(e);const LOOP_COUNT=4;const LOOP_WINDOW_MS=2e4;const MAX_ROWS=8;const MAX_HISTORY=8;const MAX_ISSUANCES=200;const MAX_SEEN_IDS=1e3;const rows=new Map;const issuances=new Map;const seenRequests=new Set;const seenResponses=new Set;const issuingEndpoints=new Set;const TOKEN_PATH=/(token|refresh|oauth|session|auth\/)/i;let check=null;const retries=new Set;let available=true;let unsubscribeNetwork=null;const listeners=new Set;let emitQueued=false;function emit(){if(emitQueued)return;emitQueued=true;Promise.resolve().then(()=>{emitQueued=false;listeners.forEach(e=>e())})}function subscribeTokens(e){listeners.add(e);return()=>{listeners.delete(e)}}function remember(e,t){if(e.has(t))return false;if(e.size>=MAX_SEEN_IDS){const s=e.values().next().value;if(s!==void 0)e.delete(s)}e.add(t);return true}function rowKey(e,t){return`${e}|${t.location}:${t.name.toLowerCase()}`}function expiryFor(e,t){const s=t?.lifetimeMs!==void 0&&t.expiresAt!==void 0;const n=s?t.expiresAt:e.expiresAt??t?.expiresAt;const f=e.expiresAt??(s?t.observedReal+t.lifetimeMs:t?.expiresAt);const r=s?t.expirySource:e.expiresAt?e.expirySource:t?.expirySource;const i=s?t.lifetimeMs:e.expiresAt!==void 0&&e.issuedAt!==void 0?e.expiresAt-e.issuedAt:void 0;return{expiresAt:n,serverExpiresAt:f,source:r,lifetimeMs:i}}function applyToken(e,t,s,n,f){const r=issuances.get(t);const i=expiryFor(s,r);const o=e.fp!==t;if(o){e.history.unshift({fp:e.fp,firstSeenReal:e.firstSeenReal,expiresAt:e.expiresAt});e.history.length=Math.min(e.history.length,MAX_HISTORY);e.fp=t;e.firstSeenReal=n;e.firstSeenApp=f;e.uses=0;e.expiredSends=0;e.rejected=0}e.info=s;e.role=r?.role??(o?void 0:e.role);e.issuedBy=r?.issuedBy??(o?void 0:e.issuedBy);e.refresh=r?.refresh??(o?void 0:e.refresh);e.expiresAt=i.expiresAt;e.serverExpiresAt=i.serverExpiresAt;e.expirySource=i.source;e.lifetimeMs=i.lifetimeMs;if(o)onNewToken(e,n)}function newRow(e,t,s,n,f){const r=issuances.get(s.fp);const i=expiryFor(s.info,r);return{key:e,origin:t,host:(0,_extract.hostOf)(t),location:s.location,name:s.name,scheme:s.scheme,fp:s.fp,info:s.info,role:r?.role,issuedBy:r?.issuedBy,refresh:r?.refresh,expiresAt:i.expiresAt,serverExpiresAt:i.serverExpiresAt,expirySource:i.source,lifetimeMs:i.lifetimeMs,firstSeenReal:n,firstSeenApp:f,lastUsedReal:n,lastUsedApp:f,uses:0,expiredSends:0,rejected:0,history:[]}}function evictOldestRow(){if(rows.size<=MAX_ROWS)return;let e=null;for(const t of rows.values()){if(!e||t.lastUsedReal<e.lastUsedReal)e=t}if(e&&e.key!==check?.tokenId)rows.delete(e.key)}function onNewToken(e,t){if(!check||check.tokenId!==e.key)return;check.newTokens+=1;if(check.status==="waiting"){check.status="refreshed";check.refreshedAt=t;if(check.ruleId&&check.forcedAt===void 0){void(0,_sharedUi.dispatchToolAction)("network","deleteOverrideRule",{id:check.ruleId}).catch(()=>{})}}if(check.newTokens>=LOOP_COUNT&&t-(check.refreshedAt??t)<=LOOP_WINDOW_MS){check.status="loop"}}function ingestRequest(e){const t=(0,_extract.originOf)(e.url);if(!t)return;const s=(0,_extract.tokensUsed)(e,parseDate);if(s.length===0)return;const n=(0,_patches.realNow)();const f=e.timestamp;for(const r of s){const i=rowKey(t,r);let o=rows.get(i);if(!o){o=newRow(i,t,r,n,f);rows.set(i,o);evictOldestRow()}else{applyToken(o,r.fp,r.info,n,f)}o.uses+=1;o.lastUsedReal=n;o.lastUsedApp=f;if(o.expiresAt!==void 0&&f>=o.expiresAt)o.expiredSends+=1;if(check&&check.tokenId===i&&check.forcedAt!==void 0&&r.fp===check.startFp){check.staleAfterFailure+=1;remember(retries,e.id)}}emit()}function ingestResponse(e){const t=(0,_extract.originOf)(e.url);if(!t)return;const s=(0,_patches.realNow)();let n=false;if(e.status===401||e.status===403){for(const u of(0,_extract.tokensUsed)(e,parseDate)){const a=rows.get(rowKey(t,u));if(a&&a.fp===u.fp){a.rejected+=1;n=true}}}const f=!!check?.ruleId&&e.override?.ruleId===check.ruleId;const r=`${e.method.toUpperCase()} ${(0,_extract.pathOf)(e.url)}`;const i=issuingEndpoints.has(r)||e.method.toUpperCase()==="POST"&&TOKEN_PATH.test((0,_extract.pathOf)(e.url));const o=e.status??0;if(check&&o>=400&&!f&&i){check.failedRefreshes+=1;check.lastRefreshError=`${e.status} ${r}`;n=true}if(check?.status==="waiting"&&check.forcedAt!==void 0&&!f&&o>=200&&o<400){if(i&&check.refreshOkAt===void 0){check.refreshOkAt=s;n=true}else if(!i&&check.refreshOkAt!==void 0&&retries.has(e.id)){check.status="refreshed";check.refreshedAt=s;check.sameToken=true;n=true}}if(check?.ruleId&&e.override?.ruleId===check.ruleId&&check.forcedAt===void 0){check.forcedAt=s;n=true}for(const u of(0,_extract.tokensIssued)(e,parseDate)){issuingEndpoints.add(u.issuedBy);issuances.set(u.fp,{...u,observedReal:s});if(issuances.size>MAX_ISSUANCES){const a=issuances.keys().next().value;if(a!==void 0)issuances.delete(a)}n=true;if(u.cookie){const a={location:"cookie",name:u.cookie,fp:u.fp,info:u.info};const l=rowKey(t,a);const c=rows.get(l);if(c)applyToken(c,u.fp,u.info,s,e.timestamp);else{rows.set(l,newRow(l,t,a,s,e.timestamp));evictOldestRow()}continue}for(const a of rows.values()){if(a.fp===u.fp)applyToken(a,u.fp,a.info,s,a.lastUsedApp)}}if(n)emit()}function ingest(e){const t=e;if(!t||typeof t.id!=="string"||typeof t.url!=="string")return;if(remember(seenRequests,t.id))ingestRequest(t);if(t.status!==void 0&&remember(seenResponses,t.id))ingestResponse(t)}function startTokenWatch(){if(unsubscribeNetwork)return true;try{const{networkEventStore:e}=(0,_utils.loadToolModule)("@buoy-gg/network");if(!e?.onEvent)throw new Error("no event store");unsubscribeNetwork=e.onEvent(ingest,true);available=true}catch{available=false}emit();return available}function isTokenWatchOn(){return unsubscribeNetwork!==null}function beginTokenCheck(e,t,s){const n=rows.get(t);if(!n)throw new Error(`No token row "${t}".`);check={kind:e,tokenId:t,startedAt:(0,_patches.realNow)(),startFp:n.fp,ruleId:s,status:"waiting",newTokens:0,staleAfterFailure:0,failedRefreshes:0};retries.clear();emit();return check}function clearTokenCheck(){check=null;retries.clear();emit()}function labelFor(e){if(e.location==="cookie")return`${e.name} cookie`;if(e.location==="query")return`${e.name} parameter`;if(e.location==="header")return`${e.name} header`;if(e.role==="id"||e.info.claims.use==="id")return"ID token";return"Access token"}function summarize(e,t){const s=[e.firstSeenReal,...e.history.map(r=>r.firstSeenReal)].slice(0,-1);const n=s.filter(r=>t-r<=LOOP_WINDOW_MS).length;const f=e.info.issuedAt;return{id:e.key,label:labelFor(e),host:e.host,location:e.location,name:e.name,scheme:e.scheme,format:e.info.format,formatLabel:e.info.formatLabel,hint:e.info.hint,claims:e.info.claims,fingerprint:e.fp,issuedAt:f,notBefore:e.info.notBefore,expiresAt:e.expiresAt,serverExpiresAt:e.serverExpiresAt,expirySource:e.expirySource,lifetimeMs:e.lifetimeMs,neverExpires:e.info.neverExpires,issuedBy:e.issuedBy,refresh:e.refresh?{expiresAt:e.refresh.expiresAt,formatLabel:e.refresh.formatLabel}:void 0,firstUsed:e.firstSeenApp,lastUsed:e.lastUsedApp,lastUsedReal:e.lastUsedReal,uses:e.uses,refreshes:e.history.length,lastRefreshAt:e.history.length?e.firstSeenReal:void 0,recentRefreshes:n,looping:n>=LOOP_COUNT,expiredSends:e.expiredSends,rejected:e.rejected}}function getTokenReport(){const e=(0,_patches.realNow)();const t=[...rows.values()].sort((s,n)=>n.lastUsedReal-s.lastUsedReal).map(s=>summarize(s,e));if(check?.status==="refreshed"){const s=rows.get(check.tokenId);if(s){check.newLifetimeMs=s.lifetimeMs;check.newIssuedBy=s.issuedBy}}return{available,watching:unsubscribeNetwork!==null,tokens:t,check:check?{...check}:null}}function getTokenRow(e){const t=getTokenReport();if(e)return t.tokens.find(s=>s.id===e||s.fingerprint===e)??null;return t.tokens.find(s=>s.expiresAt!==void 0)??t.tokens[0]??null}function getTokenOrigin(e){return rows.get(e)?.origin??null}const tokenAppNow=exports.tokenAppNow=_patches.appNow;function __ingestForTests(e){ingest(e)}function __resetTokensForTests(){rows.clear();issuances.clear();seenRequests.clear();seenResponses.clear();issuingEndpoints.clear();check=null;retries.clear();available=true;unsubscribeNetwork?.();unsubscribeNetwork=null}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{StyleSheet as T,Text as u,TouchableOpacity as
|
|
1
|
+
"use strict";import{StyleSheet as T,Text as u,TouchableOpacity as b,View as c}from"react-native";import{ChevronRight as S,NightButton as $,NightCard as A,NightFootnote as R,NightRows as v,NightSectionLabel as D,ProBadge as I,night as i}from"@buoy-gg/shared-ui";import{formatDuration as L}from"../engine/clockMath";import{useLiveClock as m}from"./useLiveClock";import{formatChipTime as z,formatClockTime as y}from"./format";import{jsx as s,jsxs as h}from"react/jsx-runtime";const x=e=>L(Math.abs(e),{signed:false});export function TokenSection({snapshot:e,run:d,openId:f,onToggle:n,isPro:o,onUpgrade:a}){const r=e.tokens;return h(c,{children:[s(D,{children:r.tokens.length>1?"Sign-in tokens":"Sign-in token"}),s(A,{children:h(v,{children:[r.tokens.map((l,p)=>h(c,{children:[s(N,{token:l,snapshot:e,index:p,open:f===l.id,onPress:()=>n(l.id)}),f===l.id?s(E,{token:l,snapshot:e,run:o?d:()=>a("Sign-in token tests"),isPro:o}):null]},l.id)),r.tokens.length===0?s(c,{style:t.row,testID:"clock-token-empty",children:s(u,{style:t.emptyText,children:r.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),s(k,{check:r.check,tokens:r.tokens,snapshot:e,run:d}),r.tokens.length===0?s(R,{children:r.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function N({token:e,snapshot:d,index:f,open:n,onPress:o}){const{virtual:a}=m(d,1e3);const r=e.expiresAt!==void 0?e.expiresAt-a:void 0;const l=e.neverExpires?"No expiry":r===void 0?"Unknown":r<=0?"Expired":x(r);const p=r!==void 0&&r<=0?t.valueDanger:r!==void 0&&r<6e4?t.valueWarning:null;return h(b,{testID:`clock-token-${f}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${r!==void 0&&r>0?`expires in ${l}`:l}`,accessibilityState:{expanded:n},activeOpacity:.6,onPress:o,style:t.row,children:[h(c,{style:t.rowText,children:[s(u,{style:t.rowTitle,numberOfLines:1,children:e.label}),s(u,{style:t.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),h(c,{style:t.rowRight,children:[s(u,{style:[t.value,p],testID:`clock-token-${f}-left`,children:l}),s(c,{style:n?t.chevronOpen:null,children:s(S,{size:16,color:i.color.textTertiary})})]})]})}function E({token:e,snapshot:d,run:f,isPro:n}){const{virtual:o,real:a}=m(d,1e3);const r=j(e,o,a);const l=e.expiresAt!==void 0&&e.expiresAt-o>1e4;return h(c,{style:t.detail,testID:"clock-token-detail",children:[r.map(p=>s(u,{style:[t.detailLine,p.tone==="warn"?t.warn:null,p.tone==="bad"?t.bad:null],children:p.text},p.text)),h(c,{style:t.buttons,children:[s(c,{style:t.button,children:s($,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!l,onPress:()=>f("jumpToTokenExpiry",{token:e.id})})}),s(c,{style:t.button,children:s($,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>f("failNextRequest",{token:e.id})})})]}),n?null:h(c,{style:t.proLine,children:[s(I,{}),s(u,{style:[t.hint,t.proHint],children:"Jump to Expiry and Fail Next Request are part of Buoy Pro."})]}),s(u,{style:t.hint,children:l||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function j(e,d,f){const n=[];if(e.expiresAt!==void 0){n.push({text:`Expires ${z(e.expiresAt)}`});if(e.lifetimeMs!==void 0&&e.lifetimeMs>0){n.push({text:`Lasts ${x(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`})}if(e.serverExpiresAt!==void 0){const o=e.expiresAt-d;const a=e.serverExpiresAt-f;if(Math.abs(o-a)>2e3){n.push({text:a>0?`The server still accepts it for ${x(a)}`:`The server stopped accepting it ${x(a)} ago`})}}}else if(!e.neverExpires){n.push({text:"The token doesn't say when it expires, and no login response did either."})}if(e.hint)n.push({text:e.formatLabel});if(e.issuedBy)n.push({text:`Issued by ${e.issuedBy}`});if(e.refresh?.expiresAt!==void 0){const o=e.refresh.expiresAt-d;n.push({text:o>0?`Refresh token expires in ${x(o)}`:"Refresh token expired"})}if(e.refreshes>0&&e.lastRefreshAt!==void 0){n.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${y(e.lastRefreshAt)}`})}n.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`});if(e.expiredSends>0){n.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"})}if(e.rejected>0){n.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"})}if(e.looping){n.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"})}return n}function k({check:e,tokens:d,snapshot:f,run:n}){const{virtual:o,real:a}=m(f,1e3);if(!e)return null;const r=d.find(g=>g.id===e.tokenId);const{text:l,tone:p}=q(e,r,o,a);return h(c,{style:t.check,children:[s(u,{style:[t.checkText,p==="good"?t.good:null,p==="bad"?t.bad:null,p==="warn"?t.warn:null],testID:"clock-token-check",children:l}),s(b,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>n("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:s(u,{style:t.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function q(e,d,f,n){if(e.status==="loop"){return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"}}if(e.status==="refreshed"&&e.sameToken){return{text:`The app got the 401 and refreshed at ${y(e.refreshedAt??n)}. The refresh sent back the same token, and the retry worked.`,tone:"good"}}if(e.status==="refreshed"){const l=e.newIssuedBy?` by ${e.newIssuedBy}`:"";const p=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${x(e.newLifetimeMs)}`:"";const g=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed";const w=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${g} at ${y(e.refreshedAt??n)}${l}${p}.${w}`,tone:w?"warn":"good"}}const o=n-e.startedAt;const a=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(o>6e4){return{text:`No new token after ${x(o)}. The app may refresh on its next action, or not at all.${a}`,tone:"warn"}}if(e.kind==="401"){return e.forcedAt===void 0?{text:`The next request to ${d?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${a}`,tone:a?"warn":void 0}}const r=d?.expiresAt!==void 0?d.expiresAt-f:void 0;return r!==void 0&&r>0?{text:`Expires in ${x(r)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}const t=T.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:i.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:i.color.text,fontSize:i.font.row},rowSubtitle:{color:i.color.textTertiary,fontSize:i.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:i.color.textSecondary,fontSize:i.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:i.color.warning},valueDanger:{color:i.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:i.color.textSecondary,fontSize:i.font.row},detail:{paddingHorizontal:i.rowPadH,paddingBottom:14,gap:4},detailLine:{color:i.color.textSecondary,fontSize:i.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:i.color.textTertiary,fontSize:i.font.caption,marginTop:6},proLine:{flexDirection:"row",alignItems:"center",gap:8,marginTop:6},proHint:{marginTop:0,flexShrink:1},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:i.labelInset},checkText:{flex:1,color:i.color.textSecondary,fontSize:i.font.caption,lineHeight:18},checkDone:{color:i.color.accent,fontSize:i.font.caption,fontWeight:"600"},good:{color:i.color.accent},warn:{color:i.color.warning},bad:{color:i.color.danger}});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{absoluteTime as K,fingerprint as l,inspectToken as A,isStructured as g,lifetimeSeconds as
|
|
1
|
+
"use strict";import{absoluteTime as K,fingerprint as l,inspectToken as A,isStructured as g,lifetimeSeconds as q}from"./decode";export function originOf(e){const t=/^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(e);return t?t[1].toLowerCase():null}export function hostOf(e){const t=originOf(e);return t?t.replace(/^[a-z][a-z0-9+.-]*:\/\//,""):"unknown"}export function pathOf(e){const t=e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i,"");const n=t.split(/[?#]/)[0]||"/";return n}function R(e){const t=e.split("#")[0].split("?")[1];if(!t)return[];const n=[];for(const o of t.split("&")){const r=o.indexOf("=");if(r<=0)continue;try{n.push([decodeURIComponent(o.slice(0,r)),decodeURIComponent(o.slice(r+1))])}catch{}}return n}const S=/(token|jwt|session|auth|appcheck|api[-_]?key|apikey|credential|bearer)/i;const H=new Set(["authorization","cookie","dpop","idempotency-key","x-request-id","x-correlation-id","www-authenticate","proxy-authenticate","x-csrf-token","x-xsrf-token"]);const C=new Set(["access_token","accesstoken","id_token","token","auth","auth_token","jwt","session","session_token"]);const $=new Set(["bearer","token","jwt","dpop","oauth","firebase"]);function L(e){const t={};if(!e)return t;for(const[n,o]of Object.entries(e)){if(typeof o==="string")t[n.toLowerCase()]=o;else if(Array.isArray(o))t[n.toLowerCase()]=o.join(", ")}return t}function N(e){const t=[];for(const n of e.split(";")){const o=n.indexOf("=");if(o<=0)continue;t.push([n.slice(0,o).trim(),n.slice(o+1).trim()])}return t}function k(e,t,n){const o=A(e,n);if(!o)return null;if(g(o)||o.hint)return o;return t?o:null}export function tokensUsed(e,t){const n=[];const o=L(e.requestHeaders);const r=o.authorization;if(r){const s=/^(\S+)\s+(\S+)$/.exec(r.trim());const i=s?s[1]:void 0;const c=s?s[2]:r.trim();if(!i||$.has(i.toLowerCase())){const u=k(c,true,t)??(i&&!/^(null|undefined)$/i.test(c)?{format:"opaque",formatLabel:"Opaque",claims:{}}:null);if(u){n.push({location:"authorization",name:"Authorization",scheme:i,fp:l(c),info:u})}}}for(const[s,i]of Object.entries(o)){if(H.has(s)||!S.test(s))continue;const c=i.replace(/^bearer\s+/i,"");const u=k(c,true,t);if(u)n.push({location:"header",name:s,fp:l(c),info:u})}if(o.cookie){for(const[s,i]of N(o.cookie)){const c=k(i,S.test(s)||/^(sid|sess)/i.test(s),t);if(c)n.push({location:"cookie",name:s,fp:l(i),info:c})}}for(const[s,i]of R(e.url)){const c=k(i,C.has(s.toLowerCase()),t);if(c&&C.has(s.toLowerCase())){n.push({location:"query",name:s,fp:l(i),info:c})}}return n}const Y=/^(access_?token|accesstoken|token|jwt|auth_?token|session_?token|sessiontoken)$/i;const T=/^(id_?token|idtoken)$/i;const m=/^(refresh_?token|refreshtoken)$/i;const U=["expires_in","expiresIn","ExpiresIn","expires","ttl"];const F=["expires_at","expiresAt","ExpiresAt","expiration","Expiration","expiry","expirationTime","expiration_time","access_token_expires_at","accessTokenExpiresAt","accessTokenExpiry"];const v=["refresh_expires_in","refresh_token_expires_in","refreshTokenExpiresIn","refreshExpiresIn"];const B=["refresh_expires_at","refreshTokenExpiresAt","refresh_token_expires_at"];function D(e){if(typeof e!=="string")return e;const t=e.trim();if(!(t.startsWith("{")||t.startsWith("[")))return null;try{return JSON.parse(t)}catch{return null}}function w(e,t,n){if(t>4||!e||typeof e!=="object")return;if(Array.isArray(e)){for(const r of e.slice(0,5))w(r,t+1,n);return}const o=e;for(const[r,s]of Object.entries(o)){if(typeof s==="string"&&(Y.test(r)||T.test(r)||m.test(r))){n.push({key:r,value:s,holder:o})}else if(s&&typeof s==="object"){w(s,t+1,n)}}}function W(e){if(m.test(e))return"refresh";if(T.test(e))return"id";if(/session/i.test(e))return"session";return"access"}function I(e,t,n,o,r){for(const s of t){const i=q(e[s]);if(i!==void 0){return{expiresAt:o+i*1e3,source:s,lifetimeMs:i*1e3}}}for(const s of n){const i=K(e[s],r);if(i!==void 0)return{expiresAt:i,source:s}}return{}}function J(e){const t=e["set-cookie"];if(!t)return[];return t.split(/,(?=\s*[A-Za-z0-9!#$%&'*+.^_`|~-]+=)/).map(n=>n.trim())}export function tokensIssued(e,t){if(e.status===void 0||e.status>=400)return[];const n=`${e.method.toUpperCase()} ${pathOf(e.url)}`;const o=e.timestamp+(e.duration??0);const r=[];const s=D(e.responseData);if(s){const c=[];w(s,0,c);const u=new Map;for(const f of c.filter(a=>m.test(a.key))){const a=A(f.value,t);if(!a)continue;const p=I(f.holder,v,B,o,t);u.set(f.holder,{fp:l(f.value),expiresAt:a.expiresAt??p.expiresAt,formatLabel:a.formatLabel})}for(const f of c){if(m.test(f.key))continue;const a=A(f.value,t);if(!a)continue;const p=I(f.holder,U,F,o,t);r.push({fp:l(f.value),info:a,role:W(f.key),expiresAt:p.expiresAt,expirySource:p.source,lifetimeMs:p.lifetimeMs,issuedBy:n,refresh:u.get(f.holder)})}}const i=L(e.responseHeaders);for(const c of J(i)){const[u,...f]=c.split(";");const a=u.indexOf("=");if(a<=0)continue;const p=u.slice(0,a).trim();const d=u.slice(a+1).trim();const x=k(d,S.test(p)||/^(sid|sess)/i.test(p),t);if(!x||d===""||d.toLowerCase()==="deleted")continue;let _;let h;let E;for(const j of f){const[M,...z]=j.split("=");const O=M.trim().toLowerCase();const y=z.join("=").trim();if(O==="max-age"&&/^-?\d+$/.test(y)){E=Number(y)*1e3;_=o+E;h="Max-Age"}else if(O==="expires"&&h!=="Max-Age"){const b=t(y);if(Number.isFinite(b)){_=b;h="Expires"}}}r.push({fp:l(d),info:x,role:"cookie",cookie:p,expiresAt:x.expiresAt??_,expirySource:x.expiresAt?x.expirySource:h,lifetimeMs:x.expiresAt?void 0:E,issuedBy:n})}return r}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{dispatchToolAction as
|
|
1
|
+
"use strict";import{dispatchToolAction as j}from"@buoy-gg/shared-ui";import{loadToolModule as D}from"@buoy-gg/shared-ui/utils";import{RealDate as P,appNow as W,realNow as x}from"../engine/patches";import{hostOf as q,originOf as U,pathOf as I,tokensIssued as z,tokensUsed as b}from"./extract";const y=e=>P.parse(e);const _=4;const v=2e4;const X=8;const H=8;const K=200;const Q=1e3;const c=new Map;const d=new Map;const B=new Set;const N=new Set;const g=new Set;const Y=/(token|refresh|oauth|session|auth\/)/i;let n=null;const h=new Set;let A=true;let p=null;const S=new Set;let R=false;function m(){if(R)return;R=true;Promise.resolve().then(()=>{R=false;S.forEach(e=>e())})}export function subscribeTokens(e){S.add(e);return()=>{S.delete(e)}}function T(e,t){if(e.has(t))return false;if(e.size>=Q){const s=e.values().next().value;if(s!==void 0)e.delete(s)}e.add(t);return true}function E(e,t){return`${e}|${t.location}:${t.name.toLowerCase()}`}function $(e,t){const s=t?.lifetimeMs!==void 0&&t.expiresAt!==void 0;const r=s?t.expiresAt:e.expiresAt??t?.expiresAt;const u=e.expiresAt??(s?t.observedReal+t.lifetimeMs:t?.expiresAt);const i=s?t.expirySource:e.expiresAt?e.expirySource:t?.expirySource;const o=s?t.lifetimeMs:e.expiresAt!==void 0&&e.issuedAt!==void 0?e.expiresAt-e.issuedAt:void 0;return{expiresAt:r,serverExpiresAt:u,source:i,lifetimeMs:o}}function M(e,t,s,r,u){const i=d.get(t);const o=$(s,i);const f=e.fp!==t;if(f){e.history.unshift({fp:e.fp,firstSeenReal:e.firstSeenReal,expiresAt:e.expiresAt});e.history.length=Math.min(e.history.length,H);e.fp=t;e.firstSeenReal=r;e.firstSeenApp=u;e.uses=0;e.expiredSends=0;e.rejected=0}e.info=s;e.role=i?.role??(f?void 0:e.role);e.issuedBy=i?.issuedBy??(f?void 0:e.issuedBy);e.refresh=i?.refresh??(f?void 0:e.refresh);e.expiresAt=o.expiresAt;e.serverExpiresAt=o.serverExpiresAt;e.expirySource=o.source;e.lifetimeMs=o.lifetimeMs;if(f)G(e,r)}function F(e,t,s,r,u){const i=d.get(s.fp);const o=$(s.info,i);return{key:e,origin:t,host:q(t),location:s.location,name:s.name,scheme:s.scheme,fp:s.fp,info:s.info,role:i?.role,issuedBy:i?.issuedBy,refresh:i?.refresh,expiresAt:o.expiresAt,serverExpiresAt:o.serverExpiresAt,expirySource:o.source,lifetimeMs:o.lifetimeMs,firstSeenReal:r,firstSeenApp:u,lastUsedReal:r,lastUsedApp:u,uses:0,expiredSends:0,rejected:0,history:[]}}function L(){if(c.size<=X)return;let e=null;for(const t of c.values()){if(!e||t.lastUsedReal<e.lastUsedReal)e=t}if(e&&e.key!==n?.tokenId)c.delete(e.key)}function G(e,t){if(!n||n.tokenId!==e.key)return;n.newTokens+=1;if(n.status==="waiting"){n.status="refreshed";n.refreshedAt=t;if(n.ruleId&&n.forcedAt===void 0){void j("network","deleteOverrideRule",{id:n.ruleId}).catch(()=>{})}}if(n.newTokens>=_&&t-(n.refreshedAt??t)<=v){n.status="loop"}}function J(e){const t=U(e.url);if(!t)return;const s=b(e,y);if(s.length===0)return;const r=x();const u=e.timestamp;for(const i of s){const o=E(t,i);let f=c.get(o);if(!f){f=F(o,t,i,r,u);c.set(o,f);L()}else{M(f,i.fp,i.info,r,u)}f.uses+=1;f.lastUsedReal=r;f.lastUsedApp=u;if(f.expiresAt!==void 0&&u>=f.expiresAt)f.expiredSends+=1;if(n&&n.tokenId===o&&n.forcedAt!==void 0&&i.fp===n.startFp){n.staleAfterFailure+=1;T(h,e.id)}}m()}function V(e){const t=U(e.url);if(!t)return;const s=x();let r=false;if(e.status===401||e.status===403){for(const l of b(e,y)){const a=c.get(E(t,l));if(a&&a.fp===l.fp){a.rejected+=1;r=true}}}const u=!!n?.ruleId&&e.override?.ruleId===n.ruleId;const i=`${e.method.toUpperCase()} ${I(e.url)}`;const o=g.has(i)||e.method.toUpperCase()==="POST"&&Y.test(I(e.url));const f=e.status??0;if(n&&f>=400&&!u&&o){n.failedRefreshes+=1;n.lastRefreshError=`${e.status} ${i}`;r=true}if(n?.status==="waiting"&&n.forcedAt!==void 0&&!u&&f>=200&&f<400){if(o&&n.refreshOkAt===void 0){n.refreshOkAt=s;r=true}else if(!o&&n.refreshOkAt!==void 0&&h.has(e.id)){n.status="refreshed";n.refreshedAt=s;n.sameToken=true;r=true}}if(n?.ruleId&&e.override?.ruleId===n.ruleId&&n.forcedAt===void 0){n.forcedAt=s;r=true}for(const l of z(e,y)){g.add(l.issuedBy);d.set(l.fp,{...l,observedReal:s});if(d.size>K){const a=d.keys().next().value;if(a!==void 0)d.delete(a)}r=true;if(l.cookie){const a={location:"cookie",name:l.cookie,fp:l.fp,info:l.info};const k=E(t,a);const O=c.get(k);if(O)M(O,l.fp,l.info,s,e.timestamp);else{c.set(k,F(k,t,a,s,e.timestamp));L()}continue}for(const a of c.values()){if(a.fp===l.fp)M(a,l.fp,a.info,s,a.lastUsedApp)}}if(r)m()}function C(e){const t=e;if(!t||typeof t.id!=="string"||typeof t.url!=="string")return;if(T(B,t.id))J(t);if(t.status!==void 0&&T(N,t.id))V(t)}export function startTokenWatch(){if(p)return true;try{const{networkEventStore:e}=D("@buoy-gg/network");if(!e?.onEvent)throw new Error("no event store");p=e.onEvent(C,true);A=true}catch{A=false}m();return A}export function isTokenWatchOn(){return p!==null}export function beginTokenCheck(e,t,s){const r=c.get(t);if(!r)throw new Error(`No token row "${t}".`);n={kind:e,tokenId:t,startedAt:x(),startFp:r.fp,ruleId:s,status:"waiting",newTokens:0,staleAfterFailure:0,failedRefreshes:0};h.clear();m();return n}export function clearTokenCheck(){n=null;h.clear();m()}function Z(e){if(e.location==="cookie")return`${e.name} cookie`;if(e.location==="query")return`${e.name} parameter`;if(e.location==="header")return`${e.name} header`;if(e.role==="id"||e.info.claims.use==="id")return"ID token";return"Access token"}function w(e,t){const s=[e.firstSeenReal,...e.history.map(i=>i.firstSeenReal)].slice(0,-1);const r=s.filter(i=>t-i<=v).length;const u=e.info.issuedAt;return{id:e.key,label:Z(e),host:e.host,location:e.location,name:e.name,scheme:e.scheme,format:e.info.format,formatLabel:e.info.formatLabel,hint:e.info.hint,claims:e.info.claims,fingerprint:e.fp,issuedAt:u,notBefore:e.info.notBefore,expiresAt:e.expiresAt,serverExpiresAt:e.serverExpiresAt,expirySource:e.expirySource,lifetimeMs:e.lifetimeMs,neverExpires:e.info.neverExpires,issuedBy:e.issuedBy,refresh:e.refresh?{expiresAt:e.refresh.expiresAt,formatLabel:e.refresh.formatLabel}:void 0,firstUsed:e.firstSeenApp,lastUsed:e.lastUsedApp,lastUsedReal:e.lastUsedReal,uses:e.uses,refreshes:e.history.length,lastRefreshAt:e.history.length?e.firstSeenReal:void 0,recentRefreshes:r,looping:r>=_,expiredSends:e.expiredSends,rejected:e.rejected}}export function getTokenReport(){const e=x();const t=[...c.values()].sort((s,r)=>r.lastUsedReal-s.lastUsedReal).map(s=>w(s,e));if(n?.status==="refreshed"){const s=c.get(n.tokenId);if(s){n.newLifetimeMs=s.lifetimeMs;n.newIssuedBy=s.issuedBy}}return{available:A,watching:p!==null,tokens:t,check:n?{...n}:null}}export function getTokenRow(e){const t=getTokenReport();if(e)return t.tokens.find(s=>s.id===e||s.fingerprint===e)??null;return t.tokens.find(s=>s.expiresAt!==void 0)??t.tokens[0]??null}export function getTokenOrigin(e){return c.get(e)?.origin??null}export const tokenAppNow=W;export function __ingestForTests(e){C(e)}export function __resetTokensForTests(){c.clear();d.clear();B.clear();N.clear();g.clear();n=null;h.clear();A=true;p?.();p=null}
|
|
@@ -40,6 +40,13 @@ export interface TokenCheck {
|
|
|
40
40
|
newTokens: number;
|
|
41
41
|
/** Requests after the forced 401 that still carried the old token. */
|
|
42
42
|
staleAfterFailure: number;
|
|
43
|
+
/** Real ms a token request succeeded after the forced 401. */
|
|
44
|
+
refreshOkAt?: number;
|
|
45
|
+
/**
|
|
46
|
+
* The refresh worked and the retried request worked, but the refresh sent
|
|
47
|
+
* back the same token (mocked sign-ins often do). Still a pass.
|
|
48
|
+
*/
|
|
49
|
+
sameToken?: boolean;
|
|
43
50
|
/** Token requests that failed while the check ran ("401 POST /oauth/token"). */
|
|
44
51
|
failedRefreshes: number;
|
|
45
52
|
lastRefreshError?: string;
|
package/lib/web/index.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use client";var gt=Object.defineProperty;var Kr=Object.getOwnPropertyDescriptor;var Zr=Object.getOwnPropertyNames;var Gr=Object.prototype.hasOwnProperty;var Yr=(e,t)=>{for(var r in t)gt(e,r,{get:t[r],enumerable:true})},bt=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of Zr(t))!Gr.call(e,o)&&o!==r&>(e,o,{get:()=>t[o],enumerable:!(n=Kr(t,o))||n.enumerable});return e},Qr=(e,t,r)=>(bt(e,t,"default"),r&&bt(r,t,"default"));var kt=(()=>{try{let e=globalThis.Capacitor;if(e&&typeof e.isNativePlatform=="function"&&e.isNativePlatform())return e.DEBUG===true}catch{}return process.env.NODE_ENV!=="production"})();typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);var vt={};Yr(vt,{AccessibilityInfo:()=>rn,ActivityIndicator:()=>ro,Alert:()=>io,Animated:()=>xt,AppRegistry:()=>on,AppState:()=>sn,Appearance:()=>nn,BackHandler:()=>an,Button:()=>no,CheckBox:()=>An,Clipboard:()=>ln,DeviceEventEmitter:()=>_n,Dimensions:()=>un,Easing:()=>cn,FlatList:()=>Tn,I18nManager:()=>dn,Image:()=>Sn,ImageBackground:()=>$n,InteractionManager:()=>pn,Keyboard:()=>fn,KeyboardAvoidingView:()=>In,LayoutAnimation:()=>hn,Linking:()=>mn,LogBox:()=>Mn,Modal:()=>eo,NativeEventEmitter:()=>yn,NativeModules:()=>tn,PanResponder:()=>gn,Picker:()=>Cn,PixelRatio:()=>bn,Platform:()=>kn,Pressable:()=>Xn,ProgressBar:()=>Rn,RefreshControl:()=>En,SafeAreaView:()=>On,ScrollView:()=>$t,SectionList:()=>Dn,Share:()=>vn,StatusBar:()=>Pn,StyleSheet:()=>G,Switch:()=>to,Text:()=>A,TextInput:()=>St,Touchable:()=>Ln,TouchableHighlight:()=>Yn,TouchableNativeFeedback:()=>Nn,TouchableOpacity:()=>B,TouchableWithoutFeedback:()=>Qn,UIManager:()=>xn,Vibration:()=>wn,View:()=>m,VirtualizedList:()=>zn,YellowBox:()=>jn,findNodeHandle:()=>oo,unstable_createElement:()=>en,useColorScheme:()=>Fn,useLocaleContext:()=>Bn,useWindowDimensions:()=>Un});Qr(vt,Xr);import*as Xr from"react-native-web";import{unstable_createElement as en,NativeModules as tn,AccessibilityInfo as rn,Animated as xt,Appearance as nn,AppRegistry as on,AppState as sn,BackHandler as an,Clipboard as ln,Dimensions as un,Easing as cn,I18nManager as dn,Keyboard as fn,InteractionManager as pn,LayoutAnimation as hn,Linking as mn,NativeEventEmitter as yn,PanResponder as gn,PixelRatio as bn,Platform as kn,Share as vn,StyleSheet as G,UIManager as xn,Vibration as wn,CheckBox as An,FlatList as Tn,Image as Sn,ImageBackground as $n,KeyboardAvoidingView as In,Picker as Cn,ProgressBar as Rn,RefreshControl as En,SafeAreaView as On,SectionList as Dn,StatusBar as Pn,Touchable as Ln,TouchableNativeFeedback as Nn,VirtualizedList as zn,YellowBox as jn,LogBox as Mn,DeviceEventEmitter as _n,useColorScheme as Fn,useLocaleContext as Bn,useWindowDimensions as Un}from"react-native-web";import*as E from"react-native-web";import{createElement as Ee,forwardRef as wt,useCallback as Hn,useRef as Vn}from"react";import{useEffect as Wn,useState as Jn}from"react";import{createPortal as qn}from"react-dom";var Kn='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';import{jsx as Zn}from"react/jsx-runtime";var te=Symbol.for("@buoy-gg/portal-host"),At=e=>{if(!(e instanceof Element))return false;if(e.closest("input, textarea, select"))return true;let t=e.closest("[contenteditable]")?.getAttribute("contenteditable")?.toLowerCase();return t===""||t==="true"||t==="plaintext-only"};function Tt(){let e=document;if(e[te])return e[te].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:Kn});let r=()=>{let u=document.fullscreenElement,y=u&&u.tagName!=="CANVAS"?u:document.body;t.parentElement!==y&&y.appendChild(t)},n=new Map,o=u=>{(!t.contains(u.target)||!At(u.target))&&n.set(u.code||u.key,{key:u.key,code:u.code,location:u.location,keyCode:u.keyCode,which:u.which,altKey:u.altKey,ctrlKey:u.ctrlKey,metaKey:u.metaKey,shiftKey:u.shiftKey})},i=u=>{n.delete(u.code||u.key)},s=()=>n.clear(),a=()=>{let u=[...n.values()];n.clear();for(let y of u)document.dispatchEvent(new KeyboardEvent("keyup",{...y,bubbles:true}))},l=u=>{At(u.target)&&u.stopPropagation()},c=u=>u.stopPropagation();return r(),document.addEventListener("fullscreenchange",r),document.addEventListener("keydown",o,true),document.addEventListener("keyup",i,true),window.addEventListener("blur",s),t.addEventListener("focusin",a),t.addEventListener("keydown",l),t.addEventListener("keyup",l),t.addEventListener("keypress",l),t.addEventListener("wheel",c,{passive:true}),e[te]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",r),document.removeEventListener("keydown",o,true),document.removeEventListener("keyup",i,true),window.removeEventListener("blur",s),t.remove(),delete e[te]}},t}function Gn({children:e}){let[t,r]=Jn(null);return Wn(()=>{let n=Tt(),o=document[te];return o.users++,r(n),()=>{--o.users===0&&o.dispose()}},[]),t?qn(Zn("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}function D(e){let t=wt((n,o)=>{let{accessibilityState:i,accessibilityValue:s,...a}=n;for(let l of["busy","checked","disabled","expanded","selected"])i?.[l]!==void 0&&a[`aria-${l}`]===void 0&&(a[`aria-${l}`]=i[l]);for(let[l,c]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))s?.[l]!==void 0&&a[`aria-${c}`]===void 0&&(a[`aria-${c}`]=s[l]);return Ee(e,{...a,ref:o})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var m=D(E.View),A=D(E.Text),St=D(E.TextInput),B=D(E.TouchableOpacity),Yn=D(E.TouchableHighlight),Qn=D(E.TouchableWithoutFeedback),Xn=D(E.Pressable),$t=D(E.ScrollView),It=wt((e,t)=>{let r=Vn(null),n=Hn(o=>{if(o){let i=o;for(;i.parentElement&&i.parentElement!==document.body;)i=i.parentElement;i.parentElement===document.body&&(r.current=i,Object.assign(i.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),Tt().appendChild(i))}else r.current&&(document.body.appendChild(r.current),r.current=null);typeof t=="function"?t(o):t&&(t.current=o)},[t]);return Ee(Gn,null,Ee(E.Modal,{...e,ref:n}))});It.displayName="Modal";var eo=D(It),to=D(E.Switch),ro=D(E.ActivityIndicator),no=D(E.Button),oo=E.findNodeHandle,io={alert(e,t,r,n){if(typeof document>"u")return;let o=document.createElement("dialog");o.dataset.buoyRoot="",o.setAttribute("aria-label",e),o.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let i=document.createElement("h2");if(i.textContent=e,i.style.cssText="font-size:18px;margin:0 0 12px",o.appendChild(i),t){let c=document.createElement("p");c.textContent=t,c.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",o.appendChild(c)}let s=document.createElement("div");s.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let a=r?.length?r:[{text:"OK"}],l=()=>{o.close?.(),o.remove()};for(let c of a){let u=document.createElement("button");u.type="button",u.textContent=c.text??"OK",u.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${c.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,u.onclick=()=>{l(),c.onPress?.()},s.appendChild(u)}o.addEventListener("cancel",c=>{c.preventDefault(),n?.cancelable!==false&&(l(),n?.onDismiss?.())}),o.appendChild(s),document.body.appendChild(o),o.showModal?o.showModal():o.setAttribute("open","")}};var Oe=Object.freeze({mode:"real",anchorReal:0,anchorVirtual:0,rate:1}),De=.1,Pe=86400,so=864e13;function M(e,t){return e.mode==="real"?t:e.mode==="frozen"?e.anchorVirtual:e.anchorVirtual+(t-e.anchorReal)*e.rate}function ao(e,t){return M(e,t)-t}function Y(e){if(!Number.isFinite(e)||Math.abs(e)>so)throw new RangeError(`Not a valid time: ${e}`);return Math.round(e)}function Le(e,t,r,n=false){return{mode:n?"frozen":"running",anchorReal:t,anchorVirtual:Y(r),rate:e.mode==="real"?1:e.rate}}function lo(e,t,r){if(!Number.isFinite(r))throw new RangeError("Jump must be a number of ms");return Le(e,t,M(e,t)+r,e.mode==="frozen")}function uo(e,t,r){return Le(e,t,r??M(e,t),true)}function co(e,t){return e.mode!=="frozen"?e:{...e,mode:"running",anchorReal:t}}function fo(e,t,r){if(!Number.isFinite(r)||r<De||r>Pe)throw new RangeError(`Speed must be between ${De}\xD7 and ${Pe}\xD7`);return e.mode==="real"&&r===1?e:{mode:"running",anchorReal:t,anchorVirtual:Y(M(e,t)),rate:r}}function Ct(e){let t=e;return!!t&&(t.mode==="real"||t.mode==="running"||t.mode==="frozen")&&Number.isFinite(t.anchorReal)&&Number.isFinite(t.anchorVirtual)&&Number.isFinite(t.rate)&&t.rate>=De&&t.rate<=Pe}var po={ms:1,millisecond:1,milliseconds:1,s:1e3,sec:1e3,secs:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,mins:6e4,minute:6e4,minutes:6e4,h:36e5,hr:36e5,hrs:36e5,hour:36e5,hours:36e5,d:864e5,day:864e5,days:864e5,w:6048e5,wk:6048e5,week:6048e5,weeks:6048e5,mo:30*864e5,month:30*864e5,months:30*864e5,y:365*864e5,yr:365*864e5,year:365*864e5,years:365*864e5};function Ne(e){if(typeof e=="number"){if(!Number.isFinite(e))throw new RangeError("Duration must be finite");return Math.round(e)}let t=String(e).trim().toLowerCase();if(!t)throw new RangeError("Duration is empty");let r=1;if((t[0]==="+"||t[0]==="-"||t[0]==="\u2212")&&(r=t[0]==="+"?1:-1,t=t.slice(1).trim()),/^\d+(\.\d+)?$/.test(t))return r*Math.round(Number(t));let n=/(\d+(?:\.\d+)?)\s*([a-z]+)/g,o=0,i="",s;for(;s=n.exec(t);){let a=po[s[2]];if(a===void 0)throw new RangeError(`Unknown time unit "${s[2]}" in "${e}"`);o+=Number(s[1])*a,i+=s[0]}if(!i||i.replace(/\s/g,"")!==t.replace(/[\s,]/g,""))throw new RangeError(`Could not read "${e}" as a duration. Try "+1d", "-2h30m" or "90s".`);return r*Math.round(o)}function re(e,{signed:t=true}={}){let r=e<0?"\u2212":"+",n=Math.abs(Math.round(e));if(n<1e3)return t&&n>0?`${r}${n}ms`:"0s";let o=[],i=[["y",365*864e5],["d",864e5],["h",36e5],["m",6e4],["s",1e3]];for(let[s,a]of i)if(n>=a&&(o.push(`${Math.floor(n/a)}${s}`),n%=a),o.length===2)break;return`${t?r:""}${o.join(" ")}`}function Rt(e,t,r){if(typeof e=="number")return Y(e);let n=String(e).trim();if(!n)throw new RangeError("Time is empty");if(/^now$/i.test(n))return t;if(/^[+\-−]/.test(n))return Y(t+Ne(n));if(/^\d{11,}$/.test(n))return Y(Number(n));let o=n.replace(/^(\d{4}-\d{2}-\d{2})[ ](\d{2}:\d{2})/,"$1T$2"),i=r(o);if(!Number.isFinite(i))throw new RangeError(`Could not read "${e}" as a time. Use ISO 8601 like 2026-12-31T23:59:50, epoch ms, or "+1d".`);return Y(i)}var ze=1e4,Et=[{id:"midnight",label:"Before midnight",hint:"23:59:50 tonight",at(e,t){let r=new t(e);return r.setHours(24,0,0,0),r.getTime()-ze}},{id:"month-end",label:"Month end",hint:"last day, 23:59:50",at(e,t){let r=new t(e);return r.setMonth(r.getMonth()+1,1),r.setHours(0,0,0,0),r.getTime()-ze}},{id:"year-end",label:"New Year's Eve",hint:"Dec 31, 23:59:50",at(e,t){let r=new t(e);return r.setFullYear(r.getFullYear()+1,0,1),r.setHours(0,0,0,0),r.getTime()-ze}},{id:"tomorrow-9",label:"Tomorrow 9 AM",hint:"start of a business day",at(e,t){let r=new t(e);return r.setDate(r.getDate()+1),r.setHours(9,0,0,0),r.getTime()}},{id:"leap-day",label:"Leap day",hint:"next Feb 29, 09:00",at(e,t){let r=new t(e).getFullYear();for(;;){let n=r%4===0&&r%100!==0||r%400===0,o=new t(r,1,29,9,0,0,0).getTime();if(n&&o>e)return o;r+=1}}}],Js=[{label:"1m",ms:6e4},{label:"15m",ms:15*6e4},{label:"1h",ms:36e5},{label:"1d",ms:864e5},{label:"7d",ms:7*864e5},{label:"30d",ms:30*864e5},{label:"1y",ms:365*864e5}];function Ot(e){return e===3600?"1h/s":e===600?"10m/s":e===60?"1m/s":`${Number.isInteger(e)?e:e.toFixed(1)}\xD7`}var P=globalThis,he="__buoyClock",T=P.__buoyRealDate??(Date[he]?Date.__buoyRealDate:Date);P.__buoyRealDate=T;var Dt=T.now.bind(T);function S(){return Dt()}P.__buoyRealNow=S;var je=null,Me=0;function me(){let e=Dt();return!je||Me>0?e:je(e)}function Pt(e){je=e}function _e(e){Me+=1;try{return e()}finally{Me-=1}}P.__buoyWithRealClock=_e;function _(...e){let t=new.target;return t?Reflect.construct(T,e.length===0?[me()]:e,t):new T(me()).toString()}_.prototype=T.prototype;Object.defineProperty(_,"name",{value:"Date"});Object.defineProperty(_,"length",{value:7});Object.defineProperty(_,"now",{value:function(){return me()},writable:true,configurable:true});Object.defineProperty(_,"parse",{value:T.parse,writable:true,configurable:true});Object.defineProperty(_,"UTC",{value:T.UTC,writable:true,configurable:true});Object.defineProperty(_,he,{value:true});Object.defineProperty(_,"__buoyRealDate",{value:T});var ne=_,ye=false,ge;function ho(){return ye&&P.Date===ne}function mo(){if(P.Date===ne){ye=true;return}let e=Object.getOwnPropertyDescriptor(P,"Date");Object.defineProperty(P,"Date",{value:ne,writable:e?.writable??true,enumerable:e?.enumerable??false,configurable:true}),ge=Object.getOwnPropertyDescriptor(T.prototype,"constructor");try{Object.defineProperty(T.prototype,"constructor",{value:ne,writable:true,enumerable:false,configurable:true})}catch{}ye=true}function yo(){if(P.Date===ne){let e=Object.getOwnPropertyDescriptor(P,"Date");Object.defineProperty(P,"Date",{value:T,writable:e?.writable??true,enumerable:e?.enumerable??false,configurable:true})}if(ge){try{Object.defineProperty(T.prototype,"constructor",ge)}catch{}ge=void 0}ye=false}var oe=[];function Lt(e){return function(t,...r){return e.call(this,t===void 0?me():t,...r)}}function go(){if(oe.length)return;let e=P.Intl?.DateTimeFormat?.prototype;if(e)for(let t of["format","formatToParts"]){let r=Object.getOwnPropertyDescriptor(e,t);if(!(!r||!r.configurable))try{if(typeof r.get=="function"){let n=r.get;Object.defineProperty(e,t,{...r,get(){return Lt(n.call(this))}})}else if(typeof r.value=="function")Object.defineProperty(e,t,{...r,value:Lt(r.value)});else continue;oe.push({proto:e,name:t,original:r})}catch{}}}function bo(){for(let{proto:e,name:t,original:r}of oe)try{Object.defineProperty(e,t,r)}catch{}oe=[]}function ko(){return oe.length>0}function vo(){mo(),go()}function xo(){yo(),bo()}var Fe=false;function wo(e){let t=Object.getPrototypeOf(e);for(;t&&t!==Object.prototype;){if(!Object.prototype.hasOwnProperty.call(t,he)){for(let r of["start","onUpdate"]){let n=Object.getOwnPropertyDescriptor(t,r);if(n&&typeof n.value=="function"){let o=n.value;t[r]=function(...i){return _e(()=>o.apply(this,i))}}}try{Object.defineProperty(t,he,{value:true})}catch{return}}t=Object.getPrototypeOf(t)}}function Ao(e){if(Fe)return true;try{let t=e;if(typeof t?.Value!="function")return false;let r=Object.getPrototypeOf(new t.Value(0)),n=r?.animate;return typeof n!="function"?false:(r.animate=function(o,...i){return o&&typeof o=="object"&&wo(o),n.call(this,o,...i)},Fe=true,true)}catch{return false}}function To(){return Fe}var ie=globalThis,Nt="__buoyClockTimer",L=new Map,J=null,So={},zt=0,q=()=>S()+zt;function $o(e){(J?.setTimeout??setTimeout)(()=>{throw e},0)}function jt(e){let t=Number(e);return Number.isFinite(t)&&t>0?t:0}function Io(){return J!==null}function Mt(){if(J)return true;let{setTimeout:e,clearTimeout:t,setInterval:r,clearInterval:n}=ie;if(typeof e!="function"||typeof t!="function")return false;if(e[Nt])return true;So={setTimeout:e,clearTimeout:t,setInterval:r,clearInterval:n},J={setTimeout:e.bind(globalThis),clearTimeout:t.bind(globalThis),setInterval:(typeof r=="function"?r:e).bind(globalThis),clearInterval:(typeof n=="function"?n:t).bind(globalThis)};let o=J,i=function(u,y,...k){if(typeof u!="function")return o.setTimeout(u,y,...k);let I=jt(y),v,R=function(){return L.delete(v),u.apply(this,k)};return v=o.setTimeout(R,y),L.set(v,{kind:"timeout",callback:u,args:k,delay:I,due:q()+I,realHandle:v,run:R}),v},s=function(u,y,...k){if(typeof u!="function")return o.setInterval(u,y,...k);let I=jt(y),v,R=function(){let z=L.get(v);return z&&(z.due=q()+I),u.apply(this,k)};return v=o.setInterval(R,y),L.set(v,{kind:"interval",callback:u,args:k,delay:I,due:q()+I,realHandle:v,run:R}),v},a=(u,y)=>{let k=L.get(u);return k?(L.delete(u),k.kind==="interval"?o.clearInterval(k.realHandle):o.clearTimeout(k.realHandle)):y(u)},l=function(u){return a(u,o.clearTimeout)},c=function(u){return a(u,o.clearInterval)};globalThis.__buoyRealTimers={setTimeout:o.setTimeout,clearTimeout:l,setInterval:o.setInterval,clearInterval:c};for(let u of[i,s,l,c])Object.defineProperty(u,Nt,{value:true});return ie.setTimeout=i,ie.clearTimeout=l,ie.setInterval=s,ie.clearInterval=c,true}function Co(){let e=q(),t=0,r=0,n=null;for(let o of L.values())if(o.kind==="interval")r+=1;else{t+=1;let i=Math.max(0,o.due-e);(n===null||i<n)&&(n=i)}return{total:t+r,timeouts:t,intervals:r,nextTimeoutInMs:n}}function Ro(e){let t=q(),r=0;for(let n of L.values())n.due-t<=e&&(r+=1);return r}function Eo(e){if(!J||!(e>0))return 0;let t=J;zt+=e;let r=q(),n=[...L.entries()].filter(([,s])=>s.due<=r).sort((s,a)=>s[1].due-a[1].due),o=0;for(let[s,a]of n)if(L.has(s)){a.kind==="timeout"?(L.delete(s),t.clearTimeout(a.realHandle)):a.due=r+a.delay;try{a.callback(...a.args)}catch(l){$o(l)}o+=1}let i=q();for(let s of L.values())s.kind==="timeout"&&(t.clearTimeout(s.realHandle),s.realHandle=t.setTimeout(s.run,Math.max(0,s.due-i)));return o}import{devToolsStorageKeys as Oo,persistentStorage as _t}from"@buoy-gg/shared-ui/web";function Do(){try{let e=globalThis.localStorage;return e?Ft(e.getItem(Be)):void 0}catch{return}}var se={persist:true,showChip:true,fireTimersOnJump:true},Po=2*6e4,Be=Oo.clock.state();function Ft(e){if(!e)return null;try{let t=JSON.parse(e);if(!t||t.v!==1)return null;let r=t.settings??{},n=t.reload&&Ct(t.reload.anchor)&&typeof t.reload.at=="number"?{anchor:t.reload.anchor,at:t.reload.at}:void 0;return{v:1,anchor:Ct(t.anchor)?t.anchor:null,...n?{reload:n}:{},settings:{persist:typeof r.persist=="boolean"?r.persist:se.persist,showChip:typeof r.showChip=="boolean"?r.showChip:se.showChip,fireTimersOnJump:typeof r.fireTimersOnJump=="boolean"?r.fireTimersOnJump:se.fireTimersOnJump}}}catch{return null}}async function Lo(){try{return Ft(await _t.getItem(Be))}catch{return null}}var Ue=Promise.resolve();function He(e){let t=JSON.stringify(e);return Ue=Ue.then(()=>_t.setItem(Be,t)).catch(()=>{}),Ue.then(()=>{})}import{dispatchToolAction as No}from"@buoy-gg/shared-ui/web";import{loadToolModule as zo}from"@buoy-gg/shared-ui/web/utils";var Bt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",be={};for(let e=0;e<Bt.length;e++)be[Bt[e]]=e;be["-"]=62;be._=63;function Ve(e){let t=e.replace(/=+$/,""),r=[],n=0,o=0;for(let i=0;i<t.length;i++){let s=be[t[i]];if(s===void 0)return null;n=n<<6|s,o+=6,o>=8&&(o-=8,r.push(n>>o&255))}return r}function jo(e){let t="";for(let r=0;r<e.length;){let n=e[r],o,i;if(n<128)o=n,i=0;else if(n>=192&&n<224)o=n&31,i=1;else if(n>=224&&n<240)o=n&15,i=2;else if(n>=240&&n<248)o=n&7,i=3;else return null;for(let s=1;s<=i;s++){let a=e[r+s];if(a===void 0||(a&192)!==128)return null;o=o<<6|a&63}t+=String.fromCodePoint(o),r+=i+1}return t}function We(e){let t=Ve(e);return t?Ut(t):null}function Ut(e){let t=jo(e);if(!t||t[0]!=="{")return null;try{let r=JSON.parse(t);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}function Je(e){let t=typeof e=="string"&&e.trim()!==""?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>0?t*1e3:void 0}function ae(e,t){if(typeof e=="number"&&Number.isFinite(e)&&e>0)return e<1e11?e*1e3:e;if(typeof e=="string"&&e.trim()!==""){let r=e.trim();if(/^\d+(\.\d+)?$/.test(r))return ae(Number(r),t);let n=t(r);return Number.isFinite(n)?n:void 0}}function Mo(e){let t=typeof e=="string"&&/^\d+(\.\d+)?$/.test(e.trim())?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>0?t:void 0}var _o=/^[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$/,Fo=/^[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$/,Ht=/^v([1-4])\.(local|public)\.([A-Za-z0-9_-]+)(?:\.([A-Za-z0-9_-]+))?$/,Bo={1:256,2:64,3:96,4:64};function U(e){if(typeof e=="string"&&e)return e;if(Array.isArray(e)){let t=e.filter(r=>typeof r=="string");return t.length?t.join(", "):void 0}}function Uo(e,t){let r=e.iss??"",n=e.use;if(r.includes("securetoken.google.com"))return"Firebase ID token";if(r.includes("firebaseappcheck"))return"Firebase App Check token";if(r.includes("cognito-idp"))return n?`Cognito ${n} token`:"Cognito token";if(r.includes("appleid.apple.com"))return"Sign in with Apple token";if(r.includes("accounts.google.com"))return"Google ID token";if(r.includes(".auth0.com")||r.includes("auth0"))return"Auth0 token";if(r.includes("clerk"))return"Clerk session token";if(r.includes("supabase")||r.includes("/auth/v1"))return"Supabase access token";if(r.includes("okta"))return"Okta token";if(r.includes("/realms/"))return"Keycloak token";if(r.includes("login.microsoftonline.com")||r.includes("sts.windows.net"))return"Microsoft Entra token";let o=typeof t?.typ=="string"?t.typ.toLowerCase():"";if(o==="at+jwt"||o==="application/at+jwt")return"OAuth access token"}function Ho(e,t){let r={iss:U(e.iss),aud:U(e.aud),sub:U(e.sub),scope:U(e.scope??e.scp),use:U(e.token_use)},n=Je(e.exp);return{claims:r,issuedAt:Je(e.iat),notBefore:Je(e.nbf),expiresAt:n,expirySource:n?t:void 0}}function Vo(e){let[t,r]=e.split("."),n=We(t);if(!n||typeof n.alg!="string"&&typeof n.typ!="string")return null;let o=We(r);if(!o)return null;let i=typeof n.alg=="string"?n.alg:void 0,s=Ho(o,"exp claim");return s.claims.alg=i,!s.claims.use&&typeof n.typ=="string"&&n.typ.toUpperCase()!=="JWT"&&(s.claims.use=n.typ),{format:"jwt",formatLabel:i?`JWT \xB7 ${i}`:"JWT",hint:Uo(s.claims,n),...s}}function Wo(e){let t=We(e.split(".")[0]);return!t||typeof t.enc!="string"?null:{format:"jwe",formatLabel:"Encrypted JWT",claims:{alg:typeof t.alg=="string"?t.alg:void 0}}}function Jo(e,t){let r=Ht.exec(e);if(!r)return null;let[,n,o,i]=r;if(o==="local")return{format:"paseto-local",formatLabel:`PASETO v${n} (encrypted)`,claims:{}};let s=Ve(i),a=Bo[n],l=s&&s.length>a?Ut(s.slice(0,s.length-a)):null,c={format:"paseto-public",formatLabel:`PASETO v${n}`,claims:{}};return l&&(c.claims={iss:U(l.iss),aud:U(l.aud),sub:U(l.sub)},c.issuedAt=ae(l.iat,t),c.notBefore=ae(l.nbf,t),c.expiresAt=ae(l.exp,t),c.expiresAt&&(c.expirySource="exp claim")),c}function qo(e){if(!e.startsWith("gAAAAA")||e.length<76)return null;let t=Ve(e);if(!t||t[0]!==128||t.length<73||(t.length-57)%16!==0)return null;let r=0;for(let n=1;n<=8;n++)r=r*256+t[n];return r<978307200||r>4102444800?null:{format:"fernet",formatLabel:"Fernet",claims:{},issuedAt:r*1e3}}var Ko=[{test:/^ya29\./,hint:"Google OAuth access token"},{test:/^gh[opsu]_/,hint:"GitHub token"},{test:/^github_pat_/,hint:"GitHub token"},{test:/^xox[abeprs]-/,hint:"Slack token"},{test:/^EAA[A-Za-z0-9]{40,}/,hint:"Facebook access token"},{test:/^shp(at|ca|pa|ss)_/,hint:"Shopify token"},{test:/^(sk|rk|pk)_(live|test)_/,hint:"Stripe API key",neverExpires:true},{test:/^AIza[0-9A-Za-z_-]{35}$/,hint:"Google API key",neverExpires:true}];function ke(e,t=Date.parse){let r=e.trim().replace(/^"(.*)"$/,"$1");if(r.length<16||/\s/.test(r))return null;if(_o.test(r)){let i=Vo(r);if(i)return i}if(Fo.test(r)){let i=Wo(r);if(i)return i}if(r.startsWith("v")&&Ht.test(r)){let i=Jo(r,t);if(i)return i}let n=qo(r);if(n)return n;let o=Ko.find(i=>i.test.test(r));return{format:"opaque",formatLabel:"Opaque",hint:o?.hint,neverExpires:o?.neverExpires,claims:{}}}function Zo(e){return!!e&&e.format!=="opaque"}function H(e){let t=2166136261;for(let r=0;r<e.length;r++)t^=e.charCodeAt(r),t=Math.imul(t,16777619)>>>0;return t.toString(16).padStart(8,"0")}function qe(e){let t=/^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(e);return t?t[1].toLowerCase():null}function Go(e){let t=qe(e);return t?t.replace(/^[a-z][a-z0-9+.-]*:\/\//,""):"unknown"}function Ke(e){return e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i,"").split(/[?#]/)[0]||"/"}function Yo(e){let t=e.split("#")[0].split("?")[1];if(!t)return[];let r=[];for(let n of t.split("&")){let o=n.indexOf("=");if(!(o<=0))try{r.push([decodeURIComponent(n.slice(0,o)),decodeURIComponent(n.slice(o+1))])}catch{}}return r}var Ze=/(token|jwt|session|auth|appcheck|api[-_]?key|apikey|credential|bearer)/i,Qo=new Set(["authorization","cookie","dpop","idempotency-key","x-request-id","x-correlation-id","www-authenticate","proxy-authenticate","x-csrf-token","x-xsrf-token"]),Vt=new Set(["access_token","accesstoken","id_token","token","auth","auth_token","jwt","session","session_token"]),Xo=new Set(["bearer","token","jwt","dpop","oauth","firebase"]);function Wt(e){let t={};if(!e)return t;for(let[r,n]of Object.entries(e))typeof n=="string"?t[r.toLowerCase()]=n:Array.isArray(n)&&(t[r.toLowerCase()]=n.join(", "));return t}function ei(e){let t=[];for(let r of e.split(";")){let n=r.indexOf("=");n<=0||t.push([r.slice(0,n).trim(),r.slice(n+1).trim()])}return t}function le(e,t,r){let n=ke(e,r);return n&&(Zo(n)||n.hint||t)?n:null}function Jt(e,t){let r=[],n=Wt(e.requestHeaders),o=n.authorization;if(o){let i=/^(\S+)\s+(\S+)$/.exec(o.trim()),s=i?i[1]:void 0,a=i?i[2]:o.trim();if(!s||Xo.has(s.toLowerCase())){let l=le(a,true,t);l&&r.push({location:"authorization",name:"Authorization",scheme:s,fp:H(a),info:l})}}for(let[i,s]of Object.entries(n)){if(Qo.has(i)||!Ze.test(i))continue;let a=s.replace(/^bearer\s+/i,""),l=le(a,true,t);l&&r.push({location:"header",name:i,fp:H(a),info:l})}if(n.cookie)for(let[i,s]of ei(n.cookie)){let a=le(s,Ze.test(i)||/^(sid|sess)/i.test(i),t);a&&r.push({location:"cookie",name:i,fp:H(s),info:a})}for(let[i,s]of Yo(e.url)){let a=le(s,Vt.has(i.toLowerCase()),t);a&&Vt.has(i.toLowerCase())&&r.push({location:"query",name:i,fp:H(s),info:a})}return r}var ti=/^(access_?token|accesstoken|token|jwt|auth_?token|session_?token|sessiontoken)$/i,qt=/^(id_?token|idtoken)$/i,ve=/^(refresh_?token|refreshtoken)$/i,ri=["expires_in","expiresIn","ExpiresIn","expires","ttl"],ni=["expires_at","expiresAt","ExpiresAt","expiration","Expiration","expiry","expirationTime","expiration_time","access_token_expires_at","accessTokenExpiresAt","accessTokenExpiry"],oi=["refresh_expires_in","refresh_token_expires_in","refreshTokenExpiresIn","refreshExpiresIn"],ii=["refresh_expires_at","refreshTokenExpiresAt","refresh_token_expires_at"];function si(e){if(typeof e!="string")return e;let t=e.trim();if(!(t.startsWith("{")||t.startsWith("[")))return null;try{return JSON.parse(t)}catch{return null}}function Ge(e,t,r){if(t>4||!e||typeof e!="object")return;if(Array.isArray(e)){for(let o of e.slice(0,5))Ge(o,t+1,r);return}let n=e;for(let[o,i]of Object.entries(n))typeof i=="string"&&(ti.test(o)||qt.test(o)||ve.test(o))?r.push({key:o,value:i,holder:n}):i&&typeof i=="object"&&Ge(i,t+1,r)}function ai(e){return ve.test(e)?"refresh":qt.test(e)?"id":/session/i.test(e)?"session":"access"}function Kt(e,t,r,n,o){for(let i of t){let s=Mo(e[i]);if(s!==void 0)return{expiresAt:n+s*1e3,source:i,lifetimeMs:s*1e3}}for(let i of r){let s=ae(e[i],o);if(s!==void 0)return{expiresAt:s,source:i}}return{}}function li(e){let t=e["set-cookie"];return t?t.split(/,(?=\s*[A-Za-z0-9!#$%&'*+.^_`|~-]+=)/).map(r=>r.trim()):[]}function ui(e,t){if(e.status===void 0||e.status>=400)return[];let r=`${e.method.toUpperCase()} ${Ke(e.url)}`,n=e.timestamp+(e.duration??0),o=[],i=si(e.responseData);if(i){let a=[];Ge(i,0,a);let l=new Map;for(let c of a.filter(u=>ve.test(u.key))){let u=ke(c.value,t);if(!u)continue;let y=Kt(c.holder,oi,ii,n,t);l.set(c.holder,{fp:H(c.value),expiresAt:u.expiresAt??y.expiresAt,formatLabel:u.formatLabel})}for(let c of a){if(ve.test(c.key))continue;let u=ke(c.value,t);if(!u)continue;let y=Kt(c.holder,ri,ni,n,t);o.push({fp:H(c.value),info:u,role:ai(c.key),expiresAt:y.expiresAt,expirySource:y.source,lifetimeMs:y.lifetimeMs,issuedBy:r,refresh:l.get(c.holder)})}}let s=Wt(e.responseHeaders);for(let a of li(s)){let[l,...c]=a.split(";"),u=l.indexOf("=");if(u<=0)continue;let y=l.slice(0,u).trim(),k=l.slice(u+1).trim(),I=le(k,Ze.test(y)||/^(sid|sess)/i.test(y),t);if(!I||k===""||k.toLowerCase()==="deleted")continue;let v,R,z;for(let Wr of c){let[Jr,...qr]=Wr.split("="),mt=Jr.trim().toLowerCase(),Re=qr.join("=").trim();if(mt==="max-age"&&/^-?\d+$/.test(Re))z=Number(Re)*1e3,v=n+z,R="Max-Age";else if(mt==="expires"&&R!=="Max-Age"){let yt=t(Re);Number.isFinite(yt)&&(v=yt,R="Expires")}}o.push({fp:H(k),info:I,role:"cookie",cookie:y,expiresAt:I.expiresAt??v,expirySource:I.expiresAt?I.expirySource:R,lifetimeMs:I.expiresAt?void 0:z,issuedBy:r})}return o}var Ye=e=>T.parse(e),Zt=4,Gt=2e4,ci=8,di=8,fi=200,pi=1e3,O=new Map,Q=new Map,hi=new Set,mi=new Set,Yt=new Set,yi=/(token|refresh|oauth|session|auth\/)/i,p=null,xe=true,Qe=null,Xe=new Set,et=false;function ue(){et||(et=true,Promise.resolve().then(()=>{et=false,Xe.forEach(e=>e())}))}function gi(e){return Xe.add(e),()=>{Xe.delete(e)}}function Qt(e,t){if(e.has(t))return false;if(e.size>=pi){let r=e.values().next().value;r!==void 0&&e.delete(r)}return e.add(t),true}function tt(e,t){return`${e}|${t.location}:${t.name.toLowerCase()}`}function Xt(e,t){let r=t?.lifetimeMs!==void 0&&t.expiresAt!==void 0,n=r?t.expiresAt:e.expiresAt??t?.expiresAt,o=e.expiresAt??(r?t.observedReal+t.lifetimeMs:t?.expiresAt),i=r?t.expirySource:e.expiresAt?e.expirySource:t?.expirySource,s=r?t.lifetimeMs:e.expiresAt!==void 0&&e.issuedAt!==void 0?e.expiresAt-e.issuedAt:void 0;return{expiresAt:n,serverExpiresAt:o,source:i,lifetimeMs:s}}function rt(e,t,r,n,o){let i=Q.get(t),s=Xt(r,i),a=e.fp!==t;a&&(e.history.unshift({fp:e.fp,firstSeenReal:e.firstSeenReal,expiresAt:e.expiresAt}),e.history.length=Math.min(e.history.length,di),e.fp=t,e.firstSeenReal=n,e.firstSeenApp=o,e.uses=0,e.expiredSends=0,e.rejected=0),e.info=r,e.role=i?.role??(a?void 0:e.role),e.issuedBy=i?.issuedBy??(a?void 0:e.issuedBy),e.refresh=i?.refresh??(a?void 0:e.refresh),e.expiresAt=s.expiresAt,e.serverExpiresAt=s.serverExpiresAt,e.expirySource=s.source,e.lifetimeMs=s.lifetimeMs,a&&bi(e,n)}function er(e,t,r,n,o){let i=Q.get(r.fp),s=Xt(r.info,i);return{key:e,origin:t,host:Go(t),location:r.location,name:r.name,scheme:r.scheme,fp:r.fp,info:r.info,role:i?.role,issuedBy:i?.issuedBy,refresh:i?.refresh,expiresAt:s.expiresAt,serverExpiresAt:s.serverExpiresAt,expirySource:s.source,lifetimeMs:s.lifetimeMs,firstSeenReal:n,firstSeenApp:o,lastUsedReal:n,lastUsedApp:o,uses:0,expiredSends:0,rejected:0,history:[]}}function tr(){if(O.size<=ci)return;let e=null;for(let t of O.values())(!e||t.lastUsedReal<e.lastUsedReal)&&(e=t);e&&e.key!==p?.tokenId&&O.delete(e.key)}function bi(e,t){!p||p.tokenId!==e.key||(p.newTokens+=1,p.status==="waiting"&&(p.status="refreshed",p.refreshedAt=t,p.ruleId&&p.forcedAt===void 0&&No("network","deleteOverrideRule",{id:p.ruleId}).catch(()=>{})),p.newTokens>=Zt&&t-(p.refreshedAt??t)<=Gt&&(p.status="loop"))}function ki(e){let t=qe(e.url);if(!t)return;let r=Jt(e,Ye);if(r.length===0)return;let n=S(),o=e.timestamp;for(let i of r){let s=tt(t,i),a=O.get(s);a?rt(a,i.fp,i.info,n,o):(a=er(s,t,i,n,o),O.set(s,a),tr()),a.uses+=1,a.lastUsedReal=n,a.lastUsedApp=o,a.expiresAt!==void 0&&o>=a.expiresAt&&(a.expiredSends+=1),p&&p.tokenId===s&&p.forcedAt!==void 0&&i.fp===p.startFp&&(p.staleAfterFailure+=1)}ue()}function vi(e){let t=qe(e.url);if(!t)return;let r=S(),n=false;if(e.status===401||e.status===403)for(let i of Jt(e,Ye)){let s=O.get(tt(t,i));s&&s.fp===i.fp&&(s.rejected+=1,n=true)}let o=!!p?.ruleId&&e.override?.ruleId===p.ruleId;if(p&&(e.status??0)>=400&&!o){let i=`${e.method.toUpperCase()} ${Ke(e.url)}`;(Yt.has(i)||e.method.toUpperCase()==="POST"&&yi.test(Ke(e.url)))&&(p.failedRefreshes+=1,p.lastRefreshError=`${e.status} ${i}`,n=true)}p?.ruleId&&e.override?.ruleId===p.ruleId&&p.forcedAt===void 0&&(p.forcedAt=r,n=true);for(let i of ui(e,Ye)){if(Yt.add(i.issuedBy),Q.set(i.fp,{...i,observedReal:r}),Q.size>fi){let s=Q.keys().next().value;s!==void 0&&Q.delete(s)}if(n=true,i.cookie){let s={location:"cookie",name:i.cookie,fp:i.fp,info:i.info},a=tt(t,s),l=O.get(a);l?rt(l,i.fp,i.info,r,e.timestamp):(O.set(a,er(a,t,s,r,e.timestamp)),tr());continue}for(let s of O.values())s.fp===i.fp&&rt(s,i.fp,s.info,r,s.lastUsedApp)}n&&ue()}function xi(e){let t=e;!t||typeof t.id!="string"||typeof t.url!="string"||(Qt(hi,t.id)&&ki(t),t.status!==void 0&&Qt(mi,t.id)&&vi(t))}function we(){if(Qe)return true;try{let{networkEventStore:e}=zo("@buoy-gg/network");if(!e?.onEvent)throw new Error("no event store");Qe=e.onEvent(xi,true),xe=true}catch{xe=false}return ue(),xe}function rr(e,t,r){let n=O.get(t);if(!n)throw new Error(`No token row "${t}".`);return p={kind:e,tokenId:t,startedAt:S(),startFp:n.fp,ruleId:r,status:"waiting",newTokens:0,staleAfterFailure:0,failedRefreshes:0},ue(),p}function wi(){p=null,ue()}function Ai(e){return e.location==="cookie"?`${e.name} cookie`:e.location==="query"?`${e.name} parameter`:e.location==="header"?`${e.name} header`:e.role==="id"||e.info.claims.use==="id"?"ID token":"Access token"}function Ti(e,t){let r=[e.firstSeenReal,...e.history.map(o=>o.firstSeenReal)].slice(0,-1).filter(o=>t-o<=Gt).length,n=e.info.issuedAt;return{id:e.key,label:Ai(e),host:e.host,location:e.location,name:e.name,scheme:e.scheme,format:e.info.format,formatLabel:e.info.formatLabel,hint:e.info.hint,claims:e.info.claims,fingerprint:e.fp,issuedAt:n,notBefore:e.info.notBefore,expiresAt:e.expiresAt,serverExpiresAt:e.serverExpiresAt,expirySource:e.expirySource,lifetimeMs:e.lifetimeMs,neverExpires:e.info.neverExpires,issuedBy:e.issuedBy,refresh:e.refresh?{expiresAt:e.refresh.expiresAt,formatLabel:e.refresh.formatLabel}:void 0,firstUsed:e.firstSeenApp,lastUsed:e.lastUsedApp,lastUsedReal:e.lastUsedReal,uses:e.uses,refreshes:e.history.length,lastRefreshAt:e.history.length?e.firstSeenReal:void 0,recentRefreshes:r,looping:r>=Zt,expiredSends:e.expiredSends,rejected:e.rejected}}function Ae(){let e=S(),t=[...O.values()].sort((r,n)=>n.lastUsedReal-r.lastUsedReal).map(r=>Ti(r,e));if(p?.status==="refreshed"){let r=O.get(p.tokenId);r&&(p.newLifetimeMs=r.lifetimeMs,p.newIssuedBy=r.issuedBy)}return{available:xe,watching:Qe!==null,tokens:t,check:p?{...p}:null}}function Si(e){let t=Ae();return e?t.tokens.find(r=>r.id===e||r.fingerprint===e)??null:t.tokens.find(r=>r.expiresAt!==void 0)??t.tokens[0]??null}function $i(e){return O.get(e)?.origin??null}import{isProNow as nr}from"@buoy-gg/shared-ui/web";var f={anchor:Oe,settings:se,lastJump:null,changedAt:null,hydrated:false},nt=new Set,Te=null;function or(){Te=null,nt.forEach(e=>e())}gi(or);function ce(e){return nt.add(e),()=>{nt.delete(e)}}function Ii(){return f.settings}function ir(){return M(f.anchor,S())}function sr(){return f.anchor.mode!=="real"}function Ci(e){if(e.mode==="real"){Pt(null),xo();return}Mt(),Pt(t=>M(f.anchor,t)),vo()}function Ri(){let e={v:1,anchor:f.settings.persist&&nr()?f.anchor:null,settings:f.settings};He(e)}function ar(){let e={v:1,anchor:f.settings.persist&&nr()?f.anchor:null,settings:f.settings};return f.settings.persist&&f.anchor.mode!=="real"&&(e.reload={anchor:f.anchor,at:S()}),He(e)}function X(e,{save:t=true}={}){f={...f,...e},e.anchor&&Ci(f.anchor),t&&Ri(),or()}function ee(e,t=f.lastJump){X({anchor:e,lastJump:t,changedAt:S(),hydrated:true})}var lr=e=>T.parse(e);function ur(e,t=false){let r=S(),n=M(f.anchor,r),o=Rt(e,n,lr),i=o-n;return ee(Le(f.anchor,r,o,t),{byMs:i,firedTimers:0,at:r}),C()}function ot(e,t){let r=Ne(e),n=S(),o=lo(f.anchor,n,r),i=(t??f.settings.fireTimersOnJump)&&r>0;if(ee(o,{byMs:r,firedTimers:0,at:n}),i){let s=Eo(r);s>0&&X({lastJump:{byMs:r,firedTimers:s,at:n}},{save:false})}return C()}function it(e){let t=S(),r=M(f.anchor,t),n=e===void 0||e===""?r:Rt(e,r,lr);return ee(uo(f.anchor,t,n)),C()}function st(){return f.anchor.mode==="frozen"&&ee(co(f.anchor,S())),C()}function cr(e){return ee(fo(f.anchor,S(),Number(e))),C()}function at(){return ee(Oe,null),C()}function dr(e){let t={...f.settings};for(let r of Object.keys(se))typeof e[r]=="boolean"&&(t[r]=e[r]);return X({settings:t}),C()}function Ei(e){return e>0?Ro(e):0}var fr=false;function pr(e){if(!e){X({hydrated:true},{save:false});return}let t=e.reload?S()-e.reload.at:1/0,r=t>=0&&t<Po?e.reload?.anchor:void 0;e.reload&&He({v:1,anchor:e.anchor,settings:e.settings});let n=e.anchor??r??null;X({settings:e.settings,anchor:n??Oe,changedAt:n?S():null,hydrated:true},{save:false})}function lt(){if(fr)return;fr=true,Mt();let e=Do();if(e!==void 0){pr(e);return}Lo().then(t=>{f.changedAt===null?pr(t):X({hydrated:true},{save:false})})}function Oi(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone??"unknown"}catch{return"unknown"}}function C(){let e=S(),t=M(f.anchor,e);return{mode:f.anchor.mode,active:f.anchor.mode!=="real",rate:f.anchor.rate,virtualNow:t,virtualIso:new T(t).toISOString(),realNow:e,offsetMs:ao(f.anchor,e),timeZone:Oi(),timers:Co(),lastJump:f.lastJump,changedAt:f.changedAt,settings:f.settings,hydrated:f.hydrated,tokens:Ae(),patched:{date:ho(),intl:ko(),timers:Io(),animatedOnRealClock:To()}}}function hr(){return Te||(Te=C()),Te}import{useSyncExternalStore as Di}from"react";import{ClockToolIcon as mr,FloatingTool as Pi,Pause as Li,Play as Ni,X as zi,dismissFloatingTool as ji,getFloatingTools as Mi,getUseIsPro as _i,night as de,openFloatingTool as yr}from"@buoy-gg/shared-ui/web";import{useEffect as Fi,useState as Bi}from"react";function V(e,t=250){let[,r]=Bi(0);Fi(()=>{let s=setInterval(()=>r(a=>a+1),t);return()=>clearInterval(s)},[t]);let n=S();if(!e)return{virtual:n,real:n};let o=n-e.realNow,i=e.mode==="real"?1:e.rate;return{virtual:e.mode==="frozen"?e.virtualNow:e.virtualNow+o*i,real:n}}var F=e=>String(e).padStart(2,"0");function fe(e){let t=new T(e);return`${F(t.getHours())}:${F(t.getMinutes())}:${F(t.getSeconds())}`}var Ui=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],gr=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function Hi(e){let t=new T(e);return`${Ui[t.getDay()]}, ${gr[t.getMonth()]} ${t.getDate()}, ${t.getFullYear()}`}function Se(e,t=true){let r=new T(e),n=t?fe(e):`${F(r.getHours())}:${F(r.getMinutes())}`;return`${gr[r.getMonth()]} ${r.getDate()} \xB7 ${n}`}function br(e){let t=new T(e);return`${t.getFullYear()}-${F(t.getMonth()+1)}-${F(t.getDate())} ${F(t.getHours())}:${F(t.getMinutes())}`}function Vi(e){if(Math.abs(e)<1e3)return"matches real time";let t=re(Math.abs(e),{signed:false});return e>0?`${t} ahead of real time`:`${t} behind real time`}function kr(e){return e.mode==="real"?{label:"Real time",tone:"neutral"}:e.mode==="frozen"?{label:"Frozen",tone:"info"}:e.rate!==1?{label:`${Ot(e.rate)} speed`,tone:"warning"}:{label:"Overridden",tone:"accent"}}function Wi(e){return`clock-jump-${e<0?"minus":"plus"}-${re(Math.abs(e),{signed:false}).replace(/\s/g,"")}`}import{jsx as N,jsxs as ut}from"react/jsx-runtime";var $e="clock-chip",vr={id:$e,render:e=>N(Ar,{...e})},Ji=()=>Mi().some(e=>e.id===$e);function qi(){yr(vr)}var xr=false;function wr(){if(xr)return;xr=true;let e=false,t=()=>{let r=sr()&&Ii().showChip;r&&!e?yr(vr):!r&&Ji()&&ji($e),e=r};ce(t),t()}function Ar({id:e,revealToken:t}){let r=Di(ce,hr,hr),{virtual:n,real:o}=V(r),i=r.mode==="frozen",s=_i()(),a=i||s,l=kr(r),c=n-o,u=`${Math.abs(c)<1e3?"0s":re(c)} \xB7 ${l.label.toLowerCase()}`;return N(Pi,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the clock chip. App time ${Se(n)}`,handleAdornment:N(mr,{size:12}),children:ut(m,{style:K.row,children:[N(mr,{size:18}),ut(m,{style:K.text,children:[N(A,{style:K.time,numberOfLines:1,testID:"clock-chip-time",children:Se(n)}),N(A,{style:K.detail,numberOfLines:1,testID:"clock-chip-detail",children:u})]}),a?ut(B,{testID:i?"clock-chip-resume":"clock-chip-freeze",accessibilityRole:"button",accessibilityLabel:i?"Resume the app clock":"Freeze the app clock",onPress:()=>i?st():it(),style:K.button,hitSlop:{top:8,bottom:8,left:4,right:4},children:[i?N(Ni,{size:16,color:de.color.accent}):null,i?null:N(Li,{size:16,color:de.color.text})]}):null,a?N(m,{style:K.separator}):null,N(B,{testID:"clock-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to real time",onPress:()=>at(),style:K.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:N(zi,{size:16,color:de.color.textSecondary})})]})})}var K=G.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:220},text:{flexShrink:1,minWidth:120},time:{color:"#F59E0B",fontSize:14,fontWeight:"600",fontVariant:["tabular-nums"]},detail:{color:de.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:G.hairlineWidth,height:20,backgroundColor:de.color.separator}});import{ClockToolIcon as Ki,CLOCK_TOOL_ICON_COLOR as Zi,createToolFactory as Gi,defineToolPreset as Yi}from"@buoy-gg/shared-ui/web";import{useEffect as Tr,useState as Qi}from"react";import{reloadApp as Xi}from"@buoy-gg/shared-ui/web";import{createSyncAdapter as es}from"@buoy-gg/shared-ui/web";import{dispatchToolAction as Sr}from"@buoy-gg/shared-ui/web";var $r="No sign-in token seen yet. Use the app so it sends a signed-in request, then try again. Tokens are read from the Network tool's captured requests.";function Ir(e){we();let t=Si(e);if(!t)throw new Error(e?`No token "${e}". Read getState for the current ids.`:$r);return t}function Cr(e,t=1e4){let r=Ir(e);if(r.expiresAt===void 0)throw new Error(r.neverExpires?`${r.label} for ${r.host} is ${r.hint??"a key"} and never expires.`:`${r.label} for ${r.host} (${r.formatLabel}) has no expiry Buoy can read. Use failNextRequest to test the refresh instead.`);let n=r.expiresAt-Math.max(0,t)-ir();if(n<=0)throw new Error(`${r.label} for ${r.host} has already expired on the app's clock. Go back to real time, or use failNextRequest.`);return ot(n),rr("expiry",r.id),C()}async function Rr(e,t=401,r=1){let n=Ir(e),o=$i(n.id);if(!o)throw new Error($r);await Er();let i=t===403?403:401,s=n.location==="authorization"||n.location==="header"?{urlPattern:`${o}/*`,requireHeader:n.name.toLowerCase()}:n.location==="query"?{urlPattern:`${o}/*${n.name}=*`}:{urlPattern:`${o}/*`},a=await Sr("network","upsertOverrideRule",{name:"Clock: force a token refresh",...s,kind:"respond",status:i,headers:{"content-type":"application/json","www-authenticate":'Bearer error="invalid_token", error_description="The access token expired"'},body:JSON.stringify({error:"invalid_token",error_description:"The access token expired (forced by Buoy Clock to test token refresh)"}),times:Math.max(1,Math.min(10,Math.round(r)))}).catch(l=>{let c=l instanceof Error?l.message:String(l);throw new Error(c.includes("Unknown tool")?"Failing a request needs the Network tool (@buoy-gg/network).":c)});if(!a?.ok||!a.rule)throw new Error(a?.error??"Network did not add the override.");return rr("401",n.id,a.rule.id),C()}async function Er(){let e=Ae().check;e?.ruleId&&e.forcedAt===void 0&&await Sr("network","deleteOverrideRule",{id:e.ruleId}).catch(()=>{})}async function Or(){return await Er(),wi(),C()}function Z(e){return e&&typeof e=="object"?e:{}}function ct(e,...t){for(let r of t){let n=e[r];if(typeof n=="string"||typeof n=="number")return n}}function pe(e,t){let r=e[t];if(typeof r=="boolean")return r;if(r==="true")return true;if(r==="false")return false}var Dr=es({version:1,getSnapshot(){return C()},subscribe(e){return ce(e)},actions:{getState(){return we(),C()},setTime(e){let t=Z(e),r=ct(t,"time","at","date","iso");if(r===void 0)throw new Error('setTime needs `time`: ISO 8601 ("2026-12-31T23:59:50"), epoch ms, or relative ("+1d").');return ur(r,pe(t,"freeze")??false)},shift(e){let t=Z(e),r=ct(t,"by","ms","duration","delta");if(r===void 0)throw new Error('shift needs `by`: a duration like "+1d", "-2h30m", "90s", or ms.');return ot(r,pe(t,"fireTimers"))},freeze(e){return it(ct(Z(e),"time","at"))},resume(){return st()},setRate(e){let t=Z(e),r=Number(t.rate??t.speed);if(!Number.isFinite(r))throw new Error("setRate needs a numeric `rate` (1 = normal speed).");return cr(r)},reset(){return at()},updateSettings(e){let t=Z(e);return dr({persist:pe(t,"persist"),showChip:pe(t,"showChip"),fireTimersOnJump:pe(t,"fireTimersOnJump")})},jumpToTokenExpiry(e){let t=Z(e),r=typeof t.token=="string"?t.token:typeof t.id=="string"?t.id:void 0,n=Number(t.leadMs??t.lead??1e4);return Cr(r,Number.isFinite(n)?n:1e4)},failNextRequest(e){let t=Z(e),r=typeof t.token=="string"?t.token:typeof t.id=="string"?t.id:void 0,n=Number(t.status??401),o=Number(t.times??1);return Rr(r,n,Number.isFinite(o)?o:1)},stopTokenCheck(){return Or()},async holdForReload(){return await ar(),C()}}});import{useState as Ie}from"react";import{ChevronRight as ts,NightButton as rs,NightCard as Ce,NightChip as ns,NightFootnote as dt,NightRows as ft,NightSectionLabel as Pr,NightSegmented as os,NightSwitch as Lr,ProBadge as is,ProUpgradeModal as ss,getUseIsPro as as,monoFont as ls,night as b,useSafeAreaInsets as us}from"@buoy-gg/shared-ui/web";import{ChevronRight as cs,NightButton as Nr,NightCard as ds,NightFootnote as fs,NightRows as ps,NightSectionLabel as hs,ProBadge as ms,night as x}from"@buoy-gg/shared-ui/web";import{jsx as w,jsxs as j}from"react/jsx-runtime";var W=e=>re(Math.abs(e),{signed:false});function ys({snapshot:e,run:t,openId:r,onToggle:n,isPro:o,onUpgrade:i}){let s=e.tokens;return j(m,{children:[w(hs,{children:s.tokens.length>1?"Sign-in tokens":"Sign-in token"}),w(ds,{children:j(ps,{children:[s.tokens.map((a,l)=>j(m,{children:[w(gs,{token:a,snapshot:e,index:l,open:r===a.id,onPress:()=>n(a.id)}),r===a.id?w(bs,{token:a,snapshot:e,run:o?t:()=>i("Sign-in token tests"),isPro:o}):null]},a.id)),s.tokens.length===0?w(m,{style:g.row,testID:"clock-token-empty",children:w(A,{style:g.emptyText,children:s.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),w(vs,{check:s.check,tokens:s.tokens,snapshot:e,run:t}),s.tokens.length===0?w(fs,{children:s.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function gs({token:e,snapshot:t,index:r,open:n,onPress:o}){let{virtual:i}=V(t,1e3),s=e.expiresAt!==void 0?e.expiresAt-i:void 0,a=e.neverExpires?"No expiry":s===void 0?"Unknown":s<=0?"Expired":W(s),l=s!==void 0&&s<=0?g.valueDanger:s!==void 0&&s<6e4?g.valueWarning:null;return j(B,{testID:`clock-token-${r}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${s!==void 0&&s>0?`expires in ${a}`:a}`,accessibilityState:{expanded:n},activeOpacity:.6,onPress:o,style:g.row,children:[j(m,{style:g.rowText,children:[w(A,{style:g.rowTitle,numberOfLines:1,children:e.label}),w(A,{style:g.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),j(m,{style:g.rowRight,children:[w(A,{style:[g.value,l],testID:`clock-token-${r}-left`,children:a}),w(m,{style:n?g.chevronOpen:null,children:w(cs,{size:16,color:x.color.textTertiary})})]})]})}function bs({token:e,snapshot:t,run:r,isPro:n}){let{virtual:o,real:i}=V(t,1e3),s=ks(e,o,i),a=e.expiresAt!==void 0&&e.expiresAt-o>1e4;return j(m,{style:g.detail,testID:"clock-token-detail",children:[s.map(l=>w(A,{style:[g.detailLine,l.tone==="warn"?g.warn:null,l.tone==="bad"?g.bad:null],children:l.text},l.text)),j(m,{style:g.buttons,children:[w(m,{style:g.button,children:w(Nr,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!a,onPress:()=>r("jumpToTokenExpiry",{token:e.id})})}),w(m,{style:g.button,children:w(Nr,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>r("failNextRequest",{token:e.id})})})]}),n?null:j(m,{style:g.proLine,children:[w(ms,{}),w(A,{style:[g.hint,g.proHint],children:"Jump to Expiry and Fail Next Request are part of Buoy Pro."})]}),w(A,{style:g.hint,children:a||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function ks(e,t,r){let n=[];if(e.expiresAt!==void 0){if(n.push({text:`Expires ${Se(e.expiresAt)}`}),e.lifetimeMs!==void 0&&e.lifetimeMs>0&&n.push({text:`Lasts ${W(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`}),e.serverExpiresAt!==void 0){let o=e.expiresAt-t,i=e.serverExpiresAt-r;Math.abs(o-i)>2e3&&n.push({text:i>0?`The server still accepts it for ${W(i)}`:`The server stopped accepting it ${W(i)} ago`})}}else e.neverExpires||n.push({text:"The token doesn't say when it expires, and no login response did either."});if(e.hint&&n.push({text:e.formatLabel}),e.issuedBy&&n.push({text:`Issued by ${e.issuedBy}`}),e.refresh?.expiresAt!==void 0){let o=e.refresh.expiresAt-t;n.push({text:o>0?`Refresh token expires in ${W(o)}`:"Refresh token expired"})}return e.refreshes>0&&e.lastRefreshAt!==void 0&&n.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${fe(e.lastRefreshAt)}`}),n.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`}),e.expiredSends>0&&n.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"}),e.rejected>0&&n.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"}),e.looping&&n.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"}),n}function vs({check:e,tokens:t,snapshot:r,run:n}){let{virtual:o,real:i}=V(r,1e3);if(!e)return null;let s=t.find(c=>c.id===e.tokenId),{text:a,tone:l}=xs(e,s,o,i);return j(m,{style:g.check,children:[w(A,{style:[g.checkText,l==="good"?g.good:null,l==="bad"?g.bad:null,l==="warn"?g.warn:null],testID:"clock-token-check",children:a}),w(B,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>n("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:w(A,{style:g.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function xs(e,t,r,n){if(e.status==="loop")return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"};if(e.status==="refreshed"){let a=e.newIssuedBy?` by ${e.newIssuedBy}`:"",l=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${W(e.newLifetimeMs)}`:"",c=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed",u=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${c} at ${fe(e.refreshedAt??n)}${a}${l}.${u}`,tone:u?"warn":"good"}}let o=n-e.startedAt,i=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(o>6e4)return{text:`No new token after ${W(o)}. The app may refresh on its next action, or not at all.${i}`,tone:"warn"};if(e.kind==="401")return e.forcedAt===void 0?{text:`The next request to ${t?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${i}`,tone:i?"warn":void 0};let s=t?.expiresAt!==void 0?t.expiresAt-r:void 0;return s!==void 0&&s>0?{text:`Expires in ${W(s)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}var g=G.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:x.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:x.color.text,fontSize:x.font.row},rowSubtitle:{color:x.color.textTertiary,fontSize:x.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:x.color.textSecondary,fontSize:x.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:x.color.warning},valueDanger:{color:x.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:x.color.textSecondary,fontSize:x.font.row},detail:{paddingHorizontal:x.rowPadH,paddingBottom:14,gap:4},detailLine:{color:x.color.textSecondary,fontSize:x.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:x.color.textTertiary,fontSize:x.font.caption,marginTop:6},proLine:{flexDirection:"row",alignItems:"center",gap:8,marginTop:6},proHint:{marginTop:0,flexShrink:1},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:x.labelInset},checkText:{flex:1,color:x.color.textSecondary,fontSize:x.font.caption,lineHeight:18},checkDone:{color:x.color.accent,fontSize:x.font.caption,fontWeight:"600"},good:{color:x.color.accent},warn:{color:x.color.warning},bad:{color:x.color.danger}});import{jsx as d,jsxs as $}from"react/jsx-runtime";var zr="#F59E0B";function jr({snapshot:e,onAction:t,onReload:r}){let n=us({minBottom:16}),[o,i]=Ie(null),[s,a]=Ie(null),l=as()(),[c,u]=Ie(null),y=v=>u(v),k=(v,R)=>{i(null),t(v,R).catch(z=>{i(z instanceof Error?z.message:String(z))})},I=v=>a(R=>R===v?null:v);return e?$($t,{style:h.fill,contentContainerStyle:[h.content,{paddingBottom:n.bottom}],testID:"clock-scroll",keyboardShouldPersistTaps:"handled",children:[d(ws,{snapshot:e}),o?d(m,{testID:"clock-error",children:d(dt,{tone:"danger",centered:true,children:o})}):null,$(m,{children:[d(Pr,{children:"Jump ahead"}),d(Ts,{run:k})]}),$(m,{children:[d(Ce,{children:$(ft,{children:[$(m,{children:[d(_r,{title:"Date & Time",testID:"clock-date-row",open:s==="date",onPress:()=>I("date"),value:d(Ss,{snapshot:e})}),s==="date"?d(Is,{snapshot:e,run:k,onDone:()=>a(null)}):null]},"date"),$(m,{style:h.row,children:[d(pt,{title:"Freeze",isPro:l}),d(Lr,{value:e.mode==="frozen",testID:"clock-freeze",accessibilityLabel:"Freeze the clock",onValueChange:v=>v&&!l?y("Freeze"):k(v?"freeze":"resume")})]},"freeze"),$(m,{children:[d(_r,{title:"Speed",pro:!l,testID:"clock-speed-row",open:s==="speed",onPress:()=>l?I("speed"):y("Speed"),value:d(A,{style:h.rowValue,children:Ur(e)})}),s==="speed"?d(Cs,{snapshot:e,run:k}):null]},"speed")]})}),d(dt,{children:"Only this app's clock changes. Screens pick up the new time when they next render, or all at once when you reload."})]}),e.tokens?d(ys,{snapshot:e,run:k,openId:s,onToggle:I,isPro:l,onUpgrade:y}):null,d(Ce,{children:$(ft,{children:[r?d(Fr,{label:"Reload App",testID:"clock-reload",onPress:r},"reload"):null,d(Fr,{label:"Use Real Time",accessibilityLabel:"Reset to real time",testID:"clock-reset",destructive:true,disabled:e.mode==="real",onPress:()=>k("reset")},"reset")]})}),$(m,{children:[d(Pr,{children:"Options"}),d(Es,{settings:e.settings,run:k,isPro:l,onUpgrade:y})]}),d(ss,{visible:c!==null&&!l,onClose:()=>u(null),featureName:c??void 0})]}):d(m,{style:h.waiting,testID:"clock-waiting",children:d(dt,{centered:true,children:"Waiting for the app's clock\u2026"})})}function pt({title:e,isPro:t}){return $(m,{style:h.titleRow,children:[d(A,{style:h.rowTitle,children:e}),t?null:d(is,{})]})}function ws({snapshot:e}){let{virtual:t,real:r}=V(e),n=kr(e),o=e.mode!=="real",i=Vi(t-r),s=e.mode==="frozen"?" \xB7 Frozen":o&&e.rate!==1?` \xB7 ${Ur(e)}`:"";return $(m,{style:h.hero,children:[d(A,{style:[h.heroTime,o?h.heroTimeActive:null],testID:"clock-hero-time",accessibilityLabel:`App clock ${fe(t)}`,children:fe(t)}),d(A,{style:h.heroDate,testID:"clock-hero-date",children:Hi(t)}),d(m,{testID:"clock-status",accessibilityLabel:`Clock status: ${n.label}${o?`, ${i}`:""}`,children:d(A,{style:[h.heroStatus,o?h.heroStatusActive:null],testID:"clock-offset",children:o?`${i}${s}`:"Real time"})})]})}var Mr=36e5,ht=24*Mr,As=[{ms:Mr,unit:"hour"},{ms:ht,unit:"day"},{ms:7*ht,unit:"week"},{ms:30*ht,unit:"month"}];function Ts({run:e}){return d(Ce,{style:h.jumpBar,children:As.map((t,r)=>$(B,{testID:Wi(t.ms),accessibilityRole:"button",accessibilityLabel:`Jump ahead one ${t.unit}`,activeOpacity:.6,onPress:()=>e("shift",{by:t.ms}),style:[h.jump,r>0?h.jumpDivider:null],children:[d(A,{style:h.jumpAmount,children:"+1"}),d(A,{style:h.jumpUnit,children:t.unit})]},t.unit))})}function _r({title:e,pro:t,value:r,open:n,onPress:o,testID:i}){return $(B,{testID:i,accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:n},activeOpacity:.6,onPress:o,style:h.row,children:[d(pt,{title:e,isPro:!t}),$(m,{style:h.rowRight,children:[r,d(m,{style:n?h.chevronOpen:null,children:d(ts,{size:16,color:b.color.textTertiary})})]})]})}function Ss({snapshot:e}){let{virtual:t}=V(e,1e3);return d(A,{style:[h.rowValue,h.tabular],numberOfLines:1,children:Se(t,false)})}function Fr({label:e,onPress:t,testID:r,destructive:n,disabled:o,accessibilityLabel:i}){return d(B,{testID:r,accessibilityRole:"button",accessibilityLabel:i??e,accessibilityState:{disabled:!!o},activeOpacity:.6,disabled:o,onPress:t,style:[h.row,o?h.rowDisabled:null],children:d(A,{style:[h.actionLabel,n?h.actionDestructive:null],children:e})})}var $s=Et.filter(e=>["midnight","month-end","year-end"].includes(e.id));function Is({snapshot:e,run:t,onDone:r}){let[n,o]=Ie(""),{virtual:i}=V(e,1e3),s=()=>n.trim()||br(i),a=e.mode==="frozen",l=c=>{t("setTime",{time:c,freeze:a}),r()};return $(m,{style:h.editor,children:[$(m,{style:h.inputRow,children:[d(St,{testID:"clock-time-input",accessibilityLabel:"Date and time",value:n,onChangeText:o,placeholder:br(i),placeholderTextColor:b.color.placeholder,autoCapitalize:"none",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>l(s()),style:h.input}),d(rs,{label:"Set",testID:"clock-time-apply",accessibilityLabel:"Set this time",size:"md",variant:"primary",fullWidth:false,onPress:()=>l(s())})]}),d(A,{style:h.hint,children:"Year-month-day and 24-hour time, or +3d, -2h"}),d(m,{style:h.presets,children:$s.map(c=>d(ns,{label:c.label,testID:`clock-preset-${c.id}`,onPress:()=>l(c.at(i,T))},c.id))})]})}var Br=[{key:"1",label:"Normal"},{key:"10",label:"10\xD7"},{key:"60",label:"1 min/s"},{key:"3600",label:"1 hr/s"}];function Ur(e){return e.mode==="real"||e.rate===1?"Normal":Br.find(t=>Number(t.key)===e.rate)?.label??Ot(e.rate)}function Cs({snapshot:e,run:t}){let r=e.mode==="real"?"1":String(e.rate);return $(m,{style:h.editor,children:[d(m,{style:h.segmentRow,children:d(os,{tabs:Br,activeKey:r,size:"sm",testIDPrefix:"clock-speed",onChange:n=>t("setRate",{rate:Number(n)})})}),d(A,{style:h.hint,children:"Taps, animations and timers keep real speed."})]})}var Rs=[{key:"showChip",title:"Show Floating Clock"},{key:"persist",title:"Keep After Reload",pro:true}];function Es({settings:e,run:t,isPro:r,onUpgrade:n}){return d(Ce,{children:d(ft,{children:Rs.map(o=>{let i=!!o.pro&&!r;return $(m,{style:h.row,children:[d(pt,{title:o.title,isPro:!i}),d(Lr,{value:i?false:e[o.key],testID:`clock-setting-${o.key}`,accessibilityLabel:o.title,onValueChange:s=>i?n(o.title):t("updateSettings",{[o.key]:s})})]},o.key)})})})}var h=G.create({fill:{flex:1},content:{paddingHorizontal:b.gutter,paddingTop:8,gap:b.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},hero:{alignItems:"center",paddingTop:12},heroTime:{color:b.color.text,fontSize:56,fontWeight:"200",fontVariant:["tabular-nums"],letterSpacing:1},heroTimeActive:{color:zr},heroDate:{color:b.color.text,fontSize:17,fontWeight:"500",marginTop:2},heroStatus:{color:b.color.textTertiary,fontSize:b.font.caption,fontWeight:"500",marginTop:6},heroStatusActive:{color:b.color.textSecondary},jumpBar:{flexDirection:"row"},jump:{flex:1,alignItems:"center",paddingVertical:12},jumpDivider:{borderLeftWidth:G.hairlineWidth,borderLeftColor:b.color.separator},jumpAmount:{color:zr,fontSize:17,fontWeight:"600",fontVariant:["tabular-nums"]},jumpUnit:{color:b.color.textSecondary,fontSize:b.font.caption,marginTop:1},row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:50,paddingHorizontal:b.rowPadH,paddingVertical:10},rowDisabled:{opacity:.4},rowTitle:{color:b.color.text,fontSize:b.font.row},titleRow:{flexDirection:"row",alignItems:"center",gap:8,flexShrink:1},rowRight:{flexDirection:"row",alignItems:"center",gap:6,flexShrink:1},rowValue:{color:b.color.textSecondary,fontSize:b.font.row},tabular:{fontVariant:["tabular-nums"]},chevronOpen:{transform:[{rotate:"90deg"}]},actionLabel:{color:b.color.accent,fontSize:b.font.row},actionDestructive:{color:b.color.danger},editor:{paddingHorizontal:b.rowPadH,paddingBottom:14,gap:10},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:b.color.text,fontFamily:ls,fontSize:15,backgroundColor:b.color.bg,borderRadius:b.radius.input,borderWidth:1,borderColor:b.color.border,paddingHorizontal:12,paddingVertical:8},hint:{color:b.color.textTertiary,fontSize:b.font.caption},presets:{flexDirection:"row",flexWrap:"wrap",gap:6},segmentRow:{flexDirection:"row"}});import{jsx as Os}from"react/jsx-runtime";var Ds=Dr.actions;async function Ps(e,t){let r=Ds[e];if(!r)throw new Error(`Unknown clock action: ${e}`);return r(t)}function Ls(){ar().then(()=>Xi("auto","buoy clock")).catch(()=>{})}function Hr(){Tr(()=>{lt(),we()},[]);let[e,t]=Qi(C);return Tr(()=>ce(()=>t(C())),[]),Os(jr,{snapshot:e,onAction:Ps,onReload:Ls})}import{jsx as Ns}from"react/jsx-runtime";var Vr=Yi({id:"clock",name:"CLOCK",description:"Travel to any date, freeze or speed up the app's clock",slot:"both",color:Zi,icon:({size:e,color:t})=>Ns(Ki,{size:e,color:t}),component:Hr,modal:{subtitle:"override the app's date & time"}}),zs=Gi(Vr);import{ClockToolIcon as js,CLOCK_TOOL_ICON_COLOR as Ms}from"@buoy-gg/shared-ui/web";var _s=typeof navigator<"u"&&navigator.product==="ReactNative",Fs=(()=>{try{return globalThis.Capacitor?.isNativePlatform?.()===true}catch{return false}})();_s||Fs?(Ao(xt),wr(),typeof kt<"u"&&kt&<()):typeof globalThis.document<"u"&&wr();export{$e as CLOCK_CHIP_ID,Ms as CLOCK_TOOL_ICON_COLOR,Hr as ClockBody,Ar as ClockChip,js as ClockToolIcon,jr as ClockToolView,Et as TIME_PRESETS,lt as bootClock,Dr as clockSyncAdapter,Vr as clockToolPreset,zs as createClockTool,Rr as failNextRequest,re as formatDuration,it as freeze,C as getClockSnapshot,Ae as getTokenReport,ke as inspectToken,sr as isClockOverridden,Cr as jumpToTokenExpiry,qi as openClockChip,Ne as parseDuration,Ei as previewJump,S as realNow,at as reset,st as resume,cr as setRate,ur as setTime,ot as shift,we as startTokenWatch,Or as stopTokenCheck,ce as subscribeClock,H as tokenFingerprint,dr as updateSettings,V as useLiveClock,ir as virtualNow,_e as withRealClock};
|
|
1
|
+
"use client";var wt=Object.defineProperty;var Qr=Object.getOwnPropertyDescriptor;var en=Object.getOwnPropertyNames;var tn=Object.prototype.hasOwnProperty;var rn=(e,t)=>{for(var r in t)wt(e,r,{get:t[r],enumerable:true})},At=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let o of en(t))!tn.call(e,o)&&o!==r&&wt(e,o,{get:()=>t[o],enumerable:!(n=Qr(t,o))||n.enumerable});return e},nn=(e,t,r)=>(At(e,t,"default"),r&&At(r,t,"default"));var St=(()=>{try{let e=globalThis.Capacitor;if(e&&typeof e.isNativePlatform=="function"&&e.isNativePlatform())return e.DEBUG===true}catch{}return process.env.NODE_ENV!=="production"})();typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);var Tt={};rn(Tt,{AccessibilityInfo:()=>ln,ActivityIndicator:()=>uo,Alert:()=>po,Animated:()=>Et,AppRegistry:()=>cn,AppState:()=>dn,Appearance:()=>un,BackHandler:()=>fn,Button:()=>co,CheckBox:()=>Cn,Clipboard:()=>pn,DeviceEventEmitter:()=>Vn,Dimensions:()=>hn,Easing:()=>mn,FlatList:()=>On,I18nManager:()=>yn,Image:()=>En,ImageBackground:()=>Rn,InteractionManager:()=>bn,Keyboard:()=>gn,KeyboardAvoidingView:()=>Dn,LayoutAnimation:()=>kn,Linking:()=>vn,LogBox:()=>Hn,Modal:()=>so,NativeEventEmitter:()=>xn,NativeModules:()=>sn,PanResponder:()=>wn,Picker:()=>Pn,PixelRatio:()=>An,Platform:()=>Sn,Pressable:()=>ao,ProgressBar:()=>Ln,RefreshControl:()=>Nn,SafeAreaView:()=>zn,ScrollView:()=>Dt,SectionList:()=>jn,Share:()=>Tn,StatusBar:()=>Mn,StyleSheet:()=>X,Switch:()=>lo,Text:()=>w,TextInput:()=>Rt,Touchable:()=>_n,TouchableHighlight:()=>oo,TouchableNativeFeedback:()=>Fn,TouchableOpacity:()=>B,TouchableWithoutFeedback:()=>io,UIManager:()=>$n,Vibration:()=>In,View:()=>m,VirtualizedList:()=>Bn,YellowBox:()=>Un,findNodeHandle:()=>fo,unstable_createElement:()=>an,useColorScheme:()=>Wn,useLocaleContext:()=>Jn,useWindowDimensions:()=>qn});nn(Tt,on);import*as on from"react-native-web";import{unstable_createElement as an,NativeModules as sn,AccessibilityInfo as ln,Appearance as un,AppRegistry as cn,AppState as dn,BackHandler as fn,Clipboard as pn,Dimensions as hn,Easing as mn,I18nManager as yn,Keyboard as gn,InteractionManager as bn,LayoutAnimation as kn,Linking as vn,NativeEventEmitter as xn,PanResponder as wn,PixelRatio as An,Platform as Sn,Share as Tn,UIManager as $n,Vibration as In,CheckBox as Cn,FlatList as On,Image as En,ImageBackground as Rn,KeyboardAvoidingView as Dn,Picker as Pn,ProgressBar as Ln,RefreshControl as Nn,SafeAreaView as zn,SectionList as jn,StatusBar as Mn,Touchable as _n,TouchableNativeFeedback as Fn,VirtualizedList as Bn,YellowBox as Un,LogBox as Hn,DeviceEventEmitter as Vn,useColorScheme as Wn,useLocaleContext as Jn,useWindowDimensions as qn}from"react-native-web";import*as E from"react-native-web";import{createElement as Pe,forwardRef as $t,useCallback as Kn,useRef as Zn}from"react";import{useEffect as Yn,useState as Gn}from"react";import{createPortal as Xn}from"react-dom";var Qn='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif';import{jsx as eo}from"react/jsx-runtime";var oe=Symbol.for("@buoy-gg/portal-host"),It=e=>{if(!(e instanceof Element))return false;if(e.closest("input, textarea, select"))return true;let t=e.closest("[contenteditable]")?.getAttribute("contenteditable")?.toLowerCase();return t===""||t==="true"||t==="plaintext-only"};function Ct(){let e=document;if(e[oe])return e[oe].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:Qn});let r=()=>{let u=document.fullscreenElement,f=u&&u.tagName!=="CANVAS"?u:document.body;t.parentElement!==f&&f.appendChild(t)},n=new Map,o=u=>{(!t.contains(u.target)||!It(u.target))&&n.set(u.code||u.key,{key:u.key,code:u.code,location:u.location,keyCode:u.keyCode,which:u.which,altKey:u.altKey,ctrlKey:u.ctrlKey,metaKey:u.metaKey,shiftKey:u.shiftKey})},i=u=>{n.delete(u.code||u.key)},a=()=>n.clear(),s=()=>{let u=[...n.values()];n.clear();for(let f of u)document.dispatchEvent(new KeyboardEvent("keyup",{...f,bubbles:true}))},l=u=>{It(u.target)&&u.stopPropagation()},c=u=>u.stopPropagation();return r(),document.addEventListener("fullscreenchange",r),document.addEventListener("keydown",o,true),document.addEventListener("keyup",i,true),window.addEventListener("blur",a),t.addEventListener("focusin",s),t.addEventListener("keydown",l),t.addEventListener("keyup",l),t.addEventListener("keypress",l),t.addEventListener("wheel",c,{passive:true}),e[oe]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",r),document.removeEventListener("keydown",o,true),document.removeEventListener("keyup",i,true),window.removeEventListener("blur",a),t.remove(),delete e[oe]}},t}function to({children:e}){let[t,r]=Gn(null);return Yn(()=>{let n=Ct(),o=document[oe];return o.users++,r(n),()=>{--o.users===0&&o.dispose()}},[]),t?Xn(eo("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var Y=E,ro=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],G=e=>typeof e=="number"?`${e}px`:e;function Le(e){if(Array.isArray(e)){let f=e.map(Le);return f.some((g,S)=>g!==e[S])?f:e}if(!e||typeof e!="object"||!ro.some(f=>e[f]!=null))return e;let{shadowColor:t,shadowOffset:r,shadowOpacity:n,shadowRadius:o,textShadowColor:i,textShadowOffset:a,textShadowRadius:s,...l}=e;if(t!=null||r!=null||n!=null||o!=null){let f=t??"black",g=n==null?f:`color-mix(in srgb, ${f} ${Math.min(n,1)*100}%, transparent)`,S=`${G(r?.width??0)} ${G(r?.height??0)} ${G(o??0)} ${g}`;l.boxShadow=typeof l.boxShadow=="string"?`${l.boxShadow}, ${S}`:l.boxShadow??S}let{width:c=0,height:u=0}=a??{};if(i&&(c||u||s)){let f=`${G(c)} ${G(u)} ${G(s??0)} ${i}`;l.textShadow=l.textShadow?`${l.textShadow}, ${f}`:f}return l}var no=Y.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});function Ot(e,t){if(typeof e=="function")return n=>Ot(e(n),t);let r=Le(e);return t?[r,no[t]]:r}var X={...Y.StyleSheet,create:e=>Y.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,r])=>[t,Le(r)])))};function D(e){let t=$t((n,o)=>{let{accessibilityState:i,accessibilityValue:a,pointerEvents:s,...l}=n;for(let u of["busy","checked","disabled","expanded","selected"])i?.[u]!==void 0&&l[`aria-${u}`]===void 0&&(l[`aria-${u}`]=i[u]);for(let[u,f]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))a?.[u]!==void 0&&l[`aria-${f}`]===void 0&&(l[`aria-${f}`]=a[u]);let c=Ot(l.style,s);return c!==l.style&&(l.style=c),Pe(e,{...l,ref:o})}),r=e.State;return r&&Object.assign(t,{State:r}),t.displayName=e.displayName??e.name??"NativeWebView",t}var m=D(E.View),w=D(E.Text),Et={...Y.Animated,View:Y.Animated.createAnimatedComponent(m),Text:Y.Animated.createAnimatedComponent(w)},Rt=D(E.TextInput),B=D(E.TouchableOpacity),oo=D(E.TouchableHighlight),io=D(E.TouchableWithoutFeedback),ao=D(E.Pressable),Dt=D(E.ScrollView),Pt=$t((e,t)=>{let r=Zn(null),n=Kn(o=>{if(o){let i=o;for(;i.parentElement&&i.parentElement!==document.body;)i=i.parentElement;i.parentElement===document.body&&(r.current=i,Object.assign(i.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),Ct().appendChild(i))}else r.current&&(document.body.appendChild(r.current),r.current=null);typeof t=="function"?t(o):t&&(t.current=o)},[t]);return Pe(to,null,Pe(E.Modal,{...e,ref:n}))});Pt.displayName="Modal";var so=D(Pt),lo=D(E.Switch),uo=D(E.ActivityIndicator),co=D(E.Button),fo=E.findNodeHandle,po={alert(e,t,r,n){if(typeof document>"u")return;let o=document.createElement("dialog");o.dataset.buoyRoot="",o.setAttribute("aria-label",e),o.style.cssText="position:fixed;inset:0;margin:auto;width:min(440px,90vw);padding:24px;border:1px solid #475569;border-radius:14px;background:#17212e;color:#f1f5f9;font:14px system-ui;box-shadow:0 20px 80px #0008;z-index:2147483647";let i=document.createElement("h2");if(i.textContent=e,i.style.cssText="font-size:18px;margin:0 0 12px",o.appendChild(i),t){let c=document.createElement("p");c.textContent=t,c.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",o.appendChild(c)}let a=document.createElement("div");a.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let s=r?.length?r:[{text:"OK"}],l=()=>{o.close?.(),o.remove()};for(let c of s){let u=document.createElement("button");u.type="button",u.textContent=c.text??"OK",u.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${c.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,u.onclick=()=>{l(),c.onPress?.()},a.appendChild(u)}o.addEventListener("cancel",c=>{c.preventDefault(),n?.cancelable!==false&&(l(),n?.onDismiss?.())}),o.appendChild(a),document.body.appendChild(o),o.showModal?o.showModal():o.setAttribute("open","")}};var Ne=Object.freeze({mode:"real",anchorReal:0,anchorVirtual:0,rate:1}),ze=.1,je=86400,ho=864e13;function M(e,t){return e.mode==="real"?t:e.mode==="frozen"?e.anchorVirtual:e.anchorVirtual+(t-e.anchorReal)*e.rate}function mo(e,t){return M(e,t)-t}function Q(e){if(!Number.isFinite(e)||Math.abs(e)>ho)throw new RangeError(`Not a valid time: ${e}`);return Math.round(e)}function Me(e,t,r,n=false){return{mode:n?"frozen":"running",anchorReal:t,anchorVirtual:Q(r),rate:e.mode==="real"?1:e.rate}}function yo(e,t,r){if(!Number.isFinite(r))throw new RangeError("Jump must be a number of ms");return Me(e,t,M(e,t)+r,e.mode==="frozen")}function go(e,t,r){return Me(e,t,r??M(e,t),true)}function bo(e,t){return e.mode!=="frozen"?e:{...e,mode:"running",anchorReal:t}}function ko(e,t,r){if(!Number.isFinite(r)||r<ze||r>je)throw new RangeError(`Speed must be between ${ze}\xD7 and ${je}\xD7`);return e.mode==="real"&&r===1?e:{mode:"running",anchorReal:t,anchorVirtual:Q(M(e,t)),rate:r}}function Lt(e){let t=e;return!!t&&(t.mode==="real"||t.mode==="running"||t.mode==="frozen")&&Number.isFinite(t.anchorReal)&&Number.isFinite(t.anchorVirtual)&&Number.isFinite(t.rate)&&t.rate>=ze&&t.rate<=je}var vo={ms:1,millisecond:1,milliseconds:1,s:1e3,sec:1e3,secs:1e3,second:1e3,seconds:1e3,m:6e4,min:6e4,mins:6e4,minute:6e4,minutes:6e4,h:36e5,hr:36e5,hrs:36e5,hour:36e5,hours:36e5,d:864e5,day:864e5,days:864e5,w:6048e5,wk:6048e5,week:6048e5,weeks:6048e5,mo:30*864e5,month:30*864e5,months:30*864e5,y:365*864e5,yr:365*864e5,year:365*864e5,years:365*864e5};function _e(e){if(typeof e=="number"){if(!Number.isFinite(e))throw new RangeError("Duration must be finite");return Math.round(e)}let t=String(e).trim().toLowerCase();if(!t)throw new RangeError("Duration is empty");let r=1;if((t[0]==="+"||t[0]==="-"||t[0]==="\u2212")&&(r=t[0]==="+"?1:-1,t=t.slice(1).trim()),/^\d+(\.\d+)?$/.test(t))return r*Math.round(Number(t));let n=/(\d+(?:\.\d+)?)\s*([a-z]+)/g,o=0,i="",a;for(;a=n.exec(t);){let s=vo[a[2]];if(s===void 0)throw new RangeError(`Unknown time unit "${a[2]}" in "${e}"`);o+=Number(a[1])*s,i+=a[0]}if(!i||i.replace(/\s/g,"")!==t.replace(/[\s,]/g,""))throw new RangeError(`Could not read "${e}" as a duration. Try "+1d", "-2h30m" or "90s".`);return r*Math.round(o)}function ie(e,{signed:t=true}={}){let r=e<0?"\u2212":"+",n=Math.abs(Math.round(e));if(n<1e3)return t&&n>0?`${r}${n}ms`:"0s";let o=[],i=[["y",365*864e5],["d",864e5],["h",36e5],["m",6e4],["s",1e3]];for(let[a,s]of i)if(n>=s&&(o.push(`${Math.floor(n/s)}${a}`),n%=s),o.length===2)break;return`${t?r:""}${o.join(" ")}`}function Nt(e,t,r){if(typeof e=="number")return Q(e);let n=String(e).trim();if(!n)throw new RangeError("Time is empty");if(/^now$/i.test(n))return t;if(/^[+\-−]/.test(n))return Q(t+_e(n));if(/^\d{11,}$/.test(n))return Q(Number(n));let o=n.replace(/^(\d{4}-\d{2}-\d{2})[ ](\d{2}:\d{2})/,"$1T$2"),i=r(o);if(!Number.isFinite(i))throw new RangeError(`Could not read "${e}" as a time. Use ISO 8601 like 2026-12-31T23:59:50, epoch ms, or "+1d".`);return Q(i)}var Fe=1e4,zt=[{id:"midnight",label:"Before midnight",hint:"23:59:50 tonight",at(e,t){let r=new t(e);return r.setHours(24,0,0,0),r.getTime()-Fe}},{id:"month-end",label:"Month end",hint:"last day, 23:59:50",at(e,t){let r=new t(e);return r.setMonth(r.getMonth()+1,1),r.setHours(0,0,0,0),r.getTime()-Fe}},{id:"year-end",label:"New Year's Eve",hint:"Dec 31, 23:59:50",at(e,t){let r=new t(e);return r.setFullYear(r.getFullYear()+1,0,1),r.setHours(0,0,0,0),r.getTime()-Fe}},{id:"tomorrow-9",label:"Tomorrow 9 AM",hint:"start of a business day",at(e,t){let r=new t(e);return r.setDate(r.getDate()+1),r.setHours(9,0,0,0),r.getTime()}},{id:"leap-day",label:"Leap day",hint:"next Feb 29, 09:00",at(e,t){let r=new t(e).getFullYear();for(;;){let n=r%4===0&&r%100!==0||r%400===0,o=new t(r,1,29,9,0,0,0).getTime();if(n&&o>e)return o;r+=1}}}],Qa=[{label:"1m",ms:6e4},{label:"15m",ms:15*6e4},{label:"1h",ms:36e5},{label:"1d",ms:864e5},{label:"7d",ms:7*864e5},{label:"30d",ms:30*864e5},{label:"1y",ms:365*864e5}];function jt(e){return e===3600?"1h/s":e===600?"10m/s":e===60?"1m/s":`${Number.isInteger(e)?e:e.toFixed(1)}\xD7`}var P=globalThis,ye="__buoyClock",T=P.__buoyRealDate??(Date[ye]?Date.__buoyRealDate:Date);P.__buoyRealDate=T;var Mt=T.now.bind(T);function $(){return Mt()}P.__buoyRealNow=$;var Be=null,Ue=0;function ge(){let e=Mt();return!Be||Ue>0?e:Be(e)}function _t(e){Be=e}function He(e){Ue+=1;try{return e()}finally{Ue-=1}}P.__buoyWithRealClock=He;function _(...e){let t=new.target;return t?Reflect.construct(T,e.length===0?[ge()]:e,t):new T(ge()).toString()}_.prototype=T.prototype;Object.defineProperty(_,"name",{value:"Date"});Object.defineProperty(_,"length",{value:7});Object.defineProperty(_,"now",{value:function(){return ge()},writable:true,configurable:true});Object.defineProperty(_,"parse",{value:T.parse,writable:true,configurable:true});Object.defineProperty(_,"UTC",{value:T.UTC,writable:true,configurable:true});Object.defineProperty(_,ye,{value:true});Object.defineProperty(_,"__buoyRealDate",{value:T});var ae=_,be=false,ke;function xo(){return be&&P.Date===ae}function wo(){if(P.Date===ae){be=true;return}let e=Object.getOwnPropertyDescriptor(P,"Date");Object.defineProperty(P,"Date",{value:ae,writable:e?.writable??true,enumerable:e?.enumerable??false,configurable:true}),ke=Object.getOwnPropertyDescriptor(T.prototype,"constructor");try{Object.defineProperty(T.prototype,"constructor",{value:ae,writable:true,enumerable:false,configurable:true})}catch{}be=true}function Ao(){if(P.Date===ae){let e=Object.getOwnPropertyDescriptor(P,"Date");Object.defineProperty(P,"Date",{value:T,writable:e?.writable??true,enumerable:e?.enumerable??false,configurable:true})}if(ke){try{Object.defineProperty(T.prototype,"constructor",ke)}catch{}ke=void 0}be=false}var se=[];function Ft(e){return function(t,...r){return e.call(this,t===void 0?ge():t,...r)}}function So(){if(se.length)return;let e=P.Intl?.DateTimeFormat?.prototype;if(e)for(let t of["format","formatToParts"]){let r=Object.getOwnPropertyDescriptor(e,t);if(!(!r||!r.configurable))try{if(typeof r.get=="function"){let n=r.get;Object.defineProperty(e,t,{...r,get(){return Ft(n.call(this))}})}else if(typeof r.value=="function")Object.defineProperty(e,t,{...r,value:Ft(r.value)});else continue;se.push({proto:e,name:t,original:r})}catch{}}}function To(){for(let{proto:e,name:t,original:r}of se)try{Object.defineProperty(e,t,r)}catch{}se=[]}function $o(){return se.length>0}function Io(){wo(),So()}function Co(){Ao(),To()}var Ve=false;function Oo(e){let t=Object.getPrototypeOf(e);for(;t&&t!==Object.prototype;){if(!Object.prototype.hasOwnProperty.call(t,ye)){for(let r of["start","onUpdate"]){let n=Object.getOwnPropertyDescriptor(t,r);if(n&&typeof n.value=="function"){let o=n.value;t[r]=function(...i){return He(()=>o.apply(this,i))}}}try{Object.defineProperty(t,ye,{value:true})}catch{return}}t=Object.getPrototypeOf(t)}}function Eo(e){if(Ve)return true;try{let t=e;if(typeof t?.Value!="function")return false;let r=Object.getPrototypeOf(new t.Value(0)),n=r?.animate;return typeof n!="function"?false:(r.animate=function(o,...i){return o&&typeof o=="object"&&Oo(o),n.call(this,o,...i)},Ve=true,true)}catch{return false}}function Ro(){return Ve}var le=globalThis,Bt="__buoyClockTimer",L=new Map,J=null,Do={},Ut=0,q=()=>$()+Ut;function Po(e){(J?.setTimeout??setTimeout)(()=>{throw e},0)}function Ht(e){let t=Number(e);return Number.isFinite(t)&&t>0?t:0}function Lo(){return J!==null}function Vt(){if(J)return true;let{setTimeout:e,clearTimeout:t,setInterval:r,clearInterval:n}=le;if(typeof e!="function"||typeof t!="function")return false;if(e[Bt])return true;Do={setTimeout:e,clearTimeout:t,setInterval:r,clearInterval:n},J={setTimeout:e.bind(globalThis),clearTimeout:t.bind(globalThis),setInterval:(typeof r=="function"?r:e).bind(globalThis),clearInterval:(typeof n=="function"?n:t).bind(globalThis)};let o=J,i=function(u,f,...g){if(typeof u!="function")return o.setTimeout(u,f,...g);let S=Ht(f),v,O=function(){return L.delete(v),u.apply(this,g)};return v=o.setTimeout(O,f),L.set(v,{kind:"timeout",callback:u,args:g,delay:S,due:q()+S,realHandle:v,run:O}),v},a=function(u,f,...g){if(typeof u!="function")return o.setInterval(u,f,...g);let S=Ht(f),v,O=function(){let z=L.get(v);return z&&(z.due=q()+S),u.apply(this,g)};return v=o.setInterval(O,f),L.set(v,{kind:"interval",callback:u,args:g,delay:S,due:q()+S,realHandle:v,run:O}),v},s=(u,f)=>{let g=L.get(u);return g?(L.delete(u),g.kind==="interval"?o.clearInterval(g.realHandle):o.clearTimeout(g.realHandle)):f(u)},l=function(u){return s(u,o.clearTimeout)},c=function(u){return s(u,o.clearInterval)};globalThis.__buoyRealTimers={setTimeout:o.setTimeout,clearTimeout:l,setInterval:o.setInterval,clearInterval:c};for(let u of[i,a,l,c])Object.defineProperty(u,Bt,{value:true});return le.setTimeout=i,le.clearTimeout=l,le.setInterval=a,le.clearInterval=c,true}function No(){let e=q(),t=0,r=0,n=null;for(let o of L.values())if(o.kind==="interval")r+=1;else{t+=1;let i=Math.max(0,o.due-e);(n===null||i<n)&&(n=i)}return{total:t+r,timeouts:t,intervals:r,nextTimeoutInMs:n}}function zo(e){let t=q(),r=0;for(let n of L.values())n.due-t<=e&&(r+=1);return r}function jo(e){if(!J||!(e>0))return 0;let t=J;Ut+=e;let r=q(),n=[...L.entries()].filter(([,a])=>a.due<=r).sort((a,s)=>a[1].due-s[1].due),o=0;for(let[a,s]of n)if(L.has(a)){s.kind==="timeout"?(L.delete(a),t.clearTimeout(s.realHandle)):s.due=r+s.delay;try{s.callback(...s.args)}catch(l){Po(l)}o+=1}let i=q();for(let a of L.values())a.kind==="timeout"&&(t.clearTimeout(a.realHandle),a.realHandle=t.setTimeout(a.run,Math.max(0,a.due-i)));return o}import{devToolsStorageKeys as Mo,persistentStorage as Wt}from"@buoy-gg/shared-ui/web";function _o(){try{let e=globalThis.localStorage;return e?Jt(e.getItem(We)):void 0}catch{return}}var ue={persist:true,showChip:true,fireTimersOnJump:true},Fo=2*6e4,We=Mo.clock.state();function Jt(e){if(!e)return null;try{let t=JSON.parse(e);if(!t||t.v!==1)return null;let r=t.settings??{},n=t.reload&&Lt(t.reload.anchor)&&typeof t.reload.at=="number"?{anchor:t.reload.anchor,at:t.reload.at}:void 0;return{v:1,anchor:Lt(t.anchor)?t.anchor:null,...n?{reload:n}:{},settings:{persist:typeof r.persist=="boolean"?r.persist:ue.persist,showChip:typeof r.showChip=="boolean"?r.showChip:ue.showChip,fireTimersOnJump:typeof r.fireTimersOnJump=="boolean"?r.fireTimersOnJump:ue.fireTimersOnJump}}}catch{return null}}async function Bo(){try{return Jt(await Wt.getItem(We))}catch{return null}}var Je=Promise.resolve();function qe(e){let t=JSON.stringify(e);return Je=Je.then(()=>Wt.setItem(We,t)).catch(()=>{}),Je.then(()=>{})}import{dispatchToolAction as Uo}from"@buoy-gg/shared-ui/web";import{loadToolModule as Ho}from"@buoy-gg/shared-ui/web/utils";var qt="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/",ve={};for(let e=0;e<qt.length;e++)ve[qt[e]]=e;ve["-"]=62;ve._=63;function Ke(e){let t=e.replace(/=+$/,""),r=[],n=0,o=0;for(let i=0;i<t.length;i++){let a=ve[t[i]];if(a===void 0)return null;n=n<<6|a,o+=6,o>=8&&(o-=8,r.push(n>>o&255))}return r}function Vo(e){let t="";for(let r=0;r<e.length;){let n=e[r],o,i;if(n<128)o=n,i=0;else if(n>=192&&n<224)o=n&31,i=1;else if(n>=224&&n<240)o=n&15,i=2;else if(n>=240&&n<248)o=n&7,i=3;else return null;for(let a=1;a<=i;a++){let s=e[r+a];if(s===void 0||(s&192)!==128)return null;o=o<<6|s&63}t+=String.fromCodePoint(o),r+=i+1}return t}function Ze(e){let t=Ke(e);return t?Kt(t):null}function Kt(e){let t=Vo(e);if(!t||t[0]!=="{")return null;try{let r=JSON.parse(t);return r&&typeof r=="object"&&!Array.isArray(r)?r:null}catch{return null}}function Ye(e){let t=typeof e=="string"&&e.trim()!==""?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>0?t*1e3:void 0}function ce(e,t){if(typeof e=="number"&&Number.isFinite(e)&&e>0)return e<1e11?e*1e3:e;if(typeof e=="string"&&e.trim()!==""){let r=e.trim();if(/^\d+(\.\d+)?$/.test(r))return ce(Number(r),t);let n=t(r);return Number.isFinite(n)?n:void 0}}function Wo(e){let t=typeof e=="string"&&/^\d+(\.\d+)?$/.test(e.trim())?Number(e):e;return typeof t=="number"&&Number.isFinite(t)&&t>0?t:void 0}var Jo=/^[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$/,qo=/^[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]*\.[A-Za-z0-9_-]{2,}\.[A-Za-z0-9_-]*$/,Zt=/^v([1-4])\.(local|public)\.([A-Za-z0-9_-]+)(?:\.([A-Za-z0-9_-]+))?$/,Ko={1:256,2:64,3:96,4:64};function U(e){if(typeof e=="string"&&e)return e;if(Array.isArray(e)){let t=e.filter(r=>typeof r=="string");return t.length?t.join(", "):void 0}}function Zo(e,t){let r=e.iss??"",n=e.use;if(r.includes("securetoken.google.com"))return"Firebase ID token";if(r.includes("firebaseappcheck"))return"Firebase App Check token";if(r.includes("cognito-idp"))return n?`Cognito ${n} token`:"Cognito token";if(r.includes("appleid.apple.com"))return"Sign in with Apple token";if(r.includes("accounts.google.com"))return"Google ID token";if(r.includes(".auth0.com")||r.includes("auth0"))return"Auth0 token";if(r.includes("clerk"))return"Clerk session token";if(r.includes("supabase")||r.includes("/auth/v1"))return"Supabase access token";if(r.includes("okta"))return"Okta token";if(r.includes("/realms/"))return"Keycloak token";if(r.includes("login.microsoftonline.com")||r.includes("sts.windows.net"))return"Microsoft Entra token";let o=typeof t?.typ=="string"?t.typ.toLowerCase():"";if(o==="at+jwt"||o==="application/at+jwt")return"OAuth access token"}function Yo(e,t){let r={iss:U(e.iss),aud:U(e.aud),sub:U(e.sub),scope:U(e.scope??e.scp),use:U(e.token_use)},n=Ye(e.exp);return{claims:r,issuedAt:Ye(e.iat),notBefore:Ye(e.nbf),expiresAt:n,expirySource:n?t:void 0}}function Go(e){let[t,r]=e.split("."),n=Ze(t);if(!n||typeof n.alg!="string"&&typeof n.typ!="string")return null;let o=Ze(r);if(!o)return null;let i=typeof n.alg=="string"?n.alg:void 0,a=Yo(o,"exp claim");return a.claims.alg=i,!a.claims.use&&typeof n.typ=="string"&&n.typ.toUpperCase()!=="JWT"&&(a.claims.use=n.typ),{format:"jwt",formatLabel:i?`JWT \xB7 ${i}`:"JWT",hint:Zo(a.claims,n),...a}}function Xo(e){let t=Ze(e.split(".")[0]);return!t||typeof t.enc!="string"?null:{format:"jwe",formatLabel:"Encrypted JWT",claims:{alg:typeof t.alg=="string"?t.alg:void 0}}}function Qo(e,t){let r=Zt.exec(e);if(!r)return null;let[,n,o,i]=r;if(o==="local")return{format:"paseto-local",formatLabel:`PASETO v${n} (encrypted)`,claims:{}};let a=Ke(i),s=Ko[n],l=a&&a.length>s?Kt(a.slice(0,a.length-s)):null,c={format:"paseto-public",formatLabel:`PASETO v${n}`,claims:{}};return l&&(c.claims={iss:U(l.iss),aud:U(l.aud),sub:U(l.sub)},c.issuedAt=ce(l.iat,t),c.notBefore=ce(l.nbf,t),c.expiresAt=ce(l.exp,t),c.expiresAt&&(c.expirySource="exp claim")),c}function ei(e){if(!e.startsWith("gAAAAA")||e.length<76)return null;let t=Ke(e);if(!t||t[0]!==128||t.length<73||(t.length-57)%16!==0)return null;let r=0;for(let n=1;n<=8;n++)r=r*256+t[n];return r<978307200||r>4102444800?null:{format:"fernet",formatLabel:"Fernet",claims:{},issuedAt:r*1e3}}var ti=[{test:/^ya29\./,hint:"Google OAuth access token"},{test:/^gh[opsu]_/,hint:"GitHub token"},{test:/^github_pat_/,hint:"GitHub token"},{test:/^xox[abeprs]-/,hint:"Slack token"},{test:/^EAA[A-Za-z0-9]{40,}/,hint:"Facebook access token"},{test:/^shp(at|ca|pa|ss)_/,hint:"Shopify token"},{test:/^(sk|rk|pk)_(live|test)_/,hint:"Stripe API key",neverExpires:true},{test:/^AIza[0-9A-Za-z_-]{35}$/,hint:"Google API key",neverExpires:true}];function xe(e,t=Date.parse){let r=e.trim().replace(/^"(.*)"$/,"$1");if(r.length<16||/\s/.test(r))return null;if(Jo.test(r)){let i=Go(r);if(i)return i}if(qo.test(r)){let i=Xo(r);if(i)return i}if(r.startsWith("v")&&Zt.test(r)){let i=Qo(r,t);if(i)return i}let n=ei(r);if(n)return n;let o=ti.find(i=>i.test.test(r));return{format:"opaque",formatLabel:"Opaque",hint:o?.hint,neverExpires:o?.neverExpires,claims:{}}}function ri(e){return!!e&&e.format!=="opaque"}function H(e){let t=2166136261;for(let r=0;r<e.length;r++)t^=e.charCodeAt(r),t=Math.imul(t,16777619)>>>0;return t.toString(16).padStart(8,"0")}function Ge(e){let t=/^([a-z][a-z0-9+.-]*:\/\/[^/?#]+)/i.exec(e);return t?t[1].toLowerCase():null}function ni(e){let t=Ge(e);return t?t.replace(/^[a-z][a-z0-9+.-]*:\/\//,""):"unknown"}function Xe(e){return e.replace(/^[a-z][a-z0-9+.-]*:\/\/[^/?#]+/i,"").split(/[?#]/)[0]||"/"}function oi(e){let t=e.split("#")[0].split("?")[1];if(!t)return[];let r=[];for(let n of t.split("&")){let o=n.indexOf("=");if(!(o<=0))try{r.push([decodeURIComponent(n.slice(0,o)),decodeURIComponent(n.slice(o+1))])}catch{}}return r}var Qe=/(token|jwt|session|auth|appcheck|api[-_]?key|apikey|credential|bearer)/i,ii=new Set(["authorization","cookie","dpop","idempotency-key","x-request-id","x-correlation-id","www-authenticate","proxy-authenticate","x-csrf-token","x-xsrf-token"]),Yt=new Set(["access_token","accesstoken","id_token","token","auth","auth_token","jwt","session","session_token"]),ai=new Set(["bearer","token","jwt","dpop","oauth","firebase"]);function Gt(e){let t={};if(!e)return t;for(let[r,n]of Object.entries(e))typeof n=="string"?t[r.toLowerCase()]=n:Array.isArray(n)&&(t[r.toLowerCase()]=n.join(", "));return t}function si(e){let t=[];for(let r of e.split(";")){let n=r.indexOf("=");n<=0||t.push([r.slice(0,n).trim(),r.slice(n+1).trim()])}return t}function de(e,t,r){let n=xe(e,r);return n&&(ri(n)||n.hint||t)?n:null}function Xt(e,t){let r=[],n=Gt(e.requestHeaders),o=n.authorization;if(o){let i=/^(\S+)\s+(\S+)$/.exec(o.trim()),a=i?i[1]:void 0,s=i?i[2]:o.trim();if(!a||ai.has(a.toLowerCase())){let l=de(s,true,t)??(a&&!/^(null|undefined)$/i.test(s)?{format:"opaque",formatLabel:"Opaque",claims:{}}:null);l&&r.push({location:"authorization",name:"Authorization",scheme:a,fp:H(s),info:l})}}for(let[i,a]of Object.entries(n)){if(ii.has(i)||!Qe.test(i))continue;let s=a.replace(/^bearer\s+/i,""),l=de(s,true,t);l&&r.push({location:"header",name:i,fp:H(s),info:l})}if(n.cookie)for(let[i,a]of si(n.cookie)){let s=de(a,Qe.test(i)||/^(sid|sess)/i.test(i),t);s&&r.push({location:"cookie",name:i,fp:H(a),info:s})}for(let[i,a]of oi(e.url)){let s=de(a,Yt.has(i.toLowerCase()),t);s&&Yt.has(i.toLowerCase())&&r.push({location:"query",name:i,fp:H(a),info:s})}return r}var li=/^(access_?token|accesstoken|token|jwt|auth_?token|session_?token|sessiontoken)$/i,Qt=/^(id_?token|idtoken)$/i,we=/^(refresh_?token|refreshtoken)$/i,ui=["expires_in","expiresIn","ExpiresIn","expires","ttl"],ci=["expires_at","expiresAt","ExpiresAt","expiration","Expiration","expiry","expirationTime","expiration_time","access_token_expires_at","accessTokenExpiresAt","accessTokenExpiry"],di=["refresh_expires_in","refresh_token_expires_in","refreshTokenExpiresIn","refreshExpiresIn"],fi=["refresh_expires_at","refreshTokenExpiresAt","refresh_token_expires_at"];function pi(e){if(typeof e!="string")return e;let t=e.trim();if(!(t.startsWith("{")||t.startsWith("[")))return null;try{return JSON.parse(t)}catch{return null}}function et(e,t,r){if(t>4||!e||typeof e!="object")return;if(Array.isArray(e)){for(let o of e.slice(0,5))et(o,t+1,r);return}let n=e;for(let[o,i]of Object.entries(n))typeof i=="string"&&(li.test(o)||Qt.test(o)||we.test(o))?r.push({key:o,value:i,holder:n}):i&&typeof i=="object"&&et(i,t+1,r)}function hi(e){return we.test(e)?"refresh":Qt.test(e)?"id":/session/i.test(e)?"session":"access"}function er(e,t,r,n,o){for(let i of t){let a=Wo(e[i]);if(a!==void 0)return{expiresAt:n+a*1e3,source:i,lifetimeMs:a*1e3}}for(let i of r){let a=ce(e[i],o);if(a!==void 0)return{expiresAt:a,source:i}}return{}}function mi(e){let t=e["set-cookie"];return t?t.split(/,(?=\s*[A-Za-z0-9!#$%&'*+.^_`|~-]+=)/).map(r=>r.trim()):[]}function yi(e,t){if(e.status===void 0||e.status>=400)return[];let r=`${e.method.toUpperCase()} ${Xe(e.url)}`,n=e.timestamp+(e.duration??0),o=[],i=pi(e.responseData);if(i){let s=[];et(i,0,s);let l=new Map;for(let c of s.filter(u=>we.test(u.key))){let u=xe(c.value,t);if(!u)continue;let f=er(c.holder,di,fi,n,t);l.set(c.holder,{fp:H(c.value),expiresAt:u.expiresAt??f.expiresAt,formatLabel:u.formatLabel})}for(let c of s){if(we.test(c.key))continue;let u=xe(c.value,t);if(!u)continue;let f=er(c.holder,ui,ci,n,t);o.push({fp:H(c.value),info:u,role:hi(c.key),expiresAt:f.expiresAt,expirySource:f.source,lifetimeMs:f.lifetimeMs,issuedBy:r,refresh:l.get(c.holder)})}}let a=Gt(e.responseHeaders);for(let s of mi(a)){let[l,...c]=s.split(";"),u=l.indexOf("=");if(u<=0)continue;let f=l.slice(0,u).trim(),g=l.slice(u+1).trim(),S=de(g,Qe.test(f)||/^(sid|sess)/i.test(f),t);if(!S||g===""||g.toLowerCase()==="deleted")continue;let v,O,z;for(let Yr of c){let[Gr,...Xr]=Yr.split("="),vt=Gr.trim().toLowerCase(),De=Xr.join("=").trim();if(vt==="max-age"&&/^-?\d+$/.test(De))z=Number(De)*1e3,v=n+z,O="Max-Age";else if(vt==="expires"&&O!=="Max-Age"){let xt=t(De);Number.isFinite(xt)&&(v=xt,O="Expires")}}o.push({fp:H(g),info:S,role:"cookie",cookie:f,expiresAt:S.expiresAt??v,expirySource:S.expiresAt?S.expirySource:O,lifetimeMs:S.expiresAt?void 0:z,issuedBy:r})}return o}var tt=e=>T.parse(e),tr=4,rr=2e4,gi=8,bi=8,ki=200,vi=1e3,R=new Map,ee=new Map,xi=new Set,wi=new Set,nr=new Set,Ai=/(token|refresh|oauth|session|auth\/)/i,p=null,Ae=new Set,Se=true,rt=null,nt=new Set,ot=false;function fe(){ot||(ot=true,Promise.resolve().then(()=>{ot=false,nt.forEach(e=>e())}))}function Si(e){return nt.add(e),()=>{nt.delete(e)}}function it(e,t){if(e.has(t))return false;if(e.size>=vi){let r=e.values().next().value;r!==void 0&&e.delete(r)}return e.add(t),true}function at(e,t){return`${e}|${t.location}:${t.name.toLowerCase()}`}function or(e,t){let r=t?.lifetimeMs!==void 0&&t.expiresAt!==void 0,n=r?t.expiresAt:e.expiresAt??t?.expiresAt,o=e.expiresAt??(r?t.observedReal+t.lifetimeMs:t?.expiresAt),i=r?t.expirySource:e.expiresAt?e.expirySource:t?.expirySource,a=r?t.lifetimeMs:e.expiresAt!==void 0&&e.issuedAt!==void 0?e.expiresAt-e.issuedAt:void 0;return{expiresAt:n,serverExpiresAt:o,source:i,lifetimeMs:a}}function st(e,t,r,n,o){let i=ee.get(t),a=or(r,i),s=e.fp!==t;s&&(e.history.unshift({fp:e.fp,firstSeenReal:e.firstSeenReal,expiresAt:e.expiresAt}),e.history.length=Math.min(e.history.length,bi),e.fp=t,e.firstSeenReal=n,e.firstSeenApp=o,e.uses=0,e.expiredSends=0,e.rejected=0),e.info=r,e.role=i?.role??(s?void 0:e.role),e.issuedBy=i?.issuedBy??(s?void 0:e.issuedBy),e.refresh=i?.refresh??(s?void 0:e.refresh),e.expiresAt=a.expiresAt,e.serverExpiresAt=a.serverExpiresAt,e.expirySource=a.source,e.lifetimeMs=a.lifetimeMs,s&&Ti(e,n)}function ir(e,t,r,n,o){let i=ee.get(r.fp),a=or(r.info,i);return{key:e,origin:t,host:ni(t),location:r.location,name:r.name,scheme:r.scheme,fp:r.fp,info:r.info,role:i?.role,issuedBy:i?.issuedBy,refresh:i?.refresh,expiresAt:a.expiresAt,serverExpiresAt:a.serverExpiresAt,expirySource:a.source,lifetimeMs:a.lifetimeMs,firstSeenReal:n,firstSeenApp:o,lastUsedReal:n,lastUsedApp:o,uses:0,expiredSends:0,rejected:0,history:[]}}function ar(){if(R.size<=gi)return;let e=null;for(let t of R.values())(!e||t.lastUsedReal<e.lastUsedReal)&&(e=t);e&&e.key!==p?.tokenId&&R.delete(e.key)}function Ti(e,t){!p||p.tokenId!==e.key||(p.newTokens+=1,p.status==="waiting"&&(p.status="refreshed",p.refreshedAt=t,p.ruleId&&p.forcedAt===void 0&&Uo("network","deleteOverrideRule",{id:p.ruleId}).catch(()=>{})),p.newTokens>=tr&&t-(p.refreshedAt??t)<=rr&&(p.status="loop"))}function $i(e){let t=Ge(e.url);if(!t)return;let r=Xt(e,tt);if(r.length===0)return;let n=$(),o=e.timestamp;for(let i of r){let a=at(t,i),s=R.get(a);s?st(s,i.fp,i.info,n,o):(s=ir(a,t,i,n,o),R.set(a,s),ar()),s.uses+=1,s.lastUsedReal=n,s.lastUsedApp=o,s.expiresAt!==void 0&&o>=s.expiresAt&&(s.expiredSends+=1),p&&p.tokenId===a&&p.forcedAt!==void 0&&i.fp===p.startFp&&(p.staleAfterFailure+=1,it(Ae,e.id))}fe()}function Ii(e){let t=Ge(e.url);if(!t)return;let r=$(),n=false;if(e.status===401||e.status===403)for(let l of Xt(e,tt)){let c=R.get(at(t,l));c&&c.fp===l.fp&&(c.rejected+=1,n=true)}let o=!!p?.ruleId&&e.override?.ruleId===p.ruleId,i=`${e.method.toUpperCase()} ${Xe(e.url)}`,a=nr.has(i)||e.method.toUpperCase()==="POST"&&Ai.test(Xe(e.url)),s=e.status??0;p&&s>=400&&!o&&a&&(p.failedRefreshes+=1,p.lastRefreshError=`${e.status} ${i}`,n=true),p?.status==="waiting"&&p.forcedAt!==void 0&&!o&&s>=200&&s<400&&(a&&p.refreshOkAt===void 0?(p.refreshOkAt=r,n=true):!a&&p.refreshOkAt!==void 0&&Ae.has(e.id)&&(p.status="refreshed",p.refreshedAt=r,p.sameToken=true,n=true)),p?.ruleId&&e.override?.ruleId===p.ruleId&&p.forcedAt===void 0&&(p.forcedAt=r,n=true);for(let l of yi(e,tt)){if(nr.add(l.issuedBy),ee.set(l.fp,{...l,observedReal:r}),ee.size>ki){let c=ee.keys().next().value;c!==void 0&&ee.delete(c)}if(n=true,l.cookie){let c={location:"cookie",name:l.cookie,fp:l.fp,info:l.info},u=at(t,c),f=R.get(u);f?st(f,l.fp,l.info,r,e.timestamp):(R.set(u,ir(u,t,c,r,e.timestamp)),ar());continue}for(let c of R.values())c.fp===l.fp&&st(c,l.fp,c.info,r,c.lastUsedApp)}n&&fe()}function Ci(e){let t=e;!t||typeof t.id!="string"||typeof t.url!="string"||(it(xi,t.id)&&$i(t),t.status!==void 0&&it(wi,t.id)&&Ii(t))}function Te(){if(rt)return true;try{let{networkEventStore:e}=Ho("@buoy-gg/network");if(!e?.onEvent)throw new Error("no event store");rt=e.onEvent(Ci,true),Se=true}catch{Se=false}return fe(),Se}function sr(e,t,r){let n=R.get(t);if(!n)throw new Error(`No token row "${t}".`);return p={kind:e,tokenId:t,startedAt:$(),startFp:n.fp,ruleId:r,status:"waiting",newTokens:0,staleAfterFailure:0,failedRefreshes:0},Ae.clear(),fe(),p}function Oi(){p=null,Ae.clear(),fe()}function Ei(e){return e.location==="cookie"?`${e.name} cookie`:e.location==="query"?`${e.name} parameter`:e.location==="header"?`${e.name} header`:e.role==="id"||e.info.claims.use==="id"?"ID token":"Access token"}function Ri(e,t){let r=[e.firstSeenReal,...e.history.map(o=>o.firstSeenReal)].slice(0,-1).filter(o=>t-o<=rr).length,n=e.info.issuedAt;return{id:e.key,label:Ei(e),host:e.host,location:e.location,name:e.name,scheme:e.scheme,format:e.info.format,formatLabel:e.info.formatLabel,hint:e.info.hint,claims:e.info.claims,fingerprint:e.fp,issuedAt:n,notBefore:e.info.notBefore,expiresAt:e.expiresAt,serverExpiresAt:e.serverExpiresAt,expirySource:e.expirySource,lifetimeMs:e.lifetimeMs,neverExpires:e.info.neverExpires,issuedBy:e.issuedBy,refresh:e.refresh?{expiresAt:e.refresh.expiresAt,formatLabel:e.refresh.formatLabel}:void 0,firstUsed:e.firstSeenApp,lastUsed:e.lastUsedApp,lastUsedReal:e.lastUsedReal,uses:e.uses,refreshes:e.history.length,lastRefreshAt:e.history.length?e.firstSeenReal:void 0,recentRefreshes:r,looping:r>=tr,expiredSends:e.expiredSends,rejected:e.rejected}}function $e(){let e=$(),t=[...R.values()].sort((r,n)=>n.lastUsedReal-r.lastUsedReal).map(r=>Ri(r,e));if(p?.status==="refreshed"){let r=R.get(p.tokenId);r&&(p.newLifetimeMs=r.lifetimeMs,p.newIssuedBy=r.issuedBy)}return{available:Se,watching:rt!==null,tokens:t,check:p?{...p}:null}}function Di(e){let t=$e();return e?t.tokens.find(r=>r.id===e||r.fingerprint===e)??null:t.tokens.find(r=>r.expiresAt!==void 0)??t.tokens[0]??null}function Pi(e){return R.get(e)?.origin??null}import{isProNow as lr}from"@buoy-gg/shared-ui/web";var h={anchor:Ne,settings:ue,lastJump:null,changedAt:null,hydrated:false},lt=new Set,Ie=null;function ur(){Ie=null,lt.forEach(e=>e())}Si(ur);function pe(e){return lt.add(e),()=>{lt.delete(e)}}function Li(){return h.settings}function cr(){return M(h.anchor,$())}function dr(){return h.anchor.mode!=="real"}function Ni(e){if(e.mode==="real"){_t(null),Co();return}Vt(),_t(t=>M(h.anchor,t)),Io()}function zi(){let e={v:1,anchor:h.settings.persist&&lr()?h.anchor:null,settings:h.settings};qe(e)}function fr(){let e={v:1,anchor:h.settings.persist&&lr()?h.anchor:null,settings:h.settings};return h.settings.persist&&h.anchor.mode!=="real"&&(e.reload={anchor:h.anchor,at:$()}),qe(e)}function te(e,{save:t=true}={}){h={...h,...e},e.anchor&&Ni(h.anchor),t&&zi(),ur()}function re(e,t=h.lastJump){te({anchor:e,lastJump:t,changedAt:$(),hydrated:true})}var pr=e=>T.parse(e);function hr(e,t=false){let r=$(),n=M(h.anchor,r),o=Nt(e,n,pr),i=o-n;return re(Me(h.anchor,r,o,t),{byMs:i,firedTimers:0,at:r}),C()}function ut(e,t){let r=_e(e),n=$(),o=yo(h.anchor,n,r),i=(t??h.settings.fireTimersOnJump)&&r>0;if(re(o,{byMs:r,firedTimers:0,at:n}),i){let a=jo(r);a>0&&te({lastJump:{byMs:r,firedTimers:a,at:n}},{save:false})}return C()}function ct(e){let t=$(),r=M(h.anchor,t),n=e===void 0||e===""?r:Nt(e,r,pr);return re(go(h.anchor,t,n)),C()}function dt(){return h.anchor.mode==="frozen"&&re(bo(h.anchor,$())),C()}function mr(e){return re(ko(h.anchor,$(),Number(e))),C()}function ft(){return re(Ne,null),C()}function yr(e){let t={...h.settings};for(let r of Object.keys(ue))typeof e[r]=="boolean"&&(t[r]=e[r]);return te({settings:t}),C()}function ji(e){return e>0?zo(e):0}var gr=false;function br(e){if(!e){te({hydrated:true},{save:false});return}let t=e.reload?$()-e.reload.at:1/0,r=t>=0&&t<Fo?e.reload?.anchor:void 0;e.reload&&qe({v:1,anchor:e.anchor,settings:e.settings});let n=e.anchor??r??null;te({settings:e.settings,anchor:n??Ne,changedAt:n?$():null,hydrated:true},{save:false})}function pt(){if(gr)return;gr=true,Vt();let e=_o();if(e!==void 0){br(e);return}Bo().then(t=>{h.changedAt===null?br(t):te({hydrated:true},{save:false})})}function Mi(){try{return Intl.DateTimeFormat().resolvedOptions().timeZone??"unknown"}catch{return"unknown"}}function C(){let e=$(),t=M(h.anchor,e);return{mode:h.anchor.mode,active:h.anchor.mode!=="real",rate:h.anchor.rate,virtualNow:t,virtualIso:new T(t).toISOString(),realNow:e,offsetMs:mo(h.anchor,e),timeZone:Mi(),timers:No(),lastJump:h.lastJump,changedAt:h.changedAt,settings:h.settings,hydrated:h.hydrated,tokens:$e(),patched:{date:xo(),intl:$o(),timers:Lo(),animatedOnRealClock:Ro()}}}function kr(){return Ie||(Ie=C()),Ie}import{useSyncExternalStore as _i}from"react";import{ClockToolIcon as vr,FloatingTool as Fi,Pause as Bi,Play as Ui,X as Hi,dismissFloatingTool as Vi,getFloatingTools as Wi,getUseIsPro as Ji,night as he,openFloatingTool as xr}from"@buoy-gg/shared-ui/web";import{useEffect as qi,useState as Ki}from"react";function V(e,t=250){let[,r]=Ki(0);qi(()=>{let a=setInterval(()=>r(s=>s+1),t);return()=>clearInterval(a)},[t]);let n=$();if(!e)return{virtual:n,real:n};let o=n-e.realNow,i=e.mode==="real"?1:e.rate;return{virtual:e.mode==="frozen"?e.virtualNow:e.virtualNow+o*i,real:n}}var F=e=>String(e).padStart(2,"0");function ne(e){let t=new T(e);return`${F(t.getHours())}:${F(t.getMinutes())}:${F(t.getSeconds())}`}var Zi=["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],wr=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];function Yi(e){let t=new T(e);return`${Zi[t.getDay()]}, ${wr[t.getMonth()]} ${t.getDate()}, ${t.getFullYear()}`}function Ce(e,t=true){let r=new T(e),n=t?ne(e):`${F(r.getHours())}:${F(r.getMinutes())}`;return`${wr[r.getMonth()]} ${r.getDate()} \xB7 ${n}`}function Ar(e){let t=new T(e);return`${t.getFullYear()}-${F(t.getMonth()+1)}-${F(t.getDate())} ${F(t.getHours())}:${F(t.getMinutes())}`}function Gi(e){if(Math.abs(e)<1e3)return"matches real time";let t=ie(Math.abs(e),{signed:false});return e>0?`${t} ahead of real time`:`${t} behind real time`}function Sr(e){return e.mode==="real"?{label:"Real time",tone:"neutral"}:e.mode==="frozen"?{label:"Frozen",tone:"info"}:e.rate!==1?{label:`${jt(e.rate)} speed`,tone:"warning"}:{label:"Overridden",tone:"accent"}}function Xi(e){return`clock-jump-${e<0?"minus":"plus"}-${ie(Math.abs(e),{signed:false}).replace(/\s/g,"")}`}import{jsx as N,jsxs as ht}from"react/jsx-runtime";var Oe="clock-chip",Tr={id:Oe,render:e=>N(Cr,{...e})},Qi=()=>Wi().some(e=>e.id===Oe);function ea(){xr(Tr)}var $r=false;function Ir(){if($r)return;$r=true;let e=false,t=()=>{let r=dr()&&Li().showChip;r&&!e?xr(Tr):!r&&Qi()&&Vi(Oe),e=r};pe(t),t()}function Cr({id:e,revealToken:t}){let r=_i(pe,kr,kr),{virtual:n,real:o}=V(r),i=r.mode==="frozen",a=Ji()(),s=i||a,l=Sr(r),c=n-o,u=`${Math.abs(c)<1e3?"0s":ie(c)} \xB7 ${l.label.toLowerCase()}`;return N(Fi,{id:e,revealToken:t,variant:"strip",dragFromSurface:true,defaultPlacement:"top",accessibilityLabel:`Move or hide the clock chip. App time ${Ce(n)}`,handleAdornment:N(vr,{size:12}),children:ht(m,{style:K.row,children:[N(vr,{size:18}),ht(m,{style:K.text,children:[N(w,{style:K.time,numberOfLines:1,testID:"clock-chip-time",children:Ce(n)}),N(w,{style:K.detail,numberOfLines:1,testID:"clock-chip-detail",children:u})]}),s?ht(B,{testID:i?"clock-chip-resume":"clock-chip-freeze",accessibilityRole:"button",accessibilityLabel:i?"Resume the app clock":"Freeze the app clock",onPress:()=>i?dt():ct(),style:K.button,hitSlop:{top:8,bottom:8,left:4,right:4},children:[i?N(Ui,{size:16,color:he.color.accent}):null,i?null:N(Bi,{size:16,color:he.color.text})]}):null,s?N(m,{style:K.separator}):null,N(B,{testID:"clock-chip-reset",accessibilityRole:"button",accessibilityLabel:"Back to real time",onPress:()=>ft(),style:K.button,hitSlop:{top:8,bottom:8,left:4,right:8},children:N(Hi,{size:16,color:he.color.textSecondary})})]})})}var K=X.create({row:{flexDirection:"row",alignItems:"center",gap:10,paddingLeft:10,paddingRight:4,paddingVertical:6,minWidth:220},text:{flexShrink:1,minWidth:120},time:{color:"#F59E0B",fontSize:14,fontWeight:"600",fontVariant:["tabular-nums"]},detail:{color:he.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},button:{width:32,height:32,alignItems:"center",justifyContent:"center",borderRadius:16},separator:{width:X.hairlineWidth,height:20,backgroundColor:he.color.separator}});import{ClockToolIcon as ta,CLOCK_TOOL_ICON_COLOR as ra,createToolFactory as na,defineToolPreset as oa}from"@buoy-gg/shared-ui/web";import{useEffect as Or,useState as ia}from"react";import{reloadApp as aa}from"@buoy-gg/shared-ui/web";import{createSyncAdapter as sa}from"@buoy-gg/shared-ui/web";import{dispatchToolAction as Er}from"@buoy-gg/shared-ui/web";var Rr="No sign-in token seen yet. Use the app so it sends a signed-in request, then try again. Tokens are read from the Network tool's captured requests.";function Dr(e){Te();let t=Di(e);if(!t)throw new Error(e?`No token "${e}". Read getState for the current ids.`:Rr);return t}function Pr(e,t=1e4){let r=Dr(e);if(r.expiresAt===void 0)throw new Error(r.neverExpires?`${r.label} for ${r.host} is ${r.hint??"a key"} and never expires.`:`${r.label} for ${r.host} (${r.formatLabel}) has no expiry Buoy can read. Use failNextRequest to test the refresh instead.`);let n=r.expiresAt-Math.max(0,t)-cr();if(n<=0)throw new Error(`${r.label} for ${r.host} has already expired on the app's clock. Go back to real time, or use failNextRequest.`);return ut(n),sr("expiry",r.id),C()}async function Lr(e,t=401,r=1){let n=Dr(e),o=Pi(n.id);if(!o)throw new Error(Rr);await Nr();let i=t===403?403:401,a=n.location==="authorization"||n.location==="header"?{urlPattern:`${o}/*`,requireHeader:n.name.toLowerCase()}:n.location==="query"?{urlPattern:`${o}/*${n.name}=*`}:{urlPattern:`${o}/*`},s=await Er("network","upsertOverrideRule",{name:"Clock: force a token refresh",...a,kind:"respond",status:i,headers:{"content-type":"application/json","www-authenticate":'Bearer error="invalid_token", error_description="The access token expired"'},body:JSON.stringify({error:"invalid_token",error_description:"The access token expired (forced by Buoy Clock to test token refresh)"}),times:Math.max(1,Math.min(10,Math.round(r)))}).catch(l=>{let c=l instanceof Error?l.message:String(l);throw new Error(c.includes("Unknown tool")?"Failing a request needs the Network tool (@buoy-gg/network).":c)});if(!s?.ok||!s.rule)throw new Error(s?.error??"Network did not add the override.");return sr("401",n.id,s.rule.id),C()}async function Nr(){let e=$e().check;e?.ruleId&&e.forcedAt===void 0&&await Er("network","deleteOverrideRule",{id:e.ruleId}).catch(()=>{})}async function zr(){return await Nr(),Oi(),C()}function Z(e){return e&&typeof e=="object"?e:{}}function mt(e,...t){for(let r of t){let n=e[r];if(typeof n=="string"||typeof n=="number")return n}}function me(e,t){let r=e[t];if(typeof r=="boolean")return r;if(r==="true")return true;if(r==="false")return false}var jr=sa({version:1,getSnapshot(){return C()},subscribe(e){return pe(e)},actions:{getState(){return Te(),C()},setTime(e){let t=Z(e),r=mt(t,"time","at","date","iso");if(r===void 0)throw new Error('setTime needs `time`: ISO 8601 ("2026-12-31T23:59:50"), epoch ms, or relative ("+1d").');return hr(r,me(t,"freeze")??false)},shift(e){let t=Z(e),r=mt(t,"by","ms","duration","delta");if(r===void 0)throw new Error('shift needs `by`: a duration like "+1d", "-2h30m", "90s", or ms.');return ut(r,me(t,"fireTimers"))},freeze(e){return ct(mt(Z(e),"time","at"))},resume(){return dt()},setRate(e){let t=Z(e),r=Number(t.rate??t.speed);if(!Number.isFinite(r))throw new Error("setRate needs a numeric `rate` (1 = normal speed).");return mr(r)},reset(){return ft()},updateSettings(e){let t=Z(e);return yr({persist:me(t,"persist"),showChip:me(t,"showChip"),fireTimersOnJump:me(t,"fireTimersOnJump")})},jumpToTokenExpiry(e){let t=Z(e),r=typeof t.token=="string"?t.token:typeof t.id=="string"?t.id:void 0,n=Number(t.leadMs??t.lead??1e4);return Pr(r,Number.isFinite(n)?n:1e4)},failNextRequest(e){let t=Z(e),r=typeof t.token=="string"?t.token:typeof t.id=="string"?t.id:void 0,n=Number(t.status??401),o=Number(t.times??1);return Lr(r,n,Number.isFinite(o)?o:1)},stopTokenCheck(){return zr()},async holdForReload(){return await fr(),C()}}});import{useState as Ee}from"react";import{ChevronRight as la,NightButton as ua,NightCard as Re,NightChip as ca,NightFootnote as yt,NightRows as gt,NightSectionLabel as Mr,NightSegmented as da,NightSwitch as _r,ProBadge as fa,ProUpgradeModal as pa,getUseIsPro as ha,monoFont as ma,night as k,useSafeAreaInsets as ya}from"@buoy-gg/shared-ui/web";import{ChevronRight as ga,NightButton as Fr,NightCard as ba,NightFootnote as ka,NightRows as va,NightSectionLabel as xa,ProBadge as wa,night as x}from"@buoy-gg/shared-ui/web";import{jsx as A,jsxs as j}from"react/jsx-runtime";var W=e=>ie(Math.abs(e),{signed:false});function Aa({snapshot:e,run:t,openId:r,onToggle:n,isPro:o,onUpgrade:i}){let a=e.tokens;return j(m,{children:[A(xa,{children:a.tokens.length>1?"Sign-in tokens":"Sign-in token"}),A(ba,{children:j(va,{children:[a.tokens.map((s,l)=>j(m,{children:[A(Sa,{token:s,snapshot:e,index:l,open:r===s.id,onPress:()=>n(s.id)}),r===s.id?A(Ta,{token:s,snapshot:e,run:o?t:()=>i("Sign-in token tests"),isPro:o}):null]},s.id)),a.tokens.length===0?A(m,{style:b.row,testID:"clock-token-empty",children:A(w,{style:b.emptyText,children:a.available?"No token seen yet":"Needs the Network tool"})},"empty"):null]})}),A(Ia,{check:a.check,tokens:a.tokens,snapshot:e,run:t}),a.tokens.length===0?A(ka,{children:a.available?"Tokens show up here when the app sends a signed-in request.":"Install @buoy-gg/network so the Clock tool can read the app's tokens."}):null]})}function Sa({token:e,snapshot:t,index:r,open:n,onPress:o}){let{virtual:i}=V(t,1e3),a=e.expiresAt!==void 0?e.expiresAt-i:void 0,s=e.neverExpires?"No expiry":a===void 0?"Unknown":a<=0?"Expired":W(a),l=a!==void 0&&a<=0?b.valueDanger:a!==void 0&&a<6e4?b.valueWarning:null;return j(B,{testID:`clock-token-${r}`,accessibilityRole:"button",accessibilityLabel:`${e.label} for ${e.host}: ${a!==void 0&&a>0?`expires in ${s}`:s}`,accessibilityState:{expanded:n},activeOpacity:.6,onPress:o,style:b.row,children:[j(m,{style:b.rowText,children:[A(w,{style:b.rowTitle,numberOfLines:1,children:e.label}),A(w,{style:b.rowSubtitle,numberOfLines:1,children:`${e.host} \xB7 ${e.hint??e.formatLabel}`})]}),j(m,{style:b.rowRight,children:[A(w,{style:[b.value,l],testID:`clock-token-${r}-left`,children:s}),A(m,{style:n?b.chevronOpen:null,children:A(ga,{size:16,color:x.color.textTertiary})})]})]})}function Ta({token:e,snapshot:t,run:r,isPro:n}){let{virtual:o,real:i}=V(t,1e3),a=$a(e,o,i),s=e.expiresAt!==void 0&&e.expiresAt-o>1e4;return j(m,{style:b.detail,testID:"clock-token-detail",children:[a.map(l=>A(w,{style:[b.detailLine,l.tone==="warn"?b.warn:null,l.tone==="bad"?b.bad:null],children:l.text},l.text)),j(m,{style:b.buttons,children:[A(m,{style:b.button,children:A(Fr,{label:"Jump to Expiry",testID:"clock-token-jump",accessibilityLabel:"Jump the app's clock to ten seconds before this token expires",size:"md",disabled:!s,onPress:()=>r("jumpToTokenExpiry",{token:e.id})})}),A(m,{style:b.button,children:A(Fr,{label:"Fail Next Request",testID:"clock-token-fail",accessibilityLabel:"Answer the app's next request to this API with 401",size:"md",onPress:()=>r("failNextRequest",{token:e.id})})})]}),n?null:j(m,{style:b.proLine,children:[A(wa,{}),A(w,{style:[b.hint,b.proHint],children:"Jump to Expiry and Fail Next Request are part of Buoy Pro."})]}),A(w,{style:b.hint,children:s||e.expiresAt===void 0?"Jump tests an app that refreshes before expiry. Fail tests one that refreshes after a 401.":"This token has already expired on the app's clock. Use Real Time to jump to it again."})]})}function $a(e,t,r){let n=[];if(e.expiresAt!==void 0){if(n.push({text:`Expires ${Ce(e.expiresAt)}`}),e.lifetimeMs!==void 0&&e.lifetimeMs>0&&n.push({text:`Lasts ${W(e.lifetimeMs)}${e.expirySource?`, from ${e.expirySource}`:""}`}),e.serverExpiresAt!==void 0){let o=e.expiresAt-t,i=e.serverExpiresAt-r;Math.abs(o-i)>2e3&&n.push({text:i>0?`The server still accepts it for ${W(i)}`:`The server stopped accepting it ${W(i)} ago`})}}else e.neverExpires||n.push({text:"The token doesn't say when it expires, and no login response did either."});if(e.hint&&n.push({text:e.formatLabel}),e.issuedBy&&n.push({text:`Issued by ${e.issuedBy}`}),e.refresh?.expiresAt!==void 0){let o=e.refresh.expiresAt-t;n.push({text:o>0?`Refresh token expires in ${W(o)}`:"Refresh token expired"})}return e.refreshes>0&&e.lastRefreshAt!==void 0&&n.push({text:`Refreshed ${e.refreshes===1?"once":`${e.refreshes} times`}, last at ${ne(e.lastRefreshAt)}`}),n.push({text:`Sent with ${e.uses} request${e.uses===1?"":"s"}`}),e.expiredSends>0&&n.push({text:`Sent ${e.expiredSends} time${e.expiredSends===1?"":"s"} after it expired on the app's clock`,tone:"warn"}),e.rejected>0&&n.push({text:`Rejected by the server ${e.rejected} time${e.rejected===1?"":"s"}`,tone:"warn"}),e.looping&&n.push({text:`Refresh loop: ${e.recentRefreshes} new tokens in 20s`,tone:"bad"}),n}function Ia({check:e,tokens:t,snapshot:r,run:n}){let{virtual:o,real:i}=V(r,1e3);if(!e)return null;let a=t.find(c=>c.id===e.tokenId),{text:s,tone:l}=Ca(e,a,o,i);return j(m,{style:b.check,children:[A(w,{style:[b.checkText,l==="good"?b.good:null,l==="bad"?b.bad:null,l==="warn"?b.warn:null],testID:"clock-token-check",children:s}),A(B,{testID:"clock-token-check-done",accessibilityRole:"button",accessibilityLabel:e.status==="waiting"?"Stop the refresh check":"Dismiss",onPress:()=>n("stopTokenCheck"),hitSlop:{top:8,bottom:8,left:8,right:8},children:A(w,{style:b.checkDone,children:e.status==="waiting"?"Stop":"Done"})})]})}function Ca(e,t,r,n){if(e.status==="loop")return{text:`Refresh loop: ${e.newTokens} new tokens since the check started. The new tokens may already look expired to the app's clock.`,tone:"bad"};if(e.status==="refreshed"&&e.sameToken)return{text:`The app got the 401 and refreshed at ${ne(e.refreshedAt??n)}. The refresh sent back the same token, and the retry worked.`,tone:"good"};if(e.status==="refreshed"){let s=e.newIssuedBy?` by ${e.newIssuedBy}`:"",l=e.newLifetimeMs&&e.newLifetimeMs>0?`. The new token lasts ${W(e.newLifetimeMs)}`:"",c=e.kind==="401"&&e.forcedAt!==void 0?"The app got the 401 and refreshed":"Refreshed",u=e.failedRefreshes>0?` ${e.failedRefreshes===1?"One token request":`${e.failedRefreshes} token requests`} failed first (${e.lastRefreshError}).`:"";return{text:`${c} at ${ne(e.refreshedAt??n)}${s}${l}.${u}`,tone:u?"warn":"good"}}let o=n-e.startedAt,i=(e.staleAfterFailure>0?` It sent the old token again ${e.staleAfterFailure} time${e.staleAfterFailure===1?"":"s"}.`:"")+(e.failedRefreshes>0?` Its token request failed (${e.lastRefreshError}).`:"");if(o>6e4)return{text:`No new token after ${W(o)}. The app may refresh on its next action, or not at all.${i}`,tone:"warn"};if(e.kind==="401")return e.forcedAt===void 0?{text:`The next request to ${t?.host??"the API"} will get a 401. Use the app to send one.`}:{text:`The app got the 401. Waiting for a new token\u2026${i}`,tone:i?"warn":void 0};let a=t?.expiresAt!==void 0?t.expiresAt-r:void 0;return a!==void 0&&a>0?{text:`Expires in ${W(a)} on the app's clock. Waiting for a new token\u2026`}:{text:"Expired on the app's clock. Waiting for the app's next request\u2026"}}var b=X.create({row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:56,paddingHorizontal:x.rowPadH,paddingVertical:10},rowText:{flex:1,minWidth:0},rowTitle:{color:x.color.text,fontSize:x.font.row},rowSubtitle:{color:x.color.textTertiary,fontSize:x.font.caption,marginTop:2},rowRight:{flexDirection:"row",alignItems:"center",gap:6},value:{color:x.color.textSecondary,fontSize:x.font.row,fontVariant:["tabular-nums"]},valueWarning:{color:x.color.warning},valueDanger:{color:x.color.danger},chevronOpen:{transform:[{rotate:"90deg"}]},emptyText:{color:x.color.textSecondary,fontSize:x.font.row},detail:{paddingHorizontal:x.rowPadH,paddingBottom:14,gap:4},detailLine:{color:x.color.textSecondary,fontSize:x.font.caption},buttons:{flexDirection:"row",gap:8,marginTop:8},button:{flex:1},hint:{color:x.color.textTertiary,fontSize:x.font.caption,marginTop:6},proLine:{flexDirection:"row",alignItems:"center",gap:8,marginTop:6},proHint:{marginTop:0,flexShrink:1},check:{flexDirection:"row",alignItems:"flex-start",gap:12,marginTop:8,marginHorizontal:x.labelInset},checkText:{flex:1,color:x.color.textSecondary,fontSize:x.font.caption,lineHeight:18},checkDone:{color:x.color.accent,fontSize:x.font.caption,fontWeight:"600"},good:{color:x.color.accent},warn:{color:x.color.warning},bad:{color:x.color.danger}});import{jsx as d,jsxs as I}from"react/jsx-runtime";var Br="#F59E0B";function Ur({snapshot:e,onAction:t,onReload:r}){let n=ya({minBottom:16}),[o,i]=Ee(null),[a,s]=Ee(null),l=ha()(),[c,u]=Ee(null),f=v=>u(v),g=(v,O)=>{i(null),t(v,O).catch(z=>{i(z instanceof Error?z.message:String(z))})},S=v=>s(O=>O===v?null:v);return e?I(Dt,{style:y.fill,contentContainerStyle:[y.content,{paddingBottom:n.bottom}],testID:"clock-scroll",keyboardShouldPersistTaps:"handled",children:[d(Oa,{snapshot:e}),o?d(m,{testID:"clock-error",children:d(yt,{tone:"danger",centered:true,children:o})}):null,I(m,{children:[d(Mr,{children:"Jump ahead"}),d(Ra,{run:g})]}),I(m,{children:[d(Re,{children:I(gt,{children:[I(m,{children:[d(Vr,{title:"Date & Time",testID:"clock-date-row",open:a==="date",onPress:()=>S("date"),value:d(Da,{snapshot:e})}),a==="date"?d(La,{snapshot:e,run:g,onDone:()=>s(null)}):null]},"date"),I(m,{style:y.row,children:[d(bt,{title:"Freeze",isPro:l}),d(_r,{value:e.mode==="frozen",testID:"clock-freeze",accessibilityLabel:"Freeze the clock",onValueChange:v=>v&&!l?f("Freeze"):g(v?"freeze":"resume")})]},"freeze"),I(m,{children:[d(Vr,{title:"Speed",pro:!l,testID:"clock-speed-row",open:a==="speed",onPress:()=>l?S("speed"):f("Speed"),value:d(w,{style:y.rowValue,children:qr(e)})}),a==="speed"?d(Na,{snapshot:e,run:g}):null]},"speed")]})}),d(yt,{children:"Only this app's clock changes. Screens pick up the new time when they next render, or all at once when you reload."})]}),e.tokens?d(Aa,{snapshot:e,run:g,openId:a,onToggle:S,isPro:l,onUpgrade:f}):null,d(Re,{children:I(gt,{children:[r?d(Wr,{label:"Reload App",testID:"clock-reload",onPress:r},"reload"):null,d(Wr,{label:"Use Real Time",accessibilityLabel:"Reset to real time",testID:"clock-reset",destructive:true,disabled:e.mode==="real",onPress:()=>g("reset")},"reset")]})}),I(m,{children:[d(Mr,{children:"Options"}),d(ja,{settings:e.settings,run:g,isPro:l,onUpgrade:f})]}),d(pa,{visible:c!==null&&!l,onClose:()=>u(null),featureName:c??void 0})]}):d(m,{style:y.waiting,testID:"clock-waiting",children:d(yt,{centered:true,children:"Waiting for the app's clock\u2026"})})}function bt({title:e,isPro:t}){return I(m,{style:y.titleRow,children:[d(w,{style:y.rowTitle,children:e}),t?null:d(fa,{})]})}function Oa({snapshot:e}){let{virtual:t,real:r}=V(e),n=Sr(e),o=e.mode!=="real",i=Gi(t-r),a=e.mode==="frozen"?" \xB7 Frozen":o&&e.rate!==1?` \xB7 ${qr(e)}`:"";return I(m,{style:y.hero,children:[d(w,{style:[y.heroTime,o?y.heroTimeActive:null],testID:"clock-hero-time",accessibilityLabel:`App clock ${ne(t)}`,children:ne(t)}),d(w,{style:y.heroDate,testID:"clock-hero-date",children:Yi(t)}),d(m,{testID:"clock-status",accessibilityLabel:`Clock status: ${n.label}${o?`, ${i}`:""}`,children:d(w,{style:[y.heroStatus,o?y.heroStatusActive:null],testID:"clock-offset",children:o?`${i}${a}`:"Real time"})})]})}var Hr=36e5,kt=24*Hr,Ea=[{ms:Hr,unit:"hour"},{ms:kt,unit:"day"},{ms:7*kt,unit:"week"},{ms:30*kt,unit:"month"}];function Ra({run:e}){return d(Re,{style:y.jumpBar,children:Ea.map((t,r)=>I(B,{testID:Xi(t.ms),accessibilityRole:"button",accessibilityLabel:`Jump ahead one ${t.unit}`,activeOpacity:.6,onPress:()=>e("shift",{by:t.ms}),style:[y.jump,r>0?y.jumpDivider:null],children:[d(w,{style:y.jumpAmount,children:"+1"}),d(w,{style:y.jumpUnit,children:t.unit})]},t.unit))})}function Vr({title:e,pro:t,value:r,open:n,onPress:o,testID:i}){return I(B,{testID:i,accessibilityRole:"button",accessibilityLabel:e,accessibilityState:{expanded:n},activeOpacity:.6,onPress:o,style:y.row,children:[d(bt,{title:e,isPro:!t}),I(m,{style:y.rowRight,children:[r,d(m,{style:n?y.chevronOpen:null,children:d(la,{size:16,color:k.color.textTertiary})})]})]})}function Da({snapshot:e}){let{virtual:t}=V(e,1e3);return d(w,{style:[y.rowValue,y.tabular],numberOfLines:1,children:Ce(t,false)})}function Wr({label:e,onPress:t,testID:r,destructive:n,disabled:o,accessibilityLabel:i}){return d(B,{testID:r,accessibilityRole:"button",accessibilityLabel:i??e,accessibilityState:{disabled:!!o},activeOpacity:.6,disabled:o,onPress:t,style:[y.row,o?y.rowDisabled:null],children:d(w,{style:[y.actionLabel,n?y.actionDestructive:null],children:e})})}var Pa=zt.filter(e=>["midnight","month-end","year-end"].includes(e.id));function La({snapshot:e,run:t,onDone:r}){let[n,o]=Ee(""),{virtual:i}=V(e,1e3),a=()=>n.trim()||Ar(i),s=e.mode==="frozen",l=c=>{t("setTime",{time:c,freeze:s}),r()};return I(m,{style:y.editor,children:[I(m,{style:y.inputRow,children:[d(Rt,{testID:"clock-time-input",accessibilityLabel:"Date and time",value:n,onChangeText:o,placeholder:Ar(i),placeholderTextColor:k.color.placeholder,autoCapitalize:"none",autoCorrect:false,returnKeyType:"done",onSubmitEditing:()=>l(a()),style:y.input}),d(ua,{label:"Set",testID:"clock-time-apply",accessibilityLabel:"Set this time",size:"md",variant:"primary",fullWidth:false,onPress:()=>l(a())})]}),d(w,{style:y.hint,children:"Year-month-day and 24-hour time, or +3d, -2h"}),d(m,{style:y.presets,children:Pa.map(c=>d(ca,{label:c.label,testID:`clock-preset-${c.id}`,onPress:()=>l(c.at(i,T))},c.id))})]})}var Jr=[{key:"1",label:"Normal"},{key:"10",label:"10\xD7"},{key:"60",label:"1 min/s"},{key:"3600",label:"1 hr/s"}];function qr(e){return e.mode==="real"||e.rate===1?"Normal":Jr.find(t=>Number(t.key)===e.rate)?.label??jt(e.rate)}function Na({snapshot:e,run:t}){let r=e.mode==="real"?"1":String(e.rate);return I(m,{style:y.editor,children:[d(m,{style:y.segmentRow,children:d(da,{tabs:Jr,activeKey:r,size:"sm",testIDPrefix:"clock-speed",onChange:n=>t("setRate",{rate:Number(n)})})}),d(w,{style:y.hint,children:"Taps, animations and timers keep real speed."})]})}var za=[{key:"showChip",title:"Show Floating Clock"},{key:"persist",title:"Keep After Reload",pro:true}];function ja({settings:e,run:t,isPro:r,onUpgrade:n}){return d(Re,{children:d(gt,{children:za.map(o=>{let i=!!o.pro&&!r;return I(m,{style:y.row,children:[d(bt,{title:o.title,isPro:!i}),d(_r,{value:i?false:e[o.key],testID:`clock-setting-${o.key}`,accessibilityLabel:o.title,onValueChange:a=>i?n(o.title):t("updateSettings",{[o.key]:a})})]},o.key)})})})}var y=X.create({fill:{flex:1},content:{paddingHorizontal:k.gutter,paddingTop:8,gap:k.groupGap},waiting:{flex:1,alignItems:"center",justifyContent:"center",padding:24},hero:{alignItems:"center",paddingTop:12},heroTime:{color:k.color.text,fontSize:56,fontWeight:"200",fontVariant:["tabular-nums"],letterSpacing:1},heroTimeActive:{color:Br},heroDate:{color:k.color.text,fontSize:17,fontWeight:"500",marginTop:2},heroStatus:{color:k.color.textTertiary,fontSize:k.font.caption,fontWeight:"500",marginTop:6},heroStatusActive:{color:k.color.textSecondary},jumpBar:{flexDirection:"row"},jump:{flex:1,alignItems:"center",paddingVertical:12},jumpDivider:{borderLeftWidth:X.hairlineWidth,borderLeftColor:k.color.separator},jumpAmount:{color:Br,fontSize:17,fontWeight:"600",fontVariant:["tabular-nums"]},jumpUnit:{color:k.color.textSecondary,fontSize:k.font.caption,marginTop:1},row:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:12,minHeight:50,paddingHorizontal:k.rowPadH,paddingVertical:10},rowDisabled:{opacity:.4},rowTitle:{color:k.color.text,fontSize:k.font.row},titleRow:{flexDirection:"row",alignItems:"center",gap:8,flexShrink:1},rowRight:{flexDirection:"row",alignItems:"center",gap:6,flexShrink:1},rowValue:{color:k.color.textSecondary,fontSize:k.font.row},tabular:{fontVariant:["tabular-nums"]},chevronOpen:{transform:[{rotate:"90deg"}]},actionLabel:{color:k.color.accent,fontSize:k.font.row},actionDestructive:{color:k.color.danger},editor:{paddingHorizontal:k.rowPadH,paddingBottom:14,gap:10},inputRow:{flexDirection:"row",alignItems:"center",gap:8},input:{flex:1,color:k.color.text,fontFamily:ma,fontSize:15,backgroundColor:k.color.bg,borderRadius:k.radius.input,borderWidth:1,borderColor:k.color.border,paddingHorizontal:12,paddingVertical:8},hint:{color:k.color.textTertiary,fontSize:k.font.caption},presets:{flexDirection:"row",flexWrap:"wrap",gap:6},segmentRow:{flexDirection:"row"}});import{jsx as Ma}from"react/jsx-runtime";var _a=jr.actions;async function Fa(e,t){let r=_a[e];if(!r)throw new Error(`Unknown clock action: ${e}`);return r(t)}function Ba(){fr().then(()=>aa("auto","buoy clock")).catch(()=>{})}function Kr(){Or(()=>{pt(),Te()},[]);let[e,t]=ia(C);return Or(()=>pe(()=>t(C())),[]),Ma(Ur,{snapshot:e,onAction:Fa,onReload:Ba})}import{jsx as Ua}from"react/jsx-runtime";var Zr=oa({id:"clock",name:"CLOCK",description:"Travel to any date, freeze or speed up the app's clock",slot:"both",color:ra,icon:({size:e,color:t})=>Ua(ta,{size:e,color:t}),component:Kr,modal:{subtitle:"override the app's date & time"}}),Ha=na(Zr);import{ClockToolIcon as Va,CLOCK_TOOL_ICON_COLOR as Wa}from"@buoy-gg/shared-ui/web";var Ja=typeof navigator<"u"&&navigator.product==="ReactNative",qa=(()=>{try{return globalThis.Capacitor?.isNativePlatform?.()===true}catch{return false}})();Ja||qa?(Eo(Et),Ir(),typeof St<"u"&&St&&pt()):typeof globalThis.document<"u"&&Ir();export{Oe as CLOCK_CHIP_ID,Wa as CLOCK_TOOL_ICON_COLOR,Kr as ClockBody,Cr as ClockChip,Va as ClockToolIcon,Ur as ClockToolView,zt as TIME_PRESETS,pt as bootClock,jr as clockSyncAdapter,Zr as clockToolPreset,Ha as createClockTool,Lr as failNextRequest,ie as formatDuration,ct as freeze,C as getClockSnapshot,$e as getTokenReport,xe as inspectToken,dr as isClockOverridden,Pr as jumpToTokenExpiry,ea as openClockChip,_e as parseDuration,ji as previewJump,$ as realNow,ft as reset,dt as resume,mr as setRate,hr as setTime,ut as shift,Te as startTokenWatch,zr as stopTokenCheck,pe as subscribeClock,H as tokenFingerprint,yr as updateSettings,V as useLiveClock,cr as virtualNow,He as withRealClock};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/clock",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.75",
|
|
4
4
|
"description": "Clock override for React Native: travel to any date, freeze or speed up time, and jump ahead while firing due timers. Test expirations, countdowns and renewals without touching the device clock.",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
"./lib/web/**/*.mjs"
|
|
18
18
|
],
|
|
19
19
|
"dependencies": {
|
|
20
|
-
"@buoy-gg/shared-ui": "^7.0.
|
|
20
|
+
"@buoy-gg/shared-ui": "^7.0.75"
|
|
21
21
|
},
|
|
22
22
|
"peerDependencies": {
|
|
23
23
|
"react": "*"
|