@buoy-gg/license 7.0.63 → 7.0.65
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/module/LicenseManager.js +1 -1
- package/lib/web/chunks/LicenseManager-G4PF6ILL.mjs +1 -0
- package/lib/web/chunks/{chunk-4ZLILVOY.mjs → chunk-OP6QSLZS.mjs} +1 -1
- package/lib/web/index.mjs +1 -1
- package/package.json +1 -1
- package/lib/web/chunks/LicenseManager-5SP7AMUW.mjs +0 -1
|
@@ -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 buoy login`). Buy a key at
|
|
15
15
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
16
|
-
*/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,error:null,errorKind:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=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{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&&(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("[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){await this.clearLicense();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);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 c=await boundedStorage(this.loadHold(),null);if(s!==this.generation)return false;const u=(c?.backoffUntil??0)-(0,_realNow.realNow)();if(u>0){return this.standDown(i,s,"License server is rate limited; retrying later.",u)}if(!t?.force&&c?.key===i&&c.verdictAt!==void 0&&(0,_realNow.realNow)()-c.verdictAt>=0&&(0,_realNow.realNow)()-c.verdictAt<_config.LICENSE_VERDICT_CACHE_DURATION){this.lock();this.state.isValidating=false;this.state.error=c.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let n;try{n=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)(n);const o=n.data?.relationships?.product?.data?.id;if((!o||o===_config.KEYGEN_CONFIG.productId)&&a.code==="EXPIRED"&&((0,_tier.isRecognizedAccount)(n.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:n.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)(n)){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(!n.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)(n.data);const _=n.data.id;const g=(0,_realNow.realNow)();const v=(0,_api.machineCount)(n)>=_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:_,licenseKey:i,fingerprint:d};this.deviceRegistrationCallback({fingerprint:d,defaultName:f});y=true}else{this.registerDeviceAsync(_,i,d,f)}}const p={licenseKey:i,licenseId:_,valid:true,isPro:l==="pro",tier:l,expiresAt:n.data.attributes.expiry??null,cachedAt:g,lastValidatedAt:g,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(g);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.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 c=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||!c)return false;this.cachedLicense=c;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)}}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();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess()}}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 c=e.trim()||(0,_fingerprint.getDefaultDeviceName)();const u=(0,_fingerprint.getDeviceMetadata)();try{await(0,_api.activateMachine)(t,i,s,c,u)}catch(n){const a=n instanceof Error?n.message:String(n);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw n}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const n=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:c},r);if(r!==this.generation)return;if(n)this.cachedLicense=n}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(s){console.warn("[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);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY);if(t)return t;const i=this.cachedLicense?.fingerprint||(0,_fingerprint.generateUUID)();await e.setItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY,i);return i})()}return this.fingerprintPromise}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(c=>{if(c.message!=="FINGERPRINT_TAKEN"&&c.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",c.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}}
|
|
16
|
+
*/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,error:null,errorKind:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=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{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&&(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){await this.clearLicense();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);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 c=await boundedStorage(this.loadHold(),null);if(s!==this.generation)return false;const u=(c?.backoffUntil??0)-(0,_realNow.realNow)();if(u>0){return this.standDown(i,s,"License server is rate limited; retrying later.",u)}if(!t?.force&&c?.key===i&&c.verdictAt!==void 0&&(0,_realNow.realNow)()-c.verdictAt>=0&&(0,_realNow.realNow)()-c.verdictAt<_config.LICENSE_VERDICT_CACHE_DURATION){this.lock();this.state.isValidating=false;this.state.error=c.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let n;try{n=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)(n);const o=n.data?.relationships?.product?.data?.id;if((!o||o===_config.KEYGEN_CONFIG.productId)&&a.code==="EXPIRED"&&((0,_tier.isRecognizedAccount)(n.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:n.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)(n)){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(!n.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)(n.data);const _=n.data.id;const g=(0,_realNow.realNow)();const v=(0,_api.machineCount)(n)>=_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:_,licenseKey:i,fingerprint:d};this.deviceRegistrationCallback({fingerprint:d,defaultName:f});y=true}else{this.registerDeviceAsync(_,i,d,f)}}const p={licenseKey:i,licenseId:_,valid:true,isPro:l==="pro",tier:l,expiresAt:n.data.attributes.expiry??null,cachedAt:g,lastValidatedAt:g,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(g);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.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 c=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||!c)return false;this.cachedLicense=c;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)}}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();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess()}}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 c=e.trim()||(0,_fingerprint.getDefaultDeviceName)();const u=(0,_fingerprint.getDeviceMetadata)();try{await(0,_api.activateMachine)(t,i,s,c,u)}catch(n){const a=n instanceof Error?n.message:String(n);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw n}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const n=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:c},r);if(r!==this.generation)return;if(n)this.cachedLicense=n}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);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await(0,_storage.getLicenseStorage)();const t=await e.getItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY);if(t)return t;const i=this.cachedLicense?.fingerprint||(0,_fingerprint.generateUUID)();await e.setItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY,i);return i})()}return this.fingerprintPromise}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(c=>{if(c.message!=="FINGERPRINT_TAKEN"&&c.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",c.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}}
|
|
@@ -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 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 B,LICENSE_STORAGE_KEY as N,LICENSE_CACHE_DURATION as b,LICENSE_REVALIDATION_INTERVAL as X,LICENSE_LAUNCH_VALIDATION_TTL as q,LICENSE_TRANSIENT_RETRY_DELAYS as J,LICENSE_RATE_LIMIT_DEFAULT_WAIT as Q,LICENSE_QUOTA_COOLDOWN as F,LICENSE_VERDICT_CACHE_DURATION as W,LICENSE_FLEET_MACHINE_THRESHOLD as j,LICENSE_QUIET_VALIDATION_TTL as $,LICENSE_HOLD_STORAGE_KEY as C,DEVICE_FINGERPRINT_STORAGE_KEY as K}from"./config.js";import{validateLicense as Z,activateMachine as O,parseValidationResult as ee,isFatalLicenseError as te,isTransientLicenseError as ie,isAcceptedValidation as se,isRateLimited as re,backoffAfter as ae,machineCount as ne}from"./api.js";import{generateUUID as P,getDeviceMetadata as G,getDefaultDeviceName as V,isDevBundle as w}from"./fingerprint";import{signCache as U,verifyCacheSignature as p}from"./cacheSignature.js";import{isBuoyToken as ce,verifyFreeToken as he}from"./freeToken.js";import{resolveTier as oe,isRecognizedAccount as le}from"./tier.js";import{resolveAccountAccess as de}from"./accountAccess.js";import{subscribeForeground as fe}from"./foreground";import{realNow as c}from"./realNow.js";import{SessionManager as g}from"./sessionManager.js";import{exchangeServiceKey as ue,isServiceKey as ye,normalizeLicenseKey as z}from"./serviceKey.js";import{checkDevToken as me,isDevToken as pe,DEV_TOKEN_IN_RELEASE as _e}from"./devToken.js";async function d(f,e){let t;try{return await Promise.race([f,new Promise(i=>{t=setTimeout(()=>i(e),15e3)})])}finally{if(t)clearTimeout(t)}}function _(f){if(f.tier==="pro"||f.tier==="free")return f.tier;return f.isPro?"pro":"free"}class ge{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;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=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{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&&(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("[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=z(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){await this.clearLicense();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=z(e);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(ce(i))return this.admitToken(i,s);if(ye(i))return this.admitServiceKey(i,s);if(pe(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 h=await d(this.loadHold(),null);if(s!==this.generation)return false;const A=(h?.backoffUntil??0)-c();if(A>0){return this.standDown(i,s,"License server is rate limited; retrying later.",A)}if(!t?.force&&h?.key===i&&h.verdictAt!==void 0&&c()-h.verdictAt>=0&&c()-h.verdictAt<W){this.lock();this.state.isValidating=false;this.state.error=h.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let n;try{n=await Z(i)}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if(ie(a)){if(re(a)){const u=Math.min(ae(a,F,Q)*2**this.retryAttempt,F);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:c()+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=ee(n);const l=n.data?.relationships?.product?.data?.id;if((!l||l===B.productId)&&a.code==="EXPIRED"&&(le(n.data)||this.cachedLicense?.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const R=c();const M=await this.saveCache({licenseKey:i,licenseId:n.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(te(a.code)||!se(n)){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:c()});return false}if(!n.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=oe(n.data);const v=n.data.id;const T=c();const D=ne(n)>=j;const S=w();const H=S&&!D;const Y=u==="free"&&(D||!S);let m=this.cachedLicense?.fingerprint;let E=this.cachedLicense?.deviceName;let k=false;if(!m){m=await d(this.getOrCreateDeviceFingerprint(),P());if(s!==this.generation)return false;E=V();k=H}let L=false;if(k){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:v,licenseKey:i,fingerprint:m};this.deviceRegistrationCallback({fingerprint:m,defaultName:E});L=true}else{this.registerDeviceAsync(v,i,m,E)}}const I={licenseKey:i,licenseId:v,valid:true,isPro:u==="pro",tier:u,expiresAt:n.data.attributes.expiry??null,cachedAt:T,lastValidatedAt:T,fingerprint:L?void 0:m,deviceName:L?void 0:E,quiet:Y||void 0};const x=await this.saveCache(I,s);if(s!==this.generation||!x)return false;this.cachedLicense=x;this.applyTier(u);this.state.isValidating=false;this.state.expiresAt=I.expiresAt?new Date(I.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 ue(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(c());this.retryAttempt=0;this.scheduleRetryIn(e,Math.max(6e4,s-60*60*1e3-c()));this.emit({type:"validated",isPro:this.isPro()});return true}admitDevToken(e){const t=me(e);if(!t.ok||!w()){const s=t.ok?_e: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=c();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=he(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=c();const r=this.cachedLicense?.fingerprint??await d(this.getOrCreateDeviceFingerprint(),P());if(t!==this.generation)return false;const h=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||!h)return false;this.cachedLicense=h;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__)o.__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(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&&c()>=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();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess()}}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 de({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>c()?Math.min(t,i):t;const r=s-c();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==e)return;this.emit({type:"validated",isPro:this.isPro()});if(c()<t)this.setVerifiedAt(e)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)o.__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 h=e.trim()||V();const A=G();try{await O(t,i,s,h,A)}catch(n){const a=n instanceof Error?n.message:String(n);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw n}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const n=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:h},r);if(r!==this.generation)return;if(n)this.cachedLicense=n}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(s){console.warn("[React Buoy] License listener error:",s)}})}isCacheValid(e){const t=c();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)?$:q;return c()-(e.lastValidatedAt??0)<t}isQuiet(e){if(e.quiet!==void 0)return e.quiet;return _(e)==="free"&&!w()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const e=await y();const t=await e.getItem(C);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 y();if(e)await t.setItem(C,JSON.stringify(e));else await t.removeItem(C)}catch{}}async persistCache(e){const t=U(e);const i=await y();await i.setItem(N,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,U(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const e=await y();const t=await e.getItem(N);if(!t)return null;const i=JSON.parse(t);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await y();const t=await e.getItem(K);if(t)return t;const i=this.cachedLicense?.fingerprint||P();await e.setItem(K,i);return i})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;const e=this.persistence.catch(()=>{}).then(async()=>{const t=await y();await t.removeItem(N)});this.persistence=e;await d(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,s){const r=G();O(e,t,i,s,r).catch(h=>{if(h.message!=="FINGERPRINT_TAKEN"&&h.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",h.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=fe(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)o.__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)},X);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 y();await e.removeItem(K)}catch{}}}export const LicenseManager=new ge;const o=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){o.__LICENSE_MANAGER_FOREGROUND_OFF__?.();o.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(o.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(o.__LICENSE_MANAGER_EXPIRY_TIMER__);if(o.__LICENSE_MANAGER_TIMER__){clearInterval(o.__LICENSE_MANAGER_TIMER__)}if(o.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(o.__LICENSE_MANAGER_RETRY_TIMER__);o.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
|
|
16
|
+
*/import{getLicenseStorage as y}from"./storage";import{KEYGEN_CONFIG as B,LICENSE_STORAGE_KEY as N,LICENSE_CACHE_DURATION as b,LICENSE_REVALIDATION_INTERVAL as X,LICENSE_LAUNCH_VALIDATION_TTL as q,LICENSE_TRANSIENT_RETRY_DELAYS as J,LICENSE_RATE_LIMIT_DEFAULT_WAIT as Q,LICENSE_QUOTA_COOLDOWN as F,LICENSE_VERDICT_CACHE_DURATION as W,LICENSE_FLEET_MACHINE_THRESHOLD as j,LICENSE_QUIET_VALIDATION_TTL as $,LICENSE_HOLD_STORAGE_KEY as C,DEVICE_FINGERPRINT_STORAGE_KEY as K}from"./config.js";import{validateLicense as Z,activateMachine as O,parseValidationResult as ee,isFatalLicenseError as te,isTransientLicenseError as ie,isAcceptedValidation as se,isRateLimited as re,backoffAfter as ae,machineCount as ne}from"./api.js";import{generateUUID as P,getDeviceMetadata as G,getDefaultDeviceName as V,isDevBundle as w}from"./fingerprint";import{signCache as U,verifyCacheSignature as p}from"./cacheSignature.js";import{isBuoyToken as ce,verifyFreeToken as he}from"./freeToken.js";import{resolveTier as oe,isRecognizedAccount as le}from"./tier.js";import{resolveAccountAccess as de}from"./accountAccess.js";import{subscribeForeground as fe}from"./foreground";import{realNow as c}from"./realNow.js";import{SessionManager as g}from"./sessionManager.js";import{exchangeServiceKey as ue,isServiceKey as ye,normalizeLicenseKey as z}from"./serviceKey.js";import{checkDevToken as me,isDevToken as pe,DEV_TOKEN_IN_RELEASE as _e}from"./devToken.js";async function d(f,e){let t;try{return await Promise.race([f,new Promise(i=>{t=setTimeout(()=>i(e),15e3)})])}finally{if(t)clearTimeout(t)}}function _(f){if(f.tier==="pro"||f.tier==="free")return f.tier;return f.isPro?"pro":"free"}class ge{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;initPromise=null;generation=0;persistence=Promise.resolve();verifiedAt=null;expiryTimer=null;removeForegroundListener=null;sessionUnsubscribe=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{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&&(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=z(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){await this.clearLicense();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=z(e);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(ce(i))return this.admitToken(i,s);if(ye(i))return this.admitServiceKey(i,s);if(pe(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 h=await d(this.loadHold(),null);if(s!==this.generation)return false;const A=(h?.backoffUntil??0)-c();if(A>0){return this.standDown(i,s,"License server is rate limited; retrying later.",A)}if(!t?.force&&h?.key===i&&h.verdictAt!==void 0&&c()-h.verdictAt>=0&&c()-h.verdictAt<W){this.lock();this.state.isValidating=false;this.state.error=h.detail||"License could not be verified";this.state.errorKind="verdict";this.emit({type:"error",isPro:false,error:this.state.error});return false}let n;try{n=await Z(i)}catch(a){const l=a instanceof Error?a.message:"Validation failed";if(s!==this.generation)return false;if(ie(a)){if(re(a)){const u=Math.min(ae(a,F,Q)*2**this.retryAttempt,F);this.retryAttempt+=1;await this.saveHold({...this.hold,backoffUntil:c()+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=ee(n);const l=n.data?.relationships?.product?.data?.id;if((!l||l===B.productId)&&a.code==="EXPIRED"&&(le(n.data)||this.cachedLicense?.licenseKey===i&&p(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){const R=c();const M=await this.saveCache({licenseKey:i,licenseId:n.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(te(a.code)||!se(n)){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:c()});return false}if(!n.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=oe(n.data);const v=n.data.id;const T=c();const D=ne(n)>=j;const S=w();const H=S&&!D;const Y=u==="free"&&(D||!S);let m=this.cachedLicense?.fingerprint;let E=this.cachedLicense?.deviceName;let k=false;if(!m){m=await d(this.getOrCreateDeviceFingerprint(),P());if(s!==this.generation)return false;E=V();k=H}let L=false;if(k){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:v,licenseKey:i,fingerprint:m};this.deviceRegistrationCallback({fingerprint:m,defaultName:E});L=true}else{this.registerDeviceAsync(v,i,m,E)}}const I={licenseKey:i,licenseId:v,valid:true,isPro:u==="pro",tier:u,expiresAt:n.data.attributes.expiry??null,cachedAt:T,lastValidatedAt:T,fingerprint:L?void 0:m,deviceName:L?void 0:E,quiet:Y||void 0};const x=await this.saveCache(I,s);if(s!==this.generation||!x)return false;this.cachedLicense=x;this.applyTier(u);this.state.isValidating=false;this.state.expiresAt=I.expiresAt?new Date(I.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 ue(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(c());this.retryAttempt=0;this.scheduleRetryIn(e,Math.max(6e4,s-60*60*1e3-c()));this.emit({type:"validated",isPro:this.isPro()});return true}admitDevToken(e){const t=me(e);if(!t.ok||!w()){const s=t.ok?_e: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=c();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=he(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=c();const r=this.cachedLicense?.fingerprint??await d(this.getOrCreateDeviceFingerprint(),P());if(t!==this.generation)return false;const h=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||!h)return false;this.cachedLicense=h;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__)o.__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(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&&c()>=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();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess()}}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 de({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>c()?Math.min(t,i):t;const r=s-c();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null;if(this.verifiedAt!==e)return;this.emit({type:"validated",isPro:this.isPro()});if(c()<t)this.setVerifiedAt(e)},Math.max(1,Math.min(r,2147483647)));if(typeof __DEV__!=="undefined"&&__DEV__)o.__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 h=e.trim()||V();const A=G();try{await O(t,i,s,h,A)}catch(n){const a=n instanceof Error?n.message:String(n);if(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",a);throw n}}if(r!==this.generation)return;if(this.cachedLicense?.licenseKey===i){const n=await this.saveCache({...this.cachedLicense,fingerprint:s,deviceName:h},r);if(r!==this.generation)return;if(n)this.cachedLicense=n}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=c();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)?$:q;return c()-(e.lastValidatedAt??0)<t}isQuiet(e){if(e.quiet!==void 0)return e.quiet;return _(e)==="free"&&!w()}async loadHold(){if(this.hold!==void 0)return this.hold;try{const e=await y();const t=await e.getItem(C);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 y();if(e)await t.setItem(C,JSON.stringify(e));else await t.removeItem(C)}catch{}}async persistCache(e){const t=U(e);const i=await y();await i.setItem(N,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,U(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});const e=await y();const t=await e.getItem(N);if(!t)return null;const i=JSON.parse(t);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}getOrCreateDeviceFingerprint(){if(!this.fingerprintPromise){this.fingerprintPromise=(async()=>{const e=await y();const t=await e.getItem(K);if(t)return t;const i=this.cachedLicense?.fingerprint||P();await e.setItem(K,i);return i})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;const e=this.persistence.catch(()=>{}).then(async()=>{const t=await y();await t.removeItem(N)});this.persistence=e;await d(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,s){const r=G();O(e,t,i,s,r).catch(h=>{if(h.message!=="FINGERPRINT_TAKEN"&&h.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",h.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=fe(()=>this.refreshAccess());if(typeof __DEV__!=="undefined"&&__DEV__)o.__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)},X);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 y();await e.removeItem(K)}catch{}}}export const LicenseManager=new ge;const o=globalThis;if(typeof __DEV__!=="undefined"&&__DEV__){o.__LICENSE_MANAGER_FOREGROUND_OFF__?.();o.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0;if(o.__LICENSE_MANAGER_EXPIRY_TIMER__)clearTimeout(o.__LICENSE_MANAGER_EXPIRY_TIMER__);if(o.__LICENSE_MANAGER_TIMER__){clearInterval(o.__LICENSE_MANAGER_TIMER__)}if(o.__LICENSE_MANAGER_RETRY_TIMER__){clearTimeout(o.__LICENSE_MANAGER_RETRY_TIMER__);o.__LICENSE_MANAGER_RETRY_TIMER__=void 0}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{m as e}from"./chunk-OP6QSLZS.mjs";import"./chunk-J7MW3NXU.mjs";export{e as LicenseManager};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use client";import{a as p,d as ke}from"./chunk-J7MW3NXU.mjs";var L=new Map,Ee={async getItem(e){try{return localStorage.getItem(e)??L.get(e)??null}catch{return L.get(e)??null}},async setItem(e,t){L.set(e,t);try{localStorage.setItem(e,t)}catch{}},async removeItem(e){L.delete(e);try{localStorage.removeItem(e)}catch{}}};async function y(){return Ee}var be="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";var xe="36abba0267f7f379d992a5b6df641daab4190bcc9e639e36f1378e3c1ac52746";var I=Object.freeze({accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"}),R=Object.freeze({free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"}),N=720*60*60*1e3,Le=1440*60*1e3,M="buoy-gg-license",V="buoy-gg-device-fingerprint",Ie=3600*1e3,Re=[5*1e3,20*1e3,60*1e3,300*1e3,900*1e3],Ne=60*1e3,q=3600*1e3,Ce=1440*60*1e3,Pe=50,Se=N,D="buoy-gg-license-hold";function h(){let e=globalThis.__buoyRealNow;return typeof e=="function"?e():Date.now()}var{apiUrl:Z}=I,T=class extends Error{constructor(e,t,i=null){super(e);this.isTransient=true;this.name="LicenseTransportError",this.status=t,this.retryAfterMs=i}};function Ke(e){let t=e?.status;return t===429||t===402}function Oe(e,t,i){return e.status===402?t:e.retryAfterMs??i}function Me(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-h())}let r=Number(t("X-RateLimit-Reset"));return Number.isFinite(r)&&r>0?Math.max(0,r*1e3-h()):null}function Q(e){return e instanceof T||e instanceof TypeError?true:typeof e=="object"&&e!==null&&e.isTransient===true}async function Ve(e){try{return(await e.json()).errors?.[0]?.detail||`HTTP ${e.status}`}catch{return`HTTP ${e.status}`}}function ee(){return{"Content-Type":"application/vnd.api+json",Accept:"application/vnd.api+json"}}async function De(e,t){let i=`${Z}/validate`,r={meta:{key:e}},s;try{s=await fetch(i,{signal:t,method:"POST",headers:ee(),body:JSON.stringify(r)})}catch(n){throw new T(n instanceof Error?n.message:"Network request failed",null)}if(!s.ok)throw new T(await Ve(s),s.status,s.status===429?Me(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 T("License server returned an unreadable response",s.status)}}async function Ue(e){let t=typeof AbortController=="function"?new AbortController:null,i;try{return await Promise.race([De(e,t?.signal),new Promise((r,s)=>{i=setTimeout(()=>{s(new T("License verification timed out. Please retry.",null)),t?.abort()},15e3)})])}finally{i&&clearTimeout(i)}}function Fe(e){if(!e.data)return false;let t=e.data.relationships?.product?.data?.id;return t&&t!==I.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 $e(e){let t=e.data?.relationships?.machines?.meta?.count;return typeof t=="number"&&Number.isFinite(t)?t:0}async function te(e,t,i,r,s){let n=`${Z}/machines`,c=await fetch(n,{method:"POST",headers:ee(),body:JSON.stringify({licenseId:e,licenseKey:t,fingerprint:i,name:r,metadata:s||{}})});if(!c.ok){let o=await c.json(),a=o.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=o.errors?.[0]?.detail||`HTTP ${c.status}`;throw new Error(l)}return c.json()}function je(e){let{meta:t,data:i}=e;return{valid:t.valid,code:t.code,detail:t.detail,metadata:i?.attributes?.metadata}}function Be(e){return["NOT_FOUND","SUSPENDED","EXPIRED","BANNED","PRODUCT_SCOPE_MISMATCH"].includes(e)}function U(){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 F(){let e=ke();if(e!==null)return e;if(typeof p<"u")return p;try{if(typeof navigator<"u"&&/electron/i.test(navigator.userAgent))return true}catch{}return typeof process<"u"&&process.env.NODE_ENV!=="production"}function ie(){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 ze(){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 re(){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 se(){let e={platform:ie(),osVersion:ze(),isSimulator:"false"},t=re();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 $(){let e=ie(),t=re();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"}var He=["v1"],Ge="buoy.gg/pro:9f3c1d7a4b2e:license-cache";function ne(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 Je(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(Ge),i.join("\0")}function ae(e,t){let i=Je(e,t),r=ne(i,2166136261),s=ne(i,2135587861);return`${t}.${r.toString(16)}${s.toString(16)}`}function oe(e){return ae(e,"v2")}function le(e){return{...e,sig:oe(e)}}function A(e){return!e||typeof e.sig!="string"||e.sig.length===0?false:e.sig===oe(e)?true:He.some(t=>e.sig.startsWith(`${t}.`)&&e.sig===ae(e,t))}import Ye from"tweetnacl";var Xe=1,We=1,qe="buoy-free-token-v1:",Ze=22,Qe=64,ce=/^BUOY1-([A-Z2-7]+)-([A-Z2-7]+)$/;function he(e){return ce.test(e.trim().toUpperCase())}var et="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";function de(e){let t=[],i=0,r=0;for(let s of e){let n=et.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 tt(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 it(e){let t="";for(let i of e)t+=i.toString(16).padStart(2,"0");return t}function rt(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 st(e,t){let i=new Uint8Array(e.length+t.length);return i.set(e,0),i.set(t,e.length),i}function nt(e){return st(rt(qe),e)}var at=be;function ot(e){let t=ce.exec(e.trim().toUpperCase());if(!t)return null;let i=de(t[1]),r=de(t[2]);if(!i||!r||i.length!==Ze||r.length!==Qe||i[0]!==Xe||i[1]!==We)return null;try{if(!Ye.sign.detached.verify(nt(i),r,tt(at)))return null}catch{return null}return{tier:"free",issuedAt:((i[2]<<24>>>0)+(i[3]<<16)+(i[4]<<8)+i[5])*1e3,accountHash:it(i.slice(6,22))}}function lt(e){let t=e.relationships?.policy?.data?.id;return t===R.free?"free":t===R.solo||t===R.business?"pro":e.attributes?.metadata?.plan==="free"?"free":"pro"}function ct(e){if(!e)return false;let t=e.relationships?.product?.data?.id;if(t)return t===I.productId;let i=e.relationships?.policy?.data?.id;return Object.values(R).some(r=>r===i)}function ue(e,t=h()){let i=e.verifiedAt!==null&&Number.isFinite(e.verifiedAt)&&e.verifiedAt<=t?e.verifiedAt+N: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}}function ht(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)}}import dt from"tweetnacl";var fe="buoys1",ut="buoy-session-v1:",pe=1,j=60,ft=64,pt=["free","pro","business"],g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function B(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+=g[s>>>18&63]+g[s>>>12&63]+g[s>>>6&63]+g[s&63]}let r=e.length-i;if(r===1){let s=e[i]<<16;t+=g[s>>>18&63]+g[s>>>12&63]}else if(r===2){let s=e[i]<<16|e[i+1]<<8;t+=g[s>>>18&63]+g[s>>>12&63]+g[s>>>6&63]}return t}function me(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|g.indexOf(s),i+=6,i>=8&&(t.push(r>>>i-8&255),i-=8);return new Uint8Array(t)}function mt(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 gt(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 yt(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 wt(e){return mt(ut+e)}function _(e,t=256){return typeof e=="string"&&e.length>0&&e.length<=t}function ge(e){return typeof e=="number"&&Number.isInteger(e)&&e>0}function vt(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return!_(t.sid)||!_(t.sub)||!_(t.aud,512)||t.team!==null&&!_(t.team)||!pt.includes(t.tier)||t.role!==void 0&&!_(t.role,64)||t.tools!==void 0&&(!Array.isArray(t.tools)||t.tools.length>256||!t.tools.every(i=>_(i,64)))||!ge(t.iat)||!ge(t.exp)||t.exp<=t.iat?null:{v:pe,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 Tt=xe;function ye(e){return e.startsWith(`${fe}.`)}function z(e,t){let i=Tt;if(!i)return{ok:false,reason:"no-key"};let r=typeof e=="string"?e.split("."):[];if(r.length!==3||r[0]!==fe)return{ok:false,reason:"malformed"};let[,s,n]=r,c=me(s),o=me(n);if(!c||!o||o.length!==ft)return{ok:false,reason:"malformed"};try{if(!dt.sign.detached.verify(wt(s),o,yt(i)))return{ok:false,reason:"signature"}}catch{return{ok:false,reason:"signature"}}let a=gt(c),l;try{l=a===null?null:JSON.parse(a)}catch{return{ok:false,reason:"malformed"}}if(!l||typeof l!="object"||l.v!==pe)return{ok:false,reason:l&&typeof l=="object"?"version":"malformed"};let d=vt(l);if(!d)return{ok:false,reason:"claims"};if(d.aud!==t.audience)return{ok:false,reason:"audience"};if(t.ignoreTime)return{ok:true,claims:d};let f=Math.floor((t.nowMs??h())/1e3);return f>=d.exp+j?{ok:false,reason:"expired"}:d.iat>f+j?{ok:false,reason:"not-yet-valid"}:{ok:true,claims:d}}var At="@buoy/session:",C=10080*60*1e3,we=360*60*1e3,_t=300*1e3,kt=15e3,Et="https://buoy.gg",bt="buoy:signin",xt=600*1e3,u=class extends Error{constructor(e,t){super(t);this.code=e;this.name="SessionError"}};function Lt(){let e=globalThis;return{fetch:(t,i)=>fetch(t,i),storage:y,now:h,random:t=>{let i=new Uint8Array(t);if(!e.crypto?.getRandomValues)throw new u("not_configured","This platform has no secure random source.");return e.crypto.getRandomValues(i)},sha256:async t=>{if(!e.crypto?.subtle)throw new u("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(),watch:t=>{let i=e.window;if(!i?.addEventListener)return()=>{};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 It(){let e=globalThis.location;if(!(!e?.origin||!/^https?:$/.test(e.protocol??"")))return e.origin}var Rt=class{constructor(e){this.signinOrigin=Et;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.deps=e??Lt(),this.audience=It()}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.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 At+(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-j)*1e3?{state:"signed_out"}:i<t?{state:"active",claims:e,grace:false,validUntil:t}:i<t+C?{state:"active",claims:e,grace:true,validUntil:t+C}:{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.claims&&this.refresh()}})??null);let e=await this.read();e&&this.adopt(e)&&(this.notify(),this.schedule())}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=z(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+C?e+C: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")),kt);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-we-this.deps.now();this.timer=this.deps.setTimer(()=>{this.timer=null,this.refresh()},Math.max(0,e))}refresh(e=false){return this.refreshing||(this.refreshing=this.deps.withLock(this.lockName,()=>this.refreshLocked(e)).catch(()=>this.retryLater()).finally(()=>{this.refreshing=null})),this.refreshing}get lockName(){return`buoy-session:${this.audience??""}`}async refreshLocked(e){let t=this.epoch,i=await this.read();if(!i){this.current&&this.clearLocal();return}if(i.refreshToken!==this.current?.refreshToken&&this.adopt(i)){this.notify(),this.schedule();return}if(!this.claims)return;if(!e&&this.claims.exp*1e3-this.deps.now()>we){this.schedule();return}let r,s;try{let n=await this.call(`${this.signinOrigin}/api/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:i.refreshToken,audience:this.audience})});r=n.status,s=await n.json().catch(()=>null)}catch{this.retryLater();return}if(t===this.epoch){if(r===200&&s&&typeof s.access_token=="string"&&typeof s.refresh_token=="string"){let n={v:1,accessToken:s.access_token,refreshToken:s.refresh_token};if(this.adopt(n)){await this.write(n),this.notify(),this.schedule();return}}if(r===400||r===401||r===403){await this.write(null),this.clearLocal();return}this.retryLater()}}retryLater(){this.armLimit(),this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=this.deps.setTimer(()=>{this.timer=null,this.refresh(true)},_t),this.notify()}clearLocal(){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 u("not_configured","Sign-in needs a web page or a configured app id.");let e=this.deps.openPopup();if(!e)throw new u("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(),c=null,o=d=>{c!==null&&this.deps.clearTimer(c),a(),d()},a=this.deps.onMessage(d=>{if(d.origin!==this.signinOrigin)return;let f=d.data;!f||f.type!==bt||f.state!==i||(typeof f.code=="string"?o(()=>r(f.code)):o(()=>s(new u("access_denied","Sign-in was cancelled."))))}),l=()=>{if(e.closed)return o(()=>s(new u("popup_closed","The sign-in window was closed.")));if(this.deps.now()-n>xt)return o(()=>s(new u("timeout","Sign-in took too long.")));c=this.deps.setTimer(l,500)};c=this.deps.setTimer(l,500)}))}finally{try{e.closed||e.close()}catch{}}}async signInWith(e){let t=this.audience;if(!t)throw new u("not_configured","Sign-in needs a web page or a configured app id.");let i=B(this.deps.random(32)),r=B(this.deps.random(16)),s=B(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}`,c=await e(n,r),o;try{o=await this.call(`${this.signinOrigin}/api/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:c,code_verifier:i,audience:t})})}catch{throw new u("network","Buoy could not be reached. Check your connection and try again.")}let a=await o.json().catch(()=>null);if(o.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 u(o.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 u("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 u("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 u("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 u(s.status===503?"unavailable":"rejected",a)}let c=this.deps.now()+(Number(n.expires_in)||600)*1e3,o=Math.max(5,Number(n.interval)||5)*1e3;for(e({userCode:n.user_code,verificationUri:n.verification_uri,verificationUriComplete:n.verification_uri_complete,expiresAt:c});;){if(await this.wait(o,t.signal),this.deps.now()>c)throw new u("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 d=l&&typeof l.error=="string"?l.error:"";if(d==="authorization_pending"||a.status>=500)continue;if(d==="slow_down"||a.status===429){o+=5e3;continue}if(d==="access_denied")throw new u("access_denied","The sign-in was turned down on buoy.gg.");if(d==="expired_token")throw new u("timeout","The code ran out. Start again for a new one.");let f=l&&typeof l.error_description=="string"?l.error_description:"Buoy did not accept this sign-in.";throw new u("rejected",f)}}wait(e,t){return new Promise((i,r)=>{let s=()=>new u("access_denied","Sign-in was cancelled.");if(t?.aborted)return r(s());let n=()=>{this.deps.clearTimer(c),r(s())},c=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{}}},k=new Rt;var Nt="bsk1_",Ct="service",Pt=15e3;function H(e){return e.startsWith(Nt)}function b(e){let t=e.trim();return H(t)||ye(t)?t:t.toUpperCase()}function St(e,t){return b(e??"")===b(t??"")}async function Kt(e,t){let i=t.fetch??((a,l)=>fetch(a,l)),r=typeof AbortController<"u"?new AbortController:void 0,s=setTimeout(()=>r?.abort(),Pt),n,c;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,c=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 c?.access_token!="string")return{ok:false,reason:"rejected",detail:typeof c?.error_description=="string"?c.error_description:"This bot key was not accepted."};let o=z(c.access_token,{audience:Ct,nowMs:h()});return o.ok?{ok:true,claims:o.claims}:{ok:false,reason:"rejected",detail:"Buoy sent a token this app could not check."}}var Ot="dev";function ve(e){return ye(e)}function Te(e,t=h()){let i=z(e,{audience:Ot,ignoreTime:true});return i.ok?t>=i.claims.exp*1e3?{ok:false,reason:"expired",message:"Your dev token ran out. Run `npx buoy login` again."}:{ok:true,claims:i.claims}:{ok:false,reason:"invalid",message:"This dev token is not valid. Run `npx buoy login` again."}}var Mt="This is a dev token. It only works in dev builds. A live build turns on Buoy with Sign in with Buoy.";async function w(e,t){let i;try{return await Promise.race([e,new Promise(r=>{i=setTimeout(()=>r(t),15e3)})])}finally{i&&clearTimeout(i)}}function E(e){return e.tier==="pro"||e.tier==="free"?e.tier:e.isPro?"pro":"free"}var Vt=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.initPromise=null;this.generation=0;this.persistence=Promise.resolve();this.verifiedAt=null;this.expiryTimer=null;this.removeForegroundListener=null;this.sessionUnsubscribe=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=k.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))),await w(k.load().catch(()=>{}),void 0);try{let t=await w(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=A(t);this.cachedLicense=t,this.state.licenseKey=t.licenseKey,i&&this.isCacheValid(t)?this.applyTier(E(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("[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=b(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=b(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()}),he(i))return this.admitToken(i,r);if(H(i))return this.admitServiceKey(i,r);if(ve(i))return this.admitDevToken(i);if(!this.cachedLicense){let a=await w(this.loadCachedLicense(),null);if(r!==this.generation)return false;a?.licenseKey===i&&(this.cachedLicense=a,A(a)&&this.isCacheValid(a)&&(this.applyTier(E(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&&A(s)&&this.isCacheValid(s)&&this.isCacheFresh(s))return this.applyTier(E(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 w(this.loadHold(),null);if(r!==this.generation)return false;let c=(n?.backoffUntil??0)-h();if(c>0)return this.standDown(i,r,"License server is rate limited; retrying later.",c);if(!t?.force&&n?.key===i&&n.verdictAt!==void 0&&h()-n.verdictAt>=0&&h()-n.verdictAt<Ce)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 o;try{o=await Ue(i)}catch(a){let l=a instanceof Error?a.message:"Validation failed";if(r!==this.generation)return false;if(Q(a)){if(Ke(a)){let d=Math.min(Oe(a,q,Ne)*2**this.retryAttempt,q);return this.retryAttempt+=1,await this.saveHold({...this.hold,backoffUntil:h()+d}),r!==this.generation?false:this.standDown(i,r,l,d)}return this.state.isValidating=false,this.cachedLicense&&this.cachedLicense.licenseKey===i&&A(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)?(this.applyTier(E(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=je(o),l=o.data?.relationships?.product?.data?.id;if((!l||l===I.productId)&&a.code==="EXPIRED"&&(ct(o.data)||this.cachedLicense?.licenseKey===i&&A(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){let O=h(),W=await this.saveCache({licenseKey:i,licenseId:o.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:O,lastValidatedAt:O,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},r);return r!==this.generation||!W?false:(this.cachedLicense=W,this.applyTier("free"),this.state.isValidating=false,this.state.expiresAt=null,this.setVerifiedAt(O),this.emit({type:"validated",isPro:false}),true)}if(Be(a.code)||!Fe(o))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:h()}),false;if(!o.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 d=lt(o.data),f=o.data.id,P=h(),G=$e(o)>=Pe,J=F(),Ae=J&&!G,_e=d==="free"&&(G||!J),v=this.cachedLicense?.fingerprint,x=this.cachedLicense?.deviceName,Y=false;if(!v){if(v=await w(this.getOrCreateDeviceFingerprint(),U()),r!==this.generation)return false;x=$(),Y=Ae}let S=false;Y&&(this.deviceRegistrationCallback?(this.pendingRegistration={licenseId:f,licenseKey:i,fingerprint:v},this.deviceRegistrationCallback({fingerprint:v,defaultName:x}),S=true):this.registerDeviceAsync(f,i,v,x));let K={licenseKey:i,licenseId:f,valid:true,isPro:d==="pro",tier:d,expiresAt:o.data.attributes.expiry??null,cachedAt:P,lastValidatedAt:P,fingerprint:S?void 0:v,deviceName:S?void 0:x,quiet:_e||void 0},X=await this.saveCache(K,r);return r!==this.generation||!X||(this.cachedLicense=X,this.applyTier(d),this.state.isValidating=false,this.state.expiresAt=K.expiresAt?new Date(K.expiresAt):null,this.setVerifiedAt(P),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=Re[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 p<"u"&&p&&(globalThis.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer)}async admitServiceKey(e,t){let i=await Kt(e,{origin:k.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(h()),this.retryAttempt=0,this.scheduleRetryIn(e,Math.max(6e4,r-3600*1e3-h())),this.emit({type:"validated",isPro:this.isPro()}),true}admitDevToken(e){let t=Te(e);if(!t.ok||!F()){let r=t.ok?Mt: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=h();return 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=ot(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=h(),s=this.cachedLicense?.fingerprint??await w(this.getOrCreateDeviceFingerprint(),U());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??$(),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&&A(s)&&this.isCacheValid(s)?(this.applyTier(E(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 p<"u"&&p&&(m.__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&&h()>=this.state.expiresAt.getTime()?"free":this.state.tier}sessionTier(){let e=k.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();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess()}}getAccountAccess(){let e=this.getKeyAccess();if(e.status==="admitted")return e;let t=k.getStatus();return t.state==="active"?{status:"admitted",reason:null,validUntil:t.validUntil}:e}getKeyAccess(){return ue({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+N,i=this.state.expiresAt?.getTime(),r=(i&&i>h()?Math.min(t,i):t)-h();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null,this.verifiedAt===e&&(this.emit({type:"validated",isPro:this.isPro()}),h()<t&&this.setVerifiedAt(e))},Math.max(1,Math.min(r,2147483647))),typeof p<"u"&&p&&(m.__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()||$(),c=se();try{await te(t,i,r,n,c)}catch(o){let a=o instanceof Error?o.message:String(o);if(!(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"))throw console.warn("[Buoy] Device registration failed:",a),o}if(s===this.generation){if(this.cachedLicense?.licenseKey===i){let o=await this.saveCache({...this.cachedLicense,fingerprint:r,deviceName:n},s);if(s!==this.generation)return;o&&(this.cachedLicense=o)}this.pendingRegistration=null}}emit(e){[...this.listeners].forEach(t=>{try{t(e)}catch(i){console.warn("[React Buoy] License listener error:",i)}})}isCacheValid(e){let t=h()-e.cachedAt;return!(!e.valid||!Number.isFinite(e.cachedAt)||t<0||t>=N)}isCacheFresh(e){let t=this.isQuiet(e)?Se:Ie;return h()-(e.lastValidatedAt??0)<t}isQuiet(e){return e.quiet!==void 0?e.quiet:E(e)==="free"&&!F()}async loadHold(){if(this.hold!==void 0)return this.hold;try{let e=await(await y()).getItem(D),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 y();e?await t.setItem(D,JSON.stringify(e)):await t.removeItem(D)}catch{}}async persistCache(e){let t=le(e);return await(await y()).setItem(M,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,w(i,le(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});let e=await(await y()).getItem(M);return e?JSON.parse(e):null}catch(e){return console.warn("[Buoy] Error loading cached license:",e),null}}getOrCreateDeviceFingerprint(){return this.fingerprintPromise||(this.fingerprintPromise=(async()=>{let e=await y(),t=await e.getItem(V);if(t)return t;let i=this.cachedLicense?.fingerprint||U();return await e.setItem(V,i),i})()),this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;let e=this.persistence.catch(()=>{}).then(async()=>{await(await y()).removeItem(M)});this.persistence=e,await w(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,r){let s=se();te(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=ht(()=>this.refreshAccess()),typeof p<"u"&&p&&(m.__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)},Le),typeof p<"u"&&p&&(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 y()).removeItem(V)}catch{}}},Dt=new Vt,m=globalThis;typeof p<"u"&&p&&(m.__LICENSE_MANAGER_FOREGROUND_OFF__?.(),m.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0,m.__LICENSE_MANAGER_EXPIRY_TIMER__&&clearTimeout(m.__LICENSE_MANAGER_EXPIRY_TIMER__),m.__LICENSE_MANAGER_TIMER__&&clearInterval(m.__LICENSE_MANAGER_TIMER__),m.__LICENSE_MANAGER_RETRY_TIMER__&&(clearTimeout(m.__LICENSE_MANAGER_RETRY_TIMER__),m.__LICENSE_MANAGER_RETRY_TIMER__=void 0));export{h as a,T as b,Q as c,he as d,ue as e,u as f,k as g,H as h,b as i,St as j,ve as k,Te as l,Dt as m};/*!
|
|
1
|
+
"use client";import{a as p,d as ke}from"./chunk-J7MW3NXU.mjs";var L=new Map,Ee={async getItem(e){try{return localStorage.getItem(e)??L.get(e)??null}catch{return L.get(e)??null}},async setItem(e,t){L.set(e,t);try{localStorage.setItem(e,t)}catch{}},async removeItem(e){L.delete(e);try{localStorage.removeItem(e)}catch{}}};async function y(){return Ee}var be="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";var xe="36abba0267f7f379d992a5b6df641daab4190bcc9e639e36f1378e3c1ac52746";var I=Object.freeze({accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",apiUrl:"https://buoy.gg/api/license"}),R=Object.freeze({free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"}),N=720*60*60*1e3,Le=1440*60*1e3,M="buoy-gg-license",V="buoy-gg-device-fingerprint",Ie=3600*1e3,Re=[5*1e3,20*1e3,60*1e3,300*1e3,900*1e3],Ne=60*1e3,q=3600*1e3,Ce=1440*60*1e3,Pe=50,Se=N,D="buoy-gg-license-hold";function h(){let e=globalThis.__buoyRealNow;return typeof e=="function"?e():Date.now()}var{apiUrl:Z}=I,T=class extends Error{constructor(e,t,i=null){super(e);this.isTransient=true;this.name="LicenseTransportError",this.status=t,this.retryAfterMs=i}};function Ke(e){let t=e?.status;return t===429||t===402}function Oe(e,t,i){return e.status===402?t:e.retryAfterMs??i}function Me(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-h())}let r=Number(t("X-RateLimit-Reset"));return Number.isFinite(r)&&r>0?Math.max(0,r*1e3-h()):null}function Q(e){return e instanceof T||e instanceof TypeError?true:typeof e=="object"&&e!==null&&e.isTransient===true}async function Ve(e){try{return(await e.json()).errors?.[0]?.detail||`HTTP ${e.status}`}catch{return`HTTP ${e.status}`}}function ee(){return{"Content-Type":"application/vnd.api+json",Accept:"application/vnd.api+json"}}async function De(e,t){let i=`${Z}/validate`,r={meta:{key:e}},s;try{s=await fetch(i,{signal:t,method:"POST",headers:ee(),body:JSON.stringify(r)})}catch(n){throw new T(n instanceof Error?n.message:"Network request failed",null)}if(!s.ok)throw new T(await Ve(s),s.status,s.status===429?Me(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 T("License server returned an unreadable response",s.status)}}async function Ue(e){let t=typeof AbortController=="function"?new AbortController:null,i;try{return await Promise.race([De(e,t?.signal),new Promise((r,s)=>{i=setTimeout(()=>{s(new T("License verification timed out. Please retry.",null)),t?.abort()},15e3)})])}finally{i&&clearTimeout(i)}}function Fe(e){if(!e.data)return false;let t=e.data.relationships?.product?.data?.id;return t&&t!==I.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 $e(e){let t=e.data?.relationships?.machines?.meta?.count;return typeof t=="number"&&Number.isFinite(t)?t:0}async function te(e,t,i,r,s){let n=`${Z}/machines`,c=await fetch(n,{method:"POST",headers:ee(),body:JSON.stringify({licenseId:e,licenseKey:t,fingerprint:i,name:r,metadata:s||{}})});if(!c.ok){let o=await c.json(),a=o.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=o.errors?.[0]?.detail||`HTTP ${c.status}`;throw new Error(l)}return c.json()}function je(e){let{meta:t,data:i}=e;return{valid:t.valid,code:t.code,detail:t.detail,metadata:i?.attributes?.metadata}}function Be(e){return["NOT_FOUND","SUSPENDED","EXPIRED","BANNED","PRODUCT_SCOPE_MISMATCH"].includes(e)}function U(){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 F(){let e=ke();if(e!==null)return e;if(typeof p<"u")return p;try{if(typeof navigator<"u"&&/electron/i.test(navigator.userAgent))return true}catch{}return typeof process<"u"&&process.env.NODE_ENV!=="production"}function ie(){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 ze(){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 re(){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 se(){let e={platform:ie(),osVersion:ze(),isSimulator:"false"},t=re();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 $(){let e=ie(),t=re();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"}var He=["v1"],Ge="buoy.gg/pro:9f3c1d7a4b2e:license-cache";function ne(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 Je(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(Ge),i.join("\0")}function ae(e,t){let i=Je(e,t),r=ne(i,2166136261),s=ne(i,2135587861);return`${t}.${r.toString(16)}${s.toString(16)}`}function oe(e){return ae(e,"v2")}function le(e){return{...e,sig:oe(e)}}function A(e){return!e||typeof e.sig!="string"||e.sig.length===0?false:e.sig===oe(e)?true:He.some(t=>e.sig.startsWith(`${t}.`)&&e.sig===ae(e,t))}import Ye from"tweetnacl";var Xe=1,We=1,qe="buoy-free-token-v1:",Ze=22,Qe=64,ce=/^BUOY1-([A-Z2-7]+)-([A-Z2-7]+)$/;function he(e){return ce.test(e.trim().toUpperCase())}var et="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";function de(e){let t=[],i=0,r=0;for(let s of e){let n=et.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 tt(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 it(e){let t="";for(let i of e)t+=i.toString(16).padStart(2,"0");return t}function rt(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 st(e,t){let i=new Uint8Array(e.length+t.length);return i.set(e,0),i.set(t,e.length),i}function nt(e){return st(rt(qe),e)}var at=be;function ot(e){let t=ce.exec(e.trim().toUpperCase());if(!t)return null;let i=de(t[1]),r=de(t[2]);if(!i||!r||i.length!==Ze||r.length!==Qe||i[0]!==Xe||i[1]!==We)return null;try{if(!Ye.sign.detached.verify(nt(i),r,tt(at)))return null}catch{return null}return{tier:"free",issuedAt:((i[2]<<24>>>0)+(i[3]<<16)+(i[4]<<8)+i[5])*1e3,accountHash:it(i.slice(6,22))}}function lt(e){let t=e.relationships?.policy?.data?.id;return t===R.free?"free":t===R.solo||t===R.business?"pro":e.attributes?.metadata?.plan==="free"?"free":"pro"}function ct(e){if(!e)return false;let t=e.relationships?.product?.data?.id;if(t)return t===I.productId;let i=e.relationships?.policy?.data?.id;return Object.values(R).some(r=>r===i)}function ue(e,t=h()){let i=e.verifiedAt!==null&&Number.isFinite(e.verifiedAt)&&e.verifiedAt<=t?e.verifiedAt+N: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}}function ht(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)}}import dt from"tweetnacl";var fe="buoys1",ut="buoy-session-v1:",pe=1,j=60,ft=64,pt=["free","pro","business"],g="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";function B(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+=g[s>>>18&63]+g[s>>>12&63]+g[s>>>6&63]+g[s&63]}let r=e.length-i;if(r===1){let s=e[i]<<16;t+=g[s>>>18&63]+g[s>>>12&63]}else if(r===2){let s=e[i]<<16|e[i+1]<<8;t+=g[s>>>18&63]+g[s>>>12&63]+g[s>>>6&63]}return t}function me(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|g.indexOf(s),i+=6,i>=8&&(t.push(r>>>i-8&255),i-=8);return new Uint8Array(t)}function mt(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 gt(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 yt(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 wt(e){return mt(ut+e)}function _(e,t=256){return typeof e=="string"&&e.length>0&&e.length<=t}function ge(e){return typeof e=="number"&&Number.isInteger(e)&&e>0}function vt(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return!_(t.sid)||!_(t.sub)||!_(t.aud,512)||t.team!==null&&!_(t.team)||!pt.includes(t.tier)||t.role!==void 0&&!_(t.role,64)||t.tools!==void 0&&(!Array.isArray(t.tools)||t.tools.length>256||!t.tools.every(i=>_(i,64)))||!ge(t.iat)||!ge(t.exp)||t.exp<=t.iat?null:{v:pe,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 Tt=xe;function ye(e){return e.startsWith(`${fe}.`)}function z(e,t){let i=Tt;if(!i)return{ok:false,reason:"no-key"};let r=typeof e=="string"?e.split("."):[];if(r.length!==3||r[0]!==fe)return{ok:false,reason:"malformed"};let[,s,n]=r,c=me(s),o=me(n);if(!c||!o||o.length!==ft)return{ok:false,reason:"malformed"};try{if(!dt.sign.detached.verify(wt(s),o,yt(i)))return{ok:false,reason:"signature"}}catch{return{ok:false,reason:"signature"}}let a=gt(c),l;try{l=a===null?null:JSON.parse(a)}catch{return{ok:false,reason:"malformed"}}if(!l||typeof l!="object"||l.v!==pe)return{ok:false,reason:l&&typeof l=="object"?"version":"malformed"};let d=vt(l);if(!d)return{ok:false,reason:"claims"};if(d.aud!==t.audience)return{ok:false,reason:"audience"};if(t.ignoreTime)return{ok:true,claims:d};let f=Math.floor((t.nowMs??h())/1e3);return f>=d.exp+j?{ok:false,reason:"expired"}:d.iat>f+j?{ok:false,reason:"not-yet-valid"}:{ok:true,claims:d}}var At="@buoy/session:",C=10080*60*1e3,we=360*60*1e3,_t=300*1e3,kt=15e3,Et="https://buoy.gg",bt="buoy:signin",xt=600*1e3,u=class extends Error{constructor(e,t){super(t);this.code=e;this.name="SessionError"}};function Lt(){let e=globalThis;return{fetch:(t,i)=>fetch(t,i),storage:y,now:h,random:t=>{let i=new Uint8Array(t);if(!e.crypto?.getRandomValues)throw new u("not_configured","This platform has no secure random source.");return e.crypto.getRandomValues(i)},sha256:async t=>{if(!e.crypto?.subtle)throw new u("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(),watch:t=>{let i=e.window;if(!i?.addEventListener)return()=>{};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 It(){let e=globalThis.location;if(!(!e?.origin||!/^https?:$/.test(e.protocol??"")))return e.origin}var Rt=class{constructor(e){this.signinOrigin=Et;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.deps=e??Lt(),this.audience=It()}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.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 At+(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-j)*1e3?{state:"signed_out"}:i<t?{state:"active",claims:e,grace:false,validUntil:t}:i<t+C?{state:"active",claims:e,grace:true,validUntil:t+C}:{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.claims&&this.refresh()}})??null);let e=await this.read();e&&this.adopt(e)&&(this.notify(),this.schedule())}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=z(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+C?e+C: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")),kt);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-we-this.deps.now();this.timer=this.deps.setTimer(()=>{this.timer=null,this.refresh()},Math.max(0,e))}refresh(e=false){return this.refreshing||(this.refreshing=this.deps.withLock(this.lockName,()=>this.refreshLocked(e)).catch(()=>this.retryLater()).finally(()=>{this.refreshing=null})),this.refreshing}get lockName(){return`buoy-session:${this.audience??""}`}async refreshLocked(e){let t=this.epoch,i=await this.read();if(!i){this.current&&this.clearLocal();return}if(i.refreshToken!==this.current?.refreshToken&&this.adopt(i)){this.notify(),this.schedule();return}if(!this.claims)return;if(!e&&this.claims.exp*1e3-this.deps.now()>we){this.schedule();return}let r,s;try{let n=await this.call(`${this.signinOrigin}/api/auth/refresh`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({refresh_token:i.refreshToken,audience:this.audience})});r=n.status,s=await n.json().catch(()=>null)}catch{this.retryLater();return}if(t===this.epoch){if(r===200&&s&&typeof s.access_token=="string"&&typeof s.refresh_token=="string"){let n={v:1,accessToken:s.access_token,refreshToken:s.refresh_token};if(this.adopt(n)){await this.write(n),this.notify(),this.schedule();return}}if(r===400||r===401||r===403){await this.write(null),this.clearLocal();return}this.retryLater()}}retryLater(){this.armLimit(),this.timer!==null&&this.deps.clearTimer(this.timer),this.timer=this.deps.setTimer(()=>{this.timer=null,this.refresh(true)},_t),this.notify()}clearLocal(){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 u("not_configured","Sign-in needs a web page or a configured app id.");let e=this.deps.openPopup();if(!e)throw new u("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(),c=null,o=d=>{c!==null&&this.deps.clearTimer(c),a(),d()},a=this.deps.onMessage(d=>{if(d.origin!==this.signinOrigin)return;let f=d.data;!f||f.type!==bt||f.state!==i||(typeof f.code=="string"?o(()=>r(f.code)):o(()=>s(new u("access_denied","Sign-in was cancelled."))))}),l=()=>{if(e.closed)return o(()=>s(new u("popup_closed","The sign-in window was closed.")));if(this.deps.now()-n>xt)return o(()=>s(new u("timeout","Sign-in took too long.")));c=this.deps.setTimer(l,500)};c=this.deps.setTimer(l,500)}))}finally{try{e.closed||e.close()}catch{}}}async signInWith(e){let t=this.audience;if(!t)throw new u("not_configured","Sign-in needs a web page or a configured app id.");let i=B(this.deps.random(32)),r=B(this.deps.random(16)),s=B(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}`,c=await e(n,r),o;try{o=await this.call(`${this.signinOrigin}/api/auth/token`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({code:c,code_verifier:i,audience:t})})}catch{throw new u("network","Buoy could not be reached. Check your connection and try again.")}let a=await o.json().catch(()=>null);if(o.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 u(o.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 u("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 u("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 u("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 u(s.status===503?"unavailable":"rejected",a)}let c=this.deps.now()+(Number(n.expires_in)||600)*1e3,o=Math.max(5,Number(n.interval)||5)*1e3;for(e({userCode:n.user_code,verificationUri:n.verification_uri,verificationUriComplete:n.verification_uri_complete,expiresAt:c});;){if(await this.wait(o,t.signal),this.deps.now()>c)throw new u("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 d=l&&typeof l.error=="string"?l.error:"";if(d==="authorization_pending"||a.status>=500)continue;if(d==="slow_down"||a.status===429){o+=5e3;continue}if(d==="access_denied")throw new u("access_denied","The sign-in was turned down on buoy.gg.");if(d==="expired_token")throw new u("timeout","The code ran out. Start again for a new one.");let f=l&&typeof l.error_description=="string"?l.error_description:"Buoy did not accept this sign-in.";throw new u("rejected",f)}}wait(e,t){return new Promise((i,r)=>{let s=()=>new u("access_denied","Sign-in was cancelled.");if(t?.aborted)return r(s());let n=()=>{this.deps.clearTimer(c),r(s())},c=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{}}},k=new Rt;var Nt="bsk1_",Ct="service",Pt=15e3;function H(e){return e.startsWith(Nt)}function b(e){let t=e.trim();return H(t)||ye(t)?t:t.toUpperCase()}function St(e,t){return b(e??"")===b(t??"")}async function Kt(e,t){let i=t.fetch??((a,l)=>fetch(a,l)),r=typeof AbortController<"u"?new AbortController:void 0,s=setTimeout(()=>r?.abort(),Pt),n,c;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,c=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 c?.access_token!="string")return{ok:false,reason:"rejected",detail:typeof c?.error_description=="string"?c.error_description:"This bot key was not accepted."};let o=z(c.access_token,{audience:Ct,nowMs:h()});return o.ok?{ok:true,claims:o.claims}:{ok:false,reason:"rejected",detail:"Buoy sent a token this app could not check."}}var Ot="dev";function ve(e){return ye(e)}function Te(e,t=h()){let i=z(e,{audience:Ot,ignoreTime:true});return i.ok?t>=i.claims.exp*1e3?{ok:false,reason:"expired",message:"Your dev token ran out. Run `npx buoy login` again."}:{ok:true,claims:i.claims}:{ok:false,reason:"invalid",message:"This dev token is not valid. Run `npx buoy login` again."}}var Mt="This is a dev token. It only works in dev builds. A live build turns on Buoy with Sign in with Buoy.";async function w(e,t){let i;try{return await Promise.race([e,new Promise(r=>{i=setTimeout(()=>r(t),15e3)})])}finally{i&&clearTimeout(i)}}function E(e){return e.tier==="pro"||e.tier==="free"?e.tier:e.isPro?"pro":"free"}var Vt=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.initPromise=null;this.generation=0;this.persistence=Promise.resolve();this.verifiedAt=null;this.expiryTimer=null;this.removeForegroundListener=null;this.sessionUnsubscribe=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=k.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))),await w(k.load().catch(()=>{}),void 0);try{let t=await w(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=A(t);this.cachedLicense=t,this.state.licenseKey=t.licenseKey,i&&this.isCacheValid(t)?this.applyTier(E(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=b(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=b(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()}),he(i))return this.admitToken(i,r);if(H(i))return this.admitServiceKey(i,r);if(ve(i))return this.admitDevToken(i);if(!this.cachedLicense){let a=await w(this.loadCachedLicense(),null);if(r!==this.generation)return false;a?.licenseKey===i&&(this.cachedLicense=a,A(a)&&this.isCacheValid(a)&&(this.applyTier(E(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&&A(s)&&this.isCacheValid(s)&&this.isCacheFresh(s))return this.applyTier(E(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 w(this.loadHold(),null);if(r!==this.generation)return false;let c=(n?.backoffUntil??0)-h();if(c>0)return this.standDown(i,r,"License server is rate limited; retrying later.",c);if(!t?.force&&n?.key===i&&n.verdictAt!==void 0&&h()-n.verdictAt>=0&&h()-n.verdictAt<Ce)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 o;try{o=await Ue(i)}catch(a){let l=a instanceof Error?a.message:"Validation failed";if(r!==this.generation)return false;if(Q(a)){if(Ke(a)){let d=Math.min(Oe(a,q,Ne)*2**this.retryAttempt,q);return this.retryAttempt+=1,await this.saveHold({...this.hold,backoffUntil:h()+d}),r!==this.generation?false:this.standDown(i,r,l,d)}return this.state.isValidating=false,this.cachedLicense&&this.cachedLicense.licenseKey===i&&A(this.cachedLicense)&&this.isCacheValid(this.cachedLicense)?(this.applyTier(E(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=je(o),l=o.data?.relationships?.product?.data?.id;if((!l||l===I.productId)&&a.code==="EXPIRED"&&(ct(o.data)||this.cachedLicense?.licenseKey===i&&A(this.cachedLicense)&&this.isCacheValid(this.cachedLicense))){let O=h(),W=await this.saveCache({licenseKey:i,licenseId:o.data?.id??"",valid:true,isPro:false,tier:"free",expiresAt:null,cachedAt:O,lastValidatedAt:O,fingerprint:this.cachedLicense?.licenseKey===i?this.cachedLicense.fingerprint:void 0},r);return r!==this.generation||!W?false:(this.cachedLicense=W,this.applyTier("free"),this.state.isValidating=false,this.state.expiresAt=null,this.setVerifiedAt(O),this.emit({type:"validated",isPro:false}),true)}if(Be(a.code)||!Fe(o))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:h()}),false;if(!o.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 d=lt(o.data),f=o.data.id,P=h(),G=$e(o)>=Pe,J=F(),Ae=J&&!G,_e=d==="free"&&(G||!J),v=this.cachedLicense?.fingerprint,x=this.cachedLicense?.deviceName,Y=false;if(!v){if(v=await w(this.getOrCreateDeviceFingerprint(),U()),r!==this.generation)return false;x=$(),Y=Ae}let S=false;Y&&(this.deviceRegistrationCallback?(this.pendingRegistration={licenseId:f,licenseKey:i,fingerprint:v},this.deviceRegistrationCallback({fingerprint:v,defaultName:x}),S=true):this.registerDeviceAsync(f,i,v,x));let K={licenseKey:i,licenseId:f,valid:true,isPro:d==="pro",tier:d,expiresAt:o.data.attributes.expiry??null,cachedAt:P,lastValidatedAt:P,fingerprint:S?void 0:v,deviceName:S?void 0:x,quiet:_e||void 0},X=await this.saveCache(K,r);return r!==this.generation||!X||(this.cachedLicense=X,this.applyTier(d),this.state.isValidating=false,this.state.expiresAt=K.expiresAt?new Date(K.expiresAt):null,this.setVerifiedAt(P),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=Re[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 p<"u"&&p&&(globalThis.__LICENSE_MANAGER_RETRY_TIMER__=this.retryTimer)}async admitServiceKey(e,t){let i=await Kt(e,{origin:k.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(h()),this.retryAttempt=0,this.scheduleRetryIn(e,Math.max(6e4,r-3600*1e3-h())),this.emit({type:"validated",isPro:this.isPro()}),true}admitDevToken(e){let t=Te(e);if(!t.ok||!F()){let r=t.ok?Mt: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=h();return 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=ot(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=h(),s=this.cachedLicense?.fingerprint??await w(this.getOrCreateDeviceFingerprint(),U());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??$(),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&&A(s)&&this.isCacheValid(s)?(this.applyTier(E(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 p<"u"&&p&&(m.__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&&h()>=this.state.expiresAt.getTime()?"free":this.state.tier}sessionTier(){let e=k.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();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess()}}getAccountAccess(){let e=this.getKeyAccess();if(e.status==="admitted")return e;let t=k.getStatus();return t.state==="active"?{status:"admitted",reason:null,validUntil:t.validUntil}:e}getKeyAccess(){return ue({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+N,i=this.state.expiresAt?.getTime(),r=(i&&i>h()?Math.min(t,i):t)-h();this.expiryTimer=setTimeout(()=>{this.expiryTimer=null,this.verifiedAt===e&&(this.emit({type:"validated",isPro:this.isPro()}),h()<t&&this.setVerifiedAt(e))},Math.max(1,Math.min(r,2147483647))),typeof p<"u"&&p&&(m.__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()||$(),c=se();try{await te(t,i,r,n,c)}catch(o){let a=o instanceof Error?o.message:String(o);if(!(a==="FINGERPRINT_TAKEN"||a==="MACHINE_LIMIT_EXCEEDED"))throw console.warn("[Buoy] Device registration failed:",a),o}if(s===this.generation){if(this.cachedLicense?.licenseKey===i){let o=await this.saveCache({...this.cachedLicense,fingerprint:r,deviceName:n},s);if(s!==this.generation)return;o&&(this.cachedLicense=o)}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=h()-e.cachedAt;return!(!e.valid||!Number.isFinite(e.cachedAt)||t<0||t>=N)}isCacheFresh(e){let t=this.isQuiet(e)?Se:Ie;return h()-(e.lastValidatedAt??0)<t}isQuiet(e){return e.quiet!==void 0?e.quiet:E(e)==="free"&&!F()}async loadHold(){if(this.hold!==void 0)return this.hold;try{let e=await(await y()).getItem(D),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 y();e?await t.setItem(D,JSON.stringify(e)):await t.removeItem(D)}catch{}}async persistCache(e){let t=le(e);return await(await y()).setItem(M,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,w(i,le(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});let e=await(await y()).getItem(M);return e?JSON.parse(e):null}catch(e){return console.warn("[Buoy] Error loading cached license:",e),null}}getOrCreateDeviceFingerprint(){return this.fingerprintPromise||(this.fingerprintPromise=(async()=>{let e=await y(),t=await e.getItem(V);if(t)return t;let i=this.cachedLicense?.fingerprint||U();return await e.setItem(V,i),i})()),this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;let e=this.persistence.catch(()=>{}).then(async()=>{await(await y()).removeItem(M)});this.persistence=e,await w(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,r){let s=se();te(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=ht(()=>this.refreshAccess()),typeof p<"u"&&p&&(m.__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)},Le),typeof p<"u"&&p&&(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 y()).removeItem(V)}catch{}}},Dt=new Vt,m=globalThis;typeof p<"u"&&p&&(m.__LICENSE_MANAGER_FOREGROUND_OFF__?.(),m.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0,m.__LICENSE_MANAGER_EXPIRY_TIMER__&&clearTimeout(m.__LICENSE_MANAGER_EXPIRY_TIMER__),m.__LICENSE_MANAGER_TIMER__&&clearInterval(m.__LICENSE_MANAGER_TIMER__),m.__LICENSE_MANAGER_RETRY_TIMER__&&(clearTimeout(m.__LICENSE_MANAGER_RETRY_TIMER__),m.__LICENSE_MANAGER_RETRY_TIMER__=void 0));export{h as a,T as b,Q as c,he as d,ue as e,u as f,k as g,H as h,b as i,St as j,ve as k,Te as l,Dt as m};/*!
|
|
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/lib/web/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use client";import{a as k,b as S,c as y,d as A,e as L,f as b,g as P,h as v,i as h,j as I,k as E,l as K,m as z,n as w,o as T,p as B,q as D,r as F,s as N}from"./chunks/chunk-D5RC3UOG.mjs";import{a as M,b as W,c as j,d as H,e as O,f as Q,g as n,h as V,i as q,j as x,k as f,l as G,m as t}from"./chunks/chunk-
|
|
1
|
+
"use client";import{a as k,b as S,c as y,d as A,e as L,f as b,g as P,h as v,i as h,j as I,k as E,l as K,m as z,n as w,o as T,p as B,q as D,r as F,s as N}from"./chunks/chunk-D5RC3UOG.mjs";import{a as M,b as W,c as j,d as H,e as O,f as Q,g as n,h as V,i as q,j as x,k as f,l as G,m as t}from"./chunks/chunk-OP6QSLZS.mjs";import{b as J,c as R,d as U,e as X}from"./chunks/chunk-J7MW3NXU.mjs";import{useEffect as Y,useState as Z}from"react";function l(s=new Date(M())){let e=s.getDay();return e===0||e===6}function p(){let[s,e]=Z(()=>l());return Y(()=>{let r=setInterval(()=>{let a=l();e(i=>i===a?i:a)},6e4);return()=>clearInterval(r)},[]),s}function g(s,e){return e&&s}import{useState as d,useEffect as C,useCallback as u}from"react";function c(){let[s,e]=d(t.getState());C(()=>{let i=t.subscribe(o=>{e(t.getState())});return t.initialize().then(()=>{e(t.getState())}),i},[]);let r=u(async i=>{let o=await t.setLicenseKey(i,{force:true});return e(t.getState()),o},[]),a=u(async()=>{await t.clearLicense(),e(t.getState())},[]);return{...s,setLicenseKey:r,clearLicense:a}}function _(){return c().access}function $(){let{tier:s,isInitialized:e}=c();return e?s:"free"}function ee(s){let{isPro:e,isInitialized:r,isValidating:a}=c();return{hasAccess:e,isPro:e,isLoading:!r||a}}function se(){let{isPro:s,isInitialized:e,access:r}=c(),a=g(r.status==="admitted",p());return e&&s||a}function ae(){let{isPro:s,isInitialized:e,access:r}=c(),a=e&&s,i=g(r.status==="admitted",p())&&!a;return{isPro:a||i,isLicensed:a,isWeekendFree:i,reason:a?"licensed":i?"weekend":null}}function te(){let[s,e]=d(()=>n.getStatus());C(()=>{let i=()=>e(n.getStatus()),o=n.subscribe(i);return n.load().then(i,i),o},[]);let r=u(()=>n.signIn(),[]),a=u(()=>n.signOut(),[]);return{status:s,signIn:r,signOut:a}}function ie(){let s=n.getAccessToken();if(s)return{token:s,origin:n.origin};let e=t.getState().licenseKey;return e&&f(e)&&t.hasAccountAccess()&&G(e).ok?{token:e,origin:n.origin}:null}async function re(s){let{LicenseManager:e}=await import("./chunks/LicenseManager-G4PF6ILL.mjs");return await e.initialize(),e.setLicenseKey(s)}function m(){return g(t.hasAccountAccess(),l())}function ne(){return t.isPro()?true:m()}function ce(s){return t.hasEntitlement(s)?true:m()}export{t as LicenseManager,W as LicenseTransportError,Q as SessionError,n as SessionManager,E as callCapacitorAsApp,I as callCapacitorNative,K as callCapacitorNativeCallback,U as capacitorDebug,v as capacitorListenerCount,R as capacitorPlatform,D as capacitorPlugin,T as clearCapacitorCalls,y as colorSchemeQueryValue,P as emitCapacitorEvent,N as getCapacitorAppHost,w as getCapacitorCalls,A as getColorSchemeQueries,ie as getSyncCredential,h as hasCapacitorPlugin,ce as hasEntitlement,S as installCapacitorBridge,b as interceptCapacitor,H as isBuoyToken,L as isCapacitorBridgeInstalled,J as isCapacitorNative,f as isDevToken,ne as isPro,V as isServiceKey,j as isTransientLicenseError,l as isWeekendFreePro,z as listenCapacitorNative,F as loadCapacitorAppHost,k as makeCapacitorCallbackId,q as normalizeLicenseKey,O as resolveAccountAccess,X as resolveDevBuild,x as sameLicenseKey,re as setLicenseKey,B as subscribeCapacitorCalls,_ as useAccountAccess,te as useBuoySession,ee as useFeatureAccess,se as useIsPro,c as useLicense,ae as useProAccess,$ as useTier,p 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-4ZLILVOY.mjs";import"./chunk-J7MW3NXU.mjs";export{e as LicenseManager};
|