@buoy-gg/license 7.0.77 → 7.0.79
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 +2 -2
- package/lib/commonjs/accountKeyNames.js +1 -0
- package/lib/commonjs/config.js +2 -2
- package/lib/commonjs/device-info.js +1 -1
- package/lib/commonjs/device-info.web.js +1 -1
- package/lib/commonjs/fingerprint.js +1 -1
- package/lib/commonjs/fingerprint.web.js +1 -1
- package/lib/commonjs/fingerprintOwner.js +1 -0
- package/lib/commonjs/headless.js +1 -1
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/index.web.js +2 -2
- package/lib/module/LicenseManager.js +1 -1
- package/lib/module/accountKeyNames.js +1 -0
- package/lib/module/config.js +1 -1
- package/lib/module/device-info.js +1 -1
- package/lib/module/device-info.web.js +1 -1
- package/lib/module/fingerprint.js +1 -1
- package/lib/module/fingerprint.web.js +1 -1
- package/lib/module/fingerprintOwner.js +1 -0
- package/lib/module/headless.js +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/index.web.js +1 -1
- package/lib/typescript/commonjs/LicenseManager.d.ts +7 -0
- package/lib/typescript/commonjs/accountKeyNames.d.ts +19 -0
- package/lib/typescript/commonjs/config.d.ts +1 -0
- package/lib/typescript/commonjs/device-info.d.ts +10 -0
- package/lib/typescript/commonjs/device-info.web.d.ts +2 -0
- package/lib/typescript/commonjs/fingerprint.d.ts +1 -1
- package/lib/typescript/commonjs/fingerprint.web.d.ts +1 -1
- package/lib/typescript/commonjs/fingerprintOwner.d.ts +37 -0
- package/lib/typescript/commonjs/headless.d.ts +1 -0
- package/lib/typescript/commonjs/index.d.ts +1 -0
- package/lib/typescript/commonjs/index.web.d.ts +1 -0
- package/lib/typescript/module/LicenseManager.d.ts +7 -0
- package/lib/typescript/module/accountKeyNames.d.ts +19 -0
- package/lib/typescript/module/config.d.ts +1 -0
- package/lib/typescript/module/device-info.d.ts +10 -0
- package/lib/typescript/module/device-info.web.d.ts +2 -0
- package/lib/typescript/module/fingerprint.d.ts +1 -1
- package/lib/typescript/module/fingerprint.web.d.ts +1 -1
- package/lib/typescript/module/fingerprintOwner.d.ts +37 -0
- package/lib/typescript/module/headless.d.ts +1 -0
- package/lib/typescript/module/index.d.ts +1 -0
- package/lib/typescript/module/index.web.d.ts +1 -0
- package/lib/web/chunks/LicenseManager-CJHAU3GD.mjs +1 -0
- package/lib/web/chunks/chunk-7T66ARUE.mjs +73 -0
- package/lib/web/index.mjs +1 -1
- package/package.json +1 -1
- package/lib/web/chunks/LicenseManager-LOBHCMIJ.mjs +0 -1
- package/lib/web/chunks/chunk-3RVGU64S.mjs +0 -73
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The env names a Buoy account key lives under. `buoy login` writes one of
|
|
3
|
+
* these, so an app's env holds its own Buoy key. That key must never leave
|
|
4
|
+
* the app through Buoy's own tools (the Env tool's sync snapshot, the device
|
|
5
|
+
* handshake, the MCP). Every place that hides it reads this one list.
|
|
6
|
+
*
|
|
7
|
+
* The Swift, Kotlin, Flutter and MAUI ports keep a copy of the same names.
|
|
8
|
+
*/
|
|
9
|
+
export declare const BUOY_ACCOUNT_KEY_NAMES: readonly string[];
|
|
10
|
+
/** Whether an env or metadata name holds a Buoy account key. */
|
|
11
|
+
export declare function isBuoyAccountKeyName(name: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* What a Buoy key shows as once hidden: that it is set, never the key. An
|
|
14
|
+
* empty value stays empty, so "not set" still reads as not set.
|
|
15
|
+
*/
|
|
16
|
+
export declare function maskBuoyAccountKey(value: string): string;
|
|
17
|
+
/** A copy of `values` with every Buoy key value masked. Other keys stay as they are. */
|
|
18
|
+
export declare function maskBuoyAccountKeys<T extends Record<string, unknown>>(values: T): T;
|
|
19
|
+
//# sourceMappingURL=accountKeyNames.d.ts.map
|
|
@@ -75,6 +75,7 @@ export declare const LICENSE_CACHE_DURATION: number;
|
|
|
75
75
|
export declare const LICENSE_REVALIDATION_INTERVAL: number;
|
|
76
76
|
export declare const LICENSE_STORAGE_KEY = "buoy-gg-license";
|
|
77
77
|
export declare const DEVICE_FINGERPRINT_STORAGE_KEY = "buoy-gg-device-fingerprint";
|
|
78
|
+
export declare const DEVICE_FINGERPRINT_OWNER_STORAGE_KEY = "buoy-gg-device-fingerprint-owner";
|
|
78
79
|
export declare const LICENSE_LAUNCH_VALIDATION_TTL: number;
|
|
79
80
|
/**
|
|
80
81
|
* Backoff for retrying a validation that failed in transit (quota, 5xx, proxy).
|
|
@@ -36,4 +36,14 @@ export declare function getDeviceMetadata(): Record<string, string>;
|
|
|
36
36
|
* Get a default device name suggestion based on platform
|
|
37
37
|
*/
|
|
38
38
|
export declare function getDefaultDeviceName(): string;
|
|
39
|
+
/**
|
|
40
|
+
* A per-device id that backups never carry to another phone, or null.
|
|
41
|
+
*
|
|
42
|
+
* Android: ANDROID_ID from RN's own PlatformConstants (no extra package).
|
|
43
|
+
* It stays the same across app updates and differs on every other phone.
|
|
44
|
+
* iOS: identifierForVendor through expo-application, when the app has it.
|
|
45
|
+
* Not in an Expo app, or before first unlock, this is null and the caller
|
|
46
|
+
* keeps the saved fingerprint, which is the safe answer.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getDeviceOwnerId(): Promise<string | null>;
|
|
39
49
|
//# sourceMappingURL=device-info.d.ts.map
|
|
@@ -28,4 +28,6 @@ export declare function getDeviceMetadata(): Record<string, string>;
|
|
|
28
28
|
* Get a default device name suggestion based on platform
|
|
29
29
|
*/
|
|
30
30
|
export declare function getDefaultDeviceName(): string;
|
|
31
|
+
/** Browsers have no backup that copies storage to another device. */
|
|
32
|
+
export declare function getDeviceOwnerId(): Promise<string | null>;
|
|
31
33
|
//# sourceMappingURL=device-info.web.d.ts.map
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* The fingerprint is a generated UUID that is stored alongside the license.
|
|
5
5
|
* It's created when the user registers their device and persists with the license data.
|
|
6
6
|
*/
|
|
7
|
-
export { generateUUID, isDevBundle, isSimulator, getDeviceMetadata, getDefaultDeviceName, } from "./device-info";
|
|
7
|
+
export { generateUUID, isDevBundle, isSimulator, getDeviceMetadata, getDefaultDeviceName, getDeviceOwnerId, } from "./device-info";
|
|
8
8
|
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* The fingerprint is a generated UUID that is stored alongside the license.
|
|
5
5
|
* It's created when the user registers their device and persists with the license data.
|
|
6
6
|
*/
|
|
7
|
-
export { generateUUID, isDevBundle, isSimulator, getDeviceMetadata, getDefaultDeviceName, } from "./device-info.web";
|
|
7
|
+
export { generateUUID, isDevBundle, isSimulator, getDeviceMetadata, getDefaultDeviceName, getDeviceOwnerId, } from "./device-info.web";
|
|
8
8
|
//# sourceMappingURL=fingerprint.web.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telling a restored phone from a normal relaunch.
|
|
3
|
+
*
|
|
4
|
+
* The fingerprint file lives in the app's documents folder (or AsyncStorage),
|
|
5
|
+
* which iOS backups and Android Auto Backup copy to a NEW phone. A copied
|
|
6
|
+
* fingerprint makes two phones one Keygen machine. Next to it we keep an
|
|
7
|
+
* "owner" marker: a hash of a per-device id that backups never carry
|
|
8
|
+
* (Android's ANDROID_ID, iOS's identifierForVendor). A saved marker that no
|
|
9
|
+
* longer matches this device means the files came from another phone.
|
|
10
|
+
*
|
|
11
|
+
* Missing markers always mean "keep": an install from before markers existed,
|
|
12
|
+
* or a device that cannot report an id, must never get a new fingerprint on a
|
|
13
|
+
* plain update. Same rule as the Android port's `loadInstallId`.
|
|
14
|
+
*/
|
|
15
|
+
export interface FingerprintResolution {
|
|
16
|
+
fingerprint: string;
|
|
17
|
+
/** The owner marker to persist (null: nothing to write). */
|
|
18
|
+
owner: string | null;
|
|
19
|
+
/** The saved files came from another device; a new fingerprint was minted. */
|
|
20
|
+
restored: boolean;
|
|
21
|
+
/** Whether the fingerprint or owner must be written back. */
|
|
22
|
+
changed: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare function resolveDeviceFingerprint(input: {
|
|
25
|
+
/** The saved device fingerprint, if any. */
|
|
26
|
+
stored: string | null;
|
|
27
|
+
/** The saved owner marker, if any. */
|
|
28
|
+
storedOwner: string | null;
|
|
29
|
+
/** This device's marker now, or null when the device can't tell. */
|
|
30
|
+
marker: string | null;
|
|
31
|
+
/** An older build kept the fingerprint only inside the license blob. */
|
|
32
|
+
blobFingerprint?: string | null;
|
|
33
|
+
mint: () => string;
|
|
34
|
+
}): FingerprintResolution;
|
|
35
|
+
/** Short, stable hash so the raw device id is never written to disk. */
|
|
36
|
+
export declare function hashDeviceMarker(id: string): string;
|
|
37
|
+
//# sourceMappingURL=fingerprintOwner.d.ts.map
|
|
@@ -15,5 +15,6 @@ export { verifySessionToken, mintSessionToken } from "./sessionToken";
|
|
|
15
15
|
export type { SessionClaims } from "./sessionToken";
|
|
16
16
|
export { exchangeServiceKey, isServiceKey, normalizeLicenseKey, sameLicenseKey, SERVICE_KEY_PREFIX, SERVICE_AUDIENCE } from "./serviceKey";
|
|
17
17
|
export type { ServiceTokenResult } from "./serviceKey";
|
|
18
|
+
export { BUOY_ACCOUNT_KEY_NAMES, isBuoyAccountKeyName, maskBuoyAccountKey, maskBuoyAccountKeys } from "./accountKeyNames";
|
|
18
19
|
export { checkDevToken, isDevToken, DEV_AUDIENCE } from "./devToken";
|
|
19
20
|
//# sourceMappingURL=headless.d.ts.map
|
|
@@ -38,6 +38,7 @@ export type { SessionStatus, SessionErrorCode, SessionConfig, CodePrompt } from
|
|
|
38
38
|
export type { SessionClaims, SessionTier } from "./sessionToken";
|
|
39
39
|
export { useBuoySession } from "./hooks";
|
|
40
40
|
export { isServiceKey, normalizeLicenseKey, sameLicenseKey } from "./serviceKey";
|
|
41
|
+
export { BUOY_ACCOUNT_KEY_NAMES, isBuoyAccountKeyName, maskBuoyAccountKey, maskBuoyAccountKeys } from "./accountKeyNames";
|
|
41
42
|
export { isCapacitorNative, capacitorPlatform, capacitorDebug, resolveDevBuild } from "./capacitorHost";
|
|
42
43
|
export { installCapacitorBridge, isCapacitorBridgeInstalled, interceptCapacitor, emitCapacitorEvent, capacitorListenerCount, hasCapacitorPlugin, capacitorPlugin, callCapacitorNative, callCapacitorAsApp, callCapacitorNativeCallback, listenCapacitorNative, makeCapacitorCallbackId, getCapacitorCalls, clearCapacitorCalls, subscribeCapacitorCalls, loadCapacitorAppHost, getCapacitorAppHost, colorSchemeQueryValue, getColorSchemeQueries, } from "./capacitorBridge";
|
|
43
44
|
export type { CapacitorCall, CapacitorCallback, CapacitorInterceptor, CapacitorCallRecord, CapacitorAppHost } from "./capacitorBridge";
|
|
@@ -27,6 +27,7 @@ export type { SessionStatus, SessionErrorCode, SessionConfig, CodePrompt } from
|
|
|
27
27
|
export type { SessionClaims, SessionTier } from "./sessionToken";
|
|
28
28
|
export { useBuoySession } from "./hooks";
|
|
29
29
|
export { isServiceKey, normalizeLicenseKey, sameLicenseKey } from "./serviceKey";
|
|
30
|
+
export { BUOY_ACCOUNT_KEY_NAMES, isBuoyAccountKeyName, maskBuoyAccountKey, maskBuoyAccountKeys } from "./accountKeyNames";
|
|
30
31
|
export { isCapacitorNative, capacitorPlatform, capacitorDebug, resolveDevBuild } from "./capacitorHost";
|
|
31
32
|
export { installCapacitorBridge, isCapacitorBridgeInstalled, interceptCapacitor, emitCapacitorEvent, capacitorListenerCount, hasCapacitorPlugin, capacitorPlugin, callCapacitorNative, callCapacitorAsApp, callCapacitorNativeCallback, listenCapacitorNative, makeCapacitorCallbackId, getCapacitorCalls, clearCapacitorCalls, subscribeCapacitorCalls, loadCapacitorAppHost, getCapacitorAppHost, colorSchemeQueryValue, getColorSchemeQueries, } from "./capacitorBridge";
|
|
32
33
|
export type { CapacitorCall, CapacitorCallback, CapacitorInterceptor, CapacitorCallRecord, CapacitorAppHost } from "./capacitorBridge";
|
|
@@ -28,6 +28,8 @@ declare class LicenseManagerImpl {
|
|
|
28
28
|
private revalidationTimer;
|
|
29
29
|
private cachedLicense;
|
|
30
30
|
private fingerprintPromise;
|
|
31
|
+
/** This install's files were restored from another device (fingerprintOwner.ts). */
|
|
32
|
+
private fingerprintRestored;
|
|
31
33
|
private initPromise;
|
|
32
34
|
/**
|
|
33
35
|
* Bumped whenever the license is deliberately changed or cleared.
|
|
@@ -239,6 +241,11 @@ declare class LicenseManagerImpl {
|
|
|
239
241
|
* blob, so anything that cleared the blob gave the device a new identity —
|
|
240
242
|
* this adopts a pre-existing blob fingerprint on first read so upgrading
|
|
241
243
|
* doesn't mint a second machine record for the same install.
|
|
244
|
+
*
|
|
245
|
+
* An owner marker saved beside it says which device it belongs to. When the
|
|
246
|
+
* files were restored from ANOTHER phone's backup the marker won't match,
|
|
247
|
+
* and this device gets a new fingerprint of its own. A missing marker (an
|
|
248
|
+
* older build, or no device id) keeps the saved one.
|
|
242
249
|
*/
|
|
243
250
|
private getOrCreateDeviceFingerprint;
|
|
244
251
|
private clearCachedLicense;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The env names a Buoy account key lives under. `buoy login` writes one of
|
|
3
|
+
* these, so an app's env holds its own Buoy key. That key must never leave
|
|
4
|
+
* the app through Buoy's own tools (the Env tool's sync snapshot, the device
|
|
5
|
+
* handshake, the MCP). Every place that hides it reads this one list.
|
|
6
|
+
*
|
|
7
|
+
* The Swift, Kotlin, Flutter and MAUI ports keep a copy of the same names.
|
|
8
|
+
*/
|
|
9
|
+
export declare const BUOY_ACCOUNT_KEY_NAMES: readonly string[];
|
|
10
|
+
/** Whether an env or metadata name holds a Buoy account key. */
|
|
11
|
+
export declare function isBuoyAccountKeyName(name: string): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* What a Buoy key shows as once hidden: that it is set, never the key. An
|
|
14
|
+
* empty value stays empty, so "not set" still reads as not set.
|
|
15
|
+
*/
|
|
16
|
+
export declare function maskBuoyAccountKey(value: string): string;
|
|
17
|
+
/** A copy of `values` with every Buoy key value masked. Other keys stay as they are. */
|
|
18
|
+
export declare function maskBuoyAccountKeys<T extends Record<string, unknown>>(values: T): T;
|
|
19
|
+
//# sourceMappingURL=accountKeyNames.d.ts.map
|
|
@@ -75,6 +75,7 @@ export declare const LICENSE_CACHE_DURATION: number;
|
|
|
75
75
|
export declare const LICENSE_REVALIDATION_INTERVAL: number;
|
|
76
76
|
export declare const LICENSE_STORAGE_KEY = "buoy-gg-license";
|
|
77
77
|
export declare const DEVICE_FINGERPRINT_STORAGE_KEY = "buoy-gg-device-fingerprint";
|
|
78
|
+
export declare const DEVICE_FINGERPRINT_OWNER_STORAGE_KEY = "buoy-gg-device-fingerprint-owner";
|
|
78
79
|
export declare const LICENSE_LAUNCH_VALIDATION_TTL: number;
|
|
79
80
|
/**
|
|
80
81
|
* Backoff for retrying a validation that failed in transit (quota, 5xx, proxy).
|
|
@@ -36,4 +36,14 @@ export declare function getDeviceMetadata(): Record<string, string>;
|
|
|
36
36
|
* Get a default device name suggestion based on platform
|
|
37
37
|
*/
|
|
38
38
|
export declare function getDefaultDeviceName(): string;
|
|
39
|
+
/**
|
|
40
|
+
* A per-device id that backups never carry to another phone, or null.
|
|
41
|
+
*
|
|
42
|
+
* Android: ANDROID_ID from RN's own PlatformConstants (no extra package).
|
|
43
|
+
* It stays the same across app updates and differs on every other phone.
|
|
44
|
+
* iOS: identifierForVendor through expo-application, when the app has it.
|
|
45
|
+
* Not in an Expo app, or before first unlock, this is null and the caller
|
|
46
|
+
* keeps the saved fingerprint, which is the safe answer.
|
|
47
|
+
*/
|
|
48
|
+
export declare function getDeviceOwnerId(): Promise<string | null>;
|
|
39
49
|
//# sourceMappingURL=device-info.d.ts.map
|
|
@@ -28,4 +28,6 @@ export declare function getDeviceMetadata(): Record<string, string>;
|
|
|
28
28
|
* Get a default device name suggestion based on platform
|
|
29
29
|
*/
|
|
30
30
|
export declare function getDefaultDeviceName(): string;
|
|
31
|
+
/** Browsers have no backup that copies storage to another device. */
|
|
32
|
+
export declare function getDeviceOwnerId(): Promise<string | null>;
|
|
31
33
|
//# sourceMappingURL=device-info.web.d.ts.map
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* The fingerprint is a generated UUID that is stored alongside the license.
|
|
5
5
|
* It's created when the user registers their device and persists with the license data.
|
|
6
6
|
*/
|
|
7
|
-
export { generateUUID, isDevBundle, isSimulator, getDeviceMetadata, getDefaultDeviceName, } from "./device-info";
|
|
7
|
+
export { generateUUID, isDevBundle, isSimulator, getDeviceMetadata, getDefaultDeviceName, getDeviceOwnerId, } from "./device-info";
|
|
8
8
|
//# sourceMappingURL=fingerprint.d.ts.map
|
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
* The fingerprint is a generated UUID that is stored alongside the license.
|
|
5
5
|
* It's created when the user registers their device and persists with the license data.
|
|
6
6
|
*/
|
|
7
|
-
export { generateUUID, isDevBundle, isSimulator, getDeviceMetadata, getDefaultDeviceName, } from "./device-info.web";
|
|
7
|
+
export { generateUUID, isDevBundle, isSimulator, getDeviceMetadata, getDefaultDeviceName, getDeviceOwnerId, } from "./device-info.web";
|
|
8
8
|
//# sourceMappingURL=fingerprint.web.d.ts.map
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Telling a restored phone from a normal relaunch.
|
|
3
|
+
*
|
|
4
|
+
* The fingerprint file lives in the app's documents folder (or AsyncStorage),
|
|
5
|
+
* which iOS backups and Android Auto Backup copy to a NEW phone. A copied
|
|
6
|
+
* fingerprint makes two phones one Keygen machine. Next to it we keep an
|
|
7
|
+
* "owner" marker: a hash of a per-device id that backups never carry
|
|
8
|
+
* (Android's ANDROID_ID, iOS's identifierForVendor). A saved marker that no
|
|
9
|
+
* longer matches this device means the files came from another phone.
|
|
10
|
+
*
|
|
11
|
+
* Missing markers always mean "keep": an install from before markers existed,
|
|
12
|
+
* or a device that cannot report an id, must never get a new fingerprint on a
|
|
13
|
+
* plain update. Same rule as the Android port's `loadInstallId`.
|
|
14
|
+
*/
|
|
15
|
+
export interface FingerprintResolution {
|
|
16
|
+
fingerprint: string;
|
|
17
|
+
/** The owner marker to persist (null: nothing to write). */
|
|
18
|
+
owner: string | null;
|
|
19
|
+
/** The saved files came from another device; a new fingerprint was minted. */
|
|
20
|
+
restored: boolean;
|
|
21
|
+
/** Whether the fingerprint or owner must be written back. */
|
|
22
|
+
changed: boolean;
|
|
23
|
+
}
|
|
24
|
+
export declare function resolveDeviceFingerprint(input: {
|
|
25
|
+
/** The saved device fingerprint, if any. */
|
|
26
|
+
stored: string | null;
|
|
27
|
+
/** The saved owner marker, if any. */
|
|
28
|
+
storedOwner: string | null;
|
|
29
|
+
/** This device's marker now, or null when the device can't tell. */
|
|
30
|
+
marker: string | null;
|
|
31
|
+
/** An older build kept the fingerprint only inside the license blob. */
|
|
32
|
+
blobFingerprint?: string | null;
|
|
33
|
+
mint: () => string;
|
|
34
|
+
}): FingerprintResolution;
|
|
35
|
+
/** Short, stable hash so the raw device id is never written to disk. */
|
|
36
|
+
export declare function hashDeviceMarker(id: string): string;
|
|
37
|
+
//# sourceMappingURL=fingerprintOwner.d.ts.map
|
|
@@ -15,5 +15,6 @@ export { verifySessionToken, mintSessionToken } from "./sessionToken";
|
|
|
15
15
|
export type { SessionClaims } from "./sessionToken";
|
|
16
16
|
export { exchangeServiceKey, isServiceKey, normalizeLicenseKey, sameLicenseKey, SERVICE_KEY_PREFIX, SERVICE_AUDIENCE } from "./serviceKey";
|
|
17
17
|
export type { ServiceTokenResult } from "./serviceKey";
|
|
18
|
+
export { BUOY_ACCOUNT_KEY_NAMES, isBuoyAccountKeyName, maskBuoyAccountKey, maskBuoyAccountKeys } from "./accountKeyNames";
|
|
18
19
|
export { checkDevToken, isDevToken, DEV_AUDIENCE } from "./devToken";
|
|
19
20
|
//# sourceMappingURL=headless.d.ts.map
|
|
@@ -38,6 +38,7 @@ export type { SessionStatus, SessionErrorCode, SessionConfig, CodePrompt } from
|
|
|
38
38
|
export type { SessionClaims, SessionTier } from "./sessionToken";
|
|
39
39
|
export { useBuoySession } from "./hooks";
|
|
40
40
|
export { isServiceKey, normalizeLicenseKey, sameLicenseKey } from "./serviceKey";
|
|
41
|
+
export { BUOY_ACCOUNT_KEY_NAMES, isBuoyAccountKeyName, maskBuoyAccountKey, maskBuoyAccountKeys } from "./accountKeyNames";
|
|
41
42
|
export { isCapacitorNative, capacitorPlatform, capacitorDebug, resolveDevBuild } from "./capacitorHost";
|
|
42
43
|
export { installCapacitorBridge, isCapacitorBridgeInstalled, interceptCapacitor, emitCapacitorEvent, capacitorListenerCount, hasCapacitorPlugin, capacitorPlugin, callCapacitorNative, callCapacitorAsApp, callCapacitorNativeCallback, listenCapacitorNative, makeCapacitorCallbackId, getCapacitorCalls, clearCapacitorCalls, subscribeCapacitorCalls, loadCapacitorAppHost, getCapacitorAppHost, colorSchemeQueryValue, getColorSchemeQueries, } from "./capacitorBridge";
|
|
43
44
|
export type { CapacitorCall, CapacitorCallback, CapacitorInterceptor, CapacitorCallRecord, CapacitorAppHost } from "./capacitorBridge";
|
|
@@ -27,6 +27,7 @@ export type { SessionStatus, SessionErrorCode, SessionConfig, CodePrompt } from
|
|
|
27
27
|
export type { SessionClaims, SessionTier } from "./sessionToken";
|
|
28
28
|
export { useBuoySession } from "./hooks";
|
|
29
29
|
export { isServiceKey, normalizeLicenseKey, sameLicenseKey } from "./serviceKey";
|
|
30
|
+
export { BUOY_ACCOUNT_KEY_NAMES, isBuoyAccountKeyName, maskBuoyAccountKey, maskBuoyAccountKeys } from "./accountKeyNames";
|
|
30
31
|
export { isCapacitorNative, capacitorPlatform, capacitorDebug, resolveDevBuild } from "./capacitorHost";
|
|
31
32
|
export { installCapacitorBridge, isCapacitorBridgeInstalled, interceptCapacitor, emitCapacitorEvent, capacitorListenerCount, hasCapacitorPlugin, capacitorPlugin, callCapacitorNative, callCapacitorAsApp, callCapacitorNativeCallback, listenCapacitorNative, makeCapacitorCallbackId, getCapacitorCalls, clearCapacitorCalls, subscribeCapacitorCalls, loadCapacitorAppHost, getCapacitorAppHost, colorSchemeQueryValue, getColorSchemeQueries, } from "./capacitorBridge";
|
|
32
33
|
export type { CapacitorCall, CapacitorCallback, CapacitorInterceptor, CapacitorCallRecord, CapacitorAppHost } from "./capacitorBridge";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use client";import{m as e}from"./chunk-7T66ARUE.mjs";import"./chunk-J7MW3NXU.mjs";export{e as LicenseManager};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use client";import{a as p,d as be}from"./chunk-J7MW3NXU.mjs";var L=new Map,xe={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 w(){return xe}var Le="3b546fc717a62683f3236c70167899a271bee3ffc04df6ec1eea60a394a2f1e9";var Ie="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,Re=1440*60*1e3,M="buoy-gg-license",V="buoy-gg-device-fingerprint",q="buoy-gg-device-fingerprint-owner",Ne=3600*1e3,Ce=[5*1e3,20*1e3,60*1e3,300*1e3,900*1e3],Se=60*1e3,Z=3600*1e3,Pe=1440*60*1e3,Ke=50,Oe=N,D="buoy-gg-license-hold";function h(){let e=globalThis.__buoyRealNow;return typeof e=="function"?e():Date.now()}var{apiUrl:Q}=I,A=class extends Error{constructor(e,t,i=null){super(e);this.isTransient=true;this.name="LicenseTransportError",this.status=t,this.retryAfterMs=i}};function Me(e){let t=e?.status;return t===429||t===402}function Ve(e,t,i){return e.status===402?t:e.retryAfterMs??i}function De(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 ee(e){return e instanceof A||e instanceof TypeError?true:typeof e=="object"&&e!==null&&e.isTransient===true}async function Ue(e){try{return(await e.json()).errors?.[0]?.detail||`HTTP ${e.status}`}catch{return`HTTP ${e.status}`}}function te(){return{"Content-Type":"application/vnd.api+json",Accept:"application/vnd.api+json"}}async function Fe(e,t){let i=`${Q}/validate`,r={meta:{key:e}},s;try{s=await fetch(i,{signal:t,method:"POST",headers:te(),body:JSON.stringify(r)})}catch(n){throw new A(n instanceof Error?n.message:"Network request failed",null)}if(!s.ok)throw new A(await Ue(s),s.status,s.status===429?De(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 A("License server returned an unreadable response",s.status)}}async function $e(e){let t=typeof AbortController=="function"?new AbortController:null,i;try{return await Promise.race([Fe(e,t?.signal),new Promise((r,s)=>{i=setTimeout(()=>{s(new A("License verification timed out. Please retry.",null)),t?.abort()},15e3)})])}finally{i&&clearTimeout(i)}}function je(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 Be(e){let t=e.data?.relationships?.machines?.meta?.count;return typeof t=="number"&&Number.isFinite(t)?t:0}async function ie(e,t,i,r,s){let n=`${Q}/machines`,c=await fetch(n,{method:"POST",headers:te(),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 He(e){let{meta:t,data:i}=e;return{valid:t.valid,code:t.code,detail:t.detail,metadata:i?.attributes?.metadata}}function ze(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=be();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 re(){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 Ge(){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 se(){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 ne(){let e={platform:re(),osVersion:Ge(),isSimulator:"false"},t=se();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=re(),t=se();if(e.startsWith("electron")){let i=e.replace("electron-","").replace("electron","Desktop");return`${i.charAt(0).toUpperCase()+i.slice(1)} App`}return t.name!=="unknown"?`${t.name} Browser`:"Web Browser"}async function Je(){return null}function Ye(e){let{stored:t,storedOwner:i,marker:r,blobFingerprint:s,mint:n}=e;if(!!r&&!!i&&i!==r)return{fingerprint:n(),owner:r,restored:true,changed:true};let c=r??i;return t?{fingerprint:t,owner:c,restored:false,changed:c!==i}:{fingerprint:s||n(),owner:c,restored:false,changed:true}}function Xe(e){let t=2166136261,i=16777619;for(let r=0;r<e.length;r++){let s=e.charCodeAt(r);t=Math.imul(t^s,16777619)>>>0,i=Math.imul(i^s,1540483477)>>>0}return`v1:${t.toString(16).padStart(8,"0")}${i.toString(16).padStart(8,"0")}`}var We=["v1"],qe="buoy.gg/pro:9f3c1d7a4b2e:license-cache";function ae(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 Ze(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(qe),i.join("\0")}function oe(e,t){let i=Ze(e,t),r=ae(i,2166136261),s=ae(i,2135587861);return`${t}.${r.toString(16)}${s.toString(16)}`}function le(e){return oe(e,"v2")}function ce(e){return{...e,sig:le(e)}}function _(e){return!e||typeof e.sig!="string"||e.sig.length===0?false:e.sig===le(e)?true:We.some(t=>e.sig.startsWith(`${t}.`)&&e.sig===oe(e,t))}import Qe from"tweetnacl";var et=1,tt=1,it="buoy-free-token-v1:",rt=22,st=64,he=/^BUOY1-([A-Z2-7]+)-([A-Z2-7]+)$/;function ue(e){return he.test(e.trim().toUpperCase())}var nt="ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";function de(e){let t=[],i=0,r=0;for(let s of e){let n=nt.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 at(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 ot(e){let t="";for(let i of e)t+=i.toString(16).padStart(2,"0");return t}function lt(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 ct(e,t){let i=new Uint8Array(e.length+t.length);return i.set(e,0),i.set(t,e.length),i}function ht(e){return ct(lt(it),e)}var ut=Le;function dt(e){let t=he.exec(e.trim().toUpperCase());if(!t)return null;let i=de(t[1]),r=de(t[2]);if(!i||!r||i.length!==rt||r.length!==st||i[0]!==et||i[1]!==tt)return null;try{if(!Qe.sign.detached.verify(ht(i),r,at(ut)))return null}catch{return null}return{tier:"free",issuedAt:((i[2]<<24>>>0)+(i[3]<<16)+(i[4]<<8)+i[5])*1e3,accountHash:ot(i.slice(6,22))}}function ft(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 pt(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 fe(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 gt(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 mt from"tweetnacl";var pe="buoys1",yt="buoy-session-v1:",ge=1,j=60,wt=64,vt=["free","pro","business"],m="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+=m[s>>>18&63]+m[s>>>12&63]+m[s>>>6&63]+m[s&63]}let r=e.length-i;if(r===1){let s=e[i]<<16;t+=m[s>>>18&63]+m[s>>>12&63]}else if(r===2){let s=e[i]<<16|e[i+1]<<8;t+=m[s>>>18&63]+m[s>>>12&63]+m[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|m.indexOf(s),i+=6,i>=8&&(t.push(r>>>i-8&255),i-=8);return new Uint8Array(t)}function Tt(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 At(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 _t(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 kt(e){return Tt(yt+e)}function k(e,t=256){return typeof e=="string"&&e.length>0&&e.length<=t}function ye(e){return typeof e=="number"&&Number.isInteger(e)&&e>0}function Et(e){if(!e||typeof e!="object"||Array.isArray(e))return null;let t=e;return!k(t.sid)||!k(t.sub)||!k(t.aud,512)||t.team!==null&&!k(t.team)||!vt.includes(t.tier)||t.role!==void 0&&!k(t.role,64)||t.tools!==void 0&&(!Array.isArray(t.tools)||t.tools.length>256||!t.tools.every(i=>k(i,64)))||!ye(t.iat)||!ye(t.exp)||t.exp<=t.iat?null:{v:ge,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 bt=Ie;function we(e){return e.startsWith(`${pe}.`)}function H(e,t){let i=bt;if(!i)return{ok:false,reason:"no-key"};let r=typeof e=="string"?e.split("."):[];if(r.length!==3||r[0]!==pe)return{ok:false,reason:"malformed"};let[,s,n]=r,c=me(s),o=me(n);if(!c||!o||o.length!==wt)return{ok:false,reason:"malformed"};try{if(!mt.sign.detached.verify(kt(s),o,_t(i)))return{ok:false,reason:"signature"}}catch{return{ok:false,reason:"signature"}}let a=At(c),l;try{l=a===null?null:JSON.parse(a)}catch{return{ok:false,reason:"malformed"}}if(!l||typeof l!="object"||l.v!==ge)return{ok:false,reason:l&&typeof l=="object"?"version":"malformed"};let u=Et(l);if(!u)return{ok:false,reason:"claims"};if(u.aud!==t.audience)return{ok:false,reason:"audience"};if(t.ignoreTime)return{ok:true,claims:u};let f=Math.floor((t.nowMs??h())/1e3);return f>=u.exp+j?{ok:false,reason:"expired"}:u.iat>f+j?{ok:false,reason:"not-yet-valid"}:{ok:true,claims:u}}var xt="@buoy/session:",C=10080*60*1e3,ve=360*60*1e3,Lt=300*1e3,It=15e3,Rt="https://buoy.gg",Nt="buoy:signin",Ct=600*1e3,d=class extends Error{constructor(e,t){super(t);this.code=e;this.name="SessionError"}};function St(){let e=globalThis;return{fetch:(t,i)=>fetch(t,i),storage:w,now:h,random:t=>{let i=new Uint8Array(t);if(!e.crypto?.getRandomValues)throw new d("not_configured","This platform has no secure random source.");return e.crypto.getRandomValues(i)},sha256:async t=>{if(!e.crypto?.subtle)throw new d("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 Pt(){let e=globalThis.location;if(!(!e?.origin||!/^https?:$/.test(e.protocol??"")))return e.origin}var Kt=class{constructor(e){this.signinOrigin=Rt;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??St(),this.audience=Pt()}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 xt+(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=H(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")),It);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-ve-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()>ve){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)},Lt),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 d("not_configured","Sign-in needs a web page or a configured app id.");let e=this.deps.openPopup();if(!e)throw new d("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=u=>{c!==null&&this.deps.clearTimer(c),a(),u()},a=this.deps.onMessage(u=>{if(u.origin!==this.signinOrigin)return;let f=u.data;!f||f.type!==Nt||f.state!==i||(typeof f.code=="string"?o(()=>r(f.code)):o(()=>s(new d("access_denied","Sign-in was cancelled."))))}),l=()=>{if(e.closed)return o(()=>s(new d("popup_closed","The sign-in window was closed.")));if(this.deps.now()-n>Ct)return o(()=>s(new d("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 d("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 d("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 d(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 d("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 d("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 d("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 d(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 d("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 u=l&&typeof l.error=="string"?l.error:"";if(u==="authorization_pending"||a.status>=500)continue;if(u==="slow_down"||a.status===429){o+=5e3;continue}if(u==="access_denied")throw new d("access_denied","The sign-in was turned down on buoy.gg.");if(u==="expired_token")throw new d("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 d("rejected",f)}}wait(e,t){return new Promise((i,r)=>{let s=()=>new d("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{}}},v=new Kt;var Ot="bsk1_",Mt="service",Vt=15e3;function z(e){return e.startsWith(Ot)}function b(e){let t=e.trim();return z(t)||we(t)?t:t.toUpperCase()}function Dt(e,t){return b(e??"")===b(t??"")}async function Ut(e,t){let i=t.fetch??((a,l)=>fetch(a,l)),r=typeof AbortController<"u"?new AbortController:void 0,s=setTimeout(()=>r?.abort(),Vt),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=H(c.access_token,{audience:Mt,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 Ft="dev";function Te(e){return we(e)}function Ae(e,t=h()){let i=H(e,{audience:Ft,ignoreTime:true});return i.ok?t>=i.claims.exp*1e3?{ok:false,reason:"expired",message:"Your dev token ran out. Run `npx --package=@buoy-gg/core buoy login` again."}:{ok:true,claims:i.claims}:{ok:false,reason:"invalid",message:"This dev token is not valid. Run `npx --package=@buoy-gg/core buoy login` again."}}var $t="This is a dev token. It only works in dev builds. A live build turns on Buoy with Sign in with Buoy.";var jt={role:null,tools:null};function _e(e){return{role:e.role??null,tools:e.tools??null}}async function y(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 Bt=class{constructor(){this.state={isInitialized:false,isValidating:false,isPro:false,tier:"free",tierSource:"none",licenseKey:null,error:null,errorKind:null,expiresAt:null};this.listeners=new Set;this.revalidationTimer=null;this.cachedLicense=null;this.fingerprintPromise=null;this.fingerprintRestored=false;this.initPromise=null;this.generation=0;this.persistence=Promise.resolve();this.verifiedAt=null;this.expiryTimer=null;this.removeForegroundListener=null;this.sessionUnsubscribe=null;this.devToken=null;this.retryTimer=null;this.retryAttempt=0;this.deviceRegistrationCallback=null;this.pendingRegistration=null}async initialize(){if(this.initPromise)return this.initPromise;if(!this.state.isInitialized)return this.initPromise=this._doInitialize(),this.initPromise}async _doInitialize(){if(this.state.isInitialized)return;let e=this.generation;this.sessionUnsubscribe||(this.sessionUnsubscribe=v.subscribe(()=>this.emit({type:"validated",isPro:this.isPro()}))),await y(v.load().catch(()=>{}),void 0);try{let t=await y(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=_(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()}),ue(i))return this.admitToken(i,r);if(z(i))return this.admitServiceKey(i,r);if(Te(i))return this.admitDevToken(i);if(!this.cachedLicense){let a=await y(this.loadCachedLicense(),null);if(r!==this.generation)return false;a?.licenseKey===i&&(this.cachedLicense=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&&_(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 y(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<Pe)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 $e(i)}catch(a){let l=a instanceof Error?a.message:"Validation failed";if(r!==this.generation)return false;if(ee(a)){if(Me(a)){let u=Math.min(Ve(a,Z,Se)*2**this.retryAttempt,Z);return this.retryAttempt+=1,await this.saveHold({...this.hold,backoffUntil:h()+u}),r!==this.generation?false:this.standDown(i,r,l,u)}return this.state.isValidating=false,this.cachedLicense&&this.cachedLicense.licenseKey===i&&_(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=He(o),l=o.data?.relationships?.product?.data?.id;if((!l||l===I.productId)&&a.code==="EXPIRED"&&(pt(o.data)||this.cachedLicense?.licenseKey===i&&_(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(ze(a.code)||!je(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 u=ft(o.data),f=o.data.id,S=h(),G=Be(o)>=Ke,J=F(),ke=J&&!G,Ee=u==="free"&&(G||!J),T=this.cachedLicense?.fingerprint,x=this.cachedLicense?.deviceName,Y=false;if(!T){if(T=await y(this.getOrCreateDeviceFingerprint(),U()),r!==this.generation)return false;x=$(),Y=ke}let P=false;Y&&(this.deviceRegistrationCallback?(this.pendingRegistration={licenseId:f,licenseKey:i,fingerprint:T},this.deviceRegistrationCallback({fingerprint:T,defaultName:x}),P=true):this.registerDeviceAsync(f,i,T,x));let K={licenseKey:i,licenseId:f,valid:true,isPro:u==="pro",tier:u,expiresAt:o.data.attributes.expiry??null,cachedAt:S,lastValidatedAt:S,fingerprint:P?void 0:T,deviceName:P?void 0:x,quiet:Ee||void 0},X=await this.saveCache(K,r);return r!==this.generation||!X||(this.cachedLicense=X,this.applyTier(u),this.state.isValidating=false,this.state.expiresAt=K.expiresAt?new Date(K.expiresAt):null,this.setVerifiedAt(S),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=Ce[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 Ut(e,{origin:v.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=Ae(e);if(!t.ok||!F()){let r=t.ok?$t: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.devToken={token:e,claims:t.claims},this.applyTier(t.claims.tier==="free"?"free":"pro"),this.state.isValidating=false,this.state.expiresAt=new Date(t.claims.exp*1e3),this.setVerifiedAt(Math.min(i,t.claims.iat*1e3)),this.retryAttempt=0,this.emit({type:"validated",isPro:this.isPro()}),true}async admitToken(e,t){let i=dt(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 y(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&&_(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&&(g.__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=v.getStatus();return e.state!=="active"?null:e.claims.tier==="free"?"free":"pro"}isPro(){return this.getTier()==="pro"}hasEntitlement(e){return this.isPro()}getState(){let{source:e,tier:t}=this.credential(),i=this.getTeamAccess();return{...this.state,tier:t,tierSource:e,isPro:t==="pro",access:this.getAccountAccess(),teamRole:i.role,allowedTools:i.tools}}getTeamAccess(){let e=v.getStatus();if(e.state==="active")return _e(e.claims);let t=this.devToken;return t&&t.token===this.state.licenseKey&&this.state.tierSource==="key"&&h()<t.claims.exp*1e3&&this.hasKeyAccess()?_e(t.claims):jt}getAccountAccess(){let e=this.getKeyAccess();if(e.status==="admitted")return e;let t=v.getStatus();return t.state==="active"?{status:"admitted",reason:null,validUntil:t.validUntil}:e}getKeyAccess(){return fe({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&&(g.__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=ne();try{await ie(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)?Oe:Ne;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 w()).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 w();e?await t.setItem(D,JSON.stringify(e)):await t.removeItem(D)}catch{}}async persistCache(e){let t=ce(e);return await(await w()).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,y(i,ce(e))}async loadCachedLicense(){try{await this.persistence.catch(()=>{});let e=await(await w()).getItem(M);if(!e)return null;let t=JSON.parse(e);if(t.fingerprint){let i=await y(this.getOrCreateDeviceFingerprint(t.fingerprint).catch(()=>null),null);if(i&&this.fingerprintRestored&&t.fingerprint!==i)return{...t,fingerprint:void 0,deviceName:void 0}}return t}catch(e){return console.warn("[Buoy] Error loading cached license:",e),null}}getOrCreateDeviceFingerprint(e){return this.fingerprintPromise||(this.fingerprintPromise=(async()=>{let t=await w(),i=await t.getItem(V),r=await t.getItem(q),s=await y(Je().catch(()=>null),null),n=Ye({stored:i,storedOwner:r,marker:s?Xe(s):null,blobFingerprint:e??this.cachedLicense?.fingerprint,mint:U});return this.fingerprintRestored=n.restored,n.changed&&(await t.setItem(V,n.fingerprint),n.owner&&await t.setItem(q,n.owner)),n.fingerprint})()),this.fingerprintPromise}async clearCachedLicense(){this.cachedLicense=null;let e=this.persistence.catch(()=>{}).then(async()=>{await(await w()).removeItem(M)});this.persistence=e,await y(e.catch(()=>{}),void 0)}registerDeviceAsync(e,t,i,r){let s=ne();ie(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=gt(()=>this.refreshAccess()),typeof p<"u"&&p&&(g.__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)},Re),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 w()).removeItem(V)}catch{}}},Ht=new Bt,g=globalThis;typeof p<"u"&&p&&(g.__LICENSE_MANAGER_FOREGROUND_OFF__?.(),g.__LICENSE_MANAGER_FOREGROUND_OFF__=void 0,g.__LICENSE_MANAGER_EXPIRY_TIMER__&&clearTimeout(g.__LICENSE_MANAGER_EXPIRY_TIMER__),g.__LICENSE_MANAGER_TIMER__&&clearInterval(g.__LICENSE_MANAGER_TIMER__),g.__LICENSE_MANAGER_RETRY_TIMER__&&(clearTimeout(g.__LICENSE_MANAGER_RETRY_TIMER__),g.__LICENSE_MANAGER_RETRY_TIMER__=void 0));export{h as a,A as b,ee as c,ue as d,fe as e,d as f,v as g,z as h,b as i,Dt as j,Te as k,Ae as l,Ht as m};/*!
|
|
2
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
3
|
+
*
|
|
4
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
5
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
6
|
+
*//*!
|
|
7
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
8
|
+
*
|
|
9
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
10
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
11
|
+
*
|
|
12
|
+
* This file configures the technological measure that controls access to paid
|
|
13
|
+
* Buoy Pro features. Modifying, patching, aliasing, stubbing, or otherwise
|
|
14
|
+
* altering it — including repointing `apiUrl` at a stand-in license server — so
|
|
15
|
+
* that Pro features unlock without a valid license is a breach of the EULA and,
|
|
16
|
+
* in the United States, circumvention of an access control under 17 U.S.C.
|
|
17
|
+
* § 1201, which applies whether or not any code is copied.
|
|
18
|
+
*
|
|
19
|
+
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
20
|
+
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
21
|
+
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
22
|
+
*//*!
|
|
23
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
24
|
+
*
|
|
25
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
26
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
27
|
+
*
|
|
28
|
+
* This file is part of the technological measure that controls access to paid
|
|
29
|
+
* Buoy Pro features. Modifying, patching, aliasing, stubbing, or otherwise
|
|
30
|
+
* altering it so that Pro features unlock without a valid license is a breach
|
|
31
|
+
* of the EULA and, in the United States, circumvention of an access control
|
|
32
|
+
* under 17 U.S.C. § 1201 — which applies whether or not any code is copied.
|
|
33
|
+
*
|
|
34
|
+
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
35
|
+
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
36
|
+
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
37
|
+
*//*!
|
|
38
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
39
|
+
*
|
|
40
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
41
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
42
|
+
*
|
|
43
|
+
* This file is part of the technological measure that controls access to paid
|
|
44
|
+
* Buoy Pro features: it decides which tier a validated key grants. Modifying,
|
|
45
|
+
* patching, aliasing, stubbing, or otherwise altering it so that Pro features
|
|
46
|
+
* unlock without a valid license is a breach of the EULA and, in the United
|
|
47
|
+
* States, circumvention of an access control under 17 U.S.C. § 1201 — which
|
|
48
|
+
* applies whether or not any code is copied.
|
|
49
|
+
*
|
|
50
|
+
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
51
|
+
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
52
|
+
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
53
|
+
*//*!
|
|
54
|
+
* PROPRIETARY — Buoy license enforcement. NOT open source.
|
|
55
|
+
*
|
|
56
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
57
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
58
|
+
*//*!
|
|
59
|
+
* PROPRIETARY — Buoy Pro license enforcement. NOT open source.
|
|
60
|
+
*
|
|
61
|
+
* Copyright (c) Buoy. All rights reserved. Licensed under the Buoy EULA
|
|
62
|
+
* (https://buoy.gg/terms), not an OSS license.
|
|
63
|
+
*
|
|
64
|
+
* This file is the technological measure that controls access to paid Buoy Pro
|
|
65
|
+
* features. Modifying, patching, aliasing, stubbing, or otherwise altering it
|
|
66
|
+
* so that Pro features unlock without a valid license is a breach of the EULA
|
|
67
|
+
* and, in the United States, circumvention of an access control under
|
|
68
|
+
* 17 U.S.C. § 1201 — which applies whether or not any code is copied.
|
|
69
|
+
*
|
|
70
|
+
* Pro is $9/mo, and is free every weekend for anyone holding a key —
|
|
71
|
+
* including a free one (`npx --package=@buoy-gg/core buoy login`). Buy a key at
|
|
72
|
+
* https://buoy.gg or use it free on Saturday and Sunday.
|
|
73
|
+
*/
|
package/lib/web/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use client";import{a as
|
|
1
|
+
"use client";import{a as S,b as _,c as K,d as L,e as P,f as h,g as B,h as I,i as Y,j as b,k as v,l as O,m as T,n as U,o as N,p as z,q as w,r as D,s as W}from"./chunks/chunk-D5RC3UOG.mjs";import{a as F,b as M,c as j,d as V,e as H,f as Q,g as r,h as X,i as $,j as x,k as g,l as d,m as n}from"./chunks/chunk-7T66ARUE.mjs";import{b as R,c as q,d as G,e as J}from"./chunks/chunk-J7MW3NXU.mjs";import{useEffect as Z,useState as ee}from"react";function u(e=new Date(F())){if(globalThis.__buoyWeekendPassOff===true)return false;let s=e.getDay();return s===0||s===6}function p(){let[e,s]=ee(()=>u());return Z(()=>{let t=setInterval(()=>{let a=u();s(i=>i===a?i:a)},6e4);return()=>clearInterval(t)},[]),e}function f(e,s){return s&&e}import{useState as m,useEffect as C,useCallback as l}from"react";function c(){let[e,s]=m(n.getState());C(()=>{let i=n.subscribe(o=>{s(n.getState())});return n.initialize().then(()=>{s(n.getState())}),i},[]);let t=l(async i=>{let o=await n.setLicenseKey(i,{force:true});return s(n.getState()),o},[]),a=l(async()=>{await n.clearLicense(),s(n.getState())},[]);return{...e,setLicenseKey:t,clearLicense:a}}function se(){return c().access}function ae(){let{tier:e,isInitialized:s}=c();return s?e:"free"}function te(e){let{isPro:s,isInitialized:t,isValidating:a}=c();return{hasAccess:s,isPro:s,isLoading:!t||a}}function ie(){let{isPro:e,isInitialized:s,access:t}=c(),a=f(t.status==="admitted",p());return s&&e||a}function ne(){let{isPro:e,isInitialized:s,access:t}=c(),a=s&&e,i=f(t.status==="admitted",p())&&!a;return{isPro:a||i,isLicensed:a,isWeekendFree:i,reason:a?"licensed":i?"weekend":null}}function re(){let[e,s]=m(()=>r.getStatus());C(()=>{let i=()=>s(r.getStatus()),o=r.subscribe(i);return r.load().then(i,i),o},[]);let t=l(()=>r.signIn(),[]),a=l(()=>r.signOut(),[]);return{status:e,signIn:t,signOut:a}}var y=["BUOY_LICENSE_KEY","BUOY_KEY","EXPO_PUBLIC_BUOY_KEY","VITE_BUOY_KEY","NEXT_PUBLIC_BUOY_KEY","REACT_APP_BUOY_KEY","licenseKey"],ce=/(^|_)BUOY_(LICENSE_)?KEY$/i;function A(e){return y.includes(e)||ce.test(e)}function E(e){return e&&(e.length>=16?`${e.slice(0,5)}\u2026\u2022\u2022\u2022\u2022 (hidden)`:"\u2022\u2022\u2022\u2022 (hidden)")}function oe(e){let s;for(let[t,a]of Object.entries(e))typeof a=="string"&&a&&A(t)&&(s??(s={...e}),s[t]=E(a));return s??e}function ue(){let e=r.getAccessToken();if(e)return{token:e,origin:r.origin};let s=n.getState().licenseKey;return s&&g(s)&&n.hasAccountAccess()&&d(s).ok?{token:s,origin:r.origin}:null}function le(e){return e.startsWith("app:")?e.slice(4)||null:/^https?:\/\//.test(e)?e:null}function ge(){let e=r.getAccessToken();if(e){let a=r.getStatus(),i=a.state==="active"?a.claims:null;return i?.team?{token:e,origin:r.origin,team:i.team,appId:le(i.aud)}:null}let s=n.getState().licenseKey;if(!s||!g(s)||!n.hasAccountAccess())return null;let t=d(s);return!t.ok||!t.claims.team?null:{token:s,origin:r.origin,team:t.claims.team,appId:null}}async function pe(e){let{LicenseManager:s}=await import("./chunks/LicenseManager-CJHAU3GD.mjs");return await s.initialize(),s.setLicenseKey(e)}function k(){return f(n.hasAccountAccess(),u())}function fe(){return n.isPro()?true:k()}function de(e){return n.hasEntitlement(e)?true:k()}export{y as BUOY_ACCOUNT_KEY_NAMES,n as LicenseManager,M as LicenseTransportError,Q as SessionError,r as SessionManager,v as callCapacitorAsApp,b as callCapacitorNative,O as callCapacitorNativeCallback,G as capacitorDebug,I as capacitorListenerCount,q as capacitorPlatform,w as capacitorPlugin,N as clearCapacitorCalls,K as colorSchemeQueryValue,B as emitCapacitorEvent,W as getCapacitorAppHost,U as getCapacitorCalls,L as getColorSchemeQueries,ue as getSyncCredential,ge as getTeamCredential,Y as hasCapacitorPlugin,de as hasEntitlement,_ as installCapacitorBridge,h as interceptCapacitor,A as isBuoyAccountKeyName,V as isBuoyToken,P as isCapacitorBridgeInstalled,R as isCapacitorNative,g as isDevToken,fe as isPro,X as isServiceKey,j as isTransientLicenseError,u as isWeekendFreePro,T as listenCapacitorNative,D as loadCapacitorAppHost,S as makeCapacitorCallbackId,E as maskBuoyAccountKey,oe as maskBuoyAccountKeys,$ as normalizeLicenseKey,H as resolveAccountAccess,J as resolveDevBuild,x as sameLicenseKey,pe as setLicenseKey,z as subscribeCapacitorCalls,se as useAccountAccess,re as useBuoySession,te as useFeatureAccess,ie as useIsPro,c as useLicense,ne as useProAccess,ae 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-3RVGU64S.mjs";import"./chunk-J7MW3NXU.mjs";export{e as LicenseManager};
|