@buoy-gg/license 7.0.85 → 7.0.86
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/LicenseManager.js +1 -1
- package/lib/commonjs/config.js +2 -2
- package/lib/module/LicenseManager.js +1 -1
- package/lib/module/config.js +1 -1
- package/lib/typescript/commonjs/LicenseManager.d.ts +13 -0
- package/lib/typescript/commonjs/config.d.ts +2 -0
- package/lib/typescript/commonjs/types.d.ts +5 -0
- package/lib/typescript/module/LicenseManager.d.ts +13 -0
- package/lib/typescript/module/config.d.ts +2 -0
- package/lib/typescript/module/types.d.ts +5 -0
- package/lib/web/chunks/LicenseManager-QVQA7ZAE.mjs +1 -0
- package/lib/web/chunks/chunk-ISATKL5M.mjs +73 -0
- package/lib/web/index.mjs +1 -1
- package/package.json +1 -1
- package/lib/web/chunks/LicenseManager-KXCX4GG2.mjs +0 -1
- package/lib/web/chunks/chunk-U4JDBLRG.mjs +0 -73
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
14
14
|
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
15
15
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
16
|
-
*/const NO_TEAM_ACCESS={role:null,tools:null};function teamAccessOf(h){return{role:h.role??null,tools:h.tools??null}}async function boundedStorage(h,t){let e;try{return await Promise.race([h,new Promise(i=>{e=setTimeout(()=>i(t),15e3)})])}finally{if(e)clearTimeout(e)}}function tierOfCache(h){if(h.tier==="pro"||h.tier==="free")return h.tier;return h.isPro?"pro":"free"}class LicenseManagerImpl{state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,error:null,errorKind:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;fingerprintRestored=false;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=null;devToken=null;retryTimer=null;retryAttempt=0;deviceRegistrationCallback=null;pendingRegistration=null;async initialize(){if(this.initPromise)return this.initPromise;if(this.state.isInitialized)return;this.initPromise=this._doInitialize();return this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;const t=this.generation;if(!this.sessionUnsubscribe){this.sessionUnsubscribe=_sessionManager.SessionManager.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))}await boundedStorage(_sessionManager.SessionManager.load().catch(()=>void 0),void 0);try{const e=await boundedStorage(this.loadCachedLicense(),null);if(t!==this.generation){this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer();return}if(e&&(this.configuredKey===void 0||e.licenseKey===this.configuredKey)){const i=(0,_cacheSignature.verifyCacheSignature)(e);this.cachedLicense=e;this.state.licenseKey=e.licenseKey;if(i&&this.isCacheValid(e))this.applyTier(tierOfCache(e));else this.lock();this.state.expiresAt=e.expiresAt?new Date(e.expiresAt):null;if(i&&this.isCacheValid(e))this.setVerifiedAt(e.cachedAt);if(this.configuredKey===void 0&&e.licenseKey&&!(i&&this.isCacheValid(e)&&this.isCacheFresh(e))){this.validateInBackground(e.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(e){console.warn("[Buoy]","[React Buoy] License initialization failed:",e);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async configure(t){if(t===void 0){await this.initialize();return this.hasAccountAccess()}const e=(0,_serviceKey.normalizeLicenseKey)(t);const i=++this.generation;this.cancelRetry();this.configuredKey=e||null;if(this.state.licenseKey!==this.configuredKey)this.lock();this.state.licenseKey=this.configuredKey;this.state.isValidating=!!e;this.emit({type:"validating",isPro:this.isPro()});await this.initialize();if(i!==this.generation)return false;if(!e){await this.clearLicense();return false}return this.setLicenseKey(e)}async setLicenseKey(t,e){if(!t||t.trim().length===0){this.state.error="License key is required";this.state.errorKind="verdict";return false}const i=(0,_serviceKey.normalizeLicenseKey)(t);const s=++this.generation;this.cancelRetry();if(!e?.isRetry)this.retryAttempt=0;if(this.state.licenseKey!==i)this.lock();this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.state.errorKind=null;this.emit({type:"validating",isPro:this.isPro()});if((0,_freeToken.isBuoyToken)(i))return this.admitToken(i,s);if((0,_serviceKey.isServiceKey)(i))return this.admitServiceKey(i,s);if((0,_devToken.isDevToken)(i))return this.admitDevToken(i);if(!this.cachedLicense){const a=await boundedStorage(this.loadCachedLicense(),null);if(s!==this.generation)return false;if(a?.licenseKey===i){this.cachedLicense=a;if((0,_cacheSignature.verifyCacheSignature)(a)&&this.isCacheValid(a)){this.applyTier(tierOfCache(a));this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.setVerifiedAt(a.cachedAt);this.emit({type:"validating",isPro:this.isPro()})}}}const r=this.cachedLicense;if(!e?.force&&r&&r.valid&&r.licenseKey===i&&r.fingerprint&&(0,_cacheSignature.verifyCacheSignature)(r)&&this.isCacheValid(r)&&this.isCacheFresh(r)){this.applyTier(tierOfCache(r));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);this.emit({type:"validated",isPro:this.state.isPro});return true}const n=await boundedStorage(this.loadHold(),null);if(s!==this.generation)return false;const u=(n?.backoffUntil??0)-(0,_realNow.realNow)();if(u>0){return this.standDown(i,s,"License server is rate limited; retrying later.",u)}if(!e?.force&&n?.key===i&&n.verdictAt!==void 0&&(0,_realNow.realNow)()-n.verdictAt>=0&&(0,_realNow.realNow)()-n.verdictAt<_config.LICENSE_VERDICT_CACHE_DURATION){this.lock();this.state.isValidating=false;this.state.error=n.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let c;try{c=await(0,_api.validateLicense)(i)}catch(a){const o=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if((0,_api.isTransientLicenseError)(a)){if((0,_api.isRateLimited)(a)){const l=Math.min((0,_api.backoffAfter)(a,_config.LICENSE_QUOTA_COOLDOWN,_config.LICENSE_RATE_LIMIT_DEFAULT_WAIT)*2**this.retryAttempt,_config.LICENSE_QUOTA_COOLDOWN);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:(0,_realNow.realNow)()+l});if(s!==this.generation)return false;return this.standDown(i,s,o,l)}this.state.isValidating=false;if(this.cachedLicense&&this.cachedLicense.licenseKey===i&&(0,_cacheSignature.verifyCacheSignature)(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)){this.applyTier(tierOfCache(this.cachedLicense));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null;this.setVerifiedAt(this.cachedLicense.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetry(i);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=o;this.state.errorKind="transport";this.scheduleRetry(i);this.emit({type:"error",isPro:this.state.isPro,error:o});return false}this.state.isValidating=false;this.state.error=o;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:o});return false}try{if(s!==this.generation)return false;const a=(0,_api.parseValidationResult)(c);const o=c.data?.relationships?.product?.data?.id;if((!o||o===_config.KEYGEN_CONFIG.productId)&&a.code==="EXPIRED"&&((0,_tier.isRecognizedAccount)(c.data)||this.cachedLicense?.licenseKey===i&&(0,_cacheSignature.verifyCacheSignature)(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const E=(0,_realNow.realNow)();const L=await this.saveCache({licenseKey:i,licenseId:c.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:E,lastValidatedAt:E,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},s);if(s!==this.generation||!L)return false;this.cachedLicense=L;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(E);this.emit({type:"validated",isPro:false});return true}if((0,_api.isFatalLicenseError)(a.code)||!(0,_api.isAcceptedValidation)(c)){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:(0,_realNow.realNow)()});return false}if(!c.data){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License not found";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const l=(0,_tier.resolveTier)(c.data);const g=c.data.id;const _=(0,_realNow.realNow)();const v=(0,_api.machineCount)(c)>=_config.LICENSE_FLEET_MACHINE_THRESHOLD;const m=(0,_fingerprint.isDevBundle)();const I=m&&!v;const R=l==="free"&&(v||!m);let d=this.cachedLicense?.fingerprint;let f=this.cachedLicense?.deviceName;let A=false;if(!d){d=await boundedStorage(this.getOrCreateDeviceFingerprint(),(0,_fingerprint.generateUUID)());if(s!==this.generation)return false;f=(0,_fingerprint.getDefaultDeviceName)();A=I}let y=false;if(A){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:g,licenseKey:i,fingerprint:d};this.deviceRegistrationCallback({fingerprint:d,defaultName:f});y=true}else{this.registerDeviceAsync(g,i,d,f)}}const p={licenseKey:i,licenseId:g,valid:true,isPro:l==="pro",tier:l,expiresAt:c.data.attributes.expiry??null,cachedAt:_,lastValidatedAt:_,fingerprint:y?void 0:d,deviceName:y?void 0:f,quiet:R||void 0};const T=await this.saveCache(p,s);if(s!==this.generation||!T)return false;this.cachedLicense=T;this.applyTier(l);this.state.isValidating=false;this.state.expiresAt=p.expiresAt?new Date(p.expiresAt):null;this.setVerifiedAt(_);if(this.hold)await this.saveHold(null);if(s!==this.generation)return false;this.retryAttempt=0;this.emit({type:"validated",isPro:this.state.isPro});return true}catch(a){const o=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;this.state.isValidating=false;this.state.error=o;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:o});return false}}scheduleRetry(t){this.cancelRetry();const e=_config.LICENSE_TRANSIENT_RETRY_DELAYS[this.retryAttempt];if(e===void 0)return;this.retryAttempt+=1;const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(t,{force:true,isRetry:true})},e);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}}async admitServiceKey(t,e){const i=await(0,_serviceKey.exchangeServiceKey)(t,{origin:_sessionManager.SessionManager.origin});if(e!==this.generation)return false;if(!i.ok){this.lock();this.state.isValidating=false;this.state.error=i.detail;this.state.errorKind=i.reason==="network"?"transport":"verdict";this.emit({type:"error",isPro:false,error:i.detail});if(i.reason==="network")this.scheduleRetry(t);return false}const s=i.claims.exp*1e3;this.applyTier(i.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(s);this.setVerifiedAt((0,_realNow.realNow)());this.retryAttempt=0;this.scheduleRetryIn(t,Math.max(6e4,s-60*60*1e3-(0,_realNow.realNow)()));this.emit({type:"validated",isPro:this.isPro()});return true}admitDevToken(t){const e=(0,_devToken.checkDevToken)(t);if(!e.ok||!(0,_fingerprint.isDevBundle)()){const s=e.ok?_devToken.DEV_TOKEN_IN_RELEASE:e.message;this.lock();this.state.isValidating=false;this.state.error=s;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:s});return false}const i=(0,_realNow.realNow)();this.devToken={token:t,claims:e.claims};this.applyTier(e.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(e.claims.exp*1e3);this.setVerifiedAt(Math.min(i,e.claims.iat*1e3));this.retryAttempt=0;this.emit({type:"validated",isPro:this.isPro()});return true}async admitToken(t,e){const i=(0,_freeToken.verifyFreeToken)(t);if(e!==this.generation)return false;if(!i){this.lock();this.state.isValidating=false;this.state.error="This key is not valid. Check that it was copied completely.";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const s=(0,_realNow.realNow)();const r=this.cachedLicense?.fingerprint??await boundedStorage(this.getOrCreateDeviceFingerprint(),(0,_fingerprint.generateUUID)());if(e!==this.generation)return false;const n=await this.saveCache({licenseKey:t,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:s,lastValidatedAt:s,fingerprint:r,deviceName:this.cachedLicense?.deviceName??(0,_fingerprint.getDefaultDeviceName)(),quiet:true},e);if(e!==this.generation||!n)return false;this.cachedLicense=n;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(s);this.retryAttempt=0;this.emit({type:"validated",isPro:false});return true}standDown(t,e,i,s){if(e!==this.generation)return false;this.state.isValidating=false;const r=this.cachedLicense;if(r&&r.licenseKey===t&&(0,_cacheSignature.verifyCacheSignature)(r)&&this.isCacheValid(r)){this.applyTier(tierOfCache(r));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetryIn(t,s);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=i;this.state.errorKind="transport";this.scheduleRetryIn(t,s);this.emit({type:"error",isPro:this.state.isPro,error:i});return false}scheduleRetryIn(t,e){this.cancelRetry();const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(t,{force:true,isRetry:true})},Math.max(1,Math.min(e,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}cancelRetry(){if(this.retryTimer){clearTimeout(this.retryTimer);this.retryTimer=null}}async clearLicense(){this.generation+=1;this.cancelRetry();this.retryAttempt=0;this.configuredKey=null;this.state.licenseKey=null;this.lock();this.state.expiresAt=null;this.state.error=null;this.state.errorKind=null;this.cachedLicense=null;this.pendingRegistration=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:false});await this.clearCachedLicense();if(this.hold?.verdictAt!==void 0){await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}}applyTier(t){this.state.tier=t;this.state.tierSource="key";this.state.isPro=t==="pro"}lock(){this.state.tier="free";this.state.tierSource="none";this.state.isPro=false;this.verifiedAt=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null}getTier(){return this.credential().tier}credential(){const t=this.keyTier();const e=this.sessionTier();if(e!==null&&(!this.hasKeyAccess()||e==="pro"&&t!=="pro")){return{source:"session",tier:e}}return{source:this.state.tierSource,tier:t}}keyTier(){if(!this.hasKeyAccess())return"free";if(this.state.expiresAt&&(0,_realNow.realNow)()>=this.state.expiresAt.getTime())return"free";return this.state.tier}sessionTier(){const t=_sessionManager.SessionManager.getStatus();if(t.state!=="active")return null;return t.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(t){return this.isPro()}getState(){const{source:t,tier:e}=this.credential();const i=this.getTeamAccess();return{...this.state,tier:e,tierSource:t,isPro:e==="pro",access:this.getAccountAccess(),teamRole:i.role,allowedTools:i.tools}}getTeamAccess(){const t=_sessionManager.SessionManager.getStatus();if(t.state==="active")return teamAccessOf(t.claims);const e=this.devToken;if(e&&e.token===this.state.licenseKey&&this.state.tierSource==="key"&&(0,_realNow.realNow)()<e.claims.exp*1e3&&this.hasKeyAccess()){return teamAccessOf(e.claims)}return NO_TEAM_ACCESS}getAccountAccess(){const t=this.getKeyAccess();if(t.status==="admitted")return t;const e=_sessionManager.SessionManager.getStatus();if(e.state==="active")return{status:"admitted",reason:null,validUntil:e.validUntil};return t}getKeyAccess(){return(0,_accountAccess.resolveAccountAccess)({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}hasKeyAccess(){return this.getKeyAccess().status==="admitted"}setVerifiedAt(t){this.verifiedAt=t;if(this.expiryTimer)clearTimeout(this.expiryTimer);const e=t+_config.LICENSE_CACHE_DURATION;const i=this.state.expiresAt?.getTime();const s=i&&i>(0,_realNow.realNow)()?Math.min(e,i):e;const r=s-(0,_realNow.realNow)();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==t)return;this.emit({type:"validated",isPro:this.isPro()});if((0,_realNow.realNow)()<e)this.setVerifiedAt(t)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer}subscribe(t){this.listeners.add(t);return()=>this.listeners.delete(t)}onDeviceRegistrationNeeded(t){this.deviceRegistrationCallback=t;return()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(t){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}const{licenseId:e,licenseKey:i,fingerprint:s}=this.pendingRegistration;const r=this.generation;const n=t.trim()||(0,_fingerprint.getDefaultDeviceName)();const u=(0,_fingerprint.getDeviceMetadata)();try{await(0,_api.activateMachine)(e,i,s,n,u)}catch(c){const a=c instanceof Error?c.message:String(c);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw c}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const c=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:n},r);if(r!==this.generation)return;if(c)this.cachedLicense=c}this.pendingRegistration=null}emit(t){const e=[...this.listeners];e.forEach(i=>{try{i(t)}catch(s){console.warn("[Buoy]","[React Buoy] License listener error:",s)}})}isCacheValid(t){const e=(0,_realNow.realNow)();const i=e-t.cachedAt;if(!t.valid||!Number.isFinite(t.cachedAt)||i<0||i>=_config.LICENSE_CACHE_DURATION){return false}return true}isCacheFresh(t){const e=this.isQuiet(t)?_config.LICENSE_QUIET_VALIDATION_TTL:_config.LICENSE_LAUNCH_VALIDATION_TTL;return(0,_realNow.realNow)()-(t.lastValidatedAt??0)<e}isQuiet(t){if(t.quiet!==void 0)return t.quiet;return tierOfCache(t)==="free"&&!(0,_fingerprint.isDevBundle)()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const t=await(0,_storage.getLicenseStorage)();const e=await t.getItem(_config.LICENSE_HOLD_STORAGE_KEY);const i=e?JSON.parse(e):null;this.hold=i&&typeof i==="object"?i:null}catch{this.hold=null}return this.hold}async saveHold(t){this.hold=t;try{const e=await(0,_storage.getLicenseStorage)();if(t)await e.setItem(_config.LICENSE_HOLD_STORAGE_KEY,JSON.stringify(t));else await e.removeItem(_config.LICENSE_HOLD_STORAGE_KEY)}catch{}}async persistCache(t){const e=(0,_cacheSignature.signCache)(t);const i=await(0,_storage.getLicenseStorage)();await i.setItem(_config.LICENSE_STORAGE_KEY,JSON.stringify(e));return e}saveCache(t,e){const i=this.persistence.catch(()=>{}).then(async()=>{if(e!==this.generation)return null;const s=await this.persistCache(t);return e===this.generation?s:null});this.persistence=i;return boundedStorage(i,(0,_cacheSignature.signCache)(t))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const t=await(0,_storage.getLicenseStorage)();const e=await t.getItem(_config.LICENSE_STORAGE_KEY);if(!e)return null;const i=JSON.parse(e);if(i.fingerprint){const s=await boundedStorage(this.getOrCreateDeviceFingerprint(i.fingerprint).catch(()=>null),null);if(s&&this.fingerprintRestored&&i.fingerprint!==s){return{...i,fingerprint:void 0,deviceName:void 0}}}return i}catch(t){console.warn("[Buoy] Error loading cached license:",t);return null}}getOrCreateDeviceFingerprint(t){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await(0,_storage.getLicenseStorage)();const i=await e.getItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY);const s=await e.getItem(_config.DEVICE_FINGERPRINT_OWNER_STORAGE_KEY);const r=await boundedStorage((0,_fingerprint.getDeviceOwnerId)().catch(()=>null),null);const n=(0,_fingerprintOwner.resolveDeviceFingerprint)({stored:i,storedOwner:s,marker:r?(0,_fingerprintOwner.hashDeviceMarker)(r):null,blobFingerprint:t??this.cachedLicense?.fingerprint,mint:_fingerprint.generateUUID});this.fingerprintRestored=n.restored;if(n.changed){await e.setItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY,n.fingerprint);if(n.owner)await e.setItem(_config.DEVICE_FINGERPRINT_OWNER_STORAGE_KEY,n.owner)}return n.fingerprint})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;const t=this.persistence.catch(()=>{}).then(async()=>{const e=await(0,_storage.getLicenseStorage)();await e.removeItem(_config.LICENSE_STORAGE_KEY)});this.persistence=t;await boundedStorage(t.catch(()=>{}),void 0)}registerDeviceAsync(t,e,i,s){const r=(0,_fingerprint.getDeviceMetadata)();(0,_api.activateMachine)(t,e,i,s,r).catch(n=>{if(n.message!=="FINGERPRINT_TAKEN"&&n.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",n.message)}})}validateInBackground(t){void this.setLicenseKey(t,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){if(!this.removeForegroundListener){this.removeForegroundListener=(0,_foreground.subscribeForeground)(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener}if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;const t=this.cachedLicense;if(t&&t.licenseKey===this.state.licenseKey&&this.isCacheFresh(t))return;this.validateInBackground(this.state.licenseKey)},_config.LICENSE_REVALIDATION_INTERVAL);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){this.removeForegroundListener?.();this.removeForegroundListener=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null;if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}this.cancelRetry()}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}this.fingerprintPromise=null;await this.clearCachedLicense();try{const t=await(0,_storage.getLicenseStorage)();await t.removeItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY)}catch{}}}const LicenseManager=exports.LicenseManager=new LicenseManagerImpl;const devTimers=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__?.();devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__);if(devTimers.__LICENSE_MANAGER_TIMER__){clearInterval(devTimers.__LICENSE_MANAGER_TIMER__)}if(devTimers.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(devTimers.__LICENSE_MANAGER_RETRY_TIMER__);devTimers.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
|
|
16
|
+
*/const NO_TEAM_ACCESS={role:null,tools:null};function teamAccessOf(h){return{role:h.role??null,tools:h.tools??null}}async function boundedStorage(h,e){let t;try{return await Promise.race([h,new Promise(i=>{t=setTimeout(()=>i(e),15e3)})])}finally{if(t)clearTimeout(t)}}function tierOfCache(h){if(h.tier==="pro"||h.tier==="free")return h.tier;return h.isPro?"pro":"free"}class LicenseManagerImpl{state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,keySignedOut:false,error:null,errorKind:null,expiresAt:null};signedOutKey=null;listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;fingerprintRestored=false;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=null;devToken=null;retryTimer=null;retryAttempt=0;deviceRegistrationCallback=null;pendingRegistration=null;async initialize(){if(this.initPromise)return this.initPromise;if(this.state.isInitialized)return;this.initPromise=this._doInitialize();return this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;const e=this.generation;if(!this.sessionUnsubscribe){this.sessionUnsubscribe=_sessionManager.SessionManager.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))}await boundedStorage(_sessionManager.SessionManager.load().catch(()=>void 0),void 0);try{await boundedStorage(this.loadSignedOutKey(),void 0);const t=await boundedStorage(this.loadCachedLicense(),null);if(e!==this.generation){this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer();return}if(t&&t.licenseKey!==this.signedOutKey&&(this.configuredKey===void 0||t.licenseKey===this.configuredKey)){const i=(0,_cacheSignature.verifyCacheSignature)(t);this.cachedLicense=t;this.state.licenseKey=t.licenseKey;if(i&&this.isCacheValid(t))this.applyTier(tierOfCache(t));else this.lock();this.state.expiresAt=t.expiresAt?new Date(t.expiresAt):null;if(i&&this.isCacheValid(t))this.setVerifiedAt(t.cachedAt);if(this.configuredKey===void 0&&t.licenseKey&&!(i&&this.isCacheValid(t)&&this.isCacheFresh(t))){this.validateInBackground(t.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(t){console.warn("[Buoy]","[React Buoy] License initialization failed:",t);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async configure(e){if(e===void 0){await this.initialize();return this.hasAccountAccess()}const t=(0,_serviceKey.normalizeLicenseKey)(e);const i=++this.generation;this.cancelRetry();this.configuredKey=t||null;if(this.state.licenseKey!==this.configuredKey)this.lock();this.state.licenseKey=this.configuredKey;this.state.isValidating=!!t;this.emit({type:"validating",isPro:this.isPro()});await this.initialize();if(i!==this.generation)return false;if(!t){this.forgetSignedOutKey();await this.clearLicense();return false}if(t===this.signedOutKey){this.configuredKey=null;this.state.licenseKey=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:this.isPro()});return false}return this.setLicenseKey(t)}async setLicenseKey(e,t){if(!e||e.trim().length===0){this.state.error="License key is required";this.state.errorKind="verdict";return false}const i=(0,_serviceKey.normalizeLicenseKey)(e);this.forgetSignedOutKey();const s=++this.generation;this.cancelRetry();if(!t?.isRetry)this.retryAttempt=0;if(this.state.licenseKey!==i)this.lock();this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.state.errorKind=null;this.emit({type:"validating",isPro:this.isPro()});if((0,_freeToken.isBuoyToken)(i))return this.admitToken(i,s);if((0,_serviceKey.isServiceKey)(i))return this.admitServiceKey(i,s);if((0,_devToken.isDevToken)(i))return this.admitDevToken(i);if(!this.cachedLicense){const a=await boundedStorage(this.loadCachedLicense(),null);if(s!==this.generation)return false;if(a?.licenseKey===i){this.cachedLicense=a;if((0,_cacheSignature.verifyCacheSignature)(a)&&this.isCacheValid(a)){this.applyTier(tierOfCache(a));this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.setVerifiedAt(a.cachedAt);this.emit({type:"validating",isPro:this.isPro()})}}}const r=this.cachedLicense;if(!t?.force&&r&&r.valid&&r.licenseKey===i&&r.fingerprint&&(0,_cacheSignature.verifyCacheSignature)(r)&&this.isCacheValid(r)&&this.isCacheFresh(r)){this.applyTier(tierOfCache(r));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);this.emit({type:"validated",isPro:this.state.isPro});return true}const n=await boundedStorage(this.loadHold(),null);if(s!==this.generation)return false;const u=(n?.backoffUntil??0)-(0,_realNow.realNow)();if(u>0){return this.standDown(i,s,"License server is rate limited; retrying later.",u)}if(!t?.force&&n?.key===i&&n.verdictAt!==void 0&&(0,_realNow.realNow)()-n.verdictAt>=0&&(0,_realNow.realNow)()-n.verdictAt<_config.LICENSE_VERDICT_CACHE_DURATION){this.lock();this.state.isValidating=false;this.state.error=n.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let c;try{c=await(0,_api.validateLicense)(i)}catch(a){const o=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if((0,_api.isTransientLicenseError)(a)){if((0,_api.isRateLimited)(a)){const l=Math.min((0,_api.backoffAfter)(a,_config.LICENSE_QUOTA_COOLDOWN,_config.LICENSE_RATE_LIMIT_DEFAULT_WAIT)*2**this.retryAttempt,_config.LICENSE_QUOTA_COOLDOWN);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:(0,_realNow.realNow)()+l});if(s!==this.generation)return false;return this.standDown(i,s,o,l)}this.state.isValidating=false;if(this.cachedLicense&&this.cachedLicense.licenseKey===i&&(0,_cacheSignature.verifyCacheSignature)(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)){this.applyTier(tierOfCache(this.cachedLicense));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null;this.setVerifiedAt(this.cachedLicense.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetry(i);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=o;this.state.errorKind="transport";this.scheduleRetry(i);this.emit({type:"error",isPro:this.state.isPro,error:o});return false}this.state.isValidating=false;this.state.error=o;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:o});return false}try{if(s!==this.generation)return false;const a=(0,_api.parseValidationResult)(c);const o=c.data?.relationships?.product?.data?.id;if((!o||o===_config.KEYGEN_CONFIG.productId)&&a.code==="EXPIRED"&&((0,_tier.isRecognizedAccount)(c.data)||this.cachedLicense?.licenseKey===i&&(0,_cacheSignature.verifyCacheSignature)(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const p=(0,_realNow.realNow)();const I=await this.saveCache({licenseKey:i,licenseId:c.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:p,lastValidatedAt:p,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},s);if(s!==this.generation||!I)return false;this.cachedLicense=I;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(p);this.emit({type:"validated",isPro:false});return true}if((0,_api.isFatalLicenseError)(a.code)||!(0,_api.isAcceptedValidation)(c)){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:(0,_realNow.realNow)()});return false}if(!c.data){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License not found";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const l=(0,_tier.resolveTier)(c.data);const g=c.data.id;const y=(0,_realNow.realNow)();const m=(0,_api.machineCount)(c)>=_config.LICENSE_FLEET_MACHINE_THRESHOLD;const v=(0,_fingerprint.isDevBundle)();const L=v&&!m;const R=l==="free"&&(m||!v);let d=this.cachedLicense?.fingerprint;let f=this.cachedLicense?.deviceName;let A=false;if(!d){d=await boundedStorage(this.getOrCreateDeviceFingerprint(),(0,_fingerprint.generateUUID)());if(s!==this.generation)return false;f=(0,_fingerprint.getDefaultDeviceName)();A=L}let _=false;if(A){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:g,licenseKey:i,fingerprint:d};this.deviceRegistrationCallback({fingerprint:d,defaultName:f});_=true}else{this.registerDeviceAsync(g,i,d,f)}}const E={licenseKey:i,licenseId:g,valid:true,isPro:l==="pro",tier:l,expiresAt:c.data.attributes.expiry??null,cachedAt:y,lastValidatedAt:y,fingerprint:_?void 0:d,deviceName:_?void 0:f,quiet:R||void 0};const T=await this.saveCache(E,s);if(s!==this.generation||!T)return false;this.cachedLicense=T;this.applyTier(l);this.state.isValidating=false;this.state.expiresAt=E.expiresAt?new Date(E.expiresAt):null;this.setVerifiedAt(y);if(this.hold)await this.saveHold(null);if(s!==this.generation)return false;this.retryAttempt=0;this.emit({type:"validated",isPro:this.state.isPro});return true}catch(a){const o=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;this.state.isValidating=false;this.state.error=o;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:o});return false}}scheduleRetry(e){this.cancelRetry();const t=_config.LICENSE_TRANSIENT_RETRY_DELAYS[this.retryAttempt];if(t===void 0)return;this.retryAttempt+=1;const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},t);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}}async admitServiceKey(e,t){const i=await(0,_serviceKey.exchangeServiceKey)(e,{origin:_sessionManager.SessionManager.origin});if(t!==this.generation)return false;if(!i.ok){this.lock();this.state.isValidating=false;this.state.error=i.detail;this.state.errorKind=i.reason==="network"?"transport":"verdict";this.emit({type:"error",isPro:false,error:i.detail});if(i.reason==="network")this.scheduleRetry(e);return false}const s=i.claims.exp*1e3;this.applyTier(i.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(s);this.setVerifiedAt((0,_realNow.realNow)());this.retryAttempt=0;this.scheduleRetryIn(e,Math.max(6e4,s-60*60*1e3-(0,_realNow.realNow)()));this.emit({type:"validated",isPro:this.isPro()});return true}admitDevToken(e){const t=(0,_devToken.checkDevToken)(e);if(!t.ok||!(0,_fingerprint.isDevBundle)()){const s=t.ok?_devToken.DEV_TOKEN_IN_RELEASE:t.message;this.lock();this.state.isValidating=false;this.state.error=s;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:s});return false}const i=(0,_realNow.realNow)();this.devToken={token:e,claims:t.claims};this.applyTier(t.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(t.claims.exp*1e3);this.setVerifiedAt(Math.min(i,t.claims.iat*1e3));this.retryAttempt=0;this.emit({type:"validated",isPro:this.isPro()});return true}async admitToken(e,t){const i=(0,_freeToken.verifyFreeToken)(e);if(t!==this.generation)return false;if(!i){this.lock();this.state.isValidating=false;this.state.error="This key is not valid. Check that it was copied completely.";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const s=(0,_realNow.realNow)();const r=this.cachedLicense?.fingerprint??await boundedStorage(this.getOrCreateDeviceFingerprint(),(0,_fingerprint.generateUUID)());if(t!==this.generation)return false;const n=await this.saveCache({licenseKey:e,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:s,lastValidatedAt:s,fingerprint:r,deviceName:this.cachedLicense?.deviceName??(0,_fingerprint.getDefaultDeviceName)(),quiet:true},t);if(t!==this.generation||!n)return false;this.cachedLicense=n;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(s);this.retryAttempt=0;this.emit({type:"validated",isPro:false});return true}standDown(e,t,i,s){if(t!==this.generation)return false;this.state.isValidating=false;const r=this.cachedLicense;if(r&&r.licenseKey===e&&(0,_cacheSignature.verifyCacheSignature)(r)&&this.isCacheValid(r)){this.applyTier(tierOfCache(r));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetryIn(e,s);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=i;this.state.errorKind="transport";this.scheduleRetryIn(e,s);this.emit({type:"error",isPro:this.state.isPro,error:i});return false}scheduleRetryIn(e,t){this.cancelRetry();const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},Math.max(1,Math.min(t,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}cancelRetry(){if(this.retryTimer){clearTimeout(this.retryTimer);this.retryTimer=null}}async clearLicense(){this.generation+=1;this.cancelRetry();this.retryAttempt=0;this.configuredKey=null;this.state.licenseKey=null;this.lock();this.state.expiresAt=null;this.state.error=null;this.state.errorKind=null;this.cachedLicense=null;this.pendingRegistration=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:false});await this.clearCachedLicense();if(this.hold?.verdictAt!==void 0){await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}}async signOut(){await this.initialize();const e=this.state.licenseKey;if(e)this.rememberSignedOutKey(e);await this.clearLicense();await this.persistence.catch(()=>{});await _sessionManager.SessionManager.signOut().catch(()=>{})}async restoreSignedOutKey(){const e=this.signedOutKey;if(!e)return false;this.configuredKey=e;return this.setLicenseKey(e,{force:true})}applyTier(e){this.state.tier=e;this.state.tierSource="key";this.state.isPro=e==="pro"}lock(){this.state.tier="free";this.state.tierSource="none";this.state.isPro=false;this.verifiedAt=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null}getTier(){return this.credential().tier}credential(){const e=this.keyTier();const t=this.sessionTier();if(t!==null&&(!this.hasKeyAccess()||t==="pro"&&e!=="pro")){return{source:"session",tier:t}}return{source:this.state.tierSource,tier:e}}keyTier(){if(!this.hasKeyAccess())return"free";if(this.state.expiresAt&&(0,_realNow.realNow)()>=this.state.expiresAt.getTime())return"free";return this.state.tier}sessionTier(){const e=_sessionManager.SessionManager.getStatus();if(e.state!=="active")return null;return e.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){const{source:e,tier:t}=this.credential();const i=this.getTeamAccess();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess(),teamRole:i.role,allowedTools:i.tools}}getTeamAccess(){const e=_sessionManager.SessionManager.getStatus();if(e.state==="active")return teamAccessOf(e.claims);const t=this.devToken;if(t&&t.token===this.state.licenseKey&&this.state.tierSource==="key"&&(0,_realNow.realNow)()<t.claims.exp*1e3&&this.hasKeyAccess()){return teamAccessOf(t.claims)}return NO_TEAM_ACCESS}getAccountAccess(){const e=this.getKeyAccess();if(e.status==="admitted")return e;const t=_sessionManager.SessionManager.getStatus();if(t.state==="active")return{status:"admitted",reason:null,validUntil:t.validUntil};return e}getKeyAccess(){return(0,_accountAccess.resolveAccountAccess)({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}hasKeyAccess(){return this.getKeyAccess().status==="admitted"}setVerifiedAt(e){this.verifiedAt=e;if(this.expiryTimer)clearTimeout(this.expiryTimer);const t=e+_config.LICENSE_CACHE_DURATION;const i=this.state.expiresAt?.getTime();const s=i&&i>(0,_realNow.realNow)()?Math.min(t,i):t;const r=s-(0,_realNow.realNow)();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==e)return;this.emit({type:"validated",isPro:this.isPro()});if((0,_realNow.realNow)()<t)this.setVerifiedAt(e)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer}subscribe(e){this.listeners.add(e);return()=>this.listeners.delete(e)}onDeviceRegistrationNeeded(e){this.deviceRegistrationCallback=e;return()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(e){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}const{licenseId:t,licenseKey:i,fingerprint:s}=this.pendingRegistration;const r=this.generation;const n=e.trim()||(0,_fingerprint.getDefaultDeviceName)();const u=(0,_fingerprint.getDeviceMetadata)();try{await(0,_api.activateMachine)(t,i,s,n,u)}catch(c){const a=c instanceof Error?c.message:String(c);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw c}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const c=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:n},r);if(r!==this.generation)return;if(c)this.cachedLicense=c}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(s){console.warn("[Buoy]","[React Buoy] License listener error:",s)}})}isCacheValid(e){const t=(0,_realNow.realNow)();const i=t-e.cachedAt;if(!e.valid||!Number.isFinite(e.cachedAt)||i<0||i>=_config.LICENSE_CACHE_DURATION){return false}return true}isCacheFresh(e){const t=this.isQuiet(e)?_config.LICENSE_QUIET_VALIDATION_TTL:_config.LICENSE_LAUNCH_VALIDATION_TTL;return(0,_realNow.realNow)()-(e.lastValidatedAt??0)<t}isQuiet(e){if(e.quiet!==void 0)return e.quiet;return tierOfCache(e)==="free"&&!(0,_fingerprint.isDevBundle)()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.LICENSE_HOLD_STORAGE_KEY);const i=t?JSON.parse(t):null;this.hold=i&&typeof i==="object"?i:null}catch{this.hold=null}return this.hold}async saveHold(e){this.hold=e;try{const t=await(0,_storage.getLicenseStorage)();if(e)await t.setItem(_config.LICENSE_HOLD_STORAGE_KEY,JSON.stringify(e));else await t.removeItem(_config.LICENSE_HOLD_STORAGE_KEY)}catch{}}async persistCache(e){const t=(0,_cacheSignature.signCache)(e);const i=await(0,_storage.getLicenseStorage)();await i.setItem(_config.LICENSE_STORAGE_KEY,JSON.stringify(t));return t}saveCache(e,t){const i=this.persistence.catch(()=>{}).then(async()=>{if(t!==this.generation)return null;const s=await this.persistCache(e);return t===this.generation?s:null});this.persistence=i;return boundedStorage(i,(0,_cacheSignature.signCache)(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.LICENSE_STORAGE_KEY);if(!t)return null;const i=JSON.parse(t);if(i.fingerprint){const s=await boundedStorage(this.getOrCreateDeviceFingerprint(i.fingerprint).catch(()=>null),null);if(s&&this.fingerprintRestored&&i.fingerprint!==s){return{...i,fingerprint:void 0,deviceName:void 0}}}return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(e){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const t=await(0,_storage.getLicenseStorage)();const i=await t.getItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY);const s=await t.getItem(_config.DEVICE_FINGERPRINT_OWNER_STORAGE_KEY);const r=await boundedStorage((0,_fingerprint.getDeviceOwnerId)().catch(()=>null),null);const n=(0,_fingerprintOwner.resolveDeviceFingerprint)({stored:i,storedOwner:s,marker:r?(0,_fingerprintOwner.hashDeviceMarker)(r):null,blobFingerprint:e??this.cachedLicense?.fingerprint,mint:_fingerprint.generateUUID});this.fingerprintRestored=n.restored;if(n.changed){await t.setItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY,n.fingerprint);if(n.owner)await t.setItem(_config.DEVICE_FINGERPRINT_OWNER_STORAGE_KEY,n.owner)}return n.fingerprint})()}return this.fingerprintPromise}async loadSignedOutKey(){await this.persistence.catch(()=>{});const e=await(0,_storage.getLicenseStorage)();this.signedOutKey=await e.getItem(_config.SIGNED_OUT_KEY_STORAGE_KEY);this.state.keySignedOut=!!this.signedOutKey}rememberSignedOutKey(e){this.signedOutKey=e;this.state.keySignedOut=true;this.persistence=this.persistence.catch(()=>{}).then(async()=>{const t=await(0,_storage.getLicenseStorage)();await t.setItem(_config.SIGNED_OUT_KEY_STORAGE_KEY,e)}).catch(()=>{})}forgetSignedOutKey(){if(!this.signedOutKey)return;this.signedOutKey=null;this.state.keySignedOut=false;this.persistence=this.persistence.catch(()=>{}).then(async()=>{const e=await(0,_storage.getLicenseStorage)();await e.removeItem(_config.SIGNED_OUT_KEY_STORAGE_KEY)}).catch(()=>{})}async clearCachedLicense(){this.cachedLicense=null;const e=this.persistence.catch(()=>{}).then(async()=>{const t=await(0,_storage.getLicenseStorage)();await t.removeItem(_config.LICENSE_STORAGE_KEY)});this.persistence=e;await boundedStorage(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,s){const r=(0,_fingerprint.getDeviceMetadata)();(0,_api.activateMachine)(e,t,i,s,r).catch(n=>{if(n.message!=="FINGERPRINT_TAKEN"&&n.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",n.message)}})}validateInBackground(e){void this.setLicenseKey(e,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){if(!this.removeForegroundListener){this.removeForegroundListener=(0,_foreground.subscribeForeground)(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener}if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;const e=this.cachedLicense;if(e&&e.licenseKey===this.state.licenseKey&&this.isCacheFresh(e))return;this.validateInBackground(this.state.licenseKey)},_config.LICENSE_REVALIDATION_INTERVAL);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){this.removeForegroundListener?.();this.removeForegroundListener=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null;if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}this.cancelRetry()}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}this.fingerprintPromise=null;await this.clearCachedLicense();try{const e=await(0,_storage.getLicenseStorage)();await e.removeItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY)}catch{}}}const LicenseManager=exports.LicenseManager=new LicenseManagerImpl;const devTimers=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__?.();devTimers.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(devTimers.__LICENSE_MANAGER_EXPIRY_TIMER__);if(devTimers.__LICENSE_MANAGER_TIMER__){clearInterval(devTimers.__LICENSE_MANAGER_TIMER__)}if(devTimers.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(devTimers.__LICENSE_MANAGER_RETRY_TIMER__);devTimers.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
|
package/lib/commonjs/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.DEVICE_FINGERPRINT_STORAGE_KEY=exports.DEVICE_FINGERPRINT_OWNER_STORAGE_KEY=void 0;Object.defineProperty(exports,"FREE_TOKEN_PUBLIC_KEY",{enumerable:true,get:function(){return _freeTokenKey.FREE_TOKEN_PUBLIC_KEY}});exports.LICENSE_VERDICT_CACHE_DURATION=exports.LICENSE_TRANSIENT_RETRY_DELAYS=exports.LICENSE_STORAGE_KEY=exports.LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_RATE_LIMIT_DEFAULT_WAIT=exports.LICENSE_QUOTA_COOLDOWN=exports.LICENSE_QUIET_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_HOLD_STORAGE_KEY=exports.LICENSE_FLEET_MACHINE_THRESHOLD=exports.LICENSE_CACHE_DURATION=exports.KEYGEN_POLICIES=exports.KEYGEN_CONFIG=void 0;Object.defineProperty(exports,"SESSION_TOKEN_PUBLIC_KEY",{enumerable:true,get:function(){return _sessionTokenKey.SESSION_TOKEN_PUBLIC_KEY}});var _freeTokenKey=require("./freeTokenKey.js");var _sessionTokenKey=require("./sessionTokenKey.js");/*!
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.DEVICE_FINGERPRINT_STORAGE_KEY=exports.DEVICE_FINGERPRINT_OWNER_STORAGE_KEY=void 0;Object.defineProperty(exports,"FREE_TOKEN_PUBLIC_KEY",{enumerable:true,get:function(){return _freeTokenKey.FREE_TOKEN_PUBLIC_KEY}});exports.LICENSE_VERDICT_CACHE_DURATION=exports.LICENSE_TRANSIENT_RETRY_DELAYS=exports.LICENSE_STORAGE_KEY=exports.LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_RATE_LIMIT_DEFAULT_WAIT=exports.LICENSE_QUOTA_COOLDOWN=exports.LICENSE_QUIET_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_HOLD_STORAGE_KEY=exports.LICENSE_FLEET_MACHINE_THRESHOLD=exports.LICENSE_CACHE_DURATION=exports.KEYGEN_POLICIES=exports.KEYGEN_CONFIG=void 0;Object.defineProperty(exports,"SESSION_TOKEN_PUBLIC_KEY",{enumerable:true,get:function(){return _sessionTokenKey.SESSION_TOKEN_PUBLIC_KEY}});exports.SIGNED_OUT_KEY_STORAGE_KEY=void 0;var _freeTokenKey=require("./freeTokenKey.js");var _sessionTokenKey=require("./sessionTokenKey.js");/*!
|
|
2
2
|
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
15
15
|
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
16
16
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
17
|
-
*/const KEYGEN_CONFIG=exports.KEYGEN_CONFIG=Object.freeze({accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"});const KEYGEN_POLICIES=exports.KEYGEN_POLICIES=Object.freeze({free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"});const LICENSE_CACHE_DURATION=exports.LICENSE_CACHE_DURATION=30*24*60*60*1e3;const LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;const LICENSE_STORAGE_KEY=exports.LICENSE_STORAGE_KEY="buoy-gg-license";const DEVICE_FINGERPRINT_STORAGE_KEY=exports.DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";const DEVICE_FINGERPRINT_OWNER_STORAGE_KEY=exports.DEVICE_FINGERPRINT_OWNER_STORAGE_KEY="buoy-gg-device-fingerprint-owner";const LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;const LICENSE_TRANSIENT_RETRY_DELAYS=exports.LICENSE_TRANSIENT_RETRY_DELAYS=[5*1e3,20*1e3,60*1e3,5*60*1e3,15*60*1e3];const LICENSE_RATE_LIMIT_DEFAULT_WAIT=exports.LICENSE_RATE_LIMIT_DEFAULT_WAIT=60*1e3;const LICENSE_QUOTA_COOLDOWN=exports.LICENSE_QUOTA_COOLDOWN=60*60*1e3;const LICENSE_VERDICT_CACHE_DURATION=exports.LICENSE_VERDICT_CACHE_DURATION=24*60*60*1e3;const LICENSE_FLEET_MACHINE_THRESHOLD=exports.LICENSE_FLEET_MACHINE_THRESHOLD=50;const LICENSE_QUIET_VALIDATION_TTL=exports.LICENSE_QUIET_VALIDATION_TTL=LICENSE_CACHE_DURATION;const LICENSE_HOLD_STORAGE_KEY=exports.LICENSE_HOLD_STORAGE_KEY="buoy-gg-license-hold";
|
|
17
|
+
*/const KEYGEN_CONFIG=exports.KEYGEN_CONFIG=Object.freeze({accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"});const KEYGEN_POLICIES=exports.KEYGEN_POLICIES=Object.freeze({free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"});const LICENSE_CACHE_DURATION=exports.LICENSE_CACHE_DURATION=30*24*60*60*1e3;const LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;const LICENSE_STORAGE_KEY=exports.LICENSE_STORAGE_KEY="buoy-gg-license";const SIGNED_OUT_KEY_STORAGE_KEY=exports.SIGNED_OUT_KEY_STORAGE_KEY="buoy-gg-signed-out-key";const DEVICE_FINGERPRINT_STORAGE_KEY=exports.DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";const DEVICE_FINGERPRINT_OWNER_STORAGE_KEY=exports.DEVICE_FINGERPRINT_OWNER_STORAGE_KEY="buoy-gg-device-fingerprint-owner";const LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;const LICENSE_TRANSIENT_RETRY_DELAYS=exports.LICENSE_TRANSIENT_RETRY_DELAYS=[5*1e3,20*1e3,60*1e3,5*60*1e3,15*60*1e3];const LICENSE_RATE_LIMIT_DEFAULT_WAIT=exports.LICENSE_RATE_LIMIT_DEFAULT_WAIT=60*1e3;const LICENSE_QUOTA_COOLDOWN=exports.LICENSE_QUOTA_COOLDOWN=60*60*1e3;const LICENSE_VERDICT_CACHE_DURATION=exports.LICENSE_VERDICT_CACHE_DURATION=24*60*60*1e3;const LICENSE_FLEET_MACHINE_THRESHOLD=exports.LICENSE_FLEET_MACHINE_THRESHOLD=50;const LICENSE_QUIET_VALIDATION_TTL=exports.LICENSE_QUIET_VALIDATION_TTL=LICENSE_CACHE_DURATION;const LICENSE_HOLD_STORAGE_KEY=exports.LICENSE_HOLD_STORAGE_KEY="buoy-gg-license-hold";
|
|
@@ -13,4 +13,4 @@
|
|
|
13
13
|
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
14
14
|
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
15
15
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
16
|
-
*/import{getLicenseStorage as y}from"./storage";import{KEYGEN_CONFIG as q,LICENSE_STORAGE_KEY as N,LICENSE_CACHE_DURATION as O,LICENSE_REVALIDATION_INTERVAL as J,LICENSE_LAUNCH_VALIDATION_TTL as Q,LICENSE_TRANSIENT_RETRY_DELAYS as W,LICENSE_RATE_LIMIT_DEFAULT_WAIT as j,LICENSE_QUOTA_COOLDOWN as F,LICENSE_VERDICT_CACHE_DURATION as $,LICENSE_FLEET_MACHINE_THRESHOLD as Z,LICENSE_QUIET_VALIDATION_TTL as ee,LICENSE_HOLD_STORAGE_KEY as C,DEVICE_FINGERPRINT_STORAGE_KEY as w,DEVICE_FINGERPRINT_OWNER_STORAGE_KEY as b}from"./config.js";import{validateLicense as te,activateMachine as G,parseValidationResult as ie,isFatalLicenseError as se,isTransientLicenseError as re,isAcceptedValidation as ae,isRateLimited as ne,backoffAfter as ce,machineCount as oe}from"./api.js";import{generateUUID as K,getDeviceMetadata as U,getDefaultDeviceName as P,isDevBundle as V,getDeviceOwnerId as he}from"./fingerprint";import{hashDeviceMarker as le,resolveDeviceFingerprint as de}from"./fingerprintOwner.js";import{signCache as z,verifyCacheSignature as p}from"./cacheSignature.js";import{isBuoyToken as fe,verifyFreeToken as ue}from"./freeToken.js";import{resolveTier as ye,isRecognizedAccount as me}from"./tier.js";import{resolveAccountAccess as pe}from"./accountAccess.js";import{subscribeForeground as ge}from"./foreground";import{realNow as o}from"./realNow.js";import{SessionManager as g}from"./sessionManager.js";import{exchangeServiceKey as _e,isServiceKey as Ae,normalizeLicenseKey as H}from"./serviceKey.js";import{checkDevToken as ve,isDevToken as Ee,DEV_TOKEN_IN_RELEASE as Te}from"./devToken.js";const Re={role:null,tools:null};function Y(d){return{role:d.role??null,tools:d.tools??null}}async function f(d,t){let e;try{return await Promise.race([d,new Promise(i=>{e=setTimeout(()=>i(t),15e3)})])}finally{if(e)clearTimeout(e)}}function _(d){if(d.tier==="pro"||d.tier==="free")return d.tier;return d.isPro?"pro":"free"}class Le{state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,error:null,errorKind:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;fingerprintRestored=false;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=null;devToken=null;retryTimer=null;retryAttempt=0;deviceRegistrationCallback=null;pendingRegistration=null;async initialize(){if(this.initPromise)return this.initPromise;if(this.state.isInitialized)return;this.initPromise=this._doInitialize();return this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;const t=this.generation;if(!this.sessionUnsubscribe){this.sessionUnsubscribe=g.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))}await f(g.load().catch(()=>void 0),void 0);try{const e=await f(this.loadCachedLicense(),null);if(t!==this.generation){this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer();return}if(e&&(this.configuredKey===void 0||e.licenseKey===this.configuredKey)){const i=p(e);this.cachedLicense=e;this.state.licenseKey=e.licenseKey;if(i&&this.isCacheValid(e))this.applyTier(_(e));else this.lock();this.state.expiresAt=e.expiresAt?new Date(e.expiresAt):null;if(i&&this.isCacheValid(e))this.setVerifiedAt(e.cachedAt);if(this.configuredKey===void 0&&e.licenseKey&&!(i&&this.isCacheValid(e)&&this.isCacheFresh(e))){this.validateInBackground(e.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(e){console.warn("[Buoy]","[React Buoy] License initialization failed:",e);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async configure(t){if(t===void 0){await this.initialize();return this.hasAccountAccess()}const e=H(t);const i=++this.generation;this.cancelRetry();this.configuredKey=e||null;if(this.state.licenseKey!==this.configuredKey)this.lock();this.state.licenseKey=this.configuredKey;this.state.isValidating=!!e;this.emit({type:"validating",isPro:this.isPro()});await this.initialize();if(i!==this.generation)return false;if(!e){await this.clearLicense();return false}return this.setLicenseKey(e)}async setLicenseKey(t,e){if(!t||t.trim().length===0){this.state.error="License key is required";this.state.errorKind="verdict";return false}const i=H(t);const s=++this.generation;this.cancelRetry();if(!e?.isRetry)this.retryAttempt=0;if(this.state.licenseKey!==i)this.lock();this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.state.errorKind=null;this.emit({type:"validating",isPro:this.isPro()});if(fe(i))return this.admitToken(i,s);if(Ae(i))return this.admitServiceKey(i,s);if(Ee(i))return this.admitDevToken(i);if(!this.cachedLicense){const a=await f(this.loadCachedLicense(),null);if(s!==this.generation)return false;if(a?.licenseKey===i){this.cachedLicense=a;if(p(a)&&this.isCacheValid(a)){this.applyTier(_(a));this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.setVerifiedAt(a.cachedAt);this.emit({type:"validating",isPro:this.isPro()})}}}const r=this.cachedLicense;if(!e?.force&&r&&r.valid&&r.licenseKey===i&&r.fingerprint&&p(r)&&this.isCacheValid(r)&&this.isCacheFresh(r)){this.applyTier(_(r));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);this.emit({type:"validated",isPro:this.state.isPro});return true}const n=await f(this.loadHold(),null);if(s!==this.generation)return false;const A=(n?.backoffUntil??0)-o();if(A>0){return this.standDown(i,s,"License server is rate limited; retrying later.",A)}if(!e?.force&&n?.key===i&&n.verdictAt!==void 0&&o()-n.verdictAt>=0&&o()-n.verdictAt<$){this.lock();this.state.isValidating=false;this.state.error=n.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let c;try{c=await te(i)}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if(re(a)){if(ne(a)){const u=Math.min(ce(a,F,j)*2**this.retryAttempt,F);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:o()+u});if(s!==this.generation)return false;return this.standDown(i,s,l,u)}this.state.isValidating=false;if(this.cachedLicense&&this.cachedLicense.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)){this.applyTier(_(this.cachedLicense));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null;this.setVerifiedAt(this.cachedLicense.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetry(i);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=l;this.state.errorKind="transport";this.scheduleRetry(i);this.emit({type:"error",isPro:this.state.isPro,error:l});return false}this.state.isValidating=false;this.state.error=l;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:l});return false}try{if(s!==this.generation)return false;const a=ie(c);const l=c.data?.relationships?.product?.data?.id;if((!l||l===q.productId)&&a.code==="EXPIRED"&&(me(c.data)||this.cachedLicense?.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const I=o();const M=await this.saveCache({licenseKey:i,licenseId:c.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:I,lastValidatedAt:I,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},s);if(s!==this.generation||!M)return false;this.cachedLicense=M;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(I);this.emit({type:"validated",isPro:false});return true}if(se(a.code)||!ae(c)){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:o()});return false}if(!c.data){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License not found";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const u=ye(c.data);const E=c.data.id;const T=o();const D=oe(c)>=Z;const k=V();const B=k&&!D;const X=u==="free"&&(D||!k);let m=this.cachedLicense?.fingerprint;let v=this.cachedLicense?.deviceName;let S=false;if(!m){m=await f(this.getOrCreateDeviceFingerprint(),K());if(s!==this.generation)return false;v=P();S=B}let R=false;if(S){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:E,licenseKey:i,fingerprint:m};this.deviceRegistrationCallback({fingerprint:m,defaultName:v});R=true}else{this.registerDeviceAsync(E,i,m,v)}}const L={licenseKey:i,licenseId:E,valid:true,isPro:u==="pro",tier:u,expiresAt:c.data.attributes.expiry??null,cachedAt:T,lastValidatedAt:T,fingerprint:R?void 0:m,deviceName:R?void 0:v,quiet:X||void 0};const x=await this.saveCache(L,s);if(s!==this.generation||!x)return false;this.cachedLicense=x;this.applyTier(u);this.state.isValidating=false;this.state.expiresAt=L.expiresAt?new Date(L.expiresAt):null;this.setVerifiedAt(T);if(this.hold)await this.saveHold(null);if(s!==this.generation)return false;this.retryAttempt=0;this.emit({type:"validated",isPro:this.state.isPro});return true}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;this.state.isValidating=false;this.state.error=l;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:l});return false}}scheduleRetry(t){this.cancelRetry();const e=W[this.retryAttempt];if(e===void 0)return;this.retryAttempt+=1;const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(t,{force:true,isRetry:true})},e);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}}async admitServiceKey(t,e){const i=await _e(t,{origin:g.origin});if(e!==this.generation)return false;if(!i.ok){this.lock();this.state.isValidating=false;this.state.error=i.detail;this.state.errorKind=i.reason==="network"?"transport":"verdict";this.emit({type:"error",isPro:false,error:i.detail});if(i.reason==="network")this.scheduleRetry(t);return false}const s=i.claims.exp*1e3;this.applyTier(i.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(s);this.setVerifiedAt(o());this.retryAttempt=0;this.scheduleRetryIn(t,Math.max(6e4,s-60*60*1e3-o()));this.emit({type:"validated",isPro:this.isPro()});return true}admitDevToken(t){const e=ve(t);if(!e.ok||!V()){const s=e.ok?Te:e.message;this.lock();this.state.isValidating=false;this.state.error=s;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:s});return false}const i=o();this.devToken={token:t,claims:e.claims};this.applyTier(e.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(e.claims.exp*1e3);this.setVerifiedAt(Math.min(i,e.claims.iat*1e3));this.retryAttempt=0;this.emit({type:"validated",isPro:this.isPro()});return true}async admitToken(t,e){const i=ue(t);if(e!==this.generation)return false;if(!i){this.lock();this.state.isValidating=false;this.state.error="This key is not valid. Check that it was copied completely.";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const s=o();const r=this.cachedLicense?.fingerprint??await f(this.getOrCreateDeviceFingerprint(),K());if(e!==this.generation)return false;const n=await this.saveCache({licenseKey:t,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:s,lastValidatedAt:s,fingerprint:r,deviceName:this.cachedLicense?.deviceName??P(),quiet:true},e);if(e!==this.generation||!n)return false;this.cachedLicense=n;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(s);this.retryAttempt=0;this.emit({type:"validated",isPro:false});return true}standDown(t,e,i,s){if(e!==this.generation)return false;this.state.isValidating=false;const r=this.cachedLicense;if(r&&r.licenseKey===t&&p(r)&&this.isCacheValid(r)){this.applyTier(_(r));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetryIn(t,s);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=i;this.state.errorKind="transport";this.scheduleRetryIn(t,s);this.emit({type:"error",isPro:this.state.isPro,error:i});return false}scheduleRetryIn(t,e){this.cancelRetry();const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(t,{force:true,isRetry:true})},Math.max(1,Math.min(e,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)h.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}cancelRetry(){if(this.retryTimer){clearTimeout(this.retryTimer);this.retryTimer=null}}async clearLicense(){this.generation+=1;this.cancelRetry();this.retryAttempt=0;this.configuredKey=null;this.state.licenseKey=null;this.lock();this.state.expiresAt=null;this.state.error=null;this.state.errorKind=null;this.cachedLicense=null;this.pendingRegistration=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:false});await this.clearCachedLicense();if(this.hold?.verdictAt!==void 0){await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}}applyTier(t){this.state.tier=t;this.state.tierSource="key";this.state.isPro=t==="pro"}lock(){this.state.tier="free";this.state.tierSource="none";this.state.isPro=false;this.verifiedAt=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null}getTier(){return this.credential().tier}credential(){const t=this.keyTier();const e=this.sessionTier();if(e!==null&&(!this.hasKeyAccess()||e==="pro"&&t!=="pro")){return{source:"session",tier:e}}return{source:this.state.tierSource,tier:t}}keyTier(){if(!this.hasKeyAccess())return"free";if(this.state.expiresAt&&o()>=this.state.expiresAt.getTime())return"free";return this.state.tier}sessionTier(){const t=g.getStatus();if(t.state!=="active")return null;return t.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(t){return this.isPro()}getState(){const{source:t,tier:e}=this.credential();const i=this.getTeamAccess();return{...this.state,tier:e,tierSource:t,isPro:e==="pro",access:this.getAccountAccess(),teamRole:i.role,allowedTools:i.tools}}getTeamAccess(){const t=g.getStatus();if(t.state==="active")return Y(t.claims);const e=this.devToken;if(e&&e.token===this.state.licenseKey&&this.state.tierSource==="key"&&o()<e.claims.exp*1e3&&this.hasKeyAccess()){return Y(e.claims)}return Re}getAccountAccess(){const t=this.getKeyAccess();if(t.status==="admitted")return t;const e=g.getStatus();if(e.state==="active")return{status:"admitted",reason:null,validUntil:e.validUntil};return t}getKeyAccess(){return pe({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}hasKeyAccess(){return this.getKeyAccess().status==="admitted"}setVerifiedAt(t){this.verifiedAt=t;if(this.expiryTimer)clearTimeout(this.expiryTimer);const e=t+O;const i=this.state.expiresAt?.getTime();const s=i&&i>o()?Math.min(e,i):e;const r=s-o();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==t)return;this.emit({type:"validated",isPro:this.isPro()});if(o()<e)this.setVerifiedAt(t)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)h.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer}subscribe(t){this.listeners.add(t);return()=>this.listeners.delete(t)}onDeviceRegistrationNeeded(t){this.deviceRegistrationCallback=t;return()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(t){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}const{licenseId:e,licenseKey:i,fingerprint:s}=this.pendingRegistration;const r=this.generation;const n=t.trim()||P();const A=U();try{await G(e,i,s,n,A)}catch(c){const a=c instanceof Error?c.message:String(c);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw c}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const c=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:n},r);if(r!==this.generation)return;if(c)this.cachedLicense=c}this.pendingRegistration=null}emit(t){const e=[...this.listeners];e.forEach(i=>{try{i(t)}catch(s){console.warn("[Buoy]","[React Buoy] License listener error:",s)}})}isCacheValid(t){const e=o();const i=e-t.cachedAt;if(!t.valid||!Number.isFinite(t.cachedAt)||i<0||i>=O){return false}return true}isCacheFresh(t){const e=this.isQuiet(t)?ee:Q;return o()-(t.lastValidatedAt??0)<e}isQuiet(t){if(t.quiet!==void 0)return t.quiet;return _(t)==="free"&&!V()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const t=await y();const e=await t.getItem(C);const i=e?JSON.parse(e):null;this.hold=i&&typeof i==="object"?i:null}catch{this.hold=null}return this.hold}async saveHold(t){this.hold=t;try{const e=await y();if(t)await e.setItem(C,JSON.stringify(t));else await e.removeItem(C)}catch{}}async persistCache(t){const e=z(t);const i=await y();await i.setItem(N,JSON.stringify(e));return e}saveCache(t,e){const i=this.persistence.catch(()=>{}).then(async()=>{if(e!==this.generation)return null;const s=await this.persistCache(t);return e===this.generation?s:null});this.persistence=i;return f(i,z(t))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const t=await y();const e=await t.getItem(N);if(!e)return null;const i=JSON.parse(e);if(i.fingerprint){const s=await f(this.getOrCreateDeviceFingerprint(i.fingerprint).catch(()=>null),null);if(s&&this.fingerprintRestored&&i.fingerprint!==s){return{...i,fingerprint:void 0,deviceName:void 0}}}return i}catch(t){console.warn("[Buoy] Error loading cached license:",t);return null}}getOrCreateDeviceFingerprint(t){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await y();const i=await e.getItem(w);const s=await e.getItem(b);const r=await f(he().catch(()=>null),null);const n=de({stored:i,storedOwner:s,marker:r?le(r):null,blobFingerprint:t??this.cachedLicense?.fingerprint,mint:K});this.fingerprintRestored=n.restored;if(n.changed){await e.setItem(w,n.fingerprint);if(n.owner)await e.setItem(b,n.owner)}return n.fingerprint})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;const t=this.persistence.catch(()=>{}).then(async()=>{const e=await y();await e.removeItem(N)});this.persistence=t;await f(t.catch(()=>{}),void 0)}registerDeviceAsync(t,e,i,s){const r=U();G(t,e,i,s,r).catch(n=>{if(n.message!=="FINGERPRINT_TAKEN"&&n.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",n.message)}})}validateInBackground(t){void this.setLicenseKey(t,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){if(!this.removeForegroundListener){this.removeForegroundListener=ge(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)h.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener}if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;const t=this.cachedLicense;if(t&&t.licenseKey===this.state.licenseKey&&this.isCacheFresh(t))return;this.validateInBackground(this.state.licenseKey)},J);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){this.removeForegroundListener?.();this.removeForegroundListener=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null;if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}this.cancelRetry()}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}this.fingerprintPromise=null;await this.clearCachedLicense();try{const t=await y();await t.removeItem(w)}catch{}}}export const LicenseManager=new Le;const h=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){h.__LICENSE_MANAGER_FOREGROUND_OFF__?.();h.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(h.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(h.__LICENSE_MANAGER_EXPIRY_TIMER__);if(h.__LICENSE_MANAGER_TIMER__){clearInterval(h.__LICENSE_MANAGER_TIMER__)}if(h.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(h.__LICENSE_MANAGER_RETRY_TIMER__);h.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
|
|
16
|
+
*/import{getLicenseStorage as f}from"./storage";import{KEYGEN_CONFIG as J,LICENSE_STORAGE_KEY as K,SIGNED_OUT_KEY_STORAGE_KEY as w,LICENSE_CACHE_DURATION as b,LICENSE_REVALIDATION_INTERVAL as Q,LICENSE_LAUNCH_VALIDATION_TTL as W,LICENSE_TRANSIENT_RETRY_DELAYS as j,LICENSE_RATE_LIMIT_DEFAULT_WAIT as $,LICENSE_QUOTA_COOLDOWN as F,LICENSE_VERDICT_CACHE_DURATION as Z,LICENSE_FLEET_MACHINE_THRESHOLD as ee,LICENSE_QUIET_VALIDATION_TTL as te,LICENSE_HOLD_STORAGE_KEY as N,DEVICE_FINGERPRINT_STORAGE_KEY as C,DEVICE_FINGERPRINT_OWNER_STORAGE_KEY as G}from"./config.js";import{validateLicense as ie,activateMachine as U,parseValidationResult as se,isFatalLicenseError as re,isTransientLicenseError as ae,isAcceptedValidation as ne,isRateLimited as ce,backoffAfter as oe,machineCount as he}from"./api.js";import{generateUUID as P,getDeviceMetadata as z,getDefaultDeviceName as V,isDevBundle as S,getDeviceOwnerId as le}from"./fingerprint";import{hashDeviceMarker as de,resolveDeviceFingerprint as ue}from"./fingerprintOwner.js";import{signCache as H,verifyCacheSignature as p}from"./cacheSignature.js";import{isBuoyToken as fe,verifyFreeToken as ye}from"./freeToken.js";import{resolveTier as ge,isRecognizedAccount as me}from"./tier.js";import{resolveAccountAccess as pe}from"./accountAccess.js";import{subscribeForeground as _e}from"./foreground";import{realNow as o}from"./realNow.js";import{SessionManager as g}from"./sessionManager.js";import{exchangeServiceKey as Ae,isServiceKey as ve,normalizeLicenseKey as Y}from"./serviceKey.js";import{checkDevToken as Ee,isDevToken as Te,DEV_TOKEN_IN_RELEASE as Ie}from"./devToken.js";const Le={role:null,tools:null};function B(u){return{role:u.role??null,tools:u.tools??null}}async function d(u,e){let t;try{return await Promise.race([u,new Promise(i=>{t=setTimeout(()=>i(e),15e3)})])}finally{if(t)clearTimeout(t)}}function _(u){if(u.tier==="pro"||u.tier==="free")return u.tier;return u.isPro?"pro":"free"}class Re{state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,keySignedOut:false,error:null,errorKind:null,expiresAt:null};signedOutKey=null;listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;fingerprintRestored=false;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=null;devToken=null;retryTimer=null;retryAttempt=0;deviceRegistrationCallback=null;pendingRegistration=null;async initialize(){if(this.initPromise)return this.initPromise;if(this.state.isInitialized)return;this.initPromise=this._doInitialize();return this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;const e=this.generation;if(!this.sessionUnsubscribe){this.sessionUnsubscribe=g.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))}await d(g.load().catch(()=>void 0),void 0);try{await d(this.loadSignedOutKey(),void 0);const t=await d(this.loadCachedLicense(),null);if(e!==this.generation){this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer();return}if(t&&t.licenseKey!==this.signedOutKey&&(this.configuredKey===void 0||t.licenseKey===this.configuredKey)){const i=p(t);this.cachedLicense=t;this.state.licenseKey=t.licenseKey;if(i&&this.isCacheValid(t))this.applyTier(_(t));else this.lock();this.state.expiresAt=t.expiresAt?new Date(t.expiresAt):null;if(i&&this.isCacheValid(t))this.setVerifiedAt(t.cachedAt);if(this.configuredKey===void 0&&t.licenseKey&&!(i&&this.isCacheValid(t)&&this.isCacheFresh(t))){this.validateInBackground(t.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(t){console.warn("[Buoy]","[React Buoy] License initialization failed:",t);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async configure(e){if(e===void 0){await this.initialize();return this.hasAccountAccess()}const t=Y(e);const i=++this.generation;this.cancelRetry();this.configuredKey=t||null;if(this.state.licenseKey!==this.configuredKey)this.lock();this.state.licenseKey=this.configuredKey;this.state.isValidating=!!t;this.emit({type:"validating",isPro:this.isPro()});await this.initialize();if(i!==this.generation)return false;if(!t){this.forgetSignedOutKey();await this.clearLicense();return false}if(t===this.signedOutKey){this.configuredKey=null;this.state.licenseKey=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:this.isPro()});return false}return this.setLicenseKey(t)}async setLicenseKey(e,t){if(!e||e.trim().length===0){this.state.error="License key is required";this.state.errorKind="verdict";return false}const i=Y(e);this.forgetSignedOutKey();const s=++this.generation;this.cancelRetry();if(!t?.isRetry)this.retryAttempt=0;if(this.state.licenseKey!==i)this.lock();this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.state.errorKind=null;this.emit({type:"validating",isPro:this.isPro()});if(fe(i))return this.admitToken(i,s);if(ve(i))return this.admitServiceKey(i,s);if(Te(i))return this.admitDevToken(i);if(!this.cachedLicense){const a=await d(this.loadCachedLicense(),null);if(s!==this.generation)return false;if(a?.licenseKey===i){this.cachedLicense=a;if(p(a)&&this.isCacheValid(a)){this.applyTier(_(a));this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.setVerifiedAt(a.cachedAt);this.emit({type:"validating",isPro:this.isPro()})}}}const r=this.cachedLicense;if(!t?.force&&r&&r.valid&&r.licenseKey===i&&r.fingerprint&&p(r)&&this.isCacheValid(r)&&this.isCacheFresh(r)){this.applyTier(_(r));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);this.emit({type:"validated",isPro:this.state.isPro});return true}const n=await d(this.loadHold(),null);if(s!==this.generation)return false;const A=(n?.backoffUntil??0)-o();if(A>0){return this.standDown(i,s,"License server is rate limited; retrying later.",A)}if(!t?.force&&n?.key===i&&n.verdictAt!==void 0&&o()-n.verdictAt>=0&&o()-n.verdictAt<Z){this.lock();this.state.isValidating=false;this.state.error=n.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let c;try{c=await ie(i)}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if(ae(a)){if(ce(a)){const y=Math.min(oe(a,F,$)*2**this.retryAttempt,F);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:o()+y});if(s!==this.generation)return false;return this.standDown(i,s,l,y)}this.state.isValidating=false;if(this.cachedLicense&&this.cachedLicense.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)){this.applyTier(_(this.cachedLicense));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null;this.setVerifiedAt(this.cachedLicense.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetry(i);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=l;this.state.errorKind="transport";this.scheduleRetry(i);this.emit({type:"error",isPro:this.state.isPro,error:l});return false}this.state.isValidating=false;this.state.error=l;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:l});return false}try{if(s!==this.generation)return false;const a=se(c);const l=c.data?.relationships?.product?.data?.id;if((!l||l===J.productId)&&a.code==="EXPIRED"&&(me(c.data)||this.cachedLicense?.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const R=o();const M=await this.saveCache({licenseKey:i,licenseId:c.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:R,lastValidatedAt:R,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},s);if(s!==this.generation||!M)return false;this.cachedLicense=M;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(R);this.emit({type:"validated",isPro:false});return true}if(re(a.code)||!ne(c)){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:o()});return false}if(!c.data){this.lock();this.state.isValidating=false;this.state.error=a.detail||"License not found";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const y=ge(c.data);const E=c.data.id;const T=o();const D=he(c)>=ee;const k=S();const X=k&&!D;const q=y==="free"&&(D||!k);let m=this.cachedLicense?.fingerprint;let v=this.cachedLicense?.deviceName;let O=false;if(!m){m=await d(this.getOrCreateDeviceFingerprint(),P());if(s!==this.generation)return false;v=V();O=X}let I=false;if(O){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:E,licenseKey:i,fingerprint:m};this.deviceRegistrationCallback({fingerprint:m,defaultName:v});I=true}else{this.registerDeviceAsync(E,i,m,v)}}const L={licenseKey:i,licenseId:E,valid:true,isPro:y==="pro",tier:y,expiresAt:c.data.attributes.expiry??null,cachedAt:T,lastValidatedAt:T,fingerprint:I?void 0:m,deviceName:I?void 0:v,quiet:q||void 0};const x=await this.saveCache(L,s);if(s!==this.generation||!x)return false;this.cachedLicense=x;this.applyTier(y);this.state.isValidating=false;this.state.expiresAt=L.expiresAt?new Date(L.expiresAt):null;this.setVerifiedAt(T);if(this.hold)await this.saveHold(null);if(s!==this.generation)return false;this.retryAttempt=0;this.emit({type:"validated",isPro:this.state.isPro});return true}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;this.state.isValidating=false;this.state.error=l;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:l});return false}}scheduleRetry(e){this.cancelRetry();const t=j[this.retryAttempt];if(t===void 0)return;this.retryAttempt+=1;const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},t);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}}async admitServiceKey(e,t){const i=await Ae(e,{origin:g.origin});if(t!==this.generation)return false;if(!i.ok){this.lock();this.state.isValidating=false;this.state.error=i.detail;this.state.errorKind=i.reason==="network"?"transport":"verdict";this.emit({type:"error",isPro:false,error:i.detail});if(i.reason==="network")this.scheduleRetry(e);return false}const s=i.claims.exp*1e3;this.applyTier(i.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(s);this.setVerifiedAt(o());this.retryAttempt=0;this.scheduleRetryIn(e,Math.max(6e4,s-60*60*1e3-o()));this.emit({type:"validated",isPro:this.isPro()});return true}admitDevToken(e){const t=Ee(e);if(!t.ok||!S()){const s=t.ok?Ie:t.message;this.lock();this.state.isValidating=false;this.state.error=s;this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:s});return false}const i=o();this.devToken={token:e,claims:t.claims};this.applyTier(t.claims.tier==="free"?"free":"pro");this.state.isValidating=false;this.state.expiresAt=new Date(t.claims.exp*1e3);this.setVerifiedAt(Math.min(i,t.claims.iat*1e3));this.retryAttempt=0;this.emit({type:"validated",isPro:this.isPro()});return true}async admitToken(e,t){const i=ye(e);if(t!==this.generation)return false;if(!i){this.lock();this.state.isValidating=false;this.state.error="This key is not valid. Check that it was copied completely.";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});await this.clearCachedLicense();return false}const s=o();const r=this.cachedLicense?.fingerprint??await d(this.getOrCreateDeviceFingerprint(),P());if(t!==this.generation)return false;const n=await this.saveCache({licenseKey:e,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:s,lastValidatedAt:s,fingerprint:r,deviceName:this.cachedLicense?.deviceName??V(),quiet:true},t);if(t!==this.generation||!n)return false;this.cachedLicense=n;this.applyTier("free");this.state.isValidating=false;this.state.expiresAt=null;this.setVerifiedAt(s);this.retryAttempt=0;this.emit({type:"validated",isPro:false});return true}standDown(e,t,i,s){if(t!==this.generation)return false;this.state.isValidating=false;const r=this.cachedLicense;if(r&&r.licenseKey===e&&p(r)&&this.isCacheValid(r)){this.applyTier(_(r));this.state.error=null;this.state.errorKind=null;this.state.expiresAt=r.expiresAt?new Date(r.expiresAt):null;this.setVerifiedAt(r.cachedAt);if(this.keyTier()!=="pro")this.scheduleRetryIn(e,s);this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.error=i;this.state.errorKind="transport";this.scheduleRetryIn(e,s);this.emit({type:"error",isPro:this.state.isPro,error:i});return false}scheduleRetryIn(e,t){this.cancelRetry();const i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null;if(i!==this.generation)return;if(this.state.isValidating)return;void this.setLicenseKey(e,{force:true,isRetry:true})},Math.max(1,Math.min(t,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)h.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer}cancelRetry(){if(this.retryTimer){clearTimeout(this.retryTimer);this.retryTimer=null}}async clearLicense(){this.generation+=1;this.cancelRetry();this.retryAttempt=0;this.configuredKey=null;this.state.licenseKey=null;this.lock();this.state.expiresAt=null;this.state.error=null;this.state.errorKind=null;this.cachedLicense=null;this.pendingRegistration=null;this.state.isValidating=false;this.emit({type:"deactivated",isPro:false});await this.clearCachedLicense();if(this.hold?.verdictAt!==void 0){await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}}async signOut(){await this.initialize();const e=this.state.licenseKey;if(e)this.rememberSignedOutKey(e);await this.clearLicense();await this.persistence.catch(()=>{});await g.signOut().catch(()=>{})}async restoreSignedOutKey(){const e=this.signedOutKey;if(!e)return false;this.configuredKey=e;return this.setLicenseKey(e,{force:true})}applyTier(e){this.state.tier=e;this.state.tierSource="key";this.state.isPro=e==="pro"}lock(){this.state.tier="free";this.state.tierSource="none";this.state.isPro=false;this.verifiedAt=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null}getTier(){return this.credential().tier}credential(){const e=this.keyTier();const t=this.sessionTier();if(t!==null&&(!this.hasKeyAccess()||t==="pro"&&e!=="pro")){return{source:"session",tier:t}}return{source:this.state.tierSource,tier:e}}keyTier(){if(!this.hasKeyAccess())return"free";if(this.state.expiresAt&&o()>=this.state.expiresAt.getTime())return"free";return this.state.tier}sessionTier(){const e=g.getStatus();if(e.state!=="active")return null;return e.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){const{source:e,tier:t}=this.credential();const i=this.getTeamAccess();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess(),teamRole:i.role,allowedTools:i.tools}}getTeamAccess(){const e=g.getStatus();if(e.state==="active")return B(e.claims);const t=this.devToken;if(t&&t.token===this.state.licenseKey&&this.state.tierSource==="key"&&o()<t.claims.exp*1e3&&this.hasKeyAccess()){return B(t.claims)}return Le}getAccountAccess(){const e=this.getKeyAccess();if(e.status==="admitted")return e;const t=g.getStatus();if(t.state==="active")return{status:"admitted",reason:null,validUntil:t.validUntil};return e}getKeyAccess(){return pe({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}hasKeyAccess(){return this.getKeyAccess().status==="admitted"}setVerifiedAt(e){this.verifiedAt=e;if(this.expiryTimer)clearTimeout(this.expiryTimer);const t=e+b;const i=this.state.expiresAt?.getTime();const s=i&&i>o()?Math.min(t,i):t;const r=s-o();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==e)return;this.emit({type:"validated",isPro:this.isPro()});if(o()<t)this.setVerifiedAt(e)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)h.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer}subscribe(e){this.listeners.add(e);return()=>this.listeners.delete(e)}onDeviceRegistrationNeeded(e){this.deviceRegistrationCallback=e;return()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(e){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}const{licenseId:t,licenseKey:i,fingerprint:s}=this.pendingRegistration;const r=this.generation;const n=e.trim()||V();const A=z();try{await U(t,i,s,n,A)}catch(c){const a=c instanceof Error?c.message:String(c);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw c}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const c=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:n},r);if(r!==this.generation)return;if(c)this.cachedLicense=c}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(s){console.warn("[Buoy]","[React Buoy] License listener error:",s)}})}isCacheValid(e){const t=o();const i=t-e.cachedAt;if(!e.valid||!Number.isFinite(e.cachedAt)||i<0||i>=b){return false}return true}isCacheFresh(e){const t=this.isQuiet(e)?te:W;return o()-(e.lastValidatedAt??0)<t}isQuiet(e){if(e.quiet!==void 0)return e.quiet;return _(e)==="free"&&!S()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const e=await f();const t=await e.getItem(N);const i=t?JSON.parse(t):null;this.hold=i&&typeof i==="object"?i:null}catch{this.hold=null}return this.hold}async saveHold(e){this.hold=e;try{const t=await f();if(e)await t.setItem(N,JSON.stringify(e));else await t.removeItem(N)}catch{}}async persistCache(e){const t=H(e);const i=await f();await i.setItem(K,JSON.stringify(t));return t}saveCache(e,t){const i=this.persistence.catch(()=>{}).then(async()=>{if(t!==this.generation)return null;const s=await this.persistCache(e);return t===this.generation?s:null});this.persistence=i;return d(i,H(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const e=await f();const t=await e.getItem(K);if(!t)return null;const i=JSON.parse(t);if(i.fingerprint){const s=await d(this.getOrCreateDeviceFingerprint(i.fingerprint).catch(()=>null),null);if(s&&this.fingerprintRestored&&i.fingerprint!==s){return{...i,fingerprint:void 0,deviceName:void 0}}}return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(e){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const t=await f();const i=await t.getItem(C);const s=await t.getItem(G);const r=await d(le().catch(()=>null),null);const n=ue({stored:i,storedOwner:s,marker:r?de(r):null,blobFingerprint:e??this.cachedLicense?.fingerprint,mint:P});this.fingerprintRestored=n.restored;if(n.changed){await t.setItem(C,n.fingerprint);if(n.owner)await t.setItem(G,n.owner)}return n.fingerprint})()}return this.fingerprintPromise}async loadSignedOutKey(){await this.persistence.catch(()=>{});const e=await f();this.signedOutKey=await e.getItem(w);this.state.keySignedOut=!!this.signedOutKey}rememberSignedOutKey(e){this.signedOutKey=e;this.state.keySignedOut=true;this.persistence=this.persistence.catch(()=>{}).then(async()=>{const t=await f();await t.setItem(w,e)}).catch(()=>{})}forgetSignedOutKey(){if(!this.signedOutKey)return;this.signedOutKey=null;this.state.keySignedOut=false;this.persistence=this.persistence.catch(()=>{}).then(async()=>{const e=await f();await e.removeItem(w)}).catch(()=>{})}async clearCachedLicense(){this.cachedLicense=null;const e=this.persistence.catch(()=>{}).then(async()=>{const t=await f();await t.removeItem(K)});this.persistence=e;await d(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,s){const r=z();U(e,t,i,s,r).catch(n=>{if(n.message!=="FINGERPRINT_TAKEN"&&n.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",n.message)}})}validateInBackground(e){void this.setLicenseKey(e,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){if(!this.removeForegroundListener){this.removeForegroundListener=_e(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)h.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener}if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;const e=this.cachedLicense;if(e&&e.licenseKey===this.state.licenseKey&&this.isCacheFresh(e))return;this.validateInBackground(this.state.licenseKey)},Q);if(typeof __DEV__!=="undefined"&&__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){this.removeForegroundListener?.();this.removeForegroundListener=null;if(this.expiryTimer)clearTimeout(this.expiryTimer);this.expiryTimer=null;if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}this.cancelRetry()}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}this.fingerprintPromise=null;await this.clearCachedLicense();try{const e=await f();await e.removeItem(C)}catch{}}}export const LicenseManager=new Re;const h=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){h.__LICENSE_MANAGER_FOREGROUND_OFF__?.();h.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(h.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(h.__LICENSE_MANAGER_EXPIRY_TIMER__);if(h.__LICENSE_MANAGER_TIMER__){clearInterval(h.__LICENSE_MANAGER_TIMER__)}if(h.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(h.__LICENSE_MANAGER_RETRY_TIMER__);h.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
|
package/lib/module/config.js
CHANGED
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
15
15
|
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
16
16
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
17
|
-
*/export const KEYGEN_CONFIG=Object.freeze({accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"});export{FREE_TOKEN_PUBLIC_KEY}from"./freeTokenKey.js";export{SESSION_TOKEN_PUBLIC_KEY}from"./sessionTokenKey.js";export const KEYGEN_POLICIES=Object.freeze({free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"});export const LICENSE_CACHE_DURATION=30*24*60*60*1e3;export const LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;export const LICENSE_STORAGE_KEY="buoy-gg-license";export const DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";export const DEVICE_FINGERPRINT_OWNER_STORAGE_KEY="buoy-gg-device-fingerprint-owner";export const LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;export const LICENSE_TRANSIENT_RETRY_DELAYS=[5*1e3,20*1e3,60*1e3,5*60*1e3,15*60*1e3];export const LICENSE_RATE_LIMIT_DEFAULT_WAIT=60*1e3;export const LICENSE_QUOTA_COOLDOWN=60*60*1e3;export const LICENSE_VERDICT_CACHE_DURATION=24*60*60*1e3;export const LICENSE_FLEET_MACHINE_THRESHOLD=50;export const LICENSE_QUIET_VALIDATION_TTL=LICENSE_CACHE_DURATION;export const LICENSE_HOLD_STORAGE_KEY="buoy-gg-license-hold";
|
|
17
|
+
*/export const KEYGEN_CONFIG=Object.freeze({accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"});export{FREE_TOKEN_PUBLIC_KEY}from"./freeTokenKey.js";export{SESSION_TOKEN_PUBLIC_KEY}from"./sessionTokenKey.js";export const KEYGEN_POLICIES=Object.freeze({free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"});export const LICENSE_CACHE_DURATION=30*24*60*60*1e3;export const LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;export const LICENSE_STORAGE_KEY="buoy-gg-license";export const SIGNED_OUT_KEY_STORAGE_KEY="buoy-gg-signed-out-key";export const DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";export const DEVICE_FINGERPRINT_OWNER_STORAGE_KEY="buoy-gg-device-fingerprint-owner";export const LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;export const LICENSE_TRANSIENT_RETRY_DELAYS=[5*1e3,20*1e3,60*1e3,5*60*1e3,15*60*1e3];export const LICENSE_RATE_LIMIT_DEFAULT_WAIT=60*1e3;export const LICENSE_QUOTA_COOLDOWN=60*60*1e3;export const LICENSE_VERDICT_CACHE_DURATION=24*60*60*1e3;export const LICENSE_FLEET_MACHINE_THRESHOLD=50;export const LICENSE_QUIET_VALIDATION_TTL=LICENSE_CACHE_DURATION;export const LICENSE_HOLD_STORAGE_KEY="buoy-gg-license-hold";
|
|
@@ -24,6 +24,8 @@ export interface DeviceRegistrationInfo {
|
|
|
24
24
|
export type DeviceRegistrationCallback = (info: DeviceRegistrationInfo) => void;
|
|
25
25
|
declare class LicenseManagerImpl {
|
|
26
26
|
private state;
|
|
27
|
+
/** The key behind `state.keySignedOut`, held so it can be matched and given back. */
|
|
28
|
+
private signedOutKey;
|
|
27
29
|
private listeners;
|
|
28
30
|
private revalidationTimer;
|
|
29
31
|
private cachedLicense;
|
|
@@ -133,6 +135,13 @@ declare class LicenseManagerImpl {
|
|
|
133
135
|
* Clear the current license
|
|
134
136
|
*/
|
|
135
137
|
clearLicense(): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Sign out of everything on this device: the sign-in and the key. The key
|
|
140
|
+
* is remembered, because a build can pass it again on the next launch.
|
|
141
|
+
*/
|
|
142
|
+
signOut(): Promise<void>;
|
|
143
|
+
/** Undo signOut() for the key. False when there is none or it's rejected. */
|
|
144
|
+
restoreSignedOutKey(): Promise<boolean>;
|
|
136
145
|
/**
|
|
137
146
|
* Set the tier a validated key granted and keep the derived fields in step.
|
|
138
147
|
*
|
|
@@ -181,6 +190,7 @@ declare class LicenseManagerImpl {
|
|
|
181
190
|
isInitialized: boolean;
|
|
182
191
|
isValidating: boolean;
|
|
183
192
|
licenseKey: string | null;
|
|
193
|
+
keySignedOut: boolean;
|
|
184
194
|
error: string | null;
|
|
185
195
|
errorKind: "transport" | "verdict" | null;
|
|
186
196
|
expiresAt: Date | null;
|
|
@@ -248,6 +258,9 @@ declare class LicenseManagerImpl {
|
|
|
248
258
|
* older build, or no device id) keeps the saved one.
|
|
249
259
|
*/
|
|
250
260
|
private getOrCreateDeviceFingerprint;
|
|
261
|
+
private loadSignedOutKey;
|
|
262
|
+
private rememberSignedOutKey;
|
|
263
|
+
private forgetSignedOutKey;
|
|
251
264
|
private clearCachedLicense;
|
|
252
265
|
/**
|
|
253
266
|
* Register device in background for visibility (non-blocking)
|
|
@@ -74,6 +74,8 @@ export declare const KEYGEN_POLICIES: Readonly<{
|
|
|
74
74
|
export declare const LICENSE_CACHE_DURATION: number;
|
|
75
75
|
export declare const LICENSE_REVALIDATION_INTERVAL: number;
|
|
76
76
|
export declare const LICENSE_STORAGE_KEY = "buoy-gg-license";
|
|
77
|
+
/** The key the person signed out of, so a build that passes it can't sign them back in. */
|
|
78
|
+
export declare const SIGNED_OUT_KEY_STORAGE_KEY = "buoy-gg-signed-out-key";
|
|
77
79
|
export declare const DEVICE_FINGERPRINT_STORAGE_KEY = "buoy-gg-device-fingerprint";
|
|
78
80
|
export declare const DEVICE_FINGERPRINT_OWNER_STORAGE_KEY = "buoy-gg-device-fingerprint-owner";
|
|
79
81
|
export declare const LICENSE_LAUNCH_VALIDATION_TTL: number;
|
|
@@ -198,6 +198,11 @@ export interface LicenseState {
|
|
|
198
198
|
/** What granted `tier`. */
|
|
199
199
|
tierSource: TierSource;
|
|
200
200
|
licenseKey: string | null;
|
|
201
|
+
/**
|
|
202
|
+
* True after the person signed out of a key. The app can still pass that
|
|
203
|
+
* key on every launch, and it stays unused until they ask for it back.
|
|
204
|
+
*/
|
|
205
|
+
keySignedOut: boolean;
|
|
201
206
|
error: string | null;
|
|
202
207
|
/**
|
|
203
208
|
* What kind of failure `error` describes, so UIs can give the right advice:
|
|
@@ -24,6 +24,8 @@ export interface DeviceRegistrationInfo {
|
|
|
24
24
|
export type DeviceRegistrationCallback = (info: DeviceRegistrationInfo) => void;
|
|
25
25
|
declare class LicenseManagerImpl {
|
|
26
26
|
private state;
|
|
27
|
+
/** The key behind `state.keySignedOut`, held so it can be matched and given back. */
|
|
28
|
+
private signedOutKey;
|
|
27
29
|
private listeners;
|
|
28
30
|
private revalidationTimer;
|
|
29
31
|
private cachedLicense;
|
|
@@ -133,6 +135,13 @@ declare class LicenseManagerImpl {
|
|
|
133
135
|
* Clear the current license
|
|
134
136
|
*/
|
|
135
137
|
clearLicense(): Promise<void>;
|
|
138
|
+
/**
|
|
139
|
+
* Sign out of everything on this device: the sign-in and the key. The key
|
|
140
|
+
* is remembered, because a build can pass it again on the next launch.
|
|
141
|
+
*/
|
|
142
|
+
signOut(): Promise<void>;
|
|
143
|
+
/** Undo signOut() for the key. False when there is none or it's rejected. */
|
|
144
|
+
restoreSignedOutKey(): Promise<boolean>;
|
|
136
145
|
/**
|
|
137
146
|
* Set the tier a validated key granted and keep the derived fields in step.
|
|
138
147
|
*
|
|
@@ -181,6 +190,7 @@ declare class LicenseManagerImpl {
|
|
|
181
190
|
isInitialized: boolean;
|
|
182
191
|
isValidating: boolean;
|
|
183
192
|
licenseKey: string | null;
|
|
193
|
+
keySignedOut: boolean;
|
|
184
194
|
error: string | null;
|
|
185
195
|
errorKind: "transport" | "verdict" | null;
|
|
186
196
|
expiresAt: Date | null;
|
|
@@ -248,6 +258,9 @@ declare class LicenseManagerImpl {
|
|
|
248
258
|
* older build, or no device id) keeps the saved one.
|
|
249
259
|
*/
|
|
250
260
|
private getOrCreateDeviceFingerprint;
|
|
261
|
+
private loadSignedOutKey;
|
|
262
|
+
private rememberSignedOutKey;
|
|
263
|
+
private forgetSignedOutKey;
|
|
251
264
|
private clearCachedLicense;
|
|
252
265
|
/**
|
|
253
266
|
* Register device in background for visibility (non-blocking)
|
|
@@ -74,6 +74,8 @@ export declare const KEYGEN_POLICIES: Readonly<{
|
|
|
74
74
|
export declare const LICENSE_CACHE_DURATION: number;
|
|
75
75
|
export declare const LICENSE_REVALIDATION_INTERVAL: number;
|
|
76
76
|
export declare const LICENSE_STORAGE_KEY = "buoy-gg-license";
|
|
77
|
+
/** The key the person signed out of, so a build that passes it can't sign them back in. */
|
|
78
|
+
export declare const SIGNED_OUT_KEY_STORAGE_KEY = "buoy-gg-signed-out-key";
|
|
77
79
|
export declare const DEVICE_FINGERPRINT_STORAGE_KEY = "buoy-gg-device-fingerprint";
|
|
78
80
|
export declare const DEVICE_FINGERPRINT_OWNER_STORAGE_KEY = "buoy-gg-device-fingerprint-owner";
|
|
79
81
|
export declare const LICENSE_LAUNCH_VALIDATION_TTL: number;
|
|
@@ -198,6 +198,11 @@ export interface LicenseState {
|
|
|
198
198
|
/** What granted `tier`. */
|
|
199
199
|
tierSource: TierSource;
|
|
200
200
|
licenseKey: string | null;
|
|
201
|
+
/**
|
|
202
|
+
* True after the person signed out of a key. The app can still pass that
|
|
203
|
+
* key on every launch, and it stays unused until they ask for it back.
|
|
204
|
+
*/
|
|
205
|
+
keySignedOut: boolean;
|
|
201
206
|
error: string | null;
|
|
202
207
|
/**
|
|
203
208
|
* What kind of failure `error` describes, so UIs can give the right advice:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{m as e}from"./chunk-ISATKL5M.mjs";import"./chunk-YHWYXKID.mjs";export{e as LicenseManager};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";import{a as j,b as at,c as ot,d as lt,e as m,f,i as ct}from"./chunk-YHWYXKID.mjs";var ue,ht=j(()=>{"use strict";f();ue='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'});import{useEffect as dt,useState as ut}from"react";import{createPortal as ft}from"react-dom";import{jsx as pt}from"react/jsx-runtime";function fe(){let e=document;if(e[S])return e[S].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:ue});let i=()=>{let o=document.fullscreenElement,d=o&&o.tagName!=="CANVAS"?o:document.body;t.parentElement!==d&&d.appendChild(t)},r=new Map,s=o=>{(!t.contains(o.target)||!H(o.target))&&r.set(o.code||o.key,{key:o.key,code:o.code,location:o.location,keyCode:o.keyCode,which:o.which,altKey:o.altKey,ctrlKey:o.ctrlKey,metaKey:o.metaKey,shiftKey:o.shiftKey})},n=o=>{r.delete(o.code||o.key)},h=()=>r.clear(),c=()=>{let o=[...r.values()];r.clear();for(let d of o)document.dispatchEvent(new KeyboardEvent("keyup",{...d,bubbles:true}))},a=o=>{H(o.target)&&o.stopPropagation()},l=o=>o.stopPropagation();return i(),document.addEventListener("fullscreenchange",i),document.addEventListener("keydown",s,true),document.addEventListener("keyup",n,true),window.addEventListener("blur",h),t.addEventListener("focusin",c),t.addEventListener("keydown",a),t.addEventListener("keyup",a),t.addEventListener("keypress",a),t.addEventListener("wheel",l,{passive:true}),e[S]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",i),document.removeEventListener("keydown",s,true),document.removeEventListener("keyup",n,true),window.removeEventListener("blur",h),t.remove(),delete e[S]}},t}function mt({children:e}){let[t,i]=ut(null);return dt(()=>{let r=fe(),s=document[S];return s.users++,i(r),()=>{--s.users===0&&s.dispose()}},[]),t?ft(pt("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var S,H,gt=j(()=>{"use strict";f();ht();S=Symbol.for("@buoy-gg/portal-host"),H=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"}});var z={};at(z,{AccessibilityInfo:()=>bt,ActivityIndicator:()=>Se,Alert:()=>Ce,Animated:()=>ve,AppRegistry:()=>At,AppState:()=>kt,Appearance:()=>Tt,BackHandler:()=>Et,Button:()=>Ie,CheckBox:()=>Ut,Clipboard:()=>xt,DeviceEventEmitter:()=>ii,Dimensions:()=>_t,Easing:()=>Lt,FlatList:()=>Ft,I18nManager:()=>St,Image:()=>Bt,ImageBackground:()=>jt,InteractionManager:()=>Rt,Keyboard:()=>It,KeyboardAvoidingView:()=>Ht,LayoutAnimation:()=>Ct,Linking:()=>Pt,LogBox:()=>ti,Modal:()=>_e,NativeEventEmitter:()=>Nt,NativeModules:()=>vt,PanResponder:()=>Kt,Picker:()=>zt,PixelRatio:()=>Ot,Platform:()=>Mt,Pressable:()=>Ee,ProgressBar:()=>Gt,RefreshControl:()=>Yt,SafeAreaView:()=>Wt,ScrollView:()=>xe,SectionList:()=>Jt,Share:()=>Vt,StatusBar:()=>Xt,StyleSheet:()=>we,Switch:()=>Le,Text:()=>J,TextInput:()=>be,Touchable:()=>qt,TouchableHighlight:()=>Ae,TouchableNativeFeedback:()=>Zt,TouchableOpacity:()=>Te,TouchableWithoutFeedback:()=>ke,UIManager:()=>Dt,Vibration:()=>$t,View:()=>W,VirtualizedList:()=>Qt,YellowBox:()=>ei,findNodeHandle:()=>Re,unstable_createElement:()=>wt,useColorScheme:()=>ri,useLocaleContext:()=>si,useWindowDimensions:()=>ni});import*as yt from"react-native-web";import{unstable_createElement as wt,NativeModules as vt,AccessibilityInfo as bt,Appearance as Tt,AppRegistry as At,AppState as kt,BackHandler as Et,Clipboard as xt,Dimensions as _t,Easing as Lt,I18nManager as St,Keyboard as It,InteractionManager as Rt,LayoutAnimation as Ct,Linking as Pt,NativeEventEmitter as Nt,PanResponder as Kt,PixelRatio as Ot,Platform as Mt,Share as Vt,UIManager as Dt,Vibration as $t,CheckBox as Ut,FlatList as Ft,Image as Bt,ImageBackground as jt,KeyboardAvoidingView as Ht,Picker as zt,ProgressBar as Gt,RefreshControl as Yt,SafeAreaView as Wt,SectionList as Jt,StatusBar as Xt,Touchable as qt,TouchableNativeFeedback as Zt,VirtualizedList as Qt,YellowBox as ei,LogBox as ti,DeviceEventEmitter as ii,useColorScheme as ri,useLocaleContext as si,useWindowDimensions as ni}from"react-native-web";import*as g from"react-native-web";import{createElement as G,forwardRef as pe,useCallback as ai,useRef as oi}from"react";function Y(e){if(Array.isArray(e)){let d=e.map(Y);return d.some((k,E)=>k!==e[E])?d:e}if(!e||typeof e!="object"||!ge.some(d=>e[d]!=null))return e;let{shadowColor:t,shadowOffset:i,shadowOpacity:r,shadowRadius:s,textShadowColor:n,textShadowOffset:h,textShadowRadius:c,...a}=e;if(t!=null||i!=null||r!=null||s!=null){let d=t??"black",k=r==null?d:`color-mix(in srgb, ${d} ${Math.min(r,1)*100}%, transparent)`,E=`${_(i?.width??0)} ${_(i?.height??0)} ${_(s??0)} ${k}`;a.boxShadow=typeof a.boxShadow=="string"?`${a.boxShadow}, ${E}`:a.boxShadow??E}let{width:l=0,height:o=0}=h??{};if(n&&(l||o||c)){let d=`${_(l)} ${_(o)} ${_(c??0)} ${n}`;a.textShadow=a.textShadow?`${a.textShadow}, ${d}`:d}return a}function me(e,t){if(typeof e=="function")return r=>me(e(r),t);let i=Y(e);return t?[i,ye[t]]:i}function y(e){let t=pe((r,s)=>{let{accessibilityState:n,accessibilityValue:h,pointerEvents:c,...a}=r;for(let o of["busy","checked","disabled","expanded","selected"])n?.[o]!==void 0&&a[`aria-${o}`]===void 0&&(a[`aria-${o}`]=n[o]);for(let[o,d]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))h?.[o]!==void 0&&a[`aria-${d}`]===void 0&&(a[`aria-${d}`]=h[o]);let l=me(a.style,c);return l!==a.style&&(a.style=l),G(e,{...a,ref:s})}),i=e.State;return i&&Object.assign(t,{State:i}),t.displayName=e.displayName??e.name??"NativeWebView",t}var x,ge,_,ye,we,W,J,ve,be,Te,Ae,ke,Ee,xe,X,_e,Le,Se,Ie,Re,Ce,li=j(()=>{f();ot(z,yt);gt();x=g,ge=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],_=e=>typeof e=="number"?`${e}px`:e;ye=x.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});we={...x.StyleSheet,create:e=>x.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,i])=>[t,Y(i)])))};W=y(g.View),J=y(g.Text),ve={...x.Animated,View:x.Animated.createAnimatedComponent(W),Text:x.Animated.createAnimatedComponent(J)},be=y(g.TextInput),Te=y(g.TouchableOpacity),Ae=y(g.TouchableHighlight),ke=y(g.TouchableWithoutFeedback),Ee=y(g.Pressable),xe=y(g.ScrollView),X=pe((e,t)=>{let i=oi(null),r=ai(s=>{if(s){let n=s;for(;n.parentElement&&n.parentElement!==document.body;)n=n.parentElement;n.parentElement===document.body&&(i.current=n,Object.assign(n.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),fe().appendChild(n))}else i.current&&(document.body.appendChild(i.current),i.current=null);typeof t=="function"?t(s):t&&(t.current=s)},[t]);return G(mt,null,G(g.Modal,{...e,ref:r}))});X.displayName="Modal";_e=y(X),Le=y(g.Switch),Se=y(g.ActivityIndicator),Ie=y(g.Button),Re=g.findNodeHandle,Ce={alert(e,t,i,r){if(typeof document>"u")return;let s=document.createElement("dialog");s.dataset.buoyRoot="",s.setAttribute("aria-label",e),s.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 n=document.createElement("h2");if(n.textContent=e,n.style.cssText="font-size:18px;margin:0 0 12px",s.appendChild(n),t){let l=document.createElement("p");l.textContent=t,l.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",s.appendChild(l)}let h=document.createElement("div");h.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let c=i?.length?i:[{text:"OK"}],a=()=>{s.close?.(),s.remove()};for(let l of c){let o=document.createElement("button");o.type="button",o.textContent=l.text??"OK",o.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${l.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,o.onclick=()=>{a(),l.onPress?.()},h.appendChild(o)}s.addEventListener("cancel",l=>{l.preventDefault(),r?.cancelable!==false&&(a(),r?.onDismiss?.())}),s.appendChild(h),document.body.appendChild(s),s.showModal?s.showModal():s.setAttribute("open","")}}});f();f();var O=new Map,ci={async getItem(e){try{return localStorage.getItem(e)??O.get(e)??null}catch{return O.get(e)??null}},async setItem(e,t){O.set(e,t);try{localStorage.setItem(e,t)}catch{}},async removeItem(e){O.delete(e);try{localStorage.removeItem(e)}catch{}}};async function v(){return ci}f();f();var hi="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";f();var di="36abba0267f7f379d992a5b6df641daab4190bcc9e639e36f1378e3c1ac52746";var M=Object.freeze({accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"}),V=Object.freeze({free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"}),D=720*60*60*1e3,ui=1440*60*1e3,q="buoy-gg-license",Z="buoy-gg-signed-out-key",Q="buoy-gg-device-fingerprint",Pe="buoy-gg-device-fingerprint-owner",fi=3600*1e3,pi=[5*1e3,20*1e3,60*1e3,300*1e3,900*1e3],mi=60*1e3,Ne=3600*1e3,gi=1440*60*1e3,yi=50,wi=D,ee="buoy-gg-license-hold";f();f();function u(){let e=globalThis.__buoyRealNow;return typeof e=="function"?e():Date.now()}var{apiUrl:Ke}=M,I=class extends Error{constructor(e,t,i=null){super(e);this.isTransient=true;this.name="LicenseTransportError",this.status=t,this.retryAfterMs=i}};function vi(e){let t=e?.status;return t===429||t===402}function bi(e,t,i){return e.status===402?t:e.retryAfterMs??i}function Ti(e){let t=s=>{try{return e.headers?.get?.(s)??null}catch{return null}},i=t("Retry-After");if(i){let s=Number(i);if(Number.isFinite(s)&&s>=0)return s*1e3;let n=Date.parse(i);if(Number.isFinite(n))return Math.max(0,n-u())}let r=Number(t("X-RateLimit-Reset"));return Number.isFinite(r)&&r>0?Math.max(0,r*1e3-u()):null}function Oe(e){return e instanceof I||e instanceof TypeError?true:typeof e=="object"&&e!==null&&e.isTransient===true}async function Ai(e){try{return(await e.json()).errors?.[0]?.detail||`HTTP ${e.status}`}catch{return`HTTP ${e.status}`}}function Me(){return{"Content-Type":"application/vnd.api+json",Accept:"application/vnd.api+json"}}async function ki(e,t){let i=`${Ke}/validate`,r={meta:{key:e}},s;try{s=await fetch(i,{signal:t,method:"POST",headers:Me(),body:JSON.stringify(r)})}catch(n){throw new I(n instanceof Error?n.message:"Network request failed",null)}if(!s.ok)throw new I(await Ai(s),s.status,s.status===429?Ti(s):null);try{let n=await s.json();if(!n||typeof n!="object"||typeof n.meta?.valid!="boolean"||typeof n.meta?.code!="string"||!n.meta.code)throw new Error("Missing license verdict");return n}catch{throw new I("License server returned an unreadable response",s.status)}}async function Ei(e){let t=typeof AbortController=="function"?new AbortController:null,i;try{return await Promise.race([ki(e,t?.signal),new Promise((r,s)=>{i=setTimeout(()=>{s(new I("License verification timed out. Please retry.",null)),t?.abort()},15e3)})])}finally{i&&clearTimeout(i)}}function xi(e){if(!e.data)return false;let t=e.data.relationships?.product?.data?.id;return t&&t!==M.productId?false:e.meta.valid&&e.meta.code==="VALID"?true:["OVERDUE","NO_MACHINE","NO_MACHINES","TOO_MANY_MACHINES","TOO_MANY_CORES","TOO_MANY_PROCESSES","FINGERPRINT_SCOPE_MISMATCH","HEARTBEAT_NOT_STARTED","HEARTBEAT_DEAD"].includes(e.meta.code)}function _i(e){let t=e.data?.relationships?.machines?.meta?.count;return typeof t=="number"&&Number.isFinite(t)?t:0}async function Ve(e,t,i,r,s){let n=`${Ke}/machines`,h=await fetch(n,{method:"POST",headers:Me(),body:JSON.stringify({licenseId:e,licenseKey:t,fingerprint:i,name:r,metadata:s||{}})});if(!h.ok){let c=await h.json(),a=c.errors?.[0]?.code;if(a==="FINGERPRINT_TAKEN")throw new Error("FINGERPRINT_TAKEN");if(a==="MACHINE_LIMIT_EXCEEDED")throw new Error("MACHINE_LIMIT_EXCEEDED");let l=c.errors?.[0]?.detail||`HTTP ${h.status}`;throw new Error(l)}return h.json()}function Li(e){let{meta:t,data:i}=e;return{valid:t.valid,code:t.code,detail:t.detail,metadata:i?.attributes?.metadata}}function Si(e){return["NOT_FOUND","SUSPENDED","EXPIRED","BANNED","PRODUCT_SCOPE_MISMATCH"].includes(e)}f();f();function te(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function ie(){let e=ct();if(e!==null)return e;if(typeof m<"u")return m;try{if(typeof navigator<"u"&&/electron/i.test(navigator.userAgent))return true}catch{}return typeof process<"u"&&process.env.NODE_ENV!=="production"}function De(){if(typeof navigator>"u")return"unknown";let e=navigator.userAgent.toLowerCase(),t=navigator.platform?.toLowerCase()||"";return e.includes("electron")?t.includes("mac")||e.includes("mac")?"electron-macos":t.includes("win")||e.includes("win")?"electron-windows":t.includes("linux")||e.includes("linux")?"electron-linux":"electron":t.includes("mac")||e.includes("mac")?"macos":t.includes("win")||e.includes("win")?"windows":t.includes("linux")||e.includes("linux")?"linux":/iphone|ipad|ipod/.test(e)?"ios-web":e.includes("android")?"android-web":"web"}function Ii(){if(typeof navigator>"u")return"unknown";let e=navigator.userAgent,t=e.match(/Mac OS X ([\d_.]+)/);if(t)return t[1].replace(/_/g,".");let i=e.match(/Windows NT ([\d.]+)/);return i?{"10.0":"10/11","6.3":"8.1","6.2":"8","6.1":"7"}[i[1]]||i[1]:e.includes("Linux")?"Linux":"unknown"}function $e(){if(typeof navigator>"u")return{name:"unknown",version:"unknown"};let e=navigator.userAgent,t=e.match(/Electron\/([\d.]+)/);if(t)return{name:"Electron",version:t[1]};let i=e.match(/Chrome\/([\d.]+)/);if(i&&!e.includes("Edg"))return{name:"Chrome",version:i[1]};let r=e.match(/Edg\/([\d.]+)/);if(r)return{name:"Edge",version:r[1]};let s=e.match(/Firefox\/([\d.]+)/);if(s)return{name:"Firefox",version:s[1]};let n=e.match(/Version\/([\d.]+).*Safari/);return n?{name:"Safari",version:n[1]}:{name:"unknown",version:"unknown"}}function Ue(){let e={platform:De(),osVersion:Ii(),isSimulator:"false"},t=$e();e.browser=t.name,e.browserVersion=t.version,typeof window<"u"&&window.screen&&(e.screenResolution=`${window.screen.width}x${window.screen.height}`),typeof navigator<"u"&&navigator.language&&(e.language=navigator.language);try{e.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{}return e}function re(){let e=De(),t=$e();if(e.startsWith("electron")){let i=e.replace("electron-","").replace("electron","Desktop");return`${i.charAt(0).toUpperCase()+i.slice(1)} App`}return t.name!=="unknown"?`${t.name} Browser`:"Web Browser"}async function Ri(){return null}f();function Ci(e){let{stored:t,storedOwner:i,marker:r,blobFingerprint:s,mint:n}=e;if(!!r&&!!i&&i!==r)return{fingerprint:n(),owner:r,restored:true,changed:true};let h=r??i;return t?{fingerprint:t,owner:h,restored:false,changed:h!==i}:{fingerprint:s||n(),owner:h,restored:false,changed:true}}function Pi(e){let t=2166136261,i=16777619;for(let r=0;r<e.length;r++){let s=e.charCodeAt(r);t=Math.imul(t^s,16777619)>>>0,i=Math.imul(i^s,1540483477)>>>0}return`v1:${t.toString(16).padStart(8,"0")}${i.toString(16).padStart(8,"0")}`}f();var Ni=["v1"],Ki="buoy.gg/pro:9f3c1d7a4b2e:license-cache";function Fe(e,t){let i=t>>>0;for(let r=0;r<e.length;r++)i^=e.charCodeAt(r),i=Math.imul(i,16777619)>>>0;return i>>>0}function Oi(e,t){let i=[t,e.licenseKey,e.licenseId,e.isPro?"1":"0",e.expiresAt??"",String(e.cachedAt)];return t!=="v1"&&i.push(e.tier??""),i.push(Ki),i.join("\0")}function Be(e,t){let i=Oi(e,t),r=Fe(i,2166136261),s=Fe(i,2135587861);return`${t}.${r.toString(16)}${s.toString(16)}`}function je(e){return Be(e,"v2")}function He(e){return{...e,sig:je(e)}}function R(e){return!e||typeof e.sig!="string"||e.sig.length===0?false:e.sig===je(e)?true:Ni.some(t=>e.sig.startsWith(`${t}.`)&&e.sig===Be(e,t))}f();import Mi from"tweetnacl";var Vi=1,Di=1,$i="buoy-free-token-v1:",Ui=22,Fi=64,ze=/^BUOY1-([A-Z2-7]+)-([A-Z2-7]+)$/;function Ge(e){return ze.test(e.trim().toUpperCase())}var Bi="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";function Ye(e){let t=[],i=0,r=0;for(let s of e){let n=Bi.indexOf(s);if(n===-1)return null;r=r<<5|n,i+=5,i>=8&&(t.push(r>>>i-8&255),i-=8)}return new Uint8Array(t)}function ji(e){let t=e.trim().toLowerCase(),i=new Uint8Array(t.length/2);for(let r=0;r<i.length;r+=1)i[r]=parseInt(t.slice(r*2,r*2+2),16);return i}function Hi(e){let t="";for(let i of e)t+=i.toString(16).padStart(2,"0");return t}function zi(e){if(typeof TextEncoder<"u")return new TextEncoder().encode(e);let t=new Uint8Array(e.length);for(let i=0;i<e.length;i+=1)t[i]=e.charCodeAt(i)&255;return t}function Gi(e,t){let i=new Uint8Array(e.length+t.length);return i.set(e,0),i.set(t,e.length),i}function Yi(e){return Gi(zi($i),e)}var Wi=hi;function Ji(e){let t=ze.exec(e.trim().toUpperCase());if(!t)return null;let i=Ye(t[1]),r=Ye(t[2]);if(!i||!r||i.length!==Ui||r.length!==Fi||i[0]!==Vi||i[1]!==Di)return null;try{if(!Mi.sign.detached.verify(Yi(i),r,ji(Wi)))return null}catch{return null}return{tier:"free",issuedAt:((i[2]<<24>>>0)+(i[3]<<16)+(i[4]<<8)+i[5])*1e3,accountHash:Hi(i.slice(6,22))}}f();function Xi(e){let t=e.relationships?.policy?.data?.id;return t===V.free?"free":t===V.solo||t===V.business?"pro":e.attributes?.metadata?.plan==="free"?"free":"pro"}function qi(e){if(!e)return false;let t=e.relationships?.product?.data?.id;if(t)return t===M.productId;let i=e.relationships?.policy?.data?.id;return Object.values(V).some(r=>r===i)}f();function We(e,t=u()){let i=e.verifiedAt!==null&&Number.isFinite(e.verifiedAt)&&e.verifiedAt<=t?e.verifiedAt+D:null;return e.initialized&&e.key&&e.tierSource!=="none"&&i!==null&&t<i?{status:"admitted",reason:null,validUntil:i}:i!==null&&t>=i?{status:"locked",reason:"verification_expired",validUntil:i}:!e.initialized||e.validating?{status:"initializing",reason:"checking",validUntil:i}:{status:"locked",reason:i!==null&&t>=i?"verification_expired":"account_required",validUntil:i}}f();function Zi(e){if(typeof window>"u"||typeof window.addEventListener!="function")return()=>{};let t=()=>{document.hidden||e()};return window.addEventListener("focus",e),document.addEventListener("visibilitychange",t),()=>{window.removeEventListener("focus",e),document.removeEventListener("visibilitychange",t)}}f();f();import Qi from"tweetnacl";var Je="buoys1",er="buoy-session-v1:",Xe=1,se=60,tr=64,ir=["free","pro","business"],T="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function ne(e){let t="",i=0;for(;i+2<e.length;i+=3){let s=e[i]<<16|e[i+1]<<8|e[i+2];t+=T[s>>>18&63]+T[s>>>12&63]+T[s>>>6&63]+T[s&63]}let r=e.length-i;if(r===1){let s=e[i]<<16;t+=T[s>>>18&63]+T[s>>>12&63]}else if(r===2){let s=e[i]<<16|e[i+1]<<8;t+=T[s>>>18&63]+T[s>>>12&63]+T[s>>>6&63]}return t}function qe(e){if(!/^[A-Za-z0-9_-]*$/.test(e)||e.length%4===1)return null;let t=[],i=0,r=0;for(let s of e)r=r<<6|T.indexOf(s),i+=6,i>=8&&(t.push(r>>>i-8&255),i-=8);return new Uint8Array(t)}function rr(e){if(typeof TextEncoder<"u")return new TextEncoder().encode(e);let t=unescape(encodeURIComponent(e)),i=new Uint8Array(t.length);for(let r=0;r<t.length;r+=1)i[r]=t.charCodeAt(r);return i}function sr(e){try{if(typeof TextDecoder<"u")return new TextDecoder("utf-8",{fatal:true}).decode(e);let t="";for(let i of e)t+=String.fromCharCode(i);return decodeURIComponent(escape(t))}catch{return null}}function nr(e){let t=e.trim().toLowerCase(),i=new Uint8Array(t.length/2);for(let r=0;r<i.length;r+=1)i[r]=parseInt(t.slice(r*2,r*2+2),16);return i}function ar(e){return rr(er+e)}function C(e,t=256){return typeof e=="string"&&e.length>0&&e.length<=t}function Ze(e){return typeof e=="number"&&Number.isInteger(e)&&e>0}function or(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return!C(t.sid)||!C(t.sub)||!C(t.aud,512)||t.team!==null&&!C(t.team)||!ir.includes(t.tier)||t.role!==void 0&&!C(t.role,64)||t.tools!==void 0&&(!Array.isArray(t.tools)||t.tools.length>256||!t.tools.every(i=>C(i,64)))||!Ze(t.iat)||!Ze(t.exp)||t.exp<=t.iat?null:{v:Xe,sid:t.sid,sub:t.sub,team:t.team,tier:t.tier,...t.role!==void 0?{role:t.role}:{},...t.tools!==void 0?{tools:[...t.tools]}:{},aud:t.aud,iat:t.iat,exp:t.exp}}var lr=di;function Qe(e){return e.startsWith(`${Je}.`)}function ae(e,t){let i=lr;if(!i)return{ok:false,reason:"no-key"};let r=typeof e=="string"?e.split("."):[];if(r.length!==3||r[0]!==Je)return{ok:false,reason:"malformed"};let[,s,n]=r,h=qe(s),c=qe(n);if(!h||!c||c.length!==tr)return{ok:false,reason:"malformed"};try{if(!Qi.sign.detached.verify(ar(s),c,nr(i)))return{ok:false,reason:"signature"}}catch{return{ok:false,reason:"signature"}}let a=sr(h),l;try{l=a===null?null:JSON.parse(a)}catch{return{ok:false,reason:"malformed"}}if(!l||typeof l!="object"||l.v!==Xe)return{ok:false,reason:l&&typeof l=="object"?"version":"malformed"};let o=or(l);if(!o)return{ok:false,reason:"claims"};if(o.aud!==t.audience)return{ok:false,reason:"audience"};if(t.ignoreTime)return{ok:true,claims:o};let d=Math.floor((t.nowMs??u())/1e3);return d>=o.exp+se?{ok:false,reason:"expired"}:o.iat>d+se?{ok:false,reason:"not-yet-valid"}:{ok:true,claims:o}}var cr="@buoy/session:",$=10080*60*1e3,et=360*60*1e3,hr=300*1e3,dr=5*1e3,ur=300*1e3,fr=15e3,pr="https://buoy.gg",mr="buoy:signin",gr=600*1e3,p=class extends Error{constructor(e,t){super(t);this.code=e;this.name="SessionError"}};function yr(){let e=globalThis;return{fetch:(t,i)=>fetch(t,i),storage:v,now:u,random:t=>{let i=new Uint8Array(t);if(!e.crypto?.getRandomValues)throw new p("not_configured","This platform has no secure random source.");return e.crypto.getRandomValues(i)},sha256:async t=>{if(!e.crypto?.subtle)throw new p("not_configured","Sign-in needs a secure page (https or localhost).");return new Uint8Array(await e.crypto.subtle.digest("SHA-256",t))},openPopup:()=>{if(!e.window?.open)return null;let t=480,i=640,r=Math.max(0,(e.window.screenX??0)+((e.window.outerWidth??t)-t)/2),s=Math.max(0,(e.window.screenY??0)+((e.window.outerHeight??i)-i)/2);return e.window.open("about:blank","buoy-signin",`popup,width=${t},height=${i},left=${r},top=${s}`)},onMessage:t=>{if(!e.window?.addEventListener)return()=>{};let i=r=>t({origin:r.origin,data:r.data});return e.window.addEventListener("message",i),()=>e.window?.removeEventListener("message",i)},withLock:(t,i)=>e.navigator?.locks?e.navigator.locks.request(t,i):i(),checksPlan:!e.window?.addEventListener||!!e.navigator?.locks,watch:t=>{let i=e.window;if(!i?.addEventListener)return wr(t.wake);let r=n=>t.storage(n.key),s=()=>{i.document?.visibilityState!=="hidden"&&t.wake()};return i.addEventListener("storage",r),i.addEventListener("online",t.wake),i.document?.addEventListener?.("visibilitychange",s),()=>{i.removeEventListener("storage",r),i.removeEventListener("online",t.wake),i.document?.removeEventListener?.("visibilitychange",s)}},setTimer:(t,i)=>setTimeout(t,Math.min(i,2147483647)),clearTimer:t=>clearTimeout(t)}}function wr(e){try{let{AppState:t}=(li(),lt(z)),i=t?.addEventListener?.("change",r=>{r==="active"&&e()});return()=>i?.remove()}catch{return()=>{}}}function vr(){let e=globalThis.location;if(!(!e?.origin||!/^https?:$/.test(e.protocol??"")))return e.origin}var br=class{constructor(e){this.signinOrigin=pr;this.current=null;this.claims=null;this.listeners=new Set;this.timer=null;this.refreshing=null;this.loaded=null;this.unwatch=null;this.limitTimer=null;this.epoch=0;this.planRetries=0;this.deps=e??yr(),this.audience=vr()}get origin(){return this.signinOrigin}configure(e){e.audience!==void 0&&(this.audience=e.audience),e.signinOrigin!==void 0&&(this.signinOrigin=e.signinOrigin.replace(/\/$/,"")),this.reset()}reset(){this.planRetries=0,this.unwatch?.(),this.unwatch=null,this.epoch+=1,this.limitTimer!==null&&this.deps.clearTimer(this.limitTimer),this.limitTimer=null,this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=null,this.current=null,this.claims=null,this.loaded=null,this.refreshing=null}get storageKey(){return cr+(this.audience??"")}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){for(let e of[...this.listeners])try{e()}catch(t){console.warn("[Buoy] sign-in listener error:",t)}}getAccessToken(){let e=this.getStatus();return e.state==="active"&&!e.grace?this.current?.accessToken??null:null}getStatus(){let e=this.claims;if(!e)return{state:"signed_out"};let t=e.exp*1e3,i=this.deps.now();return i<(e.iat-se)*1e3?{state:"signed_out"}:i<t?{state:"active",claims:e,grace:false,validUntil:t}:i<t+$?{state:"active",claims:e,grace:true,validUntil:t+$}:{state:"signed_out"}}load(){return this.loaded||(this.loaded=this.loadOnce()),this.loaded}async loadOnce(){if(!this.audience)return;this.unwatch??(this.unwatch=this.deps.watch?.({storage:t=>{(t===null||t===this.storageKey)&&this.sync()},wake:()=>{this.deps.checksPlan?this.checkPlan():this.claims&&this.refresh()}})??null);let e=await this.read();e&&this.adopt(e)&&(this.notify(),this.schedule(),this.deps.checksPlan&&this.checkPlan())}async sync(){if(!this.audience)return;let e=await this.read();if(!e){this.current&&this.clearLocal();return}e.refreshToken!==this.current?.refreshToken&&this.adopt(e)&&(this.notify(),this.schedule())}async read(){try{let e=await(await this.deps.storage()).getItem(this.storageKey);if(!e)return null;let t=JSON.parse(e);return t?.v===1&&typeof t.accessToken=="string"&&typeof t.refreshToken=="string"?t:null}catch{return null}}async write(e){let t=await this.deps.storage();e?await t.setItem(this.storageKey,JSON.stringify(e)):await t.removeItem(this.storageKey)}adopt(e){if(!this.audience)return false;let t=ae(e.accessToken,{audience:this.audience,ignoreTime:true}),i=t.ok?t.claims:null;return i?(this.current=e,this.claims=i,true):false}armLimit(){if(this.limitTimer!==null&&this.deps.clearTimer(this.limitTimer),this.limitTimer=null,!this.claims)return;let e=this.claims.exp*1e3,t=this.deps.now(),i=t<e?e:t<e+$?e+$:null;i!==null&&(this.limitTimer=this.deps.setTimer(()=>{this.limitTimer=null,this.notify(),this.armLimit()},i-t))}call(e,t){return new Promise((i,r)=>{let s=this.deps.setTimer(()=>r(new Error("timeout")),fr);this.deps.fetch(e,t).then(n=>{this.deps.clearTimer(s),i(n)},n=>{this.deps.clearTimer(s),r(n)})})}schedule(){if(this.armLimit(),this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=null,!this.claims)return;let e=this.claims.exp*1e3-et-this.deps.now();this.timer=this.deps.setTimer(()=>{this.timer=null,this.refresh()},Math.max(0,e))}refresh(e=false){return this.startRefresh(()=>this.refreshLocked(e))}checkPlan(e=hr){return this.startRefresh(()=>this.refreshLocked(false,e))}retryPlanCheck(){if(this.planRetries>=2){this.planRetries=0,this.schedule();return}this.planRetries+=1,this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=this.deps.setTimer(()=>{this.timer=null,this.checkPlan(0)},dr)}startRefresh(e){return this.refreshing||(this.refreshing=this.deps.withLock(this.lockName,e).catch(()=>this.retryLater()).finally(()=>{this.refreshing=null})),this.refreshing}get lockName(){return`buoy-session:${this.audience??""}`}async refreshLocked(e,t){let i=this.epoch,r=await this.read();if(!r){this.current&&this.clearLocal();return}if(r.refreshToken!==this.current?.refreshToken&&this.adopt(r)){this.notify(),this.schedule();return}if(!this.claims)return;let s=this.claims.exp*1e3-this.deps.now()>et,n=!e&&s&&t!==void 0,h=n&&this.planRetries>0&&this.timer===null,c=n&&this.deps.now()-this.claims.iat*1e3>=t;if(!e&&s&&!c&&!h){this.planRetries||this.schedule();return}let a=()=>n?this.retryPlanCheck():this.retryLater(),l,o;try{let d=await this.call(`${this.signinOrigin}/api/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:r.refreshToken,audience:this.audience})});l=d.status,o=await d.json().catch(()=>null)}catch{i===this.epoch&&a();return}if(i===this.epoch){if(l===200&&o&&typeof o.access_token=="string"&&typeof o.refresh_token=="string"){let d={v:1,accessToken:o.access_token,refreshToken:o.refresh_token};if(this.adopt(d)){this.planRetries=0,await this.write(d),this.notify(),this.schedule();return}}if(l===400||l===401||l===403){await this.write(null),this.clearLocal();return}a()}}retryLater(){this.armLimit(),this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=this.deps.setTimer(()=>{this.timer=null,this.refresh(true)},ur),this.notify()}clearLocal(){this.planRetries=0,this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=null,this.limitTimer!==null&&this.deps.clearTimer(this.limitTimer),this.limitTimer=null,this.current=null,this.claims=null,this.notify()}async signIn(){if(!this.audience)throw new p("not_configured","Sign-in needs a web page or a configured app id.");let e=this.deps.openPopup();if(!e)throw new p("popup_blocked","The browser blocked the sign-in window. Allow pop-ups for this site and try again.");try{return await this.signInWith((t,i)=>new Promise((r,s)=>{e.location.href=t;let n=this.deps.now(),h=null,c=o=>{h!==null&&this.deps.clearTimer(h),a(),o()},a=this.deps.onMessage(o=>{if(o.origin!==this.signinOrigin)return;let d=o.data;!d||d.type!==mr||d.state!==i||(typeof d.code=="string"?c(()=>r(d.code)):c(()=>s(new p("access_denied","Sign-in was cancelled."))))}),l=()=>{if(e.closed)return c(()=>s(new p("popup_closed","The sign-in window was closed.")));if(this.deps.now()-n>gr)return c(()=>s(new p("timeout","Sign-in took too long.")));h=this.deps.setTimer(l,500)};h=this.deps.setTimer(l,500)}))}finally{try{e.closed||e.close()}catch{}}}async signInWith(e){let t=this.audience;if(!t)throw new p("not_configured","Sign-in needs a web page or a configured app id.");let i=ne(this.deps.random(32)),r=ne(this.deps.random(16)),s=ne(await this.deps.sha256(new TextEncoder().encode(i))),n=`${this.signinOrigin}/auth/authorize?audience=${encodeURIComponent(t)}&code_challenge=${s}&code_challenge_method=S256&state=${r}`,h=await e(n,r),c;try{c=await this.call(`${this.signinOrigin}/api/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:h,code_verifier:i,audience:t})})}catch{throw new p("network","Buoy could not be reached. Check your connection and try again.")}let a=await c.json().catch(()=>null);if(c.status!==200||!a||typeof a.access_token!="string"||typeof a.refresh_token!="string"){let l=a&&typeof a.error_description=="string"?a.error_description:"Buoy did not accept this sign-in.";throw new p(c.status===503?"unavailable":"rejected",l)}return this.finishSignIn(a.access_token,a.refresh_token)}async finishSignIn(e,t){let i={v:1,accessToken:e,refreshToken:t};if(this.epoch+=1,!this.adopt(i))throw new p("rejected","Buoy sent a sign-in this app could not check.");return await this.write(i),await this.load(),this.notify(),this.schedule(),this.getStatus()}async signInWithCode(e,t={}){let i=this.audience;if(!i)throw new p("not_configured","Sign-in with a code needs this app's id (app:com.example.app).");let r=(a,l)=>this.call(`${this.signinOrigin}/api/auth/device/${a}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)}),s;try{s=await r("start",{audience:i})}catch{throw new p("network","Buoy could not be reached. Check your connection and try again.")}let n=await s.json().catch(()=>null);if(s.status!==200||!n||typeof n.device_code!="string"||typeof n.user_code!="string"||typeof n.verification_uri!="string"||typeof n.verification_uri_complete!="string"){let a=n&&typeof n.error_description=="string"?n.error_description:"Buoy could not start a sign-in.";throw new p(s.status===503?"unavailable":"rejected",a)}let h=this.deps.now()+(Number(n.expires_in)||600)*1e3,c=Math.max(5,Number(n.interval)||5)*1e3;for(e({userCode:n.user_code,verificationUri:n.verification_uri,verificationUriComplete:n.verification_uri_complete,expiresAt:h});;){if(await this.wait(c,t.signal),this.deps.now()>h)throw new p("timeout","The code ran out. Start again for a new one.");let a;try{a=await r("poll",{device_code:n.device_code})}catch{continue}let l=await a.json().catch(()=>null);if(a.status===200&&l&&typeof l.access_token=="string"&&typeof l.refresh_token=="string")return this.finishSignIn(l.access_token,l.refresh_token);let o=l&&typeof l.error=="string"?l.error:"";if(o==="authorization_pending"||a.status>=500)continue;if(o==="slow_down"||a.status===429){c+=5e3;continue}if(o==="access_denied")throw new p("access_denied","The sign-in was turned down on buoy.gg.");if(o==="expired_token")throw new p("timeout","The code ran out. Start again for a new one.");let d=l&&typeof l.error_description=="string"?l.error_description:"Buoy did not accept this sign-in.";throw new p("rejected",d)}}wait(e,t){return new Promise((i,r)=>{let s=()=>new p("access_denied","Sign-in was cancelled.");if(t?.aborted)return r(s());let n=()=>{this.deps.clearTimer(h),r(s())},h=this.deps.setTimer(()=>{t?.removeEventListener?.("abort",n),i()},e);t?.addEventListener?.("abort",n)})}async signOut(){this.epoch+=1;let e=this.current;this.clearLocal();let t=e;try{await this.deps.withLock(this.lockName,async()=>{t=await this.read()??e,await this.write(null)})}catch{await this.write(null).catch(()=>{})}if(t)try{await this.call(`${this.signinOrigin}/api/auth/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:t.refreshToken})})}catch{}}},A=new br;f();var Tr="bsk1_",Ar="service",kr=15e3;function oe(e){return e.startsWith(Tr)}function N(e){let t=e.trim();return oe(t)||Qe(t)?t:t.toUpperCase()}function Er(e,t){return N(e??"")===N(t??"")}async function xr(e,t){let i=t.fetch??((a,l)=>fetch(a,l)),r=typeof AbortController<"u"?new AbortController:void 0,s=setTimeout(()=>r?.abort(),kr),n,h;try{let a=await i(`${t.origin.replace(/\/$/,"")}/api/auth/service-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:e}),signal:r?.signal});n=a.status,h=await a.json().catch(()=>null)}catch{return{ok:false,reason:"network",detail:"Buoy could not be reached to check the bot key."}}finally{clearTimeout(s)}if(n>=500||n===429)return{ok:false,reason:"network",detail:"Buoy is busy. The bot key will be checked again soon."};if(n!==200||typeof h?.access_token!="string")return{ok:false,reason:"rejected",detail:typeof h?.error_description=="string"?h.error_description:"This bot key was not accepted."};let c=ae(h.access_token,{audience:Ar,nowMs:u()});return c.ok?{ok:true,claims:c.claims}:{ok:false,reason:"rejected",detail:"Buoy sent a token this app could not check."}}f();var _r="dev";function tt(e){return Qe(e)}function it(e,t=u()){let i=ae(e,{audience:_r,ignoreTime:true});return i.ok?t>=i.claims.exp*1e3?{ok:false,reason:"expired",message:"Your dev token ran out. Run `npx --package=@buoy-gg/core buoy login` again."}:{ok:true,claims:i.claims}:{ok:false,reason:"invalid",message:"This dev token is not valid. Run `npx --package=@buoy-gg/core buoy login` again."}}var Lr="This is a dev token. It only works in dev builds. A live build turns on Buoy with Sign in with Buoy.";var Sr={role:null,tools:null};function rt(e){return{role:e.role??null,tools:e.tools??null}}async function b(e,t){let i;try{return await Promise.race([e,new Promise(r=>{i=setTimeout(()=>r(t),15e3)})])}finally{i&&clearTimeout(i)}}function P(e){return e.tier==="pro"||e.tier==="free"?e.tier:e.isPro?"pro":"free"}var Ir=class{constructor(){this.state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,keySignedOut:false,error:null,errorKind:null,expiresAt:null};this.signedOutKey=null;this.listeners=new Set;this.revalidationTimer=null;this.cachedLicense=null;this.fingerprintPromise=null;this.fingerprintRestored=false;this.initPromise=null;this.generation=0;this.persistence=Promise.resolve();this.verifiedAt=null;this.expiryTimer=null;this.removeForegroundListener=null;this.sessionUnsubscribe=null;this.devToken=null;this.retryTimer=null;this.retryAttempt=0;this.deviceRegistrationCallback=null;this.pendingRegistration=null}async initialize(){if(this.initPromise)return this.initPromise;if(!this.state.isInitialized)return this.initPromise=this._doInitialize(),this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;let e=this.generation;this.sessionUnsubscribe||(this.sessionUnsubscribe=A.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))),await b(A.load().catch(()=>{}),void 0);try{await b(this.loadSignedOutKey(),void 0);let t=await b(this.loadCachedLicense(),null);if(e!==this.generation){this.state.isInitialized=true,this.emit({type:"initialized",isPro:this.state.isPro}),this.startRevalidationTimer();return}if(t&&t.licenseKey!==this.signedOutKey&&(this.configuredKey===void 0||t.licenseKey===this.configuredKey)){let i=R(t);this.cachedLicense=t,this.state.licenseKey=t.licenseKey,i&&this.isCacheValid(t)?this.applyTier(P(t)):this.lock(),this.state.expiresAt=t.expiresAt?new Date(t.expiresAt):null,i&&this.isCacheValid(t)&&this.setVerifiedAt(t.cachedAt),this.configuredKey===void 0&&t.licenseKey&&!(i&&this.isCacheValid(t)&&this.isCacheFresh(t))&&this.validateInBackground(t.licenseKey)}this.state.isInitialized=true,this.emit({type:"initialized",isPro:this.state.isPro}),this.startRevalidationTimer()}catch(t){console.warn("[Buoy]","[React Buoy] License initialization failed:",t),this.state.isInitialized=true,this.emit({type:"initialized",isPro:false})}}async configure(e){if(e===void 0)return await this.initialize(),this.hasAccountAccess();let t=N(e),i=++this.generation;return this.cancelRetry(),this.configuredKey=t||null,this.state.licenseKey!==this.configuredKey&&this.lock(),this.state.licenseKey=this.configuredKey,this.state.isValidating=!!t,this.emit({type:"validating",isPro:this.isPro()}),await this.initialize(),i!==this.generation?false:t?t===this.signedOutKey?(this.configuredKey=null,this.state.licenseKey=null,this.state.isValidating=false,this.emit({type:"deactivated",isPro:this.isPro()}),false):this.setLicenseKey(t):(this.forgetSignedOutKey(),await this.clearLicense(),false)}async setLicenseKey(e,t){if(!e||e.trim().length===0)return this.state.error="License key is required",this.state.errorKind="verdict",false;let i=N(e);this.forgetSignedOutKey();let r=++this.generation;if(this.cancelRetry(),t?.isRetry||(this.retryAttempt=0),this.state.licenseKey!==i&&this.lock(),this.state.licenseKey=i,this.state.isValidating=true,this.state.error=null,this.state.errorKind=null,this.emit({type:"validating",isPro:this.isPro()}),Ge(i))return this.admitToken(i,r);if(oe(i))return this.admitServiceKey(i,r);if(tt(i))return this.admitDevToken(i);if(!this.cachedLicense){let a=await b(this.loadCachedLicense(),null);if(r!==this.generation)return false;a?.licenseKey===i&&(this.cachedLicense=a,R(a)&&this.isCacheValid(a)&&(this.applyTier(P(a)),this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null,this.setVerifiedAt(a.cachedAt),this.emit({type:"validating",isPro:this.isPro()})))}let s=this.cachedLicense;if(!t?.force&&s&&s.valid&&s.licenseKey===i&&s.fingerprint&&R(s)&&this.isCacheValid(s)&&this.isCacheFresh(s))return this.applyTier(P(s)),this.state.licenseKey=i,this.state.isValidating=false,this.state.error=null,this.state.errorKind=null,this.state.expiresAt=s.expiresAt?new Date(s.expiresAt):null,this.setVerifiedAt(s.cachedAt),this.emit({type:"validated",isPro:this.state.isPro}),true;let n=await b(this.loadHold(),null);if(r!==this.generation)return false;let h=(n?.backoffUntil??0)-u();if(h>0)return this.standDown(i,r,"License server is rate limited; retrying later.",h);if(!t?.force&&n?.key===i&&n.verdictAt!==void 0&&u()-n.verdictAt>=0&&u()-n.verdictAt<gi)return this.lock(),this.state.isValidating=false,this.state.error=n.detail||"License could not be verified",this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:this.state.error}),false;let c;try{c=await Ei(i)}catch(a){let l=a instanceof Error?a.message:"Validation failed";if(r!==this.generation)return false;if(Oe(a)){if(vi(a)){let o=Math.min(bi(a,Ne,mi)*2**this.retryAttempt,Ne);return this.retryAttempt+=1,await this.saveHold({...this.hold,backoffUntil:u()+o}),r!==this.generation?false:this.standDown(i,r,l,o)}return this.state.isValidating=false,this.cachedLicense&&this.cachedLicense.licenseKey===i&&R(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)?(this.applyTier(P(this.cachedLicense)),this.state.error=null,this.state.errorKind=null,this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null,this.setVerifiedAt(this.cachedLicense.cachedAt),this.keyTier()!=="pro"&&this.scheduleRetry(i),this.emit({type:"validated",isPro:this.state.isPro}),true):(this.state.error=l,this.state.errorKind="transport",this.scheduleRetry(i),this.emit({type:"error",isPro:this.state.isPro,error:l}),false)}return this.state.isValidating=false,this.state.error=l,this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:l}),false}try{if(r!==this.generation)return false;let a=Li(c),l=c.data?.relationships?.product?.data?.id;if((!l||l===M.productId)&&a.code==="EXPIRED"&&(qi(c.data)||this.cachedLicense?.licenseKey===i&&R(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){let B=u(),de=await this.saveCache({licenseKey:i,licenseId:c.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:B,lastValidatedAt:B,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},r);return r!==this.generation||!de?false:(this.cachedLicense=de,this.applyTier("free"),this.state.isValidating=false,this.state.expiresAt=null,this.setVerifiedAt(B),this.emit({type:"validated",isPro:false}),true)}if(Si(a.code)||!xi(c))return this.lock(),this.state.isValidating=false,this.state.error=a.detail||"License could not be verified",this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:this.state.error}),await this.clearCachedLicense(),await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:u()}),false;if(!c.data)return this.lock(),this.state.isValidating=false,this.state.error=a.detail||"License not found",this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:this.state.error}),await this.clearCachedLicense(),false;let o=Xi(c.data),d=c.data.id,k=u(),E=_i(c)>=yi,le=ie(),st=le&&!E,nt=o==="free"&&(E||!le),L=this.cachedLicense?.fingerprint,K=this.cachedLicense?.deviceName,ce=false;if(!L){if(L=await b(this.getOrCreateDeviceFingerprint(),te()),r!==this.generation)return false;K=re(),ce=st}let U=false;ce&&(this.deviceRegistrationCallback?(this.pendingRegistration={licenseId:d,licenseKey:i,fingerprint:L},this.deviceRegistrationCallback({fingerprint:L,defaultName:K}),U=true):this.registerDeviceAsync(d,i,L,K));let F={licenseKey:i,licenseId:d,valid:true,isPro:o==="pro",tier:o,expiresAt:c.data.attributes.expiry??null,cachedAt:k,lastValidatedAt:k,fingerprint:U?void 0:L,deviceName:U?void 0:K,quiet:nt||void 0},he=await this.saveCache(F,r);return r!==this.generation||!he||(this.cachedLicense=he,this.applyTier(o),this.state.isValidating=false,this.state.expiresAt=F.expiresAt?new Date(F.expiresAt):null,this.setVerifiedAt(k),this.hold&&await this.saveHold(null),r!==this.generation)?false:(this.retryAttempt=0,this.emit({type:"validated",isPro:this.state.isPro}),true)}catch(a){let l=a instanceof Error?a.message:"Validation failed";return r!==this.generation||(this.state.isValidating=false,this.state.error=l,this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:l})),false}}scheduleRetry(e){this.cancelRetry();let t=pi[this.retryAttempt];if(t===void 0)return;this.retryAttempt+=1;let i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null,i===this.generation&&(this.state.isValidating||this.setLicenseKey(e,{force:true,isRetry:true}))},t),typeof m<"u"&&m&&(globalThis.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer)}async admitServiceKey(e,t){let i=await xr(e,{origin:A.origin});if(t!==this.generation)return false;if(!i.ok)return this.lock(),this.state.isValidating=false,this.state.error=i.detail,this.state.errorKind=i.reason==="network"?"transport":"verdict",this.emit({type:"error",isPro:false,error:i.detail}),i.reason==="network"&&this.scheduleRetry(e),false;let r=i.claims.exp*1e3;return this.applyTier(i.claims.tier==="free"?"free":"pro"),this.state.isValidating=false,this.state.expiresAt=new Date(r),this.setVerifiedAt(u()),this.retryAttempt=0,this.scheduleRetryIn(e,Math.max(6e4,r-3600*1e3-u())),this.emit({type:"validated",isPro:this.isPro()}),true}admitDevToken(e){let t=it(e);if(!t.ok||!ie()){let r=t.ok?Lr:t.message;return this.lock(),this.state.isValidating=false,this.state.error=r,this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:r}),false}let i=u();return this.devToken={token:e,claims:t.claims},this.applyTier(t.claims.tier==="free"?"free":"pro"),this.state.isValidating=false,this.state.expiresAt=new Date(t.claims.exp*1e3),this.setVerifiedAt(Math.min(i,t.claims.iat*1e3)),this.retryAttempt=0,this.emit({type:"validated",isPro:this.isPro()}),true}async admitToken(e,t){let i=Ji(e);if(t!==this.generation)return false;if(!i)return this.lock(),this.state.isValidating=false,this.state.error="This key is not valid. Check that it was copied completely.",this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:this.state.error}),await this.clearCachedLicense(),false;let r=u(),s=this.cachedLicense?.fingerprint??await b(this.getOrCreateDeviceFingerprint(),te());if(t!==this.generation)return false;let n=await this.saveCache({licenseKey:e,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:r,lastValidatedAt:r,fingerprint:s,deviceName:this.cachedLicense?.deviceName??re(),quiet:true},t);return t!==this.generation||!n?false:(this.cachedLicense=n,this.applyTier("free"),this.state.isValidating=false,this.state.expiresAt=null,this.setVerifiedAt(r),this.retryAttempt=0,this.emit({type:"validated",isPro:false}),true)}standDown(e,t,i,r){if(t!==this.generation)return false;this.state.isValidating=false;let s=this.cachedLicense;return s&&s.licenseKey===e&&R(s)&&this.isCacheValid(s)?(this.applyTier(P(s)),this.state.error=null,this.state.errorKind=null,this.state.expiresAt=s.expiresAt?new Date(s.expiresAt):null,this.setVerifiedAt(s.cachedAt),this.keyTier()!=="pro"&&this.scheduleRetryIn(e,r),this.emit({type:"validated",isPro:this.state.isPro}),true):(this.state.error=i,this.state.errorKind="transport",this.scheduleRetryIn(e,r),this.emit({type:"error",isPro:this.state.isPro,error:i}),false)}scheduleRetryIn(e,t){this.cancelRetry();let i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null,i===this.generation&&(this.state.isValidating||this.setLicenseKey(e,{force:true,isRetry:true}))},Math.max(1,Math.min(t,2147483647))),typeof m<"u"&&m&&(w.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer)}cancelRetry(){this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=null)}async clearLicense(){this.generation+=1,this.cancelRetry(),this.retryAttempt=0,this.configuredKey=null,this.state.licenseKey=null,this.lock(),this.state.expiresAt=null,this.state.error=null,this.state.errorKind=null,this.cachedLicense=null,this.pendingRegistration=null,this.state.isValidating=false,this.emit({type:"deactivated",isPro:false}),await this.clearCachedLicense(),this.hold?.verdictAt!==void 0&&await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}async signOut(){await this.initialize();let e=this.state.licenseKey;e&&this.rememberSignedOutKey(e),await this.clearLicense(),await this.persistence.catch(()=>{}),await A.signOut().catch(()=>{})}async restoreSignedOutKey(){let e=this.signedOutKey;return e?(this.configuredKey=e,this.setLicenseKey(e,{force:true})):false}applyTier(e){this.state.tier=e,this.state.tierSource="key",this.state.isPro=e==="pro"}lock(){this.state.tier="free",this.state.tierSource="none",this.state.isPro=false,this.verifiedAt=null,this.expiryTimer&&clearTimeout(this.expiryTimer),this.expiryTimer=null}getTier(){return this.credential().tier}credential(){let e=this.keyTier(),t=this.sessionTier();return t!==null&&(!this.hasKeyAccess()||t==="pro"&&e!=="pro")?{source:"session",tier:t}:{source:this.state.tierSource,tier:e}}keyTier(){return!this.hasKeyAccess()||this.state.expiresAt&&u()>=this.state.expiresAt.getTime()?"free":this.state.tier}sessionTier(){let e=A.getStatus();return e.state!=="active"?null:e.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){let{source:e,tier:t}=this.credential(),i=this.getTeamAccess();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess(),teamRole:i.role,allowedTools:i.tools}}getTeamAccess(){let e=A.getStatus();if(e.state==="active")return rt(e.claims);let t=this.devToken;return t&&t.token===this.state.licenseKey&&this.state.tierSource==="key"&&u()<t.claims.exp*1e3&&this.hasKeyAccess()?rt(t.claims):Sr}getAccountAccess(){let e=this.getKeyAccess();if(e.status==="admitted")return e;let t=A.getStatus();return t.state==="active"?{status:"admitted",reason:null,validUntil:t.validUntil}:e}getKeyAccess(){return We({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}hasKeyAccess(){return this.getKeyAccess().status==="admitted"}setVerifiedAt(e){this.verifiedAt=e,this.expiryTimer&&clearTimeout(this.expiryTimer);let t=e+D,i=this.state.expiresAt?.getTime(),r=(i&&i>u()?Math.min(t,i):t)-u();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null,this.verifiedAt===e&&(this.emit({type:"validated",isPro:this.isPro()}),u()<t&&this.setVerifiedAt(e))},Math.max(1,Math.min(r,2147483647))),typeof m<"u"&&m&&(w.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer)}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}onDeviceRegistrationNeeded(e){return this.deviceRegistrationCallback=e,()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(e){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}let{licenseId:t,licenseKey:i,fingerprint:r}=this.pendingRegistration,s=this.generation,n=e.trim()||re(),h=Ue();try{await Ve(t,i,r,n,h)}catch(c){let a=c instanceof Error?c.message:String(c);if(!(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"))throw console.warn("[Buoy] Device registration failed:",a),c}if(s===this.generation){if(this.cachedLicense?.licenseKey===i){let c=await this.saveCache({...this.cachedLicense,fingerprint:r,deviceName:n},s);if(s!==this.generation)return;c&&(this.cachedLicense=c)}this.pendingRegistration=null}}emit(e){[...this.listeners].forEach(t=>{try{t(e)}catch(i){console.warn("[Buoy]","[React Buoy] License listener error:",i)}})}isCacheValid(e){let t=u()-e.cachedAt;return!(!e.valid||!Number.isFinite(e.cachedAt)||t<0||t>=D)}isCacheFresh(e){let t=this.isQuiet(e)?wi:fi;return u()-(e.lastValidatedAt??0)<t}isQuiet(e){return e.quiet!==void 0?e.quiet:P(e)==="free"&&!ie()}async loadHold(){if(this.hold!==void 0)return this.hold;try{let e=await(await v()).getItem(ee),t=e?JSON.parse(e):null;this.hold=t&&typeof t=="object"?t:null}catch{this.hold=null}return this.hold}async saveHold(e){this.hold=e;try{let t=await v();e?await t.setItem(ee,JSON.stringify(e)):await t.removeItem(ee)}catch{}}async persistCache(e){let t=He(e);return await(await v()).setItem(q,JSON.stringify(t)),t}saveCache(e,t){let i=this.persistence.catch(()=>{}).then(async()=>{if(t!==this.generation)return null;let r=await this.persistCache(e);return t===this.generation?r:null});return this.persistence=i,b(i,He(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});let e=await(await v()).getItem(q);if(!e)return null;let t=JSON.parse(e);if(t.fingerprint){let i=await b(this.getOrCreateDeviceFingerprint(t.fingerprint).catch(()=>null),null);if(i&&this.fingerprintRestored&&t.fingerprint!==i)return{...t,fingerprint:void 0,deviceName:void 0}}return t}catch(e){return console.warn("[Buoy] Error loading cached license:",e),null}}getOrCreateDeviceFingerprint(e){return this.fingerprintPromise||(this.fingerprintPromise=(async()=>{let t=await v(),i=await t.getItem(Q),r=await t.getItem(Pe),s=await b(Ri().catch(()=>null),null),n=Ci({stored:i,storedOwner:r,marker:s?Pi(s):null,blobFingerprint:e??this.cachedLicense?.fingerprint,mint:te});return this.fingerprintRestored=n.restored,n.changed&&(await t.setItem(Q,n.fingerprint),n.owner&&await t.setItem(Pe,n.owner)),n.fingerprint})()),this.fingerprintPromise}async loadSignedOutKey(){await this.persistence.catch(()=>{});let e=await v();this.signedOutKey=await e.getItem(Z),this.state.keySignedOut=!!this.signedOutKey}rememberSignedOutKey(e){this.signedOutKey=e,this.state.keySignedOut=true,this.persistence=this.persistence.catch(()=>{}).then(async()=>{await(await v()).setItem(Z,e)}).catch(()=>{})}forgetSignedOutKey(){this.signedOutKey&&(this.signedOutKey=null,this.state.keySignedOut=false,this.persistence=this.persistence.catch(()=>{}).then(async()=>{await(await v()).removeItem(Z)}).catch(()=>{}))}async clearCachedLicense(){this.cachedLicense=null;let e=this.persistence.catch(()=>{}).then(async()=>{await(await v()).removeItem(q)});this.persistence=e,await b(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,r){let s=Ue();Ve(e,t,i,r,s).catch(n=>{n.message!=="FINGERPRINT_TAKEN"&&n.message!=="MACHINE_LIMIT_EXCEEDED"&&console.warn("[Buoy] Device registration failed (non-blocking):",n.message)})}validateInBackground(e){this.setLicenseKey(e,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){this.removeForegroundListener||(this.removeForegroundListener=Zi(()=>this.refreshAccess()),typeof m<"u"&&m&&(w.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener)),this.revalidationTimer&&clearInterval(this.revalidationTimer),this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;let e=this.cachedLicense;e&&e.licenseKey===this.state.licenseKey&&this.isCacheFresh(e)||this.validateInBackground(this.state.licenseKey)},ui),typeof m<"u"&&m&&(globalThis.__LICENSE_MANAGER_TIMER__=this.revalidationTimer)}stopRevalidationTimer(){this.removeForegroundListener?.(),this.removeForegroundListener=null,this.expiryTimer&&clearTimeout(this.expiryTimer),this.expiryTimer=null,this.revalidationTimer&&(clearInterval(this.revalidationTimer),this.revalidationTimer=null),this.cancelRetry()}async forceReregister(){this.cachedLicense&&(this.cachedLicense.fingerprint=void 0,this.cachedLicense.deviceName=void 0),this.fingerprintPromise=null,await this.clearCachedLicense();try{await(await v()).removeItem(Q)}catch{}}},Rr=new Ir,w=globalThis;typeof m<"u"&&m&&(w.__LICENSE_MANAGER_FOREGROUND_OFF__?.(),w.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0,w.__LICENSE_MANAGER_EXPIRY_TIMER__&&clearTimeout(w.__LICENSE_MANAGER_EXPIRY_TIMER__),w.__LICENSE_MANAGER_TIMER__&&clearInterval(w.__LICENSE_MANAGER_TIMER__),w.__LICENSE_MANAGER_RETRY_TIMER__&&(clearTimeout(w.__LICENSE_MANAGER_RETRY_TIMER__),w.__LICENSE_MANAGER_RETRY_TIMER__=void 0));export{u as a,I as b,Oe as c,Ge as d,We as e,p as f,A as g,oe as h,N as i,Er as j,tt as k,it as l,Rr as m};/*!
|
|
2
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
5
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
6
|
+
*//*!
|
|
7
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
10
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
11
|
+
*
|
|
12
|
+
* This file configures the technological measure that controls access to paid
|
|
13
|
+
* Buoy Pro features. Modifying, patching, aliasing, stubbing, or otherwise
|
|
14
|
+
* altering it — including repointing `apiUrl` at a stand-in license server — so
|
|
15
|
+
* that Pro features unlock without a valid license is a breach of the EULA and,
|
|
16
|
+
* in the United States, circumvention of an access control under 17 U.S.C.
|
|
17
|
+
* § 1201, which applies whether or not any code is copied.
|
|
18
|
+
*
|
|
19
|
+
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
20
|
+
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
21
|
+
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
22
|
+
*//*!
|
|
23
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
24
|
+
*
|
|
25
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
26
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
27
|
+
*
|
|
28
|
+
* This file is part of the technological measure that controls access to paid
|
|
29
|
+
* Buoy Pro features. Modifying, patching, aliasing, stubbing, or otherwise
|
|
30
|
+
* altering it so that Pro features unlock without a valid license is a breach
|
|
31
|
+
* of the EULA and, in the United States, circumvention of an access control
|
|
32
|
+
* under 17 U.S.C. § 1201 — which applies whether or not any code is copied.
|
|
33
|
+
*
|
|
34
|
+
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
35
|
+
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
36
|
+
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
37
|
+
*//*!
|
|
38
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
39
|
+
*
|
|
40
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
41
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
42
|
+
*
|
|
43
|
+
* This file is part of the technological measure that controls access to paid
|
|
44
|
+
* Buoy Pro features: it decides which tier a validated key grants. Modifying,
|
|
45
|
+
* patching, aliasing, stubbing, or otherwise altering it so that Pro features
|
|
46
|
+
* unlock without a valid license is a breach of the EULA and, in the United
|
|
47
|
+
* States, circumvention of an access control under 17 U.S.C. § 1201 — which
|
|
48
|
+
* applies whether or not any code is copied.
|
|
49
|
+
*
|
|
50
|
+
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
51
|
+
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
52
|
+
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
53
|
+
*//*!
|
|
54
|
+
* PROPRIETARY — Buoy license enforcement. NOT open source.
|
|
55
|
+
*
|
|
56
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
57
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
58
|
+
*//*!
|
|
59
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
60
|
+
*
|
|
61
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
62
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
63
|
+
*
|
|
64
|
+
* This file is the technological measure that controls access to paid Buoy Pro
|
|
65
|
+
* features. Modifying, patching, aliasing, stubbing, or otherwise altering it
|
|
66
|
+
* so that Pro features unlock without a valid license is a breach of the EULA
|
|
67
|
+
* and, in the United States, circumvention of an access control under
|
|
68
|
+
* 17 U.S.C. § 1201 — which applies whether or not any code is copied.
|
|
69
|
+
*
|
|
70
|
+
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
71
|
+
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
72
|
+
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
73
|
+
*/
|
package/lib/web/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use client";import{a as _,b as K,c as h,d as L,e as P,f as B,g as I,h as Y,i as O,j as b,k as v,l as T,m as U,n as N,o as w,p as z,q as D,r as W,s as j}from"./chunks/chunk-KGEZ5TEJ.mjs";import{a as F,b as M,c as V,d as H,e as Q,f as X,g as r,h as $,i as q,j as x,k as p,l as d,m as n}from"./chunks/chunk-
|
|
1
|
+
"use client";import{a as _,b as K,c as h,d as L,e as P,f as B,g as I,h as Y,i as O,j as b,k as v,l as T,m as U,n as N,o as w,p as z,q as D,r as W,s as j}from"./chunks/chunk-KGEZ5TEJ.mjs";import{a as F,b as M,c as V,d as H,e as Q,f as X,g as r,h as $,i as q,j as x,k as p,l as d,m as n}from"./chunks/chunk-ISATKL5M.mjs";import{f as o,g as R,h as G,i as J,j as Z}from"./chunks/chunk-YHWYXKID.mjs";o();o();import{useEffect as ee,useState as se}from"react";function l(e=new Date(F())){if(globalThis.__buoyWeekendPassOff===true)return false;let s=e.getDay();return s===0||s===6}function f(){let[e,s]=se(()=>l());return ee(()=>{let a=setInterval(()=>{let t=l();s(i=>i===t?i:t)},6e4);return()=>clearInterval(a)},[]),e}function m(e,s){return s&&e}o();import{useState as C,useEffect as y,useCallback as g}from"react";function c(){let[e,s]=C(n.getState());y(()=>{let i=n.subscribe(u=>{s(n.getState())});return n.initialize().then(()=>{s(n.getState())}),i},[]);let a=g(async i=>{let u=await n.setLicenseKey(i,{force:true});return s(n.getState()),u},[]),t=g(async()=>{await n.clearLicense(),s(n.getState())},[]);return{...e,setLicenseKey:a,clearLicense:t}}function te(){return c().access}function ae(){let{tier:e,isInitialized:s}=c();return s?e:"free"}function ie(e){let{isPro:s,isInitialized:a,isValidating:t}=c();return{hasAccess:s,isPro:s,isLoading:!a||t}}function ne(){let{isPro:e,isInitialized:s,access:a}=c(),t=m(a.status==="admitted",f());return s&&e||t}function re(){let{isPro:e,isInitialized:s,access:a}=c(),t=s&&e,i=m(a.status==="admitted",f())&&!t;return{isPro:t||i,isLicensed:t,isWeekendFree:i,reason:t?"licensed":i?"weekend":null}}function ce(){let[e,s]=C(()=>r.getStatus());y(()=>{let i=()=>s(r.getStatus()),u=r.subscribe(i);return r.load().then(i,i),u},[]);let a=g(()=>r.signIn(),[]),t=g(()=>r.signOut(),[]);return{status:e,signIn:a,signOut:t}}o();var A=["BUOY_LICENSE_KEY","BUOY_KEY","EXPO_PUBLIC_BUOY_KEY","VITE_BUOY_KEY","NEXT_PUBLIC_BUOY_KEY","REACT_APP_BUOY_KEY","licenseKey"],oe=/(^|_)BUOY_(LICENSE_)?KEY$/i;function E(e){return A.includes(e)||oe.test(e)}function k(e){return e&&(e.length>=16?`${e.slice(0,5)}\u2026\u2022\u2022\u2022\u2022 (hidden)`:"\u2022\u2022\u2022\u2022 (hidden)")}function ue(e){let s;for(let[a,t]of Object.entries(e))typeof t=="string"&&t&&E(a)&&(s??(s={...e}),s[a]=k(t));return s??e}o();function le(){let e=r.getAccessToken();if(e)return{token:e,origin:r.origin};let s=n.getState().licenseKey;return s&&p(s)&&n.hasAccountAccess()&&d(s).ok?{token:s,origin:r.origin}:null}function ge(e){return e.startsWith("app:")?e.slice(4)||null:/^https?:\/\//.test(e)?e:null}function pe(){let e=r.getAccessToken();if(e){let t=r.getStatus(),i=t.state==="active"?t.claims:null;return i?.team?{token:e,origin:r.origin,team:i.team,appId:ge(i.aud)}:null}let s=n.getState().licenseKey;if(!s||!p(s)||!n.hasAccountAccess())return null;let a=d(s);return!a.ok||!a.claims.team?null:{token:s,origin:r.origin,team:a.claims.team,appId:null}}async function fe(e){let{LicenseManager:s}=await import("./chunks/LicenseManager-QVQA7ZAE.mjs");return await s.initialize(),s.setLicenseKey(e)}function S(){return m(n.hasAccountAccess(),l())}function me(){return n.isPro()?true:S()}function de(e){return n.hasEntitlement(e)?true:S()}export{A as BUOY_ACCOUNT_KEY_NAMES,n as LicenseManager,M as LicenseTransportError,X as SessionError,r as SessionManager,v as callCapacitorAsApp,b as callCapacitorNative,T as callCapacitorNativeCallback,J as capacitorDebug,Y as capacitorListenerCount,G as capacitorPlatform,D as capacitorPlugin,w as clearCapacitorCalls,h as colorSchemeQueryValue,I as emitCapacitorEvent,j as getCapacitorAppHost,N as getCapacitorCalls,L as getColorSchemeQueries,le as getSyncCredential,pe as getTeamCredential,O as hasCapacitorPlugin,de as hasEntitlement,K as installCapacitorBridge,B as interceptCapacitor,E as isBuoyAccountKeyName,H as isBuoyToken,P as isCapacitorBridgeInstalled,R as isCapacitorNative,p as isDevToken,me as isPro,$ as isServiceKey,V as isTransientLicenseError,l as isWeekendFreePro,U as listenCapacitorNative,W as loadCapacitorAppHost,_ as makeCapacitorCallbackId,k as maskBuoyAccountKey,ue as maskBuoyAccountKeys,q as normalizeLicenseKey,Q as resolveAccountAccess,Z as resolveDevBuild,x as sameLicenseKey,fe as setLicenseKey,z as subscribeCapacitorCalls,te as useAccountAccess,ce as useBuoySession,ie as useFeatureAccess,ne as useIsPro,c as useLicense,re as useProAccess,ae as useTier,f as useWeekendFreePro};/*!
|
|
2
2
|
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
"use client";import{m as e}from"./chunk-U4JDBLRG.mjs";import"./chunk-YHWYXKID.mjs";export{e as LicenseManager};
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
"use client";import{a as j,b as st,c as at,d as ot,e as m,f,i as lt}from"./chunk-YHWYXKID.mjs";var de,ct=j(()=>{"use strict";f();de='-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'});import{useEffect as ht,useState as dt}from"react";import{createPortal as ut}from"react-dom";import{jsx as ft}from"react/jsx-runtime";function ue(){let e=document;if(e[S])return e[S].host;let t=document.createElement("div");t.dataset.buoyPortalHost="",Object.assign(t.style,{position:"fixed",inset:"0",zIndex:"2147483647",pointerEvents:"none",fontFamily:de});let i=()=>{let o=document.fullscreenElement,d=o&&o.tagName!=="CANVAS"?o:document.body;t.parentElement!==d&&d.appendChild(t)},r=new Map,n=o=>{(!t.contains(o.target)||!H(o.target))&&r.set(o.code||o.key,{key:o.key,code:o.code,location:o.location,keyCode:o.keyCode,which:o.which,altKey:o.altKey,ctrlKey:o.ctrlKey,metaKey:o.metaKey,shiftKey:o.shiftKey})},s=o=>{r.delete(o.code||o.key)},h=()=>r.clear(),c=()=>{let o=[...r.values()];r.clear();for(let d of o)document.dispatchEvent(new KeyboardEvent("keyup",{...d,bubbles:true}))},a=o=>{H(o.target)&&o.stopPropagation()},l=o=>o.stopPropagation();return i(),document.addEventListener("fullscreenchange",i),document.addEventListener("keydown",n,true),document.addEventListener("keyup",s,true),window.addEventListener("blur",h),t.addEventListener("focusin",c),t.addEventListener("keydown",a),t.addEventListener("keyup",a),t.addEventListener("keypress",a),t.addEventListener("wheel",l,{passive:true}),e[S]={host:t,users:0,dispose:()=>{document.removeEventListener("fullscreenchange",i),document.removeEventListener("keydown",n,true),document.removeEventListener("keyup",s,true),window.removeEventListener("blur",h),t.remove(),delete e[S]}},t}function pt({children:e}){let[t,i]=dt(null);return ht(()=>{let r=ue(),n=document[S];return n.users++,i(r),()=>{--n.users===0&&n.dispose()}},[]),t?ut(ft("div",{"data-buoy-root":"",style:{display:"contents",pointerEvents:"auto"},children:e}),t):null}var S,H,mt=j(()=>{"use strict";f();ct();S=Symbol.for("@buoy-gg/portal-host"),H=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"}});var z={};st(z,{AccessibilityInfo:()=>vt,ActivityIndicator:()=>Le,Alert:()=>Re,Animated:()=>we,AppRegistry:()=>Tt,AppState:()=>At,Appearance:()=>bt,BackHandler:()=>kt,Button:()=>Se,CheckBox:()=>$t,Clipboard:()=>Et,DeviceEventEmitter:()=>ti,Dimensions:()=>xt,Easing:()=>_t,FlatList:()=>Ut,I18nManager:()=>Lt,Image:()=>Ft,ImageBackground:()=>Bt,InteractionManager:()=>It,Keyboard:()=>St,KeyboardAvoidingView:()=>jt,LayoutAnimation:()=>Rt,Linking:()=>Ct,LogBox:()=>ei,Modal:()=>xe,NativeEventEmitter:()=>Pt,NativeModules:()=>wt,PanResponder:()=>Nt,Picker:()=>Ht,PixelRatio:()=>Kt,Platform:()=>Ot,Pressable:()=>ke,ProgressBar:()=>zt,RefreshControl:()=>Gt,SafeAreaView:()=>Yt,ScrollView:()=>Ee,SectionList:()=>Wt,Share:()=>Mt,StatusBar:()=>Jt,StyleSheet:()=>ye,Switch:()=>_e,Text:()=>J,TextInput:()=>ve,Touchable:()=>Xt,TouchableHighlight:()=>Te,TouchableNativeFeedback:()=>qt,TouchableOpacity:()=>be,TouchableWithoutFeedback:()=>Ae,UIManager:()=>Vt,Vibration:()=>Dt,View:()=>W,VirtualizedList:()=>Zt,YellowBox:()=>Qt,findNodeHandle:()=>Ie,unstable_createElement:()=>yt,useColorScheme:()=>ii,useLocaleContext:()=>ri,useWindowDimensions:()=>ni});import*as gt from"react-native-web";import{unstable_createElement as yt,NativeModules as wt,AccessibilityInfo as vt,Appearance as bt,AppRegistry as Tt,AppState as At,BackHandler as kt,Clipboard as Et,Dimensions as xt,Easing as _t,I18nManager as Lt,Keyboard as St,InteractionManager as It,LayoutAnimation as Rt,Linking as Ct,NativeEventEmitter as Pt,PanResponder as Nt,PixelRatio as Kt,Platform as Ot,Share as Mt,UIManager as Vt,Vibration as Dt,CheckBox as $t,FlatList as Ut,Image as Ft,ImageBackground as Bt,KeyboardAvoidingView as jt,Picker as Ht,ProgressBar as zt,RefreshControl as Gt,SafeAreaView as Yt,SectionList as Wt,StatusBar as Jt,Touchable as Xt,TouchableNativeFeedback as qt,VirtualizedList as Zt,YellowBox as Qt,LogBox as ei,DeviceEventEmitter as ti,useColorScheme as ii,useLocaleContext as ri,useWindowDimensions as ni}from"react-native-web";import*as g from"react-native-web";import{createElement as G,forwardRef as fe,useCallback as si,useRef as ai}from"react";function Y(e){if(Array.isArray(e)){let d=e.map(Y);return d.some((A,k)=>A!==e[k])?d:e}if(!e||typeof e!="object"||!me.some(d=>e[d]!=null))return e;let{shadowColor:t,shadowOffset:i,shadowOpacity:r,shadowRadius:n,textShadowColor:s,textShadowOffset:h,textShadowRadius:c,...a}=e;if(t!=null||i!=null||r!=null||n!=null){let d=t??"black",A=r==null?d:`color-mix(in srgb, ${d} ${Math.min(r,1)*100}%, transparent)`,k=`${x(i?.width??0)} ${x(i?.height??0)} ${x(n??0)} ${A}`;a.boxShadow=typeof a.boxShadow=="string"?`${a.boxShadow}, ${k}`:a.boxShadow??k}let{width:l=0,height:o=0}=h??{};if(s&&(l||o||c)){let d=`${x(l)} ${x(o)} ${x(c??0)} ${s}`;a.textShadow=a.textShadow?`${a.textShadow}, ${d}`:d}return a}function pe(e,t){if(typeof e=="function")return r=>pe(e(r),t);let i=Y(e);return t?[i,ge[t]]:i}function y(e){let t=fe((r,n)=>{let{accessibilityState:s,accessibilityValue:h,pointerEvents:c,...a}=r;for(let o of["busy","checked","disabled","expanded","selected"])s?.[o]!==void 0&&a[`aria-${o}`]===void 0&&(a[`aria-${o}`]=s[o]);for(let[o,d]of Object.entries({min:"valuemin",max:"valuemax",now:"valuenow",text:"valuetext"}))h?.[o]!==void 0&&a[`aria-${d}`]===void 0&&(a[`aria-${d}`]=h[o]);let l=pe(a.style,c);return l!==a.style&&(a.style=l),G(e,{...a,ref:n})}),i=e.State;return i&&Object.assign(t,{State:i}),t.displayName=e.displayName??e.name??"NativeWebView",t}var E,me,x,ge,ye,W,J,we,ve,be,Te,Ae,ke,Ee,X,xe,_e,Le,Se,Ie,Re,oi=j(()=>{f();at(z,gt);mt();E=g,me=["shadowColor","shadowOffset","shadowOpacity","shadowRadius","textShadowColor","textShadowOffset","textShadowRadius"],x=e=>typeof e=="number"?`${e}px`:e;ge=E.StyleSheet.create({auto:{pointerEvents:"auto"},none:{pointerEvents:"none"},"box-none":{pointerEvents:"box-none"},"box-only":{pointerEvents:"box-only"}});ye={...E.StyleSheet,create:e=>E.StyleSheet.create(Object.fromEntries(Object.entries(e).map(([t,i])=>[t,Y(i)])))};W=y(g.View),J=y(g.Text),we={...E.Animated,View:E.Animated.createAnimatedComponent(W),Text:E.Animated.createAnimatedComponent(J)},ve=y(g.TextInput),be=y(g.TouchableOpacity),Te=y(g.TouchableHighlight),Ae=y(g.TouchableWithoutFeedback),ke=y(g.Pressable),Ee=y(g.ScrollView),X=fe((e,t)=>{let i=ai(null),r=si(n=>{if(n){let s=n;for(;s.parentElement&&s.parentElement!==document.body;)s=s.parentElement;s.parentElement===document.body&&(i.current=s,Object.assign(s.style,{position:"relative",zIndex:"2147483647",pointerEvents:"auto"}),ue().appendChild(s))}else i.current&&(document.body.appendChild(i.current),i.current=null);typeof t=="function"?t(n):t&&(t.current=n)},[t]);return G(pt,null,G(g.Modal,{...e,ref:r}))});X.displayName="Modal";xe=y(X),_e=y(g.Switch),Le=y(g.ActivityIndicator),Se=y(g.Button),Ie=g.findNodeHandle,Re={alert(e,t,i,r){if(typeof document>"u")return;let n=document.createElement("dialog");n.dataset.buoyRoot="",n.setAttribute("aria-label",e),n.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 s=document.createElement("h2");if(s.textContent=e,s.style.cssText="font-size:18px;margin:0 0 12px",n.appendChild(s),t){let l=document.createElement("p");l.textContent=t,l.style.cssText="line-height:1.5;white-space:pre-wrap;margin:0 0 20px",n.appendChild(l)}let h=document.createElement("div");h.style.cssText="display:flex;justify-content:flex-end;flex-wrap:wrap;gap:8px";let c=i?.length?i:[{text:"OK"}],a=()=>{n.close?.(),n.remove()};for(let l of c){let o=document.createElement("button");o.type="button",o.textContent=l.text??"OK",o.style.cssText=`padding:9px 14px;border:1px solid #64748b;border-radius:7px;color:white;background:${l.style==="destructive"?"#a52b38":"#283a4d"};cursor:pointer;font:inherit`,o.onclick=()=>{a(),l.onPress?.()},h.appendChild(o)}n.addEventListener("cancel",l=>{l.preventDefault(),r?.cancelable!==false&&(a(),r?.onDismiss?.())}),n.appendChild(h),document.body.appendChild(n),n.showModal?n.showModal():n.setAttribute("open","")}}});f();f();var O=new Map,li={async getItem(e){try{return localStorage.getItem(e)??O.get(e)??null}catch{return O.get(e)??null}},async setItem(e,t){O.set(e,t);try{localStorage.setItem(e,t)}catch{}},async removeItem(e){O.delete(e);try{localStorage.removeItem(e)}catch{}}};async function T(){return li}f();f();var ci="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";f();var hi="36abba0267f7f379d992a5b6df641daab4190bcc9e639e36f1378e3c1ac52746";var M=Object.freeze({accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"}),V=Object.freeze({free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"}),D=720*60*60*1e3,di=1440*60*1e3,q="buoy-gg-license",Z="buoy-gg-device-fingerprint",Ce="buoy-gg-device-fingerprint-owner",ui=3600*1e3,fi=[5*1e3,20*1e3,60*1e3,300*1e3,900*1e3],pi=60*1e3,Pe=3600*1e3,mi=1440*60*1e3,gi=50,yi=D,Q="buoy-gg-license-hold";f();f();function u(){let e=globalThis.__buoyRealNow;return typeof e=="function"?e():Date.now()}var{apiUrl:Ne}=M,I=class extends Error{constructor(e,t,i=null){super(e);this.isTransient=true;this.name="LicenseTransportError",this.status=t,this.retryAfterMs=i}};function wi(e){let t=e?.status;return t===429||t===402}function vi(e,t,i){return e.status===402?t:e.retryAfterMs??i}function bi(e){let t=n=>{try{return e.headers?.get?.(n)??null}catch{return null}},i=t("Retry-After");if(i){let n=Number(i);if(Number.isFinite(n)&&n>=0)return n*1e3;let s=Date.parse(i);if(Number.isFinite(s))return Math.max(0,s-u())}let r=Number(t("X-RateLimit-Reset"));return Number.isFinite(r)&&r>0?Math.max(0,r*1e3-u()):null}function Ke(e){return e instanceof I||e instanceof TypeError?true:typeof e=="object"&&e!==null&&e.isTransient===true}async function Ti(e){try{return(await e.json()).errors?.[0]?.detail||`HTTP ${e.status}`}catch{return`HTTP ${e.status}`}}function Oe(){return{"Content-Type":"application/vnd.api+json",Accept:"application/vnd.api+json"}}async function Ai(e,t){let i=`${Ne}/validate`,r={meta:{key:e}},n;try{n=await fetch(i,{signal:t,method:"POST",headers:Oe(),body:JSON.stringify(r)})}catch(s){throw new I(s instanceof Error?s.message:"Network request failed",null)}if(!n.ok)throw new I(await Ti(n),n.status,n.status===429?bi(n):null);try{let s=await n.json();if(!s||typeof s!="object"||typeof s.meta?.valid!="boolean"||typeof s.meta?.code!="string"||!s.meta.code)throw new Error("Missing license verdict");return s}catch{throw new I("License server returned an unreadable response",n.status)}}async function ki(e){let t=typeof AbortController=="function"?new AbortController:null,i;try{return await Promise.race([Ai(e,t?.signal),new Promise((r,n)=>{i=setTimeout(()=>{n(new I("License verification timed out. Please retry.",null)),t?.abort()},15e3)})])}finally{i&&clearTimeout(i)}}function Ei(e){if(!e.data)return false;let t=e.data.relationships?.product?.data?.id;return t&&t!==M.productId?false:e.meta.valid&&e.meta.code==="VALID"?true:["OVERDUE","NO_MACHINE","NO_MACHINES","TOO_MANY_MACHINES","TOO_MANY_CORES","TOO_MANY_PROCESSES","FINGERPRINT_SCOPE_MISMATCH","HEARTBEAT_NOT_STARTED","HEARTBEAT_DEAD"].includes(e.meta.code)}function xi(e){let t=e.data?.relationships?.machines?.meta?.count;return typeof t=="number"&&Number.isFinite(t)?t:0}async function Me(e,t,i,r,n){let s=`${Ne}/machines`,h=await fetch(s,{method:"POST",headers:Oe(),body:JSON.stringify({licenseId:e,licenseKey:t,fingerprint:i,name:r,metadata:n||{}})});if(!h.ok){let c=await h.json(),a=c.errors?.[0]?.code;if(a==="FINGERPRINT_TAKEN")throw new Error("FINGERPRINT_TAKEN");if(a==="MACHINE_LIMIT_EXCEEDED")throw new Error("MACHINE_LIMIT_EXCEEDED");let l=c.errors?.[0]?.detail||`HTTP ${h.status}`;throw new Error(l)}return h.json()}function _i(e){let{meta:t,data:i}=e;return{valid:t.valid,code:t.code,detail:t.detail,metadata:i?.attributes?.metadata}}function Li(e){return["NOT_FOUND","SUSPENDED","EXPIRED","BANNED","PRODUCT_SCOPE_MISMATCH"].includes(e)}f();f();function ee(){return typeof crypto<"u"&&crypto.randomUUID?crypto.randomUUID():"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,e=>{let t=Math.random()*16|0;return(e==="x"?t:t&3|8).toString(16)})}function te(){let e=lt();if(e!==null)return e;if(typeof m<"u")return m;try{if(typeof navigator<"u"&&/electron/i.test(navigator.userAgent))return true}catch{}return typeof process<"u"&&process.env.NODE_ENV!=="production"}function Ve(){if(typeof navigator>"u")return"unknown";let e=navigator.userAgent.toLowerCase(),t=navigator.platform?.toLowerCase()||"";return e.includes("electron")?t.includes("mac")||e.includes("mac")?"electron-macos":t.includes("win")||e.includes("win")?"electron-windows":t.includes("linux")||e.includes("linux")?"electron-linux":"electron":t.includes("mac")||e.includes("mac")?"macos":t.includes("win")||e.includes("win")?"windows":t.includes("linux")||e.includes("linux")?"linux":/iphone|ipad|ipod/.test(e)?"ios-web":e.includes("android")?"android-web":"web"}function Si(){if(typeof navigator>"u")return"unknown";let e=navigator.userAgent,t=e.match(/Mac OS X ([\d_.]+)/);if(t)return t[1].replace(/_/g,".");let i=e.match(/Windows NT ([\d.]+)/);return i?{"10.0":"10/11","6.3":"8.1","6.2":"8","6.1":"7"}[i[1]]||i[1]:e.includes("Linux")?"Linux":"unknown"}function De(){if(typeof navigator>"u")return{name:"unknown",version:"unknown"};let e=navigator.userAgent,t=e.match(/Electron\/([\d.]+)/);if(t)return{name:"Electron",version:t[1]};let i=e.match(/Chrome\/([\d.]+)/);if(i&&!e.includes("Edg"))return{name:"Chrome",version:i[1]};let r=e.match(/Edg\/([\d.]+)/);if(r)return{name:"Edge",version:r[1]};let n=e.match(/Firefox\/([\d.]+)/);if(n)return{name:"Firefox",version:n[1]};let s=e.match(/Version\/([\d.]+).*Safari/);return s?{name:"Safari",version:s[1]}:{name:"unknown",version:"unknown"}}function $e(){let e={platform:Ve(),osVersion:Si(),isSimulator:"false"},t=De();e.browser=t.name,e.browserVersion=t.version,typeof window<"u"&&window.screen&&(e.screenResolution=`${window.screen.width}x${window.screen.height}`),typeof navigator<"u"&&navigator.language&&(e.language=navigator.language);try{e.timezone=Intl.DateTimeFormat().resolvedOptions().timeZone}catch{}return e}function ie(){let e=Ve(),t=De();if(e.startsWith("electron")){let i=e.replace("electron-","").replace("electron","Desktop");return`${i.charAt(0).toUpperCase()+i.slice(1)} App`}return t.name!=="unknown"?`${t.name} Browser`:"Web Browser"}async function Ii(){return null}f();function Ri(e){let{stored:t,storedOwner:i,marker:r,blobFingerprint:n,mint:s}=e;if(!!r&&!!i&&i!==r)return{fingerprint:s(),owner:r,restored:true,changed:true};let h=r??i;return t?{fingerprint:t,owner:h,restored:false,changed:h!==i}:{fingerprint:n||s(),owner:h,restored:false,changed:true}}function Ci(e){let t=2166136261,i=16777619;for(let r=0;r<e.length;r++){let n=e.charCodeAt(r);t=Math.imul(t^n,16777619)>>>0,i=Math.imul(i^n,1540483477)>>>0}return`v1:${t.toString(16).padStart(8,"0")}${i.toString(16).padStart(8,"0")}`}f();var Pi=["v1"],Ni="buoy.gg/pro:9f3c1d7a4b2e:license-cache";function Ue(e,t){let i=t>>>0;for(let r=0;r<e.length;r++)i^=e.charCodeAt(r),i=Math.imul(i,16777619)>>>0;return i>>>0}function Ki(e,t){let i=[t,e.licenseKey,e.licenseId,e.isPro?"1":"0",e.expiresAt??"",String(e.cachedAt)];return t!=="v1"&&i.push(e.tier??""),i.push(Ni),i.join("\0")}function Fe(e,t){let i=Ki(e,t),r=Ue(i,2166136261),n=Ue(i,2135587861);return`${t}.${r.toString(16)}${n.toString(16)}`}function Be(e){return Fe(e,"v2")}function je(e){return{...e,sig:Be(e)}}function R(e){return!e||typeof e.sig!="string"||e.sig.length===0?false:e.sig===Be(e)?true:Pi.some(t=>e.sig.startsWith(`${t}.`)&&e.sig===Fe(e,t))}f();import Oi from"tweetnacl";var Mi=1,Vi=1,Di="buoy-free-token-v1:",$i=22,Ui=64,He=/^BUOY1-([A-Z2-7]+)-([A-Z2-7]+)$/;function ze(e){return He.test(e.trim().toUpperCase())}var Fi="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";function Ge(e){let t=[],i=0,r=0;for(let n of e){let s=Fi.indexOf(n);if(s===-1)return null;r=r<<5|s,i+=5,i>=8&&(t.push(r>>>i-8&255),i-=8)}return new Uint8Array(t)}function Bi(e){let t=e.trim().toLowerCase(),i=new Uint8Array(t.length/2);for(let r=0;r<i.length;r+=1)i[r]=parseInt(t.slice(r*2,r*2+2),16);return i}function ji(e){let t="";for(let i of e)t+=i.toString(16).padStart(2,"0");return t}function Hi(e){if(typeof TextEncoder<"u")return new TextEncoder().encode(e);let t=new Uint8Array(e.length);for(let i=0;i<e.length;i+=1)t[i]=e.charCodeAt(i)&255;return t}function zi(e,t){let i=new Uint8Array(e.length+t.length);return i.set(e,0),i.set(t,e.length),i}function Gi(e){return zi(Hi(Di),e)}var Yi=ci;function Wi(e){let t=He.exec(e.trim().toUpperCase());if(!t)return null;let i=Ge(t[1]),r=Ge(t[2]);if(!i||!r||i.length!==$i||r.length!==Ui||i[0]!==Mi||i[1]!==Vi)return null;try{if(!Oi.sign.detached.verify(Gi(i),r,Bi(Yi)))return null}catch{return null}return{tier:"free",issuedAt:((i[2]<<24>>>0)+(i[3]<<16)+(i[4]<<8)+i[5])*1e3,accountHash:ji(i.slice(6,22))}}f();function Ji(e){let t=e.relationships?.policy?.data?.id;return t===V.free?"free":t===V.solo||t===V.business?"pro":e.attributes?.metadata?.plan==="free"?"free":"pro"}function Xi(e){if(!e)return false;let t=e.relationships?.product?.data?.id;if(t)return t===M.productId;let i=e.relationships?.policy?.data?.id;return Object.values(V).some(r=>r===i)}f();function Ye(e,t=u()){let i=e.verifiedAt!==null&&Number.isFinite(e.verifiedAt)&&e.verifiedAt<=t?e.verifiedAt+D:null;return e.initialized&&e.key&&e.tierSource!=="none"&&i!==null&&t<i?{status:"admitted",reason:null,validUntil:i}:i!==null&&t>=i?{status:"locked",reason:"verification_expired",validUntil:i}:!e.initialized||e.validating?{status:"initializing",reason:"checking",validUntil:i}:{status:"locked",reason:i!==null&&t>=i?"verification_expired":"account_required",validUntil:i}}f();function qi(e){if(typeof window>"u"||typeof window.addEventListener!="function")return()=>{};let t=()=>{document.hidden||e()};return window.addEventListener("focus",e),document.addEventListener("visibilitychange",t),()=>{window.removeEventListener("focus",e),document.removeEventListener("visibilitychange",t)}}f();f();import Zi from"tweetnacl";var We="buoys1",Qi="buoy-session-v1:",Je=1,re=60,er=64,tr=["free","pro","business"],v="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function ne(e){let t="",i=0;for(;i+2<e.length;i+=3){let n=e[i]<<16|e[i+1]<<8|e[i+2];t+=v[n>>>18&63]+v[n>>>12&63]+v[n>>>6&63]+v[n&63]}let r=e.length-i;if(r===1){let n=e[i]<<16;t+=v[n>>>18&63]+v[n>>>12&63]}else if(r===2){let n=e[i]<<16|e[i+1]<<8;t+=v[n>>>18&63]+v[n>>>12&63]+v[n>>>6&63]}return t}function Xe(e){if(!/^[A-Za-z0-9_-]*$/.test(e)||e.length%4===1)return null;let t=[],i=0,r=0;for(let n of e)r=r<<6|v.indexOf(n),i+=6,i>=8&&(t.push(r>>>i-8&255),i-=8);return new Uint8Array(t)}function ir(e){if(typeof TextEncoder<"u")return new TextEncoder().encode(e);let t=unescape(encodeURIComponent(e)),i=new Uint8Array(t.length);for(let r=0;r<t.length;r+=1)i[r]=t.charCodeAt(r);return i}function rr(e){try{if(typeof TextDecoder<"u")return new TextDecoder("utf-8",{fatal:true}).decode(e);let t="";for(let i of e)t+=String.fromCharCode(i);return decodeURIComponent(escape(t))}catch{return null}}function nr(e){let t=e.trim().toLowerCase(),i=new Uint8Array(t.length/2);for(let r=0;r<i.length;r+=1)i[r]=parseInt(t.slice(r*2,r*2+2),16);return i}function sr(e){return ir(Qi+e)}function C(e,t=256){return typeof e=="string"&&e.length>0&&e.length<=t}function qe(e){return typeof e=="number"&&Number.isInteger(e)&&e>0}function ar(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return!C(t.sid)||!C(t.sub)||!C(t.aud,512)||t.team!==null&&!C(t.team)||!tr.includes(t.tier)||t.role!==void 0&&!C(t.role,64)||t.tools!==void 0&&(!Array.isArray(t.tools)||t.tools.length>256||!t.tools.every(i=>C(i,64)))||!qe(t.iat)||!qe(t.exp)||t.exp<=t.iat?null:{v:Je,sid:t.sid,sub:t.sub,team:t.team,tier:t.tier,...t.role!==void 0?{role:t.role}:{},...t.tools!==void 0?{tools:[...t.tools]}:{},aud:t.aud,iat:t.iat,exp:t.exp}}var or=hi;function Ze(e){return e.startsWith(`${We}.`)}function se(e,t){let i=or;if(!i)return{ok:false,reason:"no-key"};let r=typeof e=="string"?e.split("."):[];if(r.length!==3||r[0]!==We)return{ok:false,reason:"malformed"};let[,n,s]=r,h=Xe(n),c=Xe(s);if(!h||!c||c.length!==er)return{ok:false,reason:"malformed"};try{if(!Zi.sign.detached.verify(sr(n),c,nr(i)))return{ok:false,reason:"signature"}}catch{return{ok:false,reason:"signature"}}let a=rr(h),l;try{l=a===null?null:JSON.parse(a)}catch{return{ok:false,reason:"malformed"}}if(!l||typeof l!="object"||l.v!==Je)return{ok:false,reason:l&&typeof l=="object"?"version":"malformed"};let o=ar(l);if(!o)return{ok:false,reason:"claims"};if(o.aud!==t.audience)return{ok:false,reason:"audience"};if(t.ignoreTime)return{ok:true,claims:o};let d=Math.floor((t.nowMs??u())/1e3);return d>=o.exp+re?{ok:false,reason:"expired"}:o.iat>d+re?{ok:false,reason:"not-yet-valid"}:{ok:true,claims:o}}var lr="@buoy/session:",$=10080*60*1e3,Qe=360*60*1e3,cr=300*1e3,hr=5*1e3,dr=300*1e3,ur=15e3,fr="https://buoy.gg",pr="buoy:signin",mr=600*1e3,p=class extends Error{constructor(e,t){super(t);this.code=e;this.name="SessionError"}};function gr(){let e=globalThis;return{fetch:(t,i)=>fetch(t,i),storage:T,now:u,random:t=>{let i=new Uint8Array(t);if(!e.crypto?.getRandomValues)throw new p("not_configured","This platform has no secure random source.");return e.crypto.getRandomValues(i)},sha256:async t=>{if(!e.crypto?.subtle)throw new p("not_configured","Sign-in needs a secure page (https or localhost).");return new Uint8Array(await e.crypto.subtle.digest("SHA-256",t))},openPopup:()=>{if(!e.window?.open)return null;let t=480,i=640,r=Math.max(0,(e.window.screenX??0)+((e.window.outerWidth??t)-t)/2),n=Math.max(0,(e.window.screenY??0)+((e.window.outerHeight??i)-i)/2);return e.window.open("about:blank","buoy-signin",`popup,width=${t},height=${i},left=${r},top=${n}`)},onMessage:t=>{if(!e.window?.addEventListener)return()=>{};let i=r=>t({origin:r.origin,data:r.data});return e.window.addEventListener("message",i),()=>e.window?.removeEventListener("message",i)},withLock:(t,i)=>e.navigator?.locks?e.navigator.locks.request(t,i):i(),checksPlan:!e.window?.addEventListener||!!e.navigator?.locks,watch:t=>{let i=e.window;if(!i?.addEventListener)return yr(t.wake);let r=s=>t.storage(s.key),n=()=>{i.document?.visibilityState!=="hidden"&&t.wake()};return i.addEventListener("storage",r),i.addEventListener("online",t.wake),i.document?.addEventListener?.("visibilitychange",n),()=>{i.removeEventListener("storage",r),i.removeEventListener("online",t.wake),i.document?.removeEventListener?.("visibilitychange",n)}},setTimer:(t,i)=>setTimeout(t,Math.min(i,2147483647)),clearTimer:t=>clearTimeout(t)}}function yr(e){try{let{AppState:t}=(oi(),ot(z)),i=t?.addEventListener?.("change",r=>{r==="active"&&e()});return()=>i?.remove()}catch{return()=>{}}}function wr(){let e=globalThis.location;if(!(!e?.origin||!/^https?:$/.test(e.protocol??"")))return e.origin}var vr=class{constructor(e){this.signinOrigin=fr;this.current=null;this.claims=null;this.listeners=new Set;this.timer=null;this.refreshing=null;this.loaded=null;this.unwatch=null;this.limitTimer=null;this.epoch=0;this.planRetries=0;this.deps=e??gr(),this.audience=wr()}get origin(){return this.signinOrigin}configure(e){e.audience!==void 0&&(this.audience=e.audience),e.signinOrigin!==void 0&&(this.signinOrigin=e.signinOrigin.replace(/\/$/,"")),this.reset()}reset(){this.planRetries=0,this.unwatch?.(),this.unwatch=null,this.epoch+=1,this.limitTimer!==null&&this.deps.clearTimer(this.limitTimer),this.limitTimer=null,this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=null,this.current=null,this.claims=null,this.loaded=null,this.refreshing=null}get storageKey(){return lr+(this.audience??"")}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}notify(){for(let e of[...this.listeners])try{e()}catch(t){console.warn("[Buoy] sign-in listener error:",t)}}getAccessToken(){let e=this.getStatus();return e.state==="active"&&!e.grace?this.current?.accessToken??null:null}getStatus(){let e=this.claims;if(!e)return{state:"signed_out"};let t=e.exp*1e3,i=this.deps.now();return i<(e.iat-re)*1e3?{state:"signed_out"}:i<t?{state:"active",claims:e,grace:false,validUntil:t}:i<t+$?{state:"active",claims:e,grace:true,validUntil:t+$}:{state:"signed_out"}}load(){return this.loaded||(this.loaded=this.loadOnce()),this.loaded}async loadOnce(){if(!this.audience)return;this.unwatch??(this.unwatch=this.deps.watch?.({storage:t=>{(t===null||t===this.storageKey)&&this.sync()},wake:()=>{this.deps.checksPlan?this.checkPlan():this.claims&&this.refresh()}})??null);let e=await this.read();e&&this.adopt(e)&&(this.notify(),this.schedule(),this.deps.checksPlan&&this.checkPlan())}async sync(){if(!this.audience)return;let e=await this.read();if(!e){this.current&&this.clearLocal();return}e.refreshToken!==this.current?.refreshToken&&this.adopt(e)&&(this.notify(),this.schedule())}async read(){try{let e=await(await this.deps.storage()).getItem(this.storageKey);if(!e)return null;let t=JSON.parse(e);return t?.v===1&&typeof t.accessToken=="string"&&typeof t.refreshToken=="string"?t:null}catch{return null}}async write(e){let t=await this.deps.storage();e?await t.setItem(this.storageKey,JSON.stringify(e)):await t.removeItem(this.storageKey)}adopt(e){if(!this.audience)return false;let t=se(e.accessToken,{audience:this.audience,ignoreTime:true}),i=t.ok?t.claims:null;return i?(this.current=e,this.claims=i,true):false}armLimit(){if(this.limitTimer!==null&&this.deps.clearTimer(this.limitTimer),this.limitTimer=null,!this.claims)return;let e=this.claims.exp*1e3,t=this.deps.now(),i=t<e?e:t<e+$?e+$:null;i!==null&&(this.limitTimer=this.deps.setTimer(()=>{this.limitTimer=null,this.notify(),this.armLimit()},i-t))}call(e,t){return new Promise((i,r)=>{let n=this.deps.setTimer(()=>r(new Error("timeout")),ur);this.deps.fetch(e,t).then(s=>{this.deps.clearTimer(n),i(s)},s=>{this.deps.clearTimer(n),r(s)})})}schedule(){if(this.armLimit(),this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=null,!this.claims)return;let e=this.claims.exp*1e3-Qe-this.deps.now();this.timer=this.deps.setTimer(()=>{this.timer=null,this.refresh()},Math.max(0,e))}refresh(e=false){return this.startRefresh(()=>this.refreshLocked(e))}checkPlan(e=cr){return this.startRefresh(()=>this.refreshLocked(false,e))}retryPlanCheck(){if(this.planRetries>=2){this.planRetries=0,this.schedule();return}this.planRetries+=1,this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=this.deps.setTimer(()=>{this.timer=null,this.checkPlan(0)},hr)}startRefresh(e){return this.refreshing||(this.refreshing=this.deps.withLock(this.lockName,e).catch(()=>this.retryLater()).finally(()=>{this.refreshing=null})),this.refreshing}get lockName(){return`buoy-session:${this.audience??""}`}async refreshLocked(e,t){let i=this.epoch,r=await this.read();if(!r){this.current&&this.clearLocal();return}if(r.refreshToken!==this.current?.refreshToken&&this.adopt(r)){this.notify(),this.schedule();return}if(!this.claims)return;let n=this.claims.exp*1e3-this.deps.now()>Qe,s=!e&&n&&t!==void 0,h=s&&this.planRetries>0&&this.timer===null,c=s&&this.deps.now()-this.claims.iat*1e3>=t;if(!e&&n&&!c&&!h){this.planRetries||this.schedule();return}let a=()=>s?this.retryPlanCheck():this.retryLater(),l,o;try{let d=await this.call(`${this.signinOrigin}/api/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:r.refreshToken,audience:this.audience})});l=d.status,o=await d.json().catch(()=>null)}catch{i===this.epoch&&a();return}if(i===this.epoch){if(l===200&&o&&typeof o.access_token=="string"&&typeof o.refresh_token=="string"){let d={v:1,accessToken:o.access_token,refreshToken:o.refresh_token};if(this.adopt(d)){this.planRetries=0,await this.write(d),this.notify(),this.schedule();return}}if(l===400||l===401||l===403){await this.write(null),this.clearLocal();return}a()}}retryLater(){this.armLimit(),this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=this.deps.setTimer(()=>{this.timer=null,this.refresh(true)},dr),this.notify()}clearLocal(){this.planRetries=0,this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=null,this.limitTimer!==null&&this.deps.clearTimer(this.limitTimer),this.limitTimer=null,this.current=null,this.claims=null,this.notify()}async signIn(){if(!this.audience)throw new p("not_configured","Sign-in needs a web page or a configured app id.");let e=this.deps.openPopup();if(!e)throw new p("popup_blocked","The browser blocked the sign-in window. Allow pop-ups for this site and try again.");try{return await this.signInWith((t,i)=>new Promise((r,n)=>{e.location.href=t;let s=this.deps.now(),h=null,c=o=>{h!==null&&this.deps.clearTimer(h),a(),o()},a=this.deps.onMessage(o=>{if(o.origin!==this.signinOrigin)return;let d=o.data;!d||d.type!==pr||d.state!==i||(typeof d.code=="string"?c(()=>r(d.code)):c(()=>n(new p("access_denied","Sign-in was cancelled."))))}),l=()=>{if(e.closed)return c(()=>n(new p("popup_closed","The sign-in window was closed.")));if(this.deps.now()-s>mr)return c(()=>n(new p("timeout","Sign-in took too long.")));h=this.deps.setTimer(l,500)};h=this.deps.setTimer(l,500)}))}finally{try{e.closed||e.close()}catch{}}}async signInWith(e){let t=this.audience;if(!t)throw new p("not_configured","Sign-in needs a web page or a configured app id.");let i=ne(this.deps.random(32)),r=ne(this.deps.random(16)),n=ne(await this.deps.sha256(new TextEncoder().encode(i))),s=`${this.signinOrigin}/auth/authorize?audience=${encodeURIComponent(t)}&code_challenge=${n}&code_challenge_method=S256&state=${r}`,h=await e(s,r),c;try{c=await this.call(`${this.signinOrigin}/api/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:h,code_verifier:i,audience:t})})}catch{throw new p("network","Buoy could not be reached. Check your connection and try again.")}let a=await c.json().catch(()=>null);if(c.status!==200||!a||typeof a.access_token!="string"||typeof a.refresh_token!="string"){let l=a&&typeof a.error_description=="string"?a.error_description:"Buoy did not accept this sign-in.";throw new p(c.status===503?"unavailable":"rejected",l)}return this.finishSignIn(a.access_token,a.refresh_token)}async finishSignIn(e,t){let i={v:1,accessToken:e,refreshToken:t};if(this.epoch+=1,!this.adopt(i))throw new p("rejected","Buoy sent a sign-in this app could not check.");return await this.write(i),await this.load(),this.notify(),this.schedule(),this.getStatus()}async signInWithCode(e,t={}){let i=this.audience;if(!i)throw new p("not_configured","Sign-in with a code needs this app's id (app:com.example.app).");let r=(a,l)=>this.call(`${this.signinOrigin}/api/auth/device/${a}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(l)}),n;try{n=await r("start",{audience:i})}catch{throw new p("network","Buoy could not be reached. Check your connection and try again.")}let s=await n.json().catch(()=>null);if(n.status!==200||!s||typeof s.device_code!="string"||typeof s.user_code!="string"||typeof s.verification_uri!="string"||typeof s.verification_uri_complete!="string"){let a=s&&typeof s.error_description=="string"?s.error_description:"Buoy could not start a sign-in.";throw new p(n.status===503?"unavailable":"rejected",a)}let h=this.deps.now()+(Number(s.expires_in)||600)*1e3,c=Math.max(5,Number(s.interval)||5)*1e3;for(e({userCode:s.user_code,verificationUri:s.verification_uri,verificationUriComplete:s.verification_uri_complete,expiresAt:h});;){if(await this.wait(c,t.signal),this.deps.now()>h)throw new p("timeout","The code ran out. Start again for a new one.");let a;try{a=await r("poll",{device_code:s.device_code})}catch{continue}let l=await a.json().catch(()=>null);if(a.status===200&&l&&typeof l.access_token=="string"&&typeof l.refresh_token=="string")return this.finishSignIn(l.access_token,l.refresh_token);let o=l&&typeof l.error=="string"?l.error:"";if(o==="authorization_pending"||a.status>=500)continue;if(o==="slow_down"||a.status===429){c+=5e3;continue}if(o==="access_denied")throw new p("access_denied","The sign-in was turned down on buoy.gg.");if(o==="expired_token")throw new p("timeout","The code ran out. Start again for a new one.");let d=l&&typeof l.error_description=="string"?l.error_description:"Buoy did not accept this sign-in.";throw new p("rejected",d)}}wait(e,t){return new Promise((i,r)=>{let n=()=>new p("access_denied","Sign-in was cancelled.");if(t?.aborted)return r(n());let s=()=>{this.deps.clearTimer(h),r(n())},h=this.deps.setTimer(()=>{t?.removeEventListener?.("abort",s),i()},e);t?.addEventListener?.("abort",s)})}async signOut(){this.epoch+=1;let e=this.current;this.clearLocal();let t=e;try{await this.deps.withLock(this.lockName,async()=>{t=await this.read()??e,await this.write(null)})}catch{await this.write(null).catch(()=>{})}if(t)try{await this.call(`${this.signinOrigin}/api/auth/revoke`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:t.refreshToken})})}catch{}}},_=new vr;f();var br="bsk1_",Tr="service",Ar=15e3;function ae(e){return e.startsWith(br)}function N(e){let t=e.trim();return ae(t)||Ze(t)?t:t.toUpperCase()}function kr(e,t){return N(e??"")===N(t??"")}async function Er(e,t){let i=t.fetch??((a,l)=>fetch(a,l)),r=typeof AbortController<"u"?new AbortController:void 0,n=setTimeout(()=>r?.abort(),Ar),s,h;try{let a=await i(`${t.origin.replace(/\/$/,"")}/api/auth/service-token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({key:e}),signal:r?.signal});s=a.status,h=await a.json().catch(()=>null)}catch{return{ok:false,reason:"network",detail:"Buoy could not be reached to check the bot key."}}finally{clearTimeout(n)}if(s>=500||s===429)return{ok:false,reason:"network",detail:"Buoy is busy. The bot key will be checked again soon."};if(s!==200||typeof h?.access_token!="string")return{ok:false,reason:"rejected",detail:typeof h?.error_description=="string"?h.error_description:"This bot key was not accepted."};let c=se(h.access_token,{audience:Tr,nowMs:u()});return c.ok?{ok:true,claims:c.claims}:{ok:false,reason:"rejected",detail:"Buoy sent a token this app could not check."}}f();var xr="dev";function et(e){return Ze(e)}function tt(e,t=u()){let i=se(e,{audience:xr,ignoreTime:true});return i.ok?t>=i.claims.exp*1e3?{ok:false,reason:"expired",message:"Your dev token ran out. Run `npx --package=@buoy-gg/core buoy login` again."}:{ok:true,claims:i.claims}:{ok:false,reason:"invalid",message:"This dev token is not valid. Run `npx --package=@buoy-gg/core buoy login` again."}}var _r="This is a dev token. It only works in dev builds. A live build turns on Buoy with Sign in with Buoy.";var Lr={role:null,tools:null};function it(e){return{role:e.role??null,tools:e.tools??null}}async function b(e,t){let i;try{return await Promise.race([e,new Promise(r=>{i=setTimeout(()=>r(t),15e3)})])}finally{i&&clearTimeout(i)}}function P(e){return e.tier==="pro"||e.tier==="free"?e.tier:e.isPro?"pro":"free"}var Sr=class{constructor(){this.state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,error:null,errorKind:null,expiresAt:null};this.listeners=new Set;this.revalidationTimer=null;this.cachedLicense=null;this.fingerprintPromise=null;this.fingerprintRestored=false;this.initPromise=null;this.generation=0;this.persistence=Promise.resolve();this.verifiedAt=null;this.expiryTimer=null;this.removeForegroundListener=null;this.sessionUnsubscribe=null;this.devToken=null;this.retryTimer=null;this.retryAttempt=0;this.deviceRegistrationCallback=null;this.pendingRegistration=null}async initialize(){if(this.initPromise)return this.initPromise;if(!this.state.isInitialized)return this.initPromise=this._doInitialize(),this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;let e=this.generation;this.sessionUnsubscribe||(this.sessionUnsubscribe=_.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))),await b(_.load().catch(()=>{}),void 0);try{let t=await b(this.loadCachedLicense(),null);if(e!==this.generation){this.state.isInitialized=true,this.emit({type:"initialized",isPro:this.state.isPro}),this.startRevalidationTimer();return}if(t&&(this.configuredKey===void 0||t.licenseKey===this.configuredKey)){let i=R(t);this.cachedLicense=t,this.state.licenseKey=t.licenseKey,i&&this.isCacheValid(t)?this.applyTier(P(t)):this.lock(),this.state.expiresAt=t.expiresAt?new Date(t.expiresAt):null,i&&this.isCacheValid(t)&&this.setVerifiedAt(t.cachedAt),this.configuredKey===void 0&&t.licenseKey&&!(i&&this.isCacheValid(t)&&this.isCacheFresh(t))&&this.validateInBackground(t.licenseKey)}this.state.isInitialized=true,this.emit({type:"initialized",isPro:this.state.isPro}),this.startRevalidationTimer()}catch(t){console.warn("[Buoy]","[React Buoy] License initialization failed:",t),this.state.isInitialized=true,this.emit({type:"initialized",isPro:false})}}async configure(e){if(e===void 0)return await this.initialize(),this.hasAccountAccess();let t=N(e),i=++this.generation;return this.cancelRetry(),this.configuredKey=t||null,this.state.licenseKey!==this.configuredKey&&this.lock(),this.state.licenseKey=this.configuredKey,this.state.isValidating=!!t,this.emit({type:"validating",isPro:this.isPro()}),await this.initialize(),i!==this.generation?false:t?this.setLicenseKey(t):(await this.clearLicense(),false)}async setLicenseKey(e,t){if(!e||e.trim().length===0)return this.state.error="License key is required",this.state.errorKind="verdict",false;let i=N(e),r=++this.generation;if(this.cancelRetry(),t?.isRetry||(this.retryAttempt=0),this.state.licenseKey!==i&&this.lock(),this.state.licenseKey=i,this.state.isValidating=true,this.state.error=null,this.state.errorKind=null,this.emit({type:"validating",isPro:this.isPro()}),ze(i))return this.admitToken(i,r);if(ae(i))return this.admitServiceKey(i,r);if(et(i))return this.admitDevToken(i);if(!this.cachedLicense){let a=await b(this.loadCachedLicense(),null);if(r!==this.generation)return false;a?.licenseKey===i&&(this.cachedLicense=a,R(a)&&this.isCacheValid(a)&&(this.applyTier(P(a)),this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null,this.setVerifiedAt(a.cachedAt),this.emit({type:"validating",isPro:this.isPro()})))}let n=this.cachedLicense;if(!t?.force&&n&&n.valid&&n.licenseKey===i&&n.fingerprint&&R(n)&&this.isCacheValid(n)&&this.isCacheFresh(n))return this.applyTier(P(n)),this.state.licenseKey=i,this.state.isValidating=false,this.state.error=null,this.state.errorKind=null,this.state.expiresAt=n.expiresAt?new Date(n.expiresAt):null,this.setVerifiedAt(n.cachedAt),this.emit({type:"validated",isPro:this.state.isPro}),true;let s=await b(this.loadHold(),null);if(r!==this.generation)return false;let h=(s?.backoffUntil??0)-u();if(h>0)return this.standDown(i,r,"License server is rate limited; retrying later.",h);if(!t?.force&&s?.key===i&&s.verdictAt!==void 0&&u()-s.verdictAt>=0&&u()-s.verdictAt<mi)return this.lock(),this.state.isValidating=false,this.state.error=s.detail||"License could not be verified",this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:this.state.error}),false;let c;try{c=await ki(i)}catch(a){let l=a instanceof Error?a.message:"Validation failed";if(r!==this.generation)return false;if(Ke(a)){if(wi(a)){let o=Math.min(vi(a,Pe,pi)*2**this.retryAttempt,Pe);return this.retryAttempt+=1,await this.saveHold({...this.hold,backoffUntil:u()+o}),r!==this.generation?false:this.standDown(i,r,l,o)}return this.state.isValidating=false,this.cachedLicense&&this.cachedLicense.licenseKey===i&&R(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)?(this.applyTier(P(this.cachedLicense)),this.state.error=null,this.state.errorKind=null,this.state.expiresAt=this.cachedLicense.expiresAt?new Date(this.cachedLicense.expiresAt):null,this.setVerifiedAt(this.cachedLicense.cachedAt),this.keyTier()!=="pro"&&this.scheduleRetry(i),this.emit({type:"validated",isPro:this.state.isPro}),true):(this.state.error=l,this.state.errorKind="transport",this.scheduleRetry(i),this.emit({type:"error",isPro:this.state.isPro,error:l}),false)}return this.state.isValidating=false,this.state.error=l,this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:l}),false}try{if(r!==this.generation)return false;let a=_i(c),l=c.data?.relationships?.product?.data?.id;if((!l||l===M.productId)&&a.code==="EXPIRED"&&(Xi(c.data)||this.cachedLicense?.licenseKey===i&&R(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){let B=u(),he=await this.saveCache({licenseKey:i,licenseId:c.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:B,lastValidatedAt:B,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},r);return r!==this.generation||!he?false:(this.cachedLicense=he,this.applyTier("free"),this.state.isValidating=false,this.state.expiresAt=null,this.setVerifiedAt(B),this.emit({type:"validated",isPro:false}),true)}if(Li(a.code)||!Ei(c))return this.lock(),this.state.isValidating=false,this.state.error=a.detail||"License could not be verified",this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:this.state.error}),await this.clearCachedLicense(),await this.saveHold({key:i,code:a.code,detail:this.state.error,verdictAt:u()}),false;if(!c.data)return this.lock(),this.state.isValidating=false,this.state.error=a.detail||"License not found",this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:this.state.error}),await this.clearCachedLicense(),false;let o=Ji(c.data),d=c.data.id,A=u(),k=xi(c)>=gi,oe=te(),rt=oe&&!k,nt=o==="free"&&(k||!oe),L=this.cachedLicense?.fingerprint,K=this.cachedLicense?.deviceName,le=false;if(!L){if(L=await b(this.getOrCreateDeviceFingerprint(),ee()),r!==this.generation)return false;K=ie(),le=rt}let U=false;le&&(this.deviceRegistrationCallback?(this.pendingRegistration={licenseId:d,licenseKey:i,fingerprint:L},this.deviceRegistrationCallback({fingerprint:L,defaultName:K}),U=true):this.registerDeviceAsync(d,i,L,K));let F={licenseKey:i,licenseId:d,valid:true,isPro:o==="pro",tier:o,expiresAt:c.data.attributes.expiry??null,cachedAt:A,lastValidatedAt:A,fingerprint:U?void 0:L,deviceName:U?void 0:K,quiet:nt||void 0},ce=await this.saveCache(F,r);return r!==this.generation||!ce||(this.cachedLicense=ce,this.applyTier(o),this.state.isValidating=false,this.state.expiresAt=F.expiresAt?new Date(F.expiresAt):null,this.setVerifiedAt(A),this.hold&&await this.saveHold(null),r!==this.generation)?false:(this.retryAttempt=0,this.emit({type:"validated",isPro:this.state.isPro}),true)}catch(a){let l=a instanceof Error?a.message:"Validation failed";return r!==this.generation||(this.state.isValidating=false,this.state.error=l,this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:l})),false}}scheduleRetry(e){this.cancelRetry();let t=fi[this.retryAttempt];if(t===void 0)return;this.retryAttempt+=1;let i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null,i===this.generation&&(this.state.isValidating||this.setLicenseKey(e,{force:true,isRetry:true}))},t),typeof m<"u"&&m&&(globalThis.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer)}async admitServiceKey(e,t){let i=await Er(e,{origin:_.origin});if(t!==this.generation)return false;if(!i.ok)return this.lock(),this.state.isValidating=false,this.state.error=i.detail,this.state.errorKind=i.reason==="network"?"transport":"verdict",this.emit({type:"error",isPro:false,error:i.detail}),i.reason==="network"&&this.scheduleRetry(e),false;let r=i.claims.exp*1e3;return this.applyTier(i.claims.tier==="free"?"free":"pro"),this.state.isValidating=false,this.state.expiresAt=new Date(r),this.setVerifiedAt(u()),this.retryAttempt=0,this.scheduleRetryIn(e,Math.max(6e4,r-3600*1e3-u())),this.emit({type:"validated",isPro:this.isPro()}),true}admitDevToken(e){let t=tt(e);if(!t.ok||!te()){let r=t.ok?_r:t.message;return this.lock(),this.state.isValidating=false,this.state.error=r,this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:r}),false}let i=u();return this.devToken={token:e,claims:t.claims},this.applyTier(t.claims.tier==="free"?"free":"pro"),this.state.isValidating=false,this.state.expiresAt=new Date(t.claims.exp*1e3),this.setVerifiedAt(Math.min(i,t.claims.iat*1e3)),this.retryAttempt=0,this.emit({type:"validated",isPro:this.isPro()}),true}async admitToken(e,t){let i=Wi(e);if(t!==this.generation)return false;if(!i)return this.lock(),this.state.isValidating=false,this.state.error="This key is not valid. Check that it was copied completely.",this.state.errorKind="verdict",this.emit({type:"error",isPro:false,error:this.state.error}),await this.clearCachedLicense(),false;let r=u(),n=this.cachedLicense?.fingerprint??await b(this.getOrCreateDeviceFingerprint(),ee());if(t!==this.generation)return false;let s=await this.saveCache({licenseKey:e,licenseId:`token:${i.accountHash}`,valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:r,lastValidatedAt:r,fingerprint:n,deviceName:this.cachedLicense?.deviceName??ie(),quiet:true},t);return t!==this.generation||!s?false:(this.cachedLicense=s,this.applyTier("free"),this.state.isValidating=false,this.state.expiresAt=null,this.setVerifiedAt(r),this.retryAttempt=0,this.emit({type:"validated",isPro:false}),true)}standDown(e,t,i,r){if(t!==this.generation)return false;this.state.isValidating=false;let n=this.cachedLicense;return n&&n.licenseKey===e&&R(n)&&this.isCacheValid(n)?(this.applyTier(P(n)),this.state.error=null,this.state.errorKind=null,this.state.expiresAt=n.expiresAt?new Date(n.expiresAt):null,this.setVerifiedAt(n.cachedAt),this.keyTier()!=="pro"&&this.scheduleRetryIn(e,r),this.emit({type:"validated",isPro:this.state.isPro}),true):(this.state.error=i,this.state.errorKind="transport",this.scheduleRetryIn(e,r),this.emit({type:"error",isPro:this.state.isPro,error:i}),false)}scheduleRetryIn(e,t){this.cancelRetry();let i=this.generation;this.retryTimer=setTimeout(()=>{this.retryTimer=null,i===this.generation&&(this.state.isValidating||this.setLicenseKey(e,{force:true,isRetry:true}))},Math.max(1,Math.min(t,2147483647))),typeof m<"u"&&m&&(w.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer)}cancelRetry(){this.retryTimer&&(clearTimeout(this.retryTimer),this.retryTimer=null)}async clearLicense(){this.generation+=1,this.cancelRetry(),this.retryAttempt=0,this.configuredKey=null,this.state.licenseKey=null,this.lock(),this.state.expiresAt=null,this.state.error=null,this.state.errorKind=null,this.cachedLicense=null,this.pendingRegistration=null,this.state.isValidating=false,this.emit({type:"deactivated",isPro:false}),await this.clearCachedLicense(),this.hold?.verdictAt!==void 0&&await this.saveHold(this.hold.backoffUntil?{backoffUntil:this.hold.backoffUntil}:null)}applyTier(e){this.state.tier=e,this.state.tierSource="key",this.state.isPro=e==="pro"}lock(){this.state.tier="free",this.state.tierSource="none",this.state.isPro=false,this.verifiedAt=null,this.expiryTimer&&clearTimeout(this.expiryTimer),this.expiryTimer=null}getTier(){return this.credential().tier}credential(){let e=this.keyTier(),t=this.sessionTier();return t!==null&&(!this.hasKeyAccess()||t==="pro"&&e!=="pro")?{source:"session",tier:t}:{source:this.state.tierSource,tier:e}}keyTier(){return!this.hasKeyAccess()||this.state.expiresAt&&u()>=this.state.expiresAt.getTime()?"free":this.state.tier}sessionTier(){let e=_.getStatus();return e.state!=="active"?null:e.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){let{source:e,tier:t}=this.credential(),i=this.getTeamAccess();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess(),teamRole:i.role,allowedTools:i.tools}}getTeamAccess(){let e=_.getStatus();if(e.state==="active")return it(e.claims);let t=this.devToken;return t&&t.token===this.state.licenseKey&&this.state.tierSource==="key"&&u()<t.claims.exp*1e3&&this.hasKeyAccess()?it(t.claims):Lr}getAccountAccess(){let e=this.getKeyAccess();if(e.status==="admitted")return e;let t=_.getStatus();return t.state==="active"?{status:"admitted",reason:null,validUntil:t.validUntil}:e}getKeyAccess(){return Ye({initialized:this.state.isInitialized,validating:this.state.isValidating,key:this.state.licenseKey,tierSource:this.state.tierSource,verifiedAt:this.verifiedAt})}hasAccountAccess(){return this.getAccountAccess().status==="admitted"}hasKeyAccess(){return this.getKeyAccess().status==="admitted"}setVerifiedAt(e){this.verifiedAt=e,this.expiryTimer&&clearTimeout(this.expiryTimer);let t=e+D,i=this.state.expiresAt?.getTime(),r=(i&&i>u()?Math.min(t,i):t)-u();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null,this.verifiedAt===e&&(this.emit({type:"validated",isPro:this.isPro()}),u()<t&&this.setVerifiedAt(e))},Math.max(1,Math.min(r,2147483647))),typeof m<"u"&&m&&(w.__LICENSE_MANAGER_EXPIRY_TIMER__=this.expiryTimer)}subscribe(e){return this.listeners.add(e),()=>this.listeners.delete(e)}onDeviceRegistrationNeeded(e){return this.deviceRegistrationCallback=e,()=>{this.deviceRegistrationCallback=null}}async completeDeviceRegistration(e){if(!this.pendingRegistration){console.warn("[Buoy] No pending device registration");return}let{licenseId:t,licenseKey:i,fingerprint:r}=this.pendingRegistration,n=this.generation,s=e.trim()||ie(),h=$e();try{await Me(t,i,r,s,h)}catch(c){let a=c instanceof Error?c.message:String(c);if(!(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"))throw console.warn("[Buoy] Device registration failed:",a),c}if(n===this.generation){if(this.cachedLicense?.licenseKey===i){let c=await this.saveCache({...this.cachedLicense,fingerprint:r,deviceName:s},n);if(n!==this.generation)return;c&&(this.cachedLicense=c)}this.pendingRegistration=null}}emit(e){[...this.listeners].forEach(t=>{try{t(e)}catch(i){console.warn("[Buoy]","[React Buoy] License listener error:",i)}})}isCacheValid(e){let t=u()-e.cachedAt;return!(!e.valid||!Number.isFinite(e.cachedAt)||t<0||t>=D)}isCacheFresh(e){let t=this.isQuiet(e)?yi:ui;return u()-(e.lastValidatedAt??0)<t}isQuiet(e){return e.quiet!==void 0?e.quiet:P(e)==="free"&&!te()}async loadHold(){if(this.hold!==void 0)return this.hold;try{let e=await(await T()).getItem(Q),t=e?JSON.parse(e):null;this.hold=t&&typeof t=="object"?t:null}catch{this.hold=null}return this.hold}async saveHold(e){this.hold=e;try{let t=await T();e?await t.setItem(Q,JSON.stringify(e)):await t.removeItem(Q)}catch{}}async persistCache(e){let t=je(e);return await(await T()).setItem(q,JSON.stringify(t)),t}saveCache(e,t){let i=this.persistence.catch(()=>{}).then(async()=>{if(t!==this.generation)return null;let r=await this.persistCache(e);return t===this.generation?r:null});return this.persistence=i,b(i,je(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});let e=await(await T()).getItem(q);if(!e)return null;let t=JSON.parse(e);if(t.fingerprint){let i=await b(this.getOrCreateDeviceFingerprint(t.fingerprint).catch(()=>null),null);if(i&&this.fingerprintRestored&&t.fingerprint!==i)return{...t,fingerprint:void 0,deviceName:void 0}}return t}catch(e){return console.warn("[Buoy] Error loading cached license:",e),null}}getOrCreateDeviceFingerprint(e){return this.fingerprintPromise||(this.fingerprintPromise=(async()=>{let t=await T(),i=await t.getItem(Z),r=await t.getItem(Ce),n=await b(Ii().catch(()=>null),null),s=Ri({stored:i,storedOwner:r,marker:n?Ci(n):null,blobFingerprint:e??this.cachedLicense?.fingerprint,mint:ee});return this.fingerprintRestored=s.restored,s.changed&&(await t.setItem(Z,s.fingerprint),s.owner&&await t.setItem(Ce,s.owner)),s.fingerprint})()),this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;let e=this.persistence.catch(()=>{}).then(async()=>{await(await T()).removeItem(q)});this.persistence=e,await b(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,r){let n=$e();Me(e,t,i,r,n).catch(s=>{s.message!=="FINGERPRINT_TAKEN"&&s.message!=="MACHINE_LIMIT_EXCEEDED"&&console.warn("[Buoy] Device registration failed (non-blocking):",s.message)})}validateInBackground(e){this.setLicenseKey(e,{force:true,isRetry:true})}refreshAccess(){this.emit({type:"validated",isPro:this.isPro()})}startRevalidationTimer(){this.removeForegroundListener||(this.removeForegroundListener=qi(()=>this.refreshAccess()),typeof m<"u"&&m&&(w.__LICENSE_MANAGER_FOREGROUND_OFF__=this.removeForegroundListener)),this.revalidationTimer&&clearInterval(this.revalidationTimer),this.revalidationTimer=setInterval(()=>{if(!this.state.licenseKey||this.state.isValidating)return;let e=this.cachedLicense;e&&e.licenseKey===this.state.licenseKey&&this.isCacheFresh(e)||this.validateInBackground(this.state.licenseKey)},di),typeof m<"u"&&m&&(globalThis.__LICENSE_MANAGER_TIMER__=this.revalidationTimer)}stopRevalidationTimer(){this.removeForegroundListener?.(),this.removeForegroundListener=null,this.expiryTimer&&clearTimeout(this.expiryTimer),this.expiryTimer=null,this.revalidationTimer&&(clearInterval(this.revalidationTimer),this.revalidationTimer=null),this.cancelRetry()}async forceReregister(){this.cachedLicense&&(this.cachedLicense.fingerprint=void 0,this.cachedLicense.deviceName=void 0),this.fingerprintPromise=null,await this.clearCachedLicense();try{await(await T()).removeItem(Z)}catch{}}},Ir=new Sr,w=globalThis;typeof m<"u"&&m&&(w.__LICENSE_MANAGER_FOREGROUND_OFF__?.(),w.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0,w.__LICENSE_MANAGER_EXPIRY_TIMER__&&clearTimeout(w.__LICENSE_MANAGER_EXPIRY_TIMER__),w.__LICENSE_MANAGER_TIMER__&&clearInterval(w.__LICENSE_MANAGER_TIMER__),w.__LICENSE_MANAGER_RETRY_TIMER__&&(clearTimeout(w.__LICENSE_MANAGER_RETRY_TIMER__),w.__LICENSE_MANAGER_RETRY_TIMER__=void 0));export{u as a,I as b,Ke as c,ze as d,Ye as e,p as f,_ as g,ae as h,N as i,kr as j,et as k,tt as l,Ir as m};/*!
|
|
2
|
-
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
3
|
-
*
|
|
4
|
-
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
5
|
-
* (https://buoy.gg/terms), not an OSS license.
|
|
6
|
-
*//*!
|
|
7
|
-
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
8
|
-
*
|
|
9
|
-
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
10
|
-
* (https://buoy.gg/terms), not an OSS license.
|
|
11
|
-
*
|
|
12
|
-
* This file configures the technological measure that controls access to paid
|
|
13
|
-
* Buoy Pro features. Modifying, patching, aliasing, stubbing, or otherwise
|
|
14
|
-
* altering it — including repointing `apiUrl` at a stand-in license server — so
|
|
15
|
-
* that Pro features unlock without a valid license is a breach of the EULA and,
|
|
16
|
-
* in the United States, circumvention of an access control under 17 U.S.C.
|
|
17
|
-
* § 1201, which applies whether or not any code is copied.
|
|
18
|
-
*
|
|
19
|
-
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
20
|
-
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
21
|
-
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
22
|
-
*//*!
|
|
23
|
-
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
24
|
-
*
|
|
25
|
-
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
26
|
-
* (https://buoy.gg/terms), not an OSS license.
|
|
27
|
-
*
|
|
28
|
-
* This file is part of the technological measure that controls access to paid
|
|
29
|
-
* Buoy Pro features. Modifying, patching, aliasing, stubbing, or otherwise
|
|
30
|
-
* altering it so that Pro features unlock without a valid license is a breach
|
|
31
|
-
* of the EULA and, in the United States, circumvention of an access control
|
|
32
|
-
* under 17 U.S.C. § 1201 — which applies whether or not any code is copied.
|
|
33
|
-
*
|
|
34
|
-
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
35
|
-
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
36
|
-
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
37
|
-
*//*!
|
|
38
|
-
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
39
|
-
*
|
|
40
|
-
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
41
|
-
* (https://buoy.gg/terms), not an OSS license.
|
|
42
|
-
*
|
|
43
|
-
* This file is part of the technological measure that controls access to paid
|
|
44
|
-
* Buoy Pro features: it decides which tier a validated key grants. Modifying,
|
|
45
|
-
* patching, aliasing, stubbing, or otherwise altering it so that Pro features
|
|
46
|
-
* unlock without a valid license is a breach of the EULA and, in the United
|
|
47
|
-
* States, circumvention of an access control under 17 U.S.C. § 1201 — which
|
|
48
|
-
* applies whether or not any code is copied.
|
|
49
|
-
*
|
|
50
|
-
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
51
|
-
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
52
|
-
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
53
|
-
*//*!
|
|
54
|
-
* PROPRIETARY — Buoy license enforcement. NOT open source.
|
|
55
|
-
*
|
|
56
|
-
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
57
|
-
* (https://buoy.gg/terms), not an OSS license.
|
|
58
|
-
*//*!
|
|
59
|
-
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
60
|
-
*
|
|
61
|
-
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
62
|
-
* (https://buoy.gg/terms), not an OSS license.
|
|
63
|
-
*
|
|
64
|
-
* This file is the technological measure that controls access to paid Buoy Pro
|
|
65
|
-
* features. Modifying, patching, aliasing, stubbing, or otherwise altering it
|
|
66
|
-
* so that Pro features unlock without a valid license is a breach of the EULA
|
|
67
|
-
* and, in the United States, circumvention of an access control under
|
|
68
|
-
* 17 U.S.C. § 1201 — which applies whether or not any code is copied.
|
|
69
|
-
*
|
|
70
|
-
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
71
|
-
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
72
|
-
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
73
|
-
*/
|