@buoy-gg/license 7.0.26 → 7.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/LicenseManager.js +1 -1
- package/lib/commonjs/config.js +2 -2
- package/lib/commonjs/hooks.js +1 -1
- package/lib/module/LicenseManager.js +1 -1
- package/lib/module/config.js +1 -1
- package/lib/module/hooks.js +1 -1
- package/lib/typescript/commonjs/LicenseManager.d.ts +17 -1
- package/lib/typescript/commonjs/LicenseManager.d.ts.map +1 -1
- package/lib/typescript/commonjs/config.d.ts +2 -0
- package/lib/typescript/commonjs/config.d.ts.map +1 -1
- package/lib/typescript/commonjs/hooks.d.ts.map +1 -1
- package/lib/typescript/module/LicenseManager.d.ts +17 -1
- package/lib/typescript/module/LicenseManager.d.ts.map +1 -1
- package/lib/typescript/module/config.d.ts +2 -0
- package/lib/typescript/module/config.d.ts.map +1 -1
- package/lib/typescript/module/hooks.d.ts.map +1 -1
- package/package.json +1 -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
|
-
*/const LICENSE_STORAGE_DIR="buoy-license";let _FileSystem=null;let _licenseStorage=null;const _memoryStore=new Map;function loadFileSystem(){if(_FileSystem)return _FileSystem;try{const a=require("expo-file-system/legacy");_FileSystem=a?.default||a;if(_FileSystem?.documentDirectory){return _FileSystem}_FileSystem=null}catch{}try{const a=require("expo-file-system");_FileSystem=a?.default||a;if(_FileSystem?.documentDirectory){return _FileSystem}_FileSystem=null}catch{}return null}function getLicenseStorageDir(){const a=loadFileSystem();if(!a?.documentDirectory)return null;return`${a.documentDirectory}${LICENSE_STORAGE_DIR}/`}function getLicenseFilePath(a){const e=getLicenseStorageDir();if(!e)return null;return`${e}${encodeURIComponent(a)}.json`}async function getLicenseStorage(){if(_licenseStorage)return _licenseStorage;const a=loadFileSystem();if(a?.documentDirectory){_licenseStorage={async getItem(e){const t=getLicenseFilePath(e);if(!t)return null;try{const i=await a.getInfoAsync(t);if(!i.exists)return null;return await a.readAsStringAsync(t)}catch{return null}},async setItem(e,t){const i=getLicenseStorageDir();const s=getLicenseFilePath(e);if(!i||!s)return;try{const r=await a.getInfoAsync(i);if(!r.exists){await a.makeDirectoryAsync(i,{intermediates:true})}await a.writeAsStringAsync(s,t)}catch(r){console.warn("[Buoy] License storage write failed:",r)}},async removeItem(e){const t=getLicenseFilePath(e);if(!t)return;try{await a.deleteAsync(t,{idempotent:true})}catch{}}}}else{_licenseStorage={async getItem(e){return _memoryStore.get(e)??null},async setItem(e,t){_memoryStore.set(e,t)},async removeItem(e){_memoryStore.delete(e)}}}return _licenseStorage}function tierOfCache(a){if(a.tier)return a.tier;return a.isPro?"pro":"anonymous"}class LicenseManagerImpl{state={isInitialized:false,isValidating:false,isPro:false,tier:"anonymous",tierSource:"none",licenseKey:null,error:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;initPromise=null;generation=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;try{const e=await this.loadCachedLicense();if(e){const t=(0,_cacheSignature.verifyCacheSignature)(e);this.cachedLicense=e;this.state.licenseKey=e.licenseKey;this.applyTier(t&&this.isCacheValid(e)?tierOfCache(e):"anonymous");this.state.expiresAt=e.expiresAt?new Date(e.expiresAt):null;if(e.licenseKey){this.validateInBackground(e.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(e){console.warn("[React Buoy] License initialization failed:",e);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async setLicenseKey(e){if(!e||e.trim().length===0){this.state.error="License key is required";return false}const t=e.trim().toUpperCase();this.generation+=1;const i=this.generation;this.state.licenseKey=t;this.state.isValidating=true;this.state.error=null;this.emit({type:"validating",isPro:this.state.isPro});try{const s=await(0,_api.validateLicense)(t);if(i!==this.generation)return false;const r=(0,_api.parseValidationResult)(s);if((0,_api.isFatalLicenseError)(r.code)){this.applyTier((0,_tier.tierAfterFatalError)(r.code));this.state.isValidating=false;this.state.error=r.detail;await this.clearCachedLicense();this.emit({type:"error",isPro:false,error:r.detail});return false}if(!s.data){this.state.isValidating=false;this.state.error=r.detail||"License not found";await this.clearCachedLicense();this.emit({type:"error",isPro:false,error:this.state.error});return false}const n=(0,_tier.resolveTier)(s.data);this.applyTier(n);this.state.isValidating=false;this.state.expiresAt=s.data.attributes.expiry?new Date(s.data.attributes.expiry):null;const c=s.data.id;const o=Date.now();let l=this.cachedLicense?.fingerprint;let d=this.cachedLicense?.deviceName;let u=false;if(!l){l=(0,_fingerprint.generateUUID)();d=(0,_fingerprint.getDefaultDeviceName)();u=true}let h=false;if(u){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:c,licenseKey:t,fingerprint:l};this.deviceRegistrationCallback({fingerprint:l,defaultName:d});h=true}else{this.registerDeviceAsync(c,t,l,d)}}const f={licenseKey:t,licenseId:c,valid:true,isPro:n==="pro",tier:n,expiresAt:s.data.attributes.expiry??null,cachedAt:o,lastValidatedAt:o,fingerprint:h?void 0:l,deviceName:h?void 0:d};this.cachedLicense=await this.persistCache(f);this.emit({type:"validated",isPro:this.state.isPro});return true}catch(s){const r=s instanceof Error?s.message:"Validation failed";if(i!==this.generation)return false;if(this.isNetworkError(s)&&this.cachedLicense&&this.isCacheValid(this.cachedLicense)){this.applyTier(tierOfCache(this.cachedLicense));this.state.isValidating=false;this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.isValidating=false;this.state.error=r;this.emit({type:"error",isPro:false,error:r});return false}}isNetworkError(e){if(e instanceof TypeError){return true}if(e instanceof Error){const t=e.message.toLowerCase();return t.includes("network")||t.includes("fetch")||t.includes("timeout")||t.includes("connection")||t.includes("offline")||t.includes("failed to fetch")}return false}async clearLicense(){this.generation+=1;this.state.licenseKey=null;this.applyTier("anonymous");this.state.expiresAt=null;this.state.error=null;this.cachedLicense=null;await this.clearCachedLicense();this.emit({type:"deactivated",isPro:false})}applyTier(e){this.state.tier=e;this.state.tierSource=e==="anonymous"?"none":"key";this.state.isPro=e==="pro"}getTier(){return this.state.tier}isPro(){return this.state.tier==="pro"}hasEntitlement(e){if(e==="PRO"){return this.state.isPro}return this.state.isPro}getState(){return{...this.state}}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=e.trim()||(0,_fingerprint.getDefaultDeviceName)();const n=(0,_fingerprint.getDeviceMetadata)();try{await(0,_api.activateMachine)(t,i,s,r,n)}catch(c){const o=c instanceof Error?c.message:String(c);if(o==="FINGERPRINT_TAKEN"||o==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",o);throw c}}if(this.cachedLicense){this.cachedLicense.fingerprint=s;this.cachedLicense.deviceName=r;this.cachedLicense=await this.persistCache(this.cachedLicense)}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=Date.now();const i=t-e.cachedAt;if(i>_config.LICENSE_CACHE_DURATION){return false}if(e.expiresAt){const s=new Date(e.expiresAt).getTime();if(t>s){return false}}return true}async persistCache(e){const t=(0,_cacheSignature.signCache)(e);const i=await getLicenseStorage();await i.setItem(_config.LICENSE_STORAGE_KEY,JSON.stringify(t));return t}async loadCachedLicense(){try{const e=await 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}}async clearCachedLicense(){this.cachedLicense=null;try{const e=await getLicenseStorage();await e.removeItem(_config.LICENSE_STORAGE_KEY)}catch{}}registerDeviceAsync(e,t,i,s){const r=(0,_fingerprint.getDeviceMetadata)();(0,_api.activateMachine)(e,t,i,s,r).catch(n=>{if(n.message!=="FINGERPRINT_TAKEN"&&n.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",n.message)}})}validateInBackground(e){const t=this.generation;(0,_api.validateLicense)(e).then(async i=>{if(t!==this.generation)return;const s=(0,_api.parseValidationResult)(i);if(s.valid&&i.data){const r=(0,_tier.resolveTier)(i.data);this.applyTier(r);const n=Date.now();this.cachedLicense=await this.persistCache({...this.cachedLicense??{},licenseKey:e,licenseId:i.data.id,valid:true,isPro:r==="pro",tier:r,expiresAt:i.data.attributes.expiry??null,cachedAt:n,lastValidatedAt:n});this.state.expiresAt=i.data.attributes.expiry?new Date(i.data.attributes.expiry):null;this.emit({type:"validated",isPro:this.state.isPro})}else if((0,_api.isFatalLicenseError)(s.code)){console.warn("[React Buoy] Background validation: license is invalid -",s.code);this.applyTier((0,_tier.tierAfterFatalError)(s.code));await this.clearCachedLicense();this.emit({type:"deactivated",isPro:false})}}).catch(i=>{console.warn("[React Buoy] Background validation failed:",i)})}startRevalidationTimer(){if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(this.state.licenseKey&&!this.state.isValidating){this.validateInBackground(this.state.licenseKey)}},_config.LICENSE_REVALIDATION_INTERVAL);if(__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}await this.clearCachedLicense()}}const LicenseManager=exports.LicenseManager=new LicenseManagerImpl;if(__DEV__){if(global.__LICENSE_MANAGER_TIMER__){clearInterval(global.__LICENSE_MANAGER_TIMER__)}}
|
|
16
|
+
*/const LICENSE_STORAGE_DIR="buoy-license";let _FileSystem=null;let _licenseStorage=null;const _memoryStore=new Map;function loadFileSystem(){if(_FileSystem)return _FileSystem;try{const s=require("expo-file-system/legacy");_FileSystem=s?.default||s;if(_FileSystem?.documentDirectory){return _FileSystem}_FileSystem=null}catch{}try{const s=require("expo-file-system");_FileSystem=s?.default||s;if(_FileSystem?.documentDirectory){return _FileSystem}_FileSystem=null}catch{}return null}function getLicenseStorageDir(){const s=loadFileSystem();if(!s?.documentDirectory)return null;return`${s.documentDirectory}${LICENSE_STORAGE_DIR}/`}function getLicenseFilePath(s){const e=getLicenseStorageDir();if(!e)return null;return`${e}${encodeURIComponent(s)}.json`}function loadAsyncStorage(){try{const s=require("@react-native-async-storage/async-storage");const e=s?.default||s;if(typeof e?.getItem==="function"&&typeof e.setItem==="function"&&typeof e.removeItem==="function"){return e}}catch{}return null}function hasLocalStorage(){try{return typeof localStorage!=="undefined"&&!!localStorage}catch{return false}}async function getLicenseStorage(){if(_licenseStorage)return _licenseStorage;const s=loadFileSystem();let e=null;if(s?.documentDirectory){_licenseStorage={async getItem(t){const i=getLicenseFilePath(t);if(!i)return null;try{const a=await s.getInfoAsync(i);if(!a.exists)return null;return await s.readAsStringAsync(i)}catch{return null}},async setItem(t,i){const a=getLicenseStorageDir();const n=getLicenseFilePath(t);if(!a||!n)return;try{const r=await s.getInfoAsync(a);if(!r.exists){await s.makeDirectoryAsync(a,{intermediates:true})}await s.writeAsStringAsync(n,i)}catch(r){console.warn("[Buoy] License storage write failed:",r)}},async removeItem(t){const i=getLicenseFilePath(t);if(!i)return;try{await s.deleteAsync(i,{idempotent:true})}catch{}}}}else if(e=loadAsyncStorage()){const t=e;_licenseStorage={async getItem(i){try{return await t.getItem(i)}catch{return null}},async setItem(i,a){try{await t.setItem(i,a)}catch(n){console.warn("[Buoy] License storage write failed:",n)}},async removeItem(i){try{await t.removeItem(i)}catch{}}}}else if(hasLocalStorage()){_licenseStorage={async getItem(t){try{return localStorage.getItem(t)}catch{return null}},async setItem(t,i){try{localStorage.setItem(t,i)}catch{}},async removeItem(t){try{localStorage.removeItem(t)}catch{}}}}else{_licenseStorage={async getItem(t){return _memoryStore.get(t)??null},async setItem(t,i){_memoryStore.set(t,i)},async removeItem(t){_memoryStore.delete(t)}}}return _licenseStorage}function tierOfCache(s){if(s.tier)return s.tier;return s.isPro?"pro":"anonymous"}class LicenseManagerImpl{state={isInitialized:false,isValidating:false,isPro:false,tier:"anonymous",tierSource:"none",licenseKey:null,error:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;initPromise=null;generation=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;try{const e=await this.loadCachedLicense();if(e){const t=(0,_cacheSignature.verifyCacheSignature)(e);this.cachedLicense=e;this.state.licenseKey=e.licenseKey;this.applyTier(t&&this.isCacheValid(e)?tierOfCache(e):"anonymous");this.state.expiresAt=e.expiresAt?new Date(e.expiresAt):null;if(e.licenseKey&&!(t&&this.isCacheValid(e)&&this.isCacheFresh(e))){this.validateInBackground(e.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(e){console.warn("[React Buoy] License initialization failed:",e);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async setLicenseKey(e,t){if(!e||e.trim().length===0){this.state.error="License key is required";return false}const i=e.trim().toUpperCase();const a=this.cachedLicense;if(!t?.force&&a&&a.valid&&a.licenseKey===i&&a.fingerprint&&(0,_cacheSignature.verifyCacheSignature)(a)&&this.isCacheValid(a)&&this.isCacheFresh(a)){this.applyTier(tierOfCache(a));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.expiresAt=a.expiresAt?new Date(a.expiresAt):null;this.emit({type:"validated",isPro:this.state.isPro});return true}this.generation+=1;const n=this.generation;this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.emit({type:"validating",isPro:this.state.isPro});try{const r=await(0,_api.validateLicense)(i);if(n!==this.generation)return false;const c=(0,_api.parseValidationResult)(r);if((0,_api.isFatalLicenseError)(c.code)){this.applyTier((0,_tier.tierAfterFatalError)(c.code));this.state.isValidating=false;this.state.error=c.detail;await this.clearCachedLicense();this.emit({type:"error",isPro:false,error:c.detail});return false}if(!r.data){this.state.isValidating=false;this.state.error=c.detail||"License not found";await this.clearCachedLicense();this.emit({type:"error",isPro:false,error:this.state.error});return false}const o=(0,_tier.resolveTier)(r.data);this.applyTier(o);this.state.isValidating=false;this.state.expiresAt=r.data.attributes.expiry?new Date(r.data.attributes.expiry):null;const d=r.data.id;const f=Date.now();let l=this.cachedLicense?.fingerprint;let h=this.cachedLicense?.deviceName;let g=false;if(!l){l=await this.getOrCreateDeviceFingerprint();h=(0,_fingerprint.getDefaultDeviceName)();g=true}let u=false;if(g){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:d,licenseKey:i,fingerprint:l};this.deviceRegistrationCallback({fingerprint:l,defaultName:h});u=true}else{this.registerDeviceAsync(d,i,l,h)}}const y={licenseKey:i,licenseId:d,valid:true,isPro:o==="pro",tier:o,expiresAt:r.data.attributes.expiry??null,cachedAt:f,lastValidatedAt:f,fingerprint:u?void 0:l,deviceName:u?void 0:h};this.cachedLicense=await this.persistCache(y);this.emit({type:"validated",isPro:this.state.isPro});return true}catch(r){const c=r instanceof Error?r.message:"Validation failed";if(n!==this.generation)return false;if(this.isNetworkError(r)&&this.cachedLicense&&this.isCacheValid(this.cachedLicense)){this.applyTier(tierOfCache(this.cachedLicense));this.state.isValidating=false;this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.isValidating=false;this.state.error=c;this.emit({type:"error",isPro:false,error:c});return false}}isNetworkError(e){if(e instanceof TypeError){return true}if(e instanceof Error){const t=e.message.toLowerCase();return t.includes("network")||t.includes("fetch")||t.includes("timeout")||t.includes("connection")||t.includes("offline")||t.includes("failed to fetch")}return false}async clearLicense(){this.generation+=1;this.state.licenseKey=null;this.applyTier("anonymous");this.state.expiresAt=null;this.state.error=null;this.cachedLicense=null;await this.clearCachedLicense();this.emit({type:"deactivated",isPro:false})}applyTier(e){this.state.tier=e;this.state.tierSource=e==="anonymous"?"none":"key";this.state.isPro=e==="pro"}getTier(){return this.state.tier}isPro(){return this.state.tier==="pro"}hasEntitlement(e){if(e==="PRO"){return this.state.isPro}return this.state.isPro}getState(){return{...this.state}}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:a}=this.pendingRegistration;const n=e.trim()||(0,_fingerprint.getDefaultDeviceName)();const r=(0,_fingerprint.getDeviceMetadata)();try{await(0,_api.activateMachine)(t,i,a,n,r)}catch(c){const o=c instanceof Error?c.message:String(c);if(o==="FINGERPRINT_TAKEN"||o==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",o);throw c}}if(this.cachedLicense){this.cachedLicense.fingerprint=a;this.cachedLicense.deviceName=n;this.cachedLicense=await this.persistCache(this.cachedLicense)}this.pendingRegistration=null}emit(e){const t=[...this.listeners];t.forEach(i=>{try{i(e)}catch(a){console.warn("[React Buoy] License listener error:",a)}})}isCacheValid(e){const t=Date.now();const i=t-e.cachedAt;if(i>_config.LICENSE_CACHE_DURATION){return false}if(e.expiresAt){const a=new Date(e.expiresAt).getTime();if(t>a){return false}}return true}isCacheFresh(e){return Date.now()-(e.lastValidatedAt??0)<_config.LICENSE_LAUNCH_VALIDATION_TTL}async persistCache(e){const t=(0,_cacheSignature.signCache)(e);const i=await getLicenseStorage();await i.setItem(_config.LICENSE_STORAGE_KEY,JSON.stringify(t));return t}async loadCachedLicense(){try{const e=await 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 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;try{const e=await getLicenseStorage();await e.removeItem(_config.LICENSE_STORAGE_KEY)}catch{}}registerDeviceAsync(e,t,i,a){const n=(0,_fingerprint.getDeviceMetadata)();(0,_api.activateMachine)(e,t,i,a,n).catch(r=>{if(r.message!=="FINGERPRINT_TAKEN"&&r.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",r.message)}})}validateInBackground(e){const t=this.generation;(0,_api.validateLicense)(e).then(async i=>{if(t!==this.generation)return;const a=(0,_api.parseValidationResult)(i);if(a.valid&&i.data){const n=(0,_tier.resolveTier)(i.data);this.applyTier(n);const r=Date.now();this.cachedLicense=await this.persistCache({...this.cachedLicense??{},licenseKey:e,licenseId:i.data.id,valid:true,isPro:n==="pro",tier:n,expiresAt:i.data.attributes.expiry??null,cachedAt:r,lastValidatedAt:r});this.state.expiresAt=i.data.attributes.expiry?new Date(i.data.attributes.expiry):null;this.emit({type:"validated",isPro:this.state.isPro})}else if((0,_api.isFatalLicenseError)(a.code)){console.warn("[React Buoy] Background validation: license is invalid -",a.code);this.applyTier((0,_tier.tierAfterFatalError)(a.code));await this.clearCachedLicense();this.emit({type:"deactivated",isPro:false})}}).catch(i=>{console.warn("[React Buoy] Background validation failed:",i)})}startRevalidationTimer(){if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(this.state.licenseKey&&!this.state.isValidating){this.validateInBackground(this.state.licenseKey)}},_config.LICENSE_REVALIDATION_INTERVAL);if(__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}}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 getLicenseStorage();await e.removeItem(_config.DEVICE_FINGERPRINT_STORAGE_KEY)}catch{}}}const LicenseManager=exports.LicenseManager=new LicenseManagerImpl;if(__DEV__){if(global.__LICENSE_MANAGER_TIMER__){clearInterval(global.__LICENSE_MANAGER_TIMER__)}}
|
package/lib/commonjs/config.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LICENSE_STORAGE_KEY=exports.LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_CACHE_DURATION=exports.KEYGEN_POLICIES=exports.KEYGEN_CONFIG=exports.ANONYMOUS_TIER_ENABLED=void 0;/*!
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.LICENSE_STORAGE_KEY=exports.LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_CACHE_DURATION=exports.KEYGEN_POLICIES=exports.KEYGEN_CONFIG=exports.DEVICE_FINGERPRINT_STORAGE_KEY=exports.ANONYMOUS_TIER_ENABLED=void 0;/*!
|
|
2
2
|
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
3
3
|
*
|
|
4
4
|
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
15
15
|
* including a free one (`npx buoy login`). Buy a key at
|
|
16
16
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
17
|
-
*/const KEYGEN_CONFIG=exports.KEYGEN_CONFIG={accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",productToken:"prod-4467c14b75b715e91884945cd3e69705846ccbce7dd5e380236a1ab3bc03139fv3",apiUrl:"https://api.keygen.sh/v1/accounts"};const KEYGEN_POLICIES=exports.KEYGEN_POLICIES={free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"};const LICENSE_CACHE_DURATION=exports.LICENSE_CACHE_DURATION=30*24*60*60*1e3;const LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;const LICENSE_STORAGE_KEY=exports.LICENSE_STORAGE_KEY="buoy-gg-license";const ANONYMOUS_TIER_ENABLED=exports.ANONYMOUS_TIER_ENABLED=true;
|
|
17
|
+
*/const KEYGEN_CONFIG=exports.KEYGEN_CONFIG={accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",productToken:"prod-4467c14b75b715e91884945cd3e69705846ccbce7dd5e380236a1ab3bc03139fv3",apiUrl:"https://api.keygen.sh/v1/accounts"};const KEYGEN_POLICIES=exports.KEYGEN_POLICIES={free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"};const LICENSE_CACHE_DURATION=exports.LICENSE_CACHE_DURATION=30*24*60*60*1e3;const LICENSE_REVALIDATION_INTERVAL=exports.LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;const LICENSE_STORAGE_KEY=exports.LICENSE_STORAGE_KEY="buoy-gg-license";const DEVICE_FINGERPRINT_STORAGE_KEY=exports.DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";const LICENSE_LAUNCH_VALIDATION_TTL=exports.LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;const ANONYMOUS_TIER_ENABLED=exports.ANONYMOUS_TIER_ENABLED=true;
|
package/lib/commonjs/hooks.js
CHANGED
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
15
15
|
* including a free one (`npx buoy login`). Buy a key at
|
|
16
16
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
17
|
-
*/function useLicense(){const[t,e]=(0,_react.useState)(_LicenseManager.LicenseManager.getState());(0,_react.useEffect)(()=>{const n=_LicenseManager.LicenseManager.subscribe(i=>{e(_LicenseManager.LicenseManager.getState())});_LicenseManager.LicenseManager.initialize().then(()=>{e(_LicenseManager.LicenseManager.getState())});return n},[]);const r=(0,_react.useCallback)(async n=>{const i=await _LicenseManager.LicenseManager.setLicenseKey(n);e(_LicenseManager.LicenseManager.getState());return i},[]);const s=(0,_react.useCallback)(async()=>{await _LicenseManager.LicenseManager.clearLicense();e(_LicenseManager.LicenseManager.getState())},[]);return{...t,setLicenseKey:r,clearLicense:s}}function useTier(){const{tier:t,isInitialized:e}=useLicense();return e?t:"anonymous"}function useFeatureAccess(t){const{isPro:e,isInitialized:r,isValidating:s}=useLicense();const n=e;const i=!r||s;return{hasAccess:n,isPro:e,isLoading:i}}function useIsPro(){const{isPro:t,isInitialized:e,tier:r}=useLicense();const s=(0,_weekendPro.weekendPassAppliesTo)(r,(0,_weekendPro.useWeekendFreePro)());return e&&t||s}function useProAccess(){const{isPro:t,isInitialized:e,tier:r}=useLicense();const s=e&&t;const n=(0,_weekendPro.weekendPassAppliesTo)(r,(0,_weekendPro.useWeekendFreePro)())&&!s;const i=s?"licensed":n?"weekend":null;return{isPro:s||n,isLicensed:s,isWeekendFree:n,reason:i}}
|
|
17
|
+
*/function useLicense(){const[t,e]=(0,_react.useState)(_LicenseManager.LicenseManager.getState());(0,_react.useEffect)(()=>{const n=_LicenseManager.LicenseManager.subscribe(i=>{e(_LicenseManager.LicenseManager.getState())});_LicenseManager.LicenseManager.initialize().then(()=>{e(_LicenseManager.LicenseManager.getState())});return n},[]);const r=(0,_react.useCallback)(async n=>{const i=await _LicenseManager.LicenseManager.setLicenseKey(n,{force:true});e(_LicenseManager.LicenseManager.getState());return i},[]);const s=(0,_react.useCallback)(async()=>{await _LicenseManager.LicenseManager.clearLicense();e(_LicenseManager.LicenseManager.getState())},[]);return{...t,setLicenseKey:r,clearLicense:s}}function useTier(){const{tier:t,isInitialized:e}=useLicense();return e?t:"anonymous"}function useFeatureAccess(t){const{isPro:e,isInitialized:r,isValidating:s}=useLicense();const n=e;const i=!r||s;return{hasAccess:n,isPro:e,isLoading:i}}function useIsPro(){const{isPro:t,isInitialized:e,tier:r}=useLicense();const s=(0,_weekendPro.weekendPassAppliesTo)(r,(0,_weekendPro.useWeekendFreePro)());return e&&t||s}function useProAccess(){const{isPro:t,isInitialized:e,tier:r}=useLicense();const s=e&&t;const n=(0,_weekendPro.weekendPassAppliesTo)(r,(0,_weekendPro.useWeekendFreePro)())&&!s;const i=s?"licensed":n?"weekend":null;return{isPro:s||n,isLicensed:s,isWeekendFree:n,reason:i}}
|
|
@@ -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
|
-
*/const S="buoy-license";let c=null;let h=null;const y=new Map;function v(){if(c)return c;try{const a=require("expo-file-system/legacy");c=a?.default||a;if(c?.documentDirectory){return c}c=null}catch{}try{const a=require("expo-file-system");c=a?.default||a;if(c?.documentDirectory){return c}c=null}catch{}return null}function L(){const a=v();if(!a?.documentDirectory)return null;return`${a.documentDirectory}${S}/`}function g(a){const e=L();if(!e)return null;return`${e}${encodeURIComponent(a)}.json`}async function m(){if(h)return h;const a=v();if(a?.documentDirectory){h={async getItem(e){const t=g(e);if(!t)return null;try{const i=await a.getInfoAsync(t);if(!i.exists)return null;return await a.readAsStringAsync(t)}catch{return null}},async setItem(e,t){const i=L();const s=g(e);if(!i||!s)return;try{const r=await a.getInfoAsync(i);if(!r.exists){await a.makeDirectoryAsync(i,{intermediates:true})}await a.writeAsStringAsync(s,t)}catch(r){console.warn("[Buoy] License storage write failed:",r)}},async removeItem(e){const t=g(e);if(!t)return;try{await a.deleteAsync(t,{idempotent:true})}catch{}}}}else{h={async getItem(e){return y.get(e)??null},async setItem(e,t){y.set(e,t)},async removeItem(e){y.delete(e)}}}return h}import{LICENSE_STORAGE_KEY as p,LICENSE_CACHE_DURATION as x,LICENSE_REVALIDATION_INTERVAL as V}from"./config.js";import{validateLicense as E,activateMachine as w,parseValidationResult as A,isFatalLicenseError as _}from"./api.js";import{generateUUID as b,getDeviceMetadata as C,getDefaultDeviceName as R}from"./fingerprint";import{signCache as k,verifyCacheSignature as M}from"./cacheSignature.js";import{resolveTier as T,tierAfterFatalError as P}from"./tier.js";function D(a){if(a.tier)return a.tier;return a.isPro?"pro":"anonymous"}class B{state={isInitialized:false,isValidating:false,isPro:false,tier:"anonymous",tierSource:"none",licenseKey:null,error:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;initPromise=null;generation=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;try{const e=await this.loadCachedLicense();if(e){const t=M(e);this.cachedLicense=e;this.state.licenseKey=e.licenseKey;this.applyTier(t&&this.isCacheValid(e)?D(e):"anonymous");this.state.expiresAt=e.expiresAt?new Date(e.expiresAt):null;if(e.licenseKey){this.validateInBackground(e.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(e){console.warn("[React Buoy] License initialization failed:",e);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async setLicenseKey(e){if(!e||e.trim().length===0){this.state.error="License key is required";return false}const t=e.trim().toUpperCase();this.generation+=1;const i=this.generation;this.state.licenseKey=t;this.state.isValidating=true;this.state.error=null;this.emit({type:"validating",isPro:this.state.isPro});try{const s=await E(t);if(i!==this.generation)return false;const r=A(s);if(_(r.code)){this.applyTier(P(r.code));this.state.isValidating=false;this.state.error=r.detail;await this.clearCachedLicense();this.emit({type:"error",isPro:false,error:r.detail});return false}if(!s.data){this.state.isValidating=false;this.state.error=r.detail||"License not found";await this.clearCachedLicense();this.emit({type:"error",isPro:false,error:this.state.error});return false}const n=T(s.data);this.applyTier(n);this.state.isValidating=false;this.state.expiresAt=s.data.attributes.expiry?new Date(s.data.attributes.expiry):null;const o=s.data.id;const l=Date.now();let d=this.cachedLicense?.fingerprint;let u=this.cachedLicense?.deviceName;let I=false;if(!d){d=b();u=R();I=true}let f=false;if(I){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:o,licenseKey:t,fingerprint:d};this.deviceRegistrationCallback({fingerprint:d,defaultName:u});f=true}else{this.registerDeviceAsync(o,t,d,u)}}const N={licenseKey:t,licenseId:o,valid:true,isPro:n==="pro",tier:n,expiresAt:s.data.attributes.expiry??null,cachedAt:l,lastValidatedAt:l,fingerprint:f?void 0:d,deviceName:f?void 0:u};this.cachedLicense=await this.persistCache(N);this.emit({type:"validated",isPro:this.state.isPro});return true}catch(s){const r=s instanceof Error?s.message:"Validation failed";if(i!==this.generation)return false;if(this.isNetworkError(s)&&this.cachedLicense&&this.isCacheValid(this.cachedLicense)){this.applyTier(D(this.cachedLicense));this.state.isValidating=false;this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.isValidating=false;this.state.error=r;this.emit({type:"error",isPro:false,error:r});return false}}isNetworkError(e){if(e instanceof TypeError){return true}if(e instanceof Error){const t=e.message.toLowerCase();return t.includes("network")||t.includes("fetch")||t.includes("timeout")||t.includes("connection")||t.includes("offline")||t.includes("failed to fetch")}return false}async clearLicense(){this.generation+=1;this.state.licenseKey=null;this.applyTier("anonymous");this.state.expiresAt=null;this.state.error=null;this.cachedLicense=null;await this.clearCachedLicense();this.emit({type:"deactivated",isPro:false})}applyTier(e){this.state.tier=e;this.state.tierSource=e==="anonymous"?"none":"key";this.state.isPro=e==="pro"}getTier(){return this.state.tier}isPro(){return this.state.tier==="pro"}hasEntitlement(e){if(e==="PRO"){return this.state.isPro}return this.state.isPro}getState(){return{...this.state}}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=e.trim()||R();const n=C();try{await w(t,i,s,r,n)}catch(o){const l=o instanceof Error?o.message:String(o);if(l==="FINGERPRINT_TAKEN"||l==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",l);throw o}}if(this.cachedLicense){this.cachedLicense.fingerprint=s;this.cachedLicense.deviceName=r;this.cachedLicense=await this.persistCache(this.cachedLicense)}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=Date.now();const i=t-e.cachedAt;if(i>x){return false}if(e.expiresAt){const s=new Date(e.expiresAt).getTime();if(t>s){return false}}return true}async persistCache(e){const t=k(e);const i=await m();await i.setItem(p,JSON.stringify(t));return t}async loadCachedLicense(){try{const e=await m();const t=await e.getItem(p);if(!t)return null;const i=JSON.parse(t);return i}catch(e){console.warn("[Buoy] Error loading cached license:",e);return null}}async clearCachedLicense(){this.cachedLicense=null;try{const e=await m();await e.removeItem(p)}catch{}}registerDeviceAsync(e,t,i,s){const r=C();w(e,t,i,s,r).catch(n=>{if(n.message!=="FINGERPRINT_TAKEN"&&n.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",n.message)}})}validateInBackground(e){const t=this.generation;E(e).then(async i=>{if(t!==this.generation)return;const s=A(i);if(s.valid&&i.data){const r=T(i.data);this.applyTier(r);const n=Date.now();this.cachedLicense=await this.persistCache({...this.cachedLicense??{},licenseKey:e,licenseId:i.data.id,valid:true,isPro:r==="pro",tier:r,expiresAt:i.data.attributes.expiry??null,cachedAt:n,lastValidatedAt:n});this.state.expiresAt=i.data.attributes.expiry?new Date(i.data.attributes.expiry):null;this.emit({type:"validated",isPro:this.state.isPro})}else if(_(s.code)){console.warn("[React Buoy] Background validation: license is invalid -",s.code);this.applyTier(P(s.code));await this.clearCachedLicense();this.emit({type:"deactivated",isPro:false})}}).catch(i=>{console.warn("[React Buoy] Background validation failed:",i)})}startRevalidationTimer(){if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(this.state.licenseKey&&!this.state.isValidating){this.validateInBackground(this.state.licenseKey)}},V);if(__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}}async forceReregister(){if(this.cachedLicense){this.cachedLicense.fingerprint=void 0;this.cachedLicense.deviceName=void 0}await this.clearCachedLicense()}}export const LicenseManager=new B;if(__DEV__){if(global.__LICENSE_MANAGER_TIMER__){clearInterval(global.__LICENSE_MANAGER_TIMER__)}}
|
|
16
|
+
*/const k="buoy-license";let o=null;let h=null;const m=new Map;function A(){if(o)return o;try{const a=require("expo-file-system/legacy");o=a?.default||a;if(o?.documentDirectory){return o}o=null}catch{}try{const a=require("expo-file-system");o=a?.default||a;if(o?.documentDirectory){return o}o=null}catch{}return null}function _(){const a=A();if(!a?.documentDirectory)return null;return`${a.documentDirectory}${k}/`}function p(a){const e=_();if(!e)return null;return`${e}${encodeURIComponent(a)}.json`}function K(){try{const a=require("@react-native-async-storage/async-storage");const e=a?.default||a;if(typeof e?.getItem==="function"&&typeof e.setItem==="function"&&typeof e.removeItem==="function"){return e}}catch{}return null}function M(){try{return typeof localStorage!=="undefined"&&!!localStorage}catch{return false}}async function u(){if(h)return h;const a=A();let e=null;if(a?.documentDirectory){h={async getItem(t){const i=p(t);if(!i)return null;try{const s=await a.getInfoAsync(i);if(!s.exists)return null;return await a.readAsStringAsync(i)}catch{return null}},async setItem(t,i){const s=_();const n=p(t);if(!s||!n)return;try{const r=await a.getInfoAsync(s);if(!r.exists){await a.makeDirectoryAsync(s,{intermediates:true})}await a.writeAsStringAsync(n,i)}catch(r){console.warn("[Buoy] License storage write failed:",r)}},async removeItem(t){const i=p(t);if(!i)return;try{await a.deleteAsync(i,{idempotent:true})}catch{}}}}else if(e=K()){const t=e;h={async getItem(i){try{return await t.getItem(i)}catch{return null}},async setItem(i,s){try{await t.setItem(i,s)}catch(n){console.warn("[Buoy] License storage write failed:",n)}},async removeItem(i){try{await t.removeItem(i)}catch{}}}}else if(M()){h={async getItem(t){try{return localStorage.getItem(t)}catch{return null}},async setItem(t,i){try{localStorage.setItem(t,i)}catch{}},async removeItem(t){try{localStorage.removeItem(t)}catch{}}}}else{h={async getItem(t){return m.get(t)??null},async setItem(t,i){m.set(t,i)},async removeItem(t){m.delete(t)}}}return h}import{LICENSE_STORAGE_KEY as I,LICENSE_CACHE_DURATION as B,LICENSE_REVALIDATION_INTERVAL as F,LICENSE_LAUNCH_VALIDATION_TTL as z,DEVICE_FINGERPRINT_STORAGE_KEY as v}from"./config.js";import{validateLicense as C,activateMachine as P,parseValidationResult as R,isFatalLicenseError as T}from"./api.js";import{generateUUID as O,getDeviceMetadata as D,getDefaultDeviceName as N}from"./fingerprint";import{signCache as G,verifyCacheSignature as S}from"./cacheSignature.js";import{resolveTier as x,tierAfterFatalError as V}from"./tier.js";function w(a){if(a.tier)return a.tier;return a.isPro?"pro":"anonymous"}class U{state={isInitialized:false,isValidating:false,isPro:false,tier:"anonymous",tierSource:"none",licenseKey:null,error:null,expiresAt:null};listeners=new Set;revalidationTimer=null;cachedLicense=null;fingerprintPromise=null;initPromise=null;generation=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;try{const e=await this.loadCachedLicense();if(e){const t=S(e);this.cachedLicense=e;this.state.licenseKey=e.licenseKey;this.applyTier(t&&this.isCacheValid(e)?w(e):"anonymous");this.state.expiresAt=e.expiresAt?new Date(e.expiresAt):null;if(e.licenseKey&&!(t&&this.isCacheValid(e)&&this.isCacheFresh(e))){this.validateInBackground(e.licenseKey)}}this.state.isInitialized=true;this.emit({type:"initialized",isPro:this.state.isPro});this.startRevalidationTimer()}catch(e){console.warn("[React Buoy] License initialization failed:",e);this.state.isInitialized=true;this.emit({type:"initialized",isPro:false})}}async setLicenseKey(e,t){if(!e||e.trim().length===0){this.state.error="License key is required";return false}const i=e.trim().toUpperCase();const s=this.cachedLicense;if(!t?.force&&s&&s.valid&&s.licenseKey===i&&s.fingerprint&&S(s)&&this.isCacheValid(s)&&this.isCacheFresh(s)){this.applyTier(w(s));this.state.licenseKey=i;this.state.isValidating=false;this.state.error=null;this.state.expiresAt=s.expiresAt?new Date(s.expiresAt):null;this.emit({type:"validated",isPro:this.state.isPro});return true}this.generation+=1;const n=this.generation;this.state.licenseKey=i;this.state.isValidating=true;this.state.error=null;this.emit({type:"validating",isPro:this.state.isPro});try{const r=await C(i);if(n!==this.generation)return false;const c=R(r);if(T(c.code)){this.applyTier(V(c.code));this.state.isValidating=false;this.state.error=c.detail;await this.clearCachedLicense();this.emit({type:"error",isPro:false,error:c.detail});return false}if(!r.data){this.state.isValidating=false;this.state.error=c.detail||"License not found";await this.clearCachedLicense();this.emit({type:"error",isPro:false,error:this.state.error});return false}const l=x(r.data);this.applyTier(l);this.state.isValidating=false;this.state.expiresAt=r.data.attributes.expiry?new Date(r.data.attributes.expiry):null;const g=r.data.id;const L=Date.now();let d=this.cachedLicense?.fingerprint;let f=this.cachedLicense?.deviceName;let E=false;if(!d){d=await this.getOrCreateDeviceFingerprint();f=N();E=true}let y=false;if(E){if(this.deviceRegistrationCallback){this.pendingRegistration={licenseId:g,licenseKey:i,fingerprint:d};this.deviceRegistrationCallback({fingerprint:d,defaultName:f});y=true}else{this.registerDeviceAsync(g,i,d,f)}}const b={licenseKey:i,licenseId:g,valid:true,isPro:l==="pro",tier:l,expiresAt:r.data.attributes.expiry??null,cachedAt:L,lastValidatedAt:L,fingerprint:y?void 0:d,deviceName:y?void 0:f};this.cachedLicense=await this.persistCache(b);this.emit({type:"validated",isPro:this.state.isPro});return true}catch(r){const c=r instanceof Error?r.message:"Validation failed";if(n!==this.generation)return false;if(this.isNetworkError(r)&&this.cachedLicense&&this.isCacheValid(this.cachedLicense)){this.applyTier(w(this.cachedLicense));this.state.isValidating=false;this.emit({type:"validated",isPro:this.state.isPro});return true}this.state.isValidating=false;this.state.error=c;this.emit({type:"error",isPro:false,error:c});return false}}isNetworkError(e){if(e instanceof TypeError){return true}if(e instanceof Error){const t=e.message.toLowerCase();return t.includes("network")||t.includes("fetch")||t.includes("timeout")||t.includes("connection")||t.includes("offline")||t.includes("failed to fetch")}return false}async clearLicense(){this.generation+=1;this.state.licenseKey=null;this.applyTier("anonymous");this.state.expiresAt=null;this.state.error=null;this.cachedLicense=null;await this.clearCachedLicense();this.emit({type:"deactivated",isPro:false})}applyTier(e){this.state.tier=e;this.state.tierSource=e==="anonymous"?"none":"key";this.state.isPro=e==="pro"}getTier(){return this.state.tier}isPro(){return this.state.tier==="pro"}hasEntitlement(e){if(e==="PRO"){return this.state.isPro}return this.state.isPro}getState(){return{...this.state}}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 n=e.trim()||N();const r=D();try{await P(t,i,s,n,r)}catch(c){const l=c instanceof Error?c.message:String(c);if(l==="FINGERPRINT_TAKEN"||l==="MACHINE_LIMIT_EXCEEDED"){}else{console.warn("[Buoy] Device registration failed:",l);throw c}}if(this.cachedLicense){this.cachedLicense.fingerprint=s;this.cachedLicense.deviceName=n;this.cachedLicense=await this.persistCache(this.cachedLicense)}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=Date.now();const i=t-e.cachedAt;if(i>B){return false}if(e.expiresAt){const s=new Date(e.expiresAt).getTime();if(t>s){return false}}return true}isCacheFresh(e){return Date.now()-(e.lastValidatedAt??0)<z}async persistCache(e){const t=G(e);const i=await u();await i.setItem(I,JSON.stringify(t));return t}async loadCachedLicense(){try{const e=await u();const t=await e.getItem(I);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 u();const t=await e.getItem(v);if(t)return t;const i=this.cachedLicense?.fingerprint||O();await e.setItem(v,i);return i})()}return this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;try{const e=await u();await e.removeItem(I)}catch{}}registerDeviceAsync(e,t,i,s){const n=D();P(e,t,i,s,n).catch(r=>{if(r.message!=="FINGERPRINT_TAKEN"&&r.message!=="MACHINE_LIMIT_EXCEEDED"){console.warn("[Buoy] Device registration failed (non-blocking):",r.message)}})}validateInBackground(e){const t=this.generation;C(e).then(async i=>{if(t!==this.generation)return;const s=R(i);if(s.valid&&i.data){const n=x(i.data);this.applyTier(n);const r=Date.now();this.cachedLicense=await this.persistCache({...this.cachedLicense??{},licenseKey:e,licenseId:i.data.id,valid:true,isPro:n==="pro",tier:n,expiresAt:i.data.attributes.expiry??null,cachedAt:r,lastValidatedAt:r});this.state.expiresAt=i.data.attributes.expiry?new Date(i.data.attributes.expiry):null;this.emit({type:"validated",isPro:this.state.isPro})}else if(T(s.code)){console.warn("[React Buoy] Background validation: license is invalid -",s.code);this.applyTier(V(s.code));await this.clearCachedLicense();this.emit({type:"deactivated",isPro:false})}}).catch(i=>{console.warn("[React Buoy] Background validation failed:",i)})}startRevalidationTimer(){if(this.revalidationTimer){clearInterval(this.revalidationTimer)}this.revalidationTimer=setInterval(()=>{if(this.state.licenseKey&&!this.state.isValidating){this.validateInBackground(this.state.licenseKey)}},F);if(__DEV__){global.__LICENSE_MANAGER_TIMER__=this.revalidationTimer}}stopRevalidationTimer(){if(this.revalidationTimer){clearInterval(this.revalidationTimer);this.revalidationTimer=null}}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 u();await e.removeItem(v)}catch{}}}export const LicenseManager=new U;if(__DEV__){if(global.__LICENSE_MANAGER_TIMER__){clearInterval(global.__LICENSE_MANAGER_TIMER__)}}
|
package/lib/module/config.js
CHANGED
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
15
15
|
* including a free one (`npx buoy login`). Buy a key at
|
|
16
16
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
17
|
-
*/export const KEYGEN_CONFIG={accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",productToken:"prod-4467c14b75b715e91884945cd3e69705846ccbce7dd5e380236a1ab3bc03139fv3",apiUrl:"https://api.keygen.sh/v1/accounts"};export const KEYGEN_POLICIES={free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"};export const LICENSE_CACHE_DURATION=30*24*60*60*1e3;export const LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;export const LICENSE_STORAGE_KEY="buoy-gg-license";export const ANONYMOUS_TIER_ENABLED=true;
|
|
17
|
+
*/export const KEYGEN_CONFIG={accountId:"b0eba0e8-e904-4906-b644-38f9aab57bed",productId:"bf67cb43-eeef-40ca-b308-e6e1b22c0eaa",productToken:"prod-4467c14b75b715e91884945cd3e69705846ccbce7dd5e380236a1ab3bc03139fv3",apiUrl:"https://api.keygen.sh/v1/accounts"};export const KEYGEN_POLICIES={free:"394e3351-1249-4f73-807a-703408604c0e",solo:"fa5d3c8f-5379-40f1-b63e-ab8a974b2f28",business:"690c2212-8e54-426f-b4b4-002ee1c0ae2b"};export const LICENSE_CACHE_DURATION=30*24*60*60*1e3;export const LICENSE_REVALIDATION_INTERVAL=24*60*60*1e3;export const LICENSE_STORAGE_KEY="buoy-gg-license";export const DEVICE_FINGERPRINT_STORAGE_KEY="buoy-gg-device-fingerprint";export const LICENSE_LAUNCH_VALIDATION_TTL=60*60*1e3;export const ANONYMOUS_TIER_ENABLED=true;
|
package/lib/module/hooks.js
CHANGED
|
@@ -14,4 +14,4 @@
|
|
|
14
14
|
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
15
15
|
* including a free one (`npx buoy login`). Buy a key at
|
|
16
16
|
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
17
|
-
*/import{useState as l,useEffect as d,useCallback as c}from"react";import{LicenseManager as n}from"./LicenseManager.js";import{useWeekendFreePro as a,weekendPassAppliesTo as u}from"./weekendPro.js";export function useLicense(){const[i,e]=l(n.getState());d(()=>{const s=n.subscribe(o=>{e(n.getState())});n.initialize().then(()=>{e(n.getState())});return s},[]);const r=c(async s=>{const o=await n.setLicenseKey(s);e(n.getState());return o},[]);const t=c(async()=>{await n.clearLicense();e(n.getState())},[]);return{...i,setLicenseKey:r,clearLicense:t}}export function useTier(){const{tier:i,isInitialized:e}=useLicense();return e?i:"anonymous"}export function useFeatureAccess(i){const{isPro:e,isInitialized:r,isValidating:t}=useLicense();const s=e;const o=!r||t;return{hasAccess:s,isPro:e,isLoading:o}}export function useIsPro(){const{isPro:i,isInitialized:e,tier:r}=useLicense();const t=u(r,a());return e&&i||t}export function useProAccess(){const{isPro:i,isInitialized:e,tier:r}=useLicense();const t=e&&i;const s=u(r,a())&&!t;const o=t?"licensed":s?"weekend":null;return{isPro:t||s,isLicensed:t,isWeekendFree:s,reason:o}}
|
|
17
|
+
*/import{useState as l,useEffect as d,useCallback as c}from"react";import{LicenseManager as n}from"./LicenseManager.js";import{useWeekendFreePro as a,weekendPassAppliesTo as u}from"./weekendPro.js";export function useLicense(){const[i,e]=l(n.getState());d(()=>{const s=n.subscribe(o=>{e(n.getState())});n.initialize().then(()=>{e(n.getState())});return s},[]);const r=c(async s=>{const o=await n.setLicenseKey(s,{force:true});e(n.getState());return o},[]);const t=c(async()=>{await n.clearLicense();e(n.getState())},[]);return{...i,setLicenseKey:r,clearLicense:t}}export function useTier(){const{tier:i,isInitialized:e}=useLicense();return e?i:"anonymous"}export function useFeatureAccess(i){const{isPro:e,isInitialized:r,isValidating:t}=useLicense();const s=e;const o=!r||t;return{hasAccess:s,isPro:e,isLoading:o}}export function useIsPro(){const{isPro:i,isInitialized:e,tier:r}=useLicense();const t=u(r,a());return e&&i||t}export function useProAccess(){const{isPro:i,isInitialized:e,tier:r}=useLicense();const t=e&&i;const s=u(r,a())&&!t;const o=t?"licensed":s?"weekend":null;return{isPro:t||s,isLicensed:t,isWeekendFree:s,reason:o}}
|
|
@@ -27,6 +27,7 @@ declare class LicenseManagerImpl {
|
|
|
27
27
|
private listeners;
|
|
28
28
|
private revalidationTimer;
|
|
29
29
|
private cachedLicense;
|
|
30
|
+
private fingerprintPromise;
|
|
30
31
|
private initPromise;
|
|
31
32
|
/**
|
|
32
33
|
* Bumped whenever the license is deliberately changed or cleared.
|
|
@@ -58,7 +59,9 @@ declare class LicenseManagerImpl {
|
|
|
58
59
|
* No device registration or limits - we trust our customers.
|
|
59
60
|
* Keygen tracks validation calls for usage analytics.
|
|
60
61
|
*/
|
|
61
|
-
setLicenseKey(licenseKey: string
|
|
62
|
+
setLicenseKey(licenseKey: string, opts?: {
|
|
63
|
+
force?: boolean;
|
|
64
|
+
}): Promise<boolean>;
|
|
62
65
|
/**
|
|
63
66
|
* Check if an error is a network error (not an API validation error)
|
|
64
67
|
*/
|
|
@@ -108,6 +111,11 @@ declare class LicenseManagerImpl {
|
|
|
108
111
|
completeDeviceRegistration(deviceName: string): Promise<void>;
|
|
109
112
|
private emit;
|
|
110
113
|
private isCacheValid;
|
|
114
|
+
/**
|
|
115
|
+
* Whether the cache was validated against Keygen recently enough that a
|
|
116
|
+
* launch-time revalidation would add nothing (see LICENSE_LAUNCH_VALIDATION_TTL).
|
|
117
|
+
*/
|
|
118
|
+
private isCacheFresh;
|
|
111
119
|
/**
|
|
112
120
|
* Write the cache with a fresh checksum. Every write goes through here so a
|
|
113
121
|
* blob can never land on disk unsigned — an unsigned blob is treated as
|
|
@@ -115,6 +123,14 @@ declare class LicenseManagerImpl {
|
|
|
115
123
|
*/
|
|
116
124
|
private persistCache;
|
|
117
125
|
private loadCachedLicense;
|
|
126
|
+
/**
|
|
127
|
+
* The install's stable device fingerprint, created once and persisted under
|
|
128
|
+
* its own key. Older versions kept the fingerprint only inside the license
|
|
129
|
+
* blob, so anything that cleared the blob gave the device a new identity —
|
|
130
|
+
* this adopts a pre-existing blob fingerprint on first read so upgrading
|
|
131
|
+
* doesn't mint a second machine record for the same install.
|
|
132
|
+
*/
|
|
133
|
+
private getOrCreateDeviceFingerprint;
|
|
118
134
|
private clearCachedLicense;
|
|
119
135
|
/**
|
|
120
136
|
* Register device in background for visibility (non-blocking)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LicenseManager.d.ts","sourceRoot":"","sources":["../../../src/LicenseManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"LicenseManager.d.ts","sourceRoot":"","sources":["../../../src/LicenseManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA0QH,OAAO,KAAK,EACV,QAAQ,EAER,YAAY,EAEZ,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,kDAAkD;AAClD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,mDAAmD;AACnD,MAAM,MAAM,0BAA0B,GAAG,CAAC,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAC;AAsBhF,cAAM,kBAAkB;IACtB,OAAO,CAAC,KAAK,CASX;IAEF,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,kBAAkB,CAAgC;IAG1D,OAAO,CAAC,WAAW,CAA8B;IAEjD;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,UAAU,CAAK;IAGvB,OAAO,CAAC,0BAA0B,CAA2C;IAC7E,OAAO,CAAC,mBAAmB,CAAoC;IAE/D;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAUjC;;OAEG;YACW,aAAa;IAiD3B;;;;;;OAMG;IACG,aAAa,CACjB,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACzB,OAAO,CAAC,OAAO,CAAC;IAwKnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAkBtB;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAQjB;;OAEG;IACH,OAAO,IAAI,QAAQ;IAInB;;OAEG;IACH,KAAK,IAAI,OAAO;IAIhB;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAOrC;;OAEG;IACH,QAAQ,IAAI,QAAQ,CAAC,YAAY,CAAC;IAIlC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,IAAI;IAKhD;;;;;OAKG;IACH,0BAA0B,CAAC,QAAQ,EAAE,0BAA0B,GAAG,MAAM,IAAI;IAO5E;;;OAGG;IACG,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCnE,OAAO,CAAC,IAAI;IAYZ,OAAO,CAAC,YAAY;IAkBpB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;OAIG;YACW,YAAY;YAOZ,iBAAiB;IAc/B;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;YAetB,kBAAkB;IAWhC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,oBAAoB;IAmD5B,OAAO,CAAC,sBAAsB;IAmB9B;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAO7B;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CAevC;AAGD,eAAO,MAAM,cAAc,oBAA2B,CAAC"}
|
|
@@ -53,6 +53,8 @@ export declare const KEYGEN_POLICIES: {
|
|
|
53
53
|
export declare const LICENSE_CACHE_DURATION: number;
|
|
54
54
|
export declare const LICENSE_REVALIDATION_INTERVAL: number;
|
|
55
55
|
export declare const LICENSE_STORAGE_KEY = "buoy-gg-license";
|
|
56
|
+
export declare const DEVICE_FINGERPRINT_STORAGE_KEY = "buoy-gg-device-fingerprint";
|
|
57
|
+
export declare const LICENSE_LAUNCH_VALIDATION_TTL: number;
|
|
56
58
|
/**
|
|
57
59
|
* Master switch for the ANONYMOUS tier.
|
|
58
60
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;GAEG;AAEH,eAAO,MAAM,aAAa;;IAExB;;;;;;;;OAQG;;;;CAMK,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe;IAC1B,iEAAiE;;IAEjE,qEAAqE;;IAErE,oDAAoD;;CAE5C,CAAC;AAGX,eAAO,MAAM,sBAAsB,QAA2B,CAAC;AAI/D,eAAO,MAAM,6BAA6B,QAAsB,CAAC;AAIjE,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;GAEG;AAEH,eAAO,MAAM,aAAa;;IAExB;;;;;;;;OAQG;;;;CAMK,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe;IAC1B,iEAAiE;;IAEjE,qEAAqE;;IAErE,oDAAoD;;CAE5C,CAAC;AAGX,eAAO,MAAM,sBAAsB,QAA2B,CAAC;AAI/D,eAAO,MAAM,6BAA6B,QAAsB,CAAC;AAIjE,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAMrD,eAAO,MAAM,8BAA8B,+BAA+B,CAAC;AAM3E,eAAO,MAAM,6BAA6B,QAAiB,CAAC;AAE5D;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,sBAAsB,OAAO,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAYH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAgB,MAAM,SAAS,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,IAAI,YAAY,GAAG;IAC3C,qCAAqC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,gCAAgC;IAChC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAYH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAgB,MAAM,SAAS,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,IAAI,YAAY,GAAG;IAC3C,qCAAqC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,gCAAgC;IAChC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC,CAmCA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,IAAI,QAAQ,CAGlC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB,CAWA;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAKlC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI;IAC9B,sDAAsD;IACtD,KAAK,EAAE,OAAO,CAAC;IACf,+CAA+C;IAC/C,UAAU,EAAE,OAAO,CAAC;IACpB,2CAA2C;IAC3C,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,eAAe,CAAC;CACzB,CAaA"}
|
|
@@ -27,6 +27,7 @@ declare class LicenseManagerImpl {
|
|
|
27
27
|
private listeners;
|
|
28
28
|
private revalidationTimer;
|
|
29
29
|
private cachedLicense;
|
|
30
|
+
private fingerprintPromise;
|
|
30
31
|
private initPromise;
|
|
31
32
|
/**
|
|
32
33
|
* Bumped whenever the license is deliberately changed or cleared.
|
|
@@ -58,7 +59,9 @@ declare class LicenseManagerImpl {
|
|
|
58
59
|
* No device registration or limits - we trust our customers.
|
|
59
60
|
* Keygen tracks validation calls for usage analytics.
|
|
60
61
|
*/
|
|
61
|
-
setLicenseKey(licenseKey: string
|
|
62
|
+
setLicenseKey(licenseKey: string, opts?: {
|
|
63
|
+
force?: boolean;
|
|
64
|
+
}): Promise<boolean>;
|
|
62
65
|
/**
|
|
63
66
|
* Check if an error is a network error (not an API validation error)
|
|
64
67
|
*/
|
|
@@ -108,6 +111,11 @@ declare class LicenseManagerImpl {
|
|
|
108
111
|
completeDeviceRegistration(deviceName: string): Promise<void>;
|
|
109
112
|
private emit;
|
|
110
113
|
private isCacheValid;
|
|
114
|
+
/**
|
|
115
|
+
* Whether the cache was validated against Keygen recently enough that a
|
|
116
|
+
* launch-time revalidation would add nothing (see LICENSE_LAUNCH_VALIDATION_TTL).
|
|
117
|
+
*/
|
|
118
|
+
private isCacheFresh;
|
|
111
119
|
/**
|
|
112
120
|
* Write the cache with a fresh checksum. Every write goes through here so a
|
|
113
121
|
* blob can never land on disk unsigned — an unsigned blob is treated as
|
|
@@ -115,6 +123,14 @@ declare class LicenseManagerImpl {
|
|
|
115
123
|
*/
|
|
116
124
|
private persistCache;
|
|
117
125
|
private loadCachedLicense;
|
|
126
|
+
/**
|
|
127
|
+
* The install's stable device fingerprint, created once and persisted under
|
|
128
|
+
* its own key. Older versions kept the fingerprint only inside the license
|
|
129
|
+
* blob, so anything that cleared the blob gave the device a new identity —
|
|
130
|
+
* this adopts a pre-existing blob fingerprint on first read so upgrading
|
|
131
|
+
* doesn't mint a second machine record for the same install.
|
|
132
|
+
*/
|
|
133
|
+
private getOrCreateDeviceFingerprint;
|
|
118
134
|
private clearCachedLicense;
|
|
119
135
|
/**
|
|
120
136
|
* Register device in background for visibility (non-blocking)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"LicenseManager.d.ts","sourceRoot":"","sources":["../../../src/LicenseManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;
|
|
1
|
+
{"version":3,"file":"LicenseManager.d.ts","sourceRoot":"","sources":["../../../src/LicenseManager.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AA0QH,OAAO,KAAK,EACV,QAAQ,EAER,YAAY,EAEZ,eAAe,EAChB,MAAM,SAAS,CAAC;AAEjB,kDAAkD;AAClD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,mDAAmD;AACnD,MAAM,MAAM,0BAA0B,GAAG,CAAC,IAAI,EAAE,sBAAsB,KAAK,IAAI,CAAC;AAsBhF,cAAM,kBAAkB;IACtB,OAAO,CAAC,KAAK,CASX;IAEF,OAAO,CAAC,SAAS,CAAmC;IACpD,OAAO,CAAC,iBAAiB,CAA+C;IACxE,OAAO,CAAC,aAAa,CAA8B;IACnD,OAAO,CAAC,kBAAkB,CAAgC;IAG1D,OAAO,CAAC,WAAW,CAA8B;IAEjD;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,UAAU,CAAK;IAGvB,OAAO,CAAC,0BAA0B,CAA2C;IAC7E,OAAO,CAAC,mBAAmB,CAAoC;IAE/D;;OAEG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAUjC;;OAEG;YACW,aAAa;IAiD3B;;;;;;OAMG;IACG,aAAa,CACjB,UAAU,EAAE,MAAM,EAClB,IAAI,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,OAAO,CAAA;KAAE,GACzB,OAAO,CAAC,OAAO,CAAC;IAwKnB;;OAEG;IACH,OAAO,CAAC,cAAc;IAkBtB;;OAEG;IACG,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;IAanC;;;;;OAKG;IACH,OAAO,CAAC,SAAS;IAQjB;;OAEG;IACH,OAAO,IAAI,QAAQ;IAInB;;OAEG;IACH,KAAK,IAAI,OAAO;IAIhB;;OAEG;IACH,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAOrC;;OAEG;IACH,QAAQ,IAAI,QAAQ,CAAC,YAAY,CAAC;IAIlC;;OAEG;IACH,SAAS,CAAC,QAAQ,EAAE,eAAe,GAAG,MAAM,IAAI;IAKhD;;;;;OAKG;IACH,0BAA0B,CAAC,QAAQ,EAAE,0BAA0B,GAAG,MAAM,IAAI;IAO5E;;;OAGG;IACG,0BAA0B,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAoCnE,OAAO,CAAC,IAAI;IAYZ,OAAO,CAAC,YAAY;IAkBpB;;;OAGG;IACH,OAAO,CAAC,YAAY;IAIpB;;;;OAIG;YACW,YAAY;YAOZ,iBAAiB;IAc/B;;;;;;OAMG;IACH,OAAO,CAAC,4BAA4B;YAetB,kBAAkB;IAWhC;;;OAGG;IACH,OAAO,CAAC,mBAAmB;IAiB3B,OAAO,CAAC,oBAAoB;IAmD5B,OAAO,CAAC,sBAAsB;IAmB9B;;OAEG;IACH,qBAAqB,IAAI,IAAI;IAO7B;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CAevC;AAGD,eAAO,MAAM,cAAc,oBAA2B,CAAC"}
|
|
@@ -53,6 +53,8 @@ export declare const KEYGEN_POLICIES: {
|
|
|
53
53
|
export declare const LICENSE_CACHE_DURATION: number;
|
|
54
54
|
export declare const LICENSE_REVALIDATION_INTERVAL: number;
|
|
55
55
|
export declare const LICENSE_STORAGE_KEY = "buoy-gg-license";
|
|
56
|
+
export declare const DEVICE_FINGERPRINT_STORAGE_KEY = "buoy-gg-device-fingerprint";
|
|
57
|
+
export declare const LICENSE_LAUNCH_VALIDATION_TTL: number;
|
|
56
58
|
/**
|
|
57
59
|
* Master switch for the ANONYMOUS tier.
|
|
58
60
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;GAEG;AAEH,eAAO,MAAM,aAAa;;IAExB;;;;;;;;OAQG;;;;CAMK,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe;IAC1B,iEAAiE;;IAEjE,qEAAqE;;IAErE,oDAAoD;;CAE5C,CAAC;AAGX,eAAO,MAAM,sBAAsB,QAA2B,CAAC;AAI/D,eAAO,MAAM,6BAA6B,QAAsB,CAAC;AAIjE,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;GAEG;AAEH,eAAO,MAAM,aAAa;;IAExB;;;;;;;;OAQG;;;;CAMK,CAAC;AAEX;;;;;;;;GAQG;AACH,eAAO,MAAM,eAAe;IAC1B,iEAAiE;;IAEjE,qEAAqE;;IAErE,oDAAoD;;CAE5C,CAAC;AAGX,eAAO,MAAM,sBAAsB,QAA2B,CAAC;AAI/D,eAAO,MAAM,6BAA6B,QAAsB,CAAC;AAIjE,eAAO,MAAM,mBAAmB,oBAAoB,CAAC;AAMrD,eAAO,MAAM,8BAA8B,+BAA+B,CAAC;AAM3E,eAAO,MAAM,6BAA6B,QAAiB,CAAC;AAE5D;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,sBAAsB,OAAO,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAYH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAgB,MAAM,SAAS,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,IAAI,YAAY,GAAG;IAC3C,qCAAqC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,gCAAgC;IAChC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/hooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAYH,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAgB,MAAM,SAAS,CAAC;AAEpE;;;;;GAKG;AACH,MAAM,MAAM,eAAe,GAAG,UAAU,GAAG,SAAS,GAAG,IAAI,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,IAAI,YAAY,GAAG;IAC3C,qCAAqC;IACrC,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,gCAAgC;IAChC,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACnC,CAmCA;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,OAAO,IAAI,QAAQ,CAGlC;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG;IACtD,SAAS,EAAE,OAAO,CAAC;IACnB,KAAK,EAAE,OAAO,CAAC;IACf,SAAS,EAAE,OAAO,CAAC;CACpB,CAWA;AAED;;;;GAIG;AACH,wBAAgB,QAAQ,IAAI,OAAO,CAKlC;AAED;;;;GAIG;AACH,wBAAgB,YAAY,IAAI;IAC9B,sDAAsD;IACtD,KAAK,EAAE,OAAO,CAAC;IACf,+CAA+C;IAC/C,UAAU,EAAE,OAAO,CAAC;IACpB,2CAA2C;IAC3C,aAAa,EAAE,OAAO,CAAC;IACvB,MAAM,EAAE,eAAe,CAAC;CACzB,CAaA"}
|