@buoy-gg/storage 7.0.55 → 7.0.57
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/storage/components/StorageActionButtons.js +1 -1
- package/lib/commonjs/storage/components/StorageEventDetailContent.js +1 -1
- package/lib/commonjs/storage/components/StorageModalWithTabs.js +1 -1
- package/lib/commonjs/storage/hooks/useAsyncStorageKeys.js +1 -1
- package/lib/commonjs/storage/sync/storageSyncAdapter.js +1 -1
- package/lib/commonjs/storage/utils/AsyncStorageListener.web.js +1 -1
- package/lib/commonjs/storage/utils/appAsyncStorage.js +1 -0
- package/lib/commonjs/storage/utils/appAsyncStorage.web.js +1 -0
- package/lib/commonjs/storage/utils/asyncStorageCompat.js +1 -1
- package/lib/commonjs/storage/utils/browserStorageLifecycle.web.js +1 -1
- package/lib/commonjs/storage/utils/capacitorPreferences.js +1 -0
- package/lib/commonjs/storage/utils/clearAllStorage.js +1 -1
- package/lib/commonjs/storage/utils/setStorageValue.js +1 -1
- package/lib/commonjs/storage/utils/snapshotProvider.js +1 -1
- package/lib/commonjs/storage/utils/storageLabels.web.js +1 -1
- package/lib/commonjs/storage/utils/storageQueryUtils.js +1 -1
- package/lib/commonjs/storage/utils/storageTimeTravelUtils.js +1 -1
- package/lib/module/storage/components/StorageActionButtons.js +1 -1
- package/lib/module/storage/components/StorageEventDetailContent.js +1 -1
- package/lib/module/storage/components/StorageModalWithTabs.js +1 -1
- package/lib/module/storage/hooks/useAsyncStorageKeys.js +1 -1
- package/lib/module/storage/sync/storageSyncAdapter.js +1 -1
- package/lib/module/storage/utils/AsyncStorageListener.web.js +1 -1
- package/lib/module/storage/utils/appAsyncStorage.js +1 -0
- package/lib/module/storage/utils/appAsyncStorage.web.js +1 -0
- package/lib/module/storage/utils/asyncStorageCompat.js +1 -1
- package/lib/module/storage/utils/browserStorageLifecycle.web.js +1 -1
- package/lib/module/storage/utils/capacitorPreferences.js +1 -0
- package/lib/module/storage/utils/clearAllStorage.js +1 -1
- package/lib/module/storage/utils/setStorageValue.js +1 -1
- package/lib/module/storage/utils/snapshotProvider.js +1 -1
- package/lib/module/storage/utils/storageLabels.web.js +1 -1
- package/lib/module/storage/utils/storageQueryUtils.js +1 -1
- package/lib/module/storage/utils/storageTimeTravelUtils.js +1 -1
- package/lib/typescript/storage/utils/appAsyncStorage.d.ts +7 -0
- package/lib/typescript/storage/utils/appAsyncStorage.web.d.ts +5 -0
- package/lib/typescript/storage/utils/capacitorPreferences.d.ts +25 -0
- package/lib/web/index.mjs +2 -2
- package/package.json +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import l from"
|
|
1
|
+
"use strict";import l from"../utils/appAsyncStorage";import{approxJsonSize as p,isDevToolsStorageKey as y,isOverWireBudget as v,isJsonSerializable as T}from"@buoy-gg/shared-ui";import{readMany as b,writeMany as V,removeMany as I}from"../utils/asyncStorageCompat";import{batchPairsOf as M,storageEventStore as u}from"../stores/storageEventStore";import{clearAllAppStorage as _}from"../utils/clearAllStorage";import{undoOperation as q,jumpToState as K,canUndo as N}from"../utils/storageTimeTravelUtils";import{mmkvInstanceRegistry as f}from"../utils/MMKVInstanceRegistry";import{detectMMKVType as g}from"../utils/mmkvTypeDetection";import{secureStoreRegistry as c}from"../utils/SecureStoreRegistry";export const VALUE_ON_DEVICE=Object.freeze({__buoyValueOnDevice:true,note:"Value stays on the device \u2014 fetched on demand via getEventDetail / mmkv.get / secure.get."});export const SNAPSHOT_VALUE_INLINE_LIMIT=16*1024;export const SNAPSHOT_EVENTS_BUDGET=1.25*1024*1024;const h=8*1024*1024;function m(e){if(e===void 0)return e;return v(e,SNAPSHOT_VALUE_INLINE_LIMIT)?VALUE_ON_DEVICE:e}function d(e,t){const n=e.data;if(!n)return e;const r=t(n.value);const s=t(n.prevValue);const o=M(e);const i=t(o.pairs);const a=t(o.prevPairs);if(r===n.value&&s===n.prevValue&&i===o.pairs&&a===o.prevPairs){return e}return{...e,data:{...n,value:r,prevValue:s,...e.storageType==="async"?{pairs:i,prevPairs:a}:{}}}}function k(e){if(e===void 0)return e;if(!v(e,h))return e;return T(e)?{__buoyTruncated:true,note:`Exceeds the ${h/(1024*1024)}MB detail limit \u2014 inspect it on-device.`}:VALUE_ON_DEVICE}const w=new WeakMap;const E=new WeakMap;function x(e){const t=w.get(e);if(t)return t;let n;try{const r=d(e,m);n={event:r,bytes:p(r,SNAPSHOT_EVENTS_BUDGET).bytes}}catch{const r=d(e,()=>VALUE_ON_DEVICE);n={event:r,bytes:1024}}w.set(e,n);return n}function O(e){const t=E.get(e);if(t)return t;const n=d(e,s=>s===void 0?void 0:VALUE_ON_DEVICE);const r={event:n,bytes:p(n,SNAPSHOT_EVENTS_BUDGET).bytes};E.set(e,r);return r}function P(e){const t=new Array(e.length);let n=0;for(let r=0;r<e.length;r++){const s=x(e[r]);if(n+s.bytes<=SNAPSHOT_EVENTS_BUDGET){t[r]=s.event;n+=s.bytes}else{const o=O(e[r]);t[r]=o.event;n+=o.bytes}}return t}function A(e){const t=f.get(e);if(!t){throw new Error(`No MMKV instance registered as "${e}"`)}if(t.instance?.isReadOnly){throw new Error(`MMKV instance "${e}" is registered read-only`)}return t.instance}let S=[];export function setToolRequiredStorageKeys(e){S=e}export const storageSyncAdapter={version:3,getSnapshot:()=>P(u.getEvents().filter(e=>{const t=e.data?.key;return!(typeof t==="string"&&y(t))})),subscribe:e=>u.subscribeToEvents(e),actions:{clearEvents:()=>{u.clearEvents()},getRequiredKeys:()=>S,getEventDetail:e=>{const{id:t}=e??{};if(!t)return{found:false,reason:"missing id"};const n=u.getEvents().find(s=>s.id===t);if(!n)return{found:false,reason:"unknown id"};const r=d(n,k);return{found:true,id:t,event:r}},clearAppStorage:()=>_(),"timeTravel.undo":async e=>{const t=e?.id;if(!t)throw new Error("timeTravel.undo requires an event `id`");const n=u.getEvents().find(s=>s.id===t);if(!n)throw new Error(`No storage event with id "${t}"`);if(n.storageType==="mmkv"){throw new Error("Time travel supports AsyncStorage events only")}const r=n;if(!N(r)){throw new Error(`Event "${t}" (${r.action}) has no previous value captured, so it cannot be undone`)}await q(r);return{undone:true,action:r.action,key:r.data?.key}},"timeTravel.jump":async e=>{const{id:t,scope:n="key"}=e??{};if(!t)throw new Error("timeTravel.jump requires an event `id`");const r=u.getEvents().filter(a=>a.storageType!=="mmkv").slice().reverse();const s=r.find(a=>a.id===t);if(!s)throw new Error(`No AsyncStorage event with id "${t}"`);const o=n==="all"?r:r.filter(a=>a.data?.key===s.data?.key);const i=o.findIndex(a=>a.id===t);if(i===-1)throw new Error(`Event "${t}" is not in the timeline`);await K(o,i);return{jumped:true,scope:n,replayed:i+1,of:o.length,key:s.data?.key}},"async.getAllKeys":async()=>(await l.getAllKeys()).filter(e=>!y(e)),"async.multiGet":async e=>(await b(e.keys)).filter(([t])=>!y(t)),"async.getItem":e=>{const{key:t}=e;return y(t)?Promise.resolve(null):l.getItem(t)},"async.setItem":e=>{const{key:t,value:n}=e;return l.setItem(t,n)},"async.removeItem":e=>l.removeItem(e.key),"async.multiRemove":e=>I(e.keys),"async.multiSet":e=>V(e.pairs),"async.clear":()=>l.clear(),"mmkv.snapshot":()=>f.getAll().map(({id:e,instance:t,encrypted:n,readOnly:r})=>{let s=[];try{s=t.getAllKeys().filter(o=>!y(o)).map(o=>{const{value:i,type:a}=g(t,o);return{key:o,value:m(i),valueType:a}})}catch{}return{id:e,encrypted:n,readOnly:r,entries:s}}),"mmkv.get":e=>{const{instanceId:t,key:n}=e??{};if(!t||!n){return{found:false,reason:"missing instanceId/key"}}const r=f.get(t);if(!r){return{found:false,reason:"unknown instance"}}const{value:s,type:o}=g(r.instance,n);return{found:true,instanceId:t,key:n,value:k(s),valueType:o}},"mmkv.set":e=>{const{instanceId:t,key:n,value:r}=e;A(t).set(n,r)},"mmkv.remove":e=>{const{instanceId:t,key:n}=e;const r=A(t);if(r.remove)r.remove(n);else r.delete?.(n)},"secure.keys":async()=>{const e=c.getModule();return Promise.all(c.getAll().map(async({key:t,options:n,description:r})=>{let s=null;if(e&&!n.requireAuthentication){try{s=await e.getItemAsync(t,n)!=null}catch{s=null}}return{key:t,description:r,keychainService:n.keychainService,requireAuthentication:n.requireAuthentication??false,hasValue:s}}))},"secure.snapshot":async()=>{const e=c.getModule();const t=c.getAll();const n=[];for(const{key:r,options:s,description:o}of t){let i=null;if(e&&!s.requireAuthentication){try{i=await e.getItemAsync(r,s)}catch{}}n.push({key:r,description:o,keychainService:s.keychainService,requireAuthentication:s.requireAuthentication??false,value:i==null?i:m(i)})}return n},"secure.get":e=>{const{key:t}=e;const n=c.getAll().find(s=>s.key===t);const r=c.getModule();if(!n||!r||n.options.requireAuthentication){return Promise.resolve(null)}return r.getItemAsync(t,n.options)},"secure.set":e=>{const{key:t,value:n}=e;return c.setValue(t,n)},"secure.delete":e=>c.deleteValue(e.key)}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{subscribeToBrowserStorage as
|
|
1
|
+
"use strict";import{subscribeToBrowserStorage as c}from"@buoy-gg/shared-ui/utils";import{subscribePreferencesChanges as p,usesCapacitorPreferences as d}from"./capacitorPreferences";const t=new Set;let r;let n=false;const l=new Set(["@react_buoy_storage_event_filters","@react_buoy_storage_key_filters","@react_buoy_storage_is_monitoring","REACT_QUERY_OFFLINE_CACHE"]);const o=e=>[...l].some(s=>e.startsWith(s));function u(e){for(const s of[...t]){try{s(e)}catch{}}}export async function startListening(){if(r||typeof window==="undefined")return;if(d()){r=p(e=>{if(!n)u(e)});return}r=c(e=>{if(n||e.area!=="localStorage"||e.key!==void 0&&o(e.key))return;const{area:s,action:a,...i}=e;if(i.prevPairs)i.prevPairs=i.prevPairs.filter(([f])=>!o(f));u({action:a,data:i,timestamp:new Date})})}export function stopListening(){r?.();r=void 0}export function addListener(e){t.add(e);return()=>{t.delete(e)}}export function removeAllListeners(){t.clear()}export function isListening(){return!!r}export function getListenerCount(){return t.size}export function pauseCapture(){n=true}export function resumeCapture(){n=false}export function isPaused(){return n}const _={startListening,stopListening,addListener,removeAllListeners,pause:pauseCapture,resume:resumeCapture,get isActive(){return isListening()},get listenerCount(){return t.size},get paused(){return n}};export default _;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import t from"@react-native-async-storage/async-storage";export default t;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import r from"@react-native-async-storage/async-storage";import{preferencesAsyncStorage as o,usesCapacitorPreferences as s}from"./capacitorPreferences";const t=()=>s()?o:r;const l={getItem:e=>t().getItem(e),setItem:(e,m)=>t().setItem(e,m),removeItem:e=>t().removeItem(e),clear:()=>t().clear(),getAllKeys:()=>t().getAllKeys(),multiGet:e=>t().multiGet(e),multiSet:e=>t().multiSet(e),multiRemove:e=>t().multiRemove(e),mergeItem:(e,m)=>t().mergeItem(e,m),multiMerge:e=>t().multiMerge(e)};export default l;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import r from"
|
|
1
|
+
"use strict";import r from"./appAsyncStorage";export const asyncStorage=r;export const asyncStorageCaps={hasLegacyMultiApi:typeof asyncStorage?.multiGet==="function",hasMergeApi:typeof asyncStorage?.mergeItem==="function"};export async function readMany(t){if(typeof asyncStorage.multiGet==="function"){return await asyncStorage.multiGet(t)}const e=await asyncStorage.getMany(t);return t.map(n=>[n,e[n]??null])}export async function writeMany(t){if(typeof asyncStorage.multiSet==="function"){return asyncStorage.multiSet(t)}const e={};for(const[n,o]of t)e[n]=o;return asyncStorage.setMany(e)}export async function removeMany(t){if(typeof asyncStorage.multiRemove==="function"){return asyncStorage.multiRemove(t)}return asyncStorage.removeMany(t)}export default asyncStorage;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{getBrowserStorage as
|
|
1
|
+
"use strict";import{getBrowserStorage as s,subscribeToBrowserStorage as a}from"@buoy-gg/shared-ui/utils";import{isDevToolsStorageKey as i}from"@buoy-gg/shared-ui";import{registerMMKVInstance as g,unregisterMMKVInstance as l}from"./MMKVInstanceRegistry";import{usesCapacitorPreferences as c}from"./capacitorPreferences";let u=0;function d(o){const t=()=>s(o);const n=()=>Array.from({length:t().length},(e,r)=>t().key(r)).filter(e=>e!==null&&!(o==="localStorage"&&i(e)));return{set(e,r){t().setItem(e,String(r))},getString(e){return t().getItem(e)??void 0},getNumber(){return void 0},getBoolean(){return void 0},getBuffer(){return void 0},contains(e){return t().getItem(e)!==null},delete(e){const r=this.contains(e);t().removeItem(e);return r},getAllKeys:n,clearAll(){for(const e of n())t().removeItem(e)},get size(){return n().reduce((e,r)=>e+2*(r.length+(t().getItem(r)?.length??0)),0)},addOnValueChangedListener(e){return{remove:a(r=>{if(r.area!==o)return;if(r.key!==void 0){if(!(o==="localStorage"&&i(r.key)))e(r.key)}else r.prevPairs?.forEach(([f])=>e(f))})}}}}function m(){return c()?["localStorage","sessionStorage"]:["sessionStorage"]}export function startBrowserStorageCapture(){if(typeof window==="undefined")return()=>{};try{s("sessionStorage")}catch{return()=>{}}const o=m();if(++u===1)for(const n of o)g(n,d(n));let t=true;return()=>{if(t){t=false;if(--u===0)for(const n of o)l(n)}}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";import{callCapacitorNative as s,hasCapacitorPlugin as g,installCapacitorBridge as h,interceptCapacitor as P,isCapacitorNative as I}from"@buoy-gg/license";const n="Preferences";export function usesCapacitorPreferences(){return I()&&g(n)}const u=new Set;function i(e,t){const r={action:e,data:t,timestamp:new Date};for(const a of Array.from(u)){try{a(r)}catch{}}}export function subscribePreferencesChanges(e){u.add(e);S();return()=>{u.delete(e)}}async function c(e){const{value:t}=await s(n,"get",{key:e});return t??null}async function m(){const{keys:e}=await s(n,"keys");return Array.isArray(e)?e:[]}async function l(e){return Promise.all(e.map(async t=>[t,await c(t)]))}let p=false;function S(){if(p||!usesCapacitorPreferences()||!h())return;p=true;P({plugin:n,methods:["set","remove","clear"],promise:async(e,t)=>{if(u.size===0)return t();const r=typeof e.options.key==="string"?e.options.key:void 0;if(e.method==="clear"){const w=m().catch(()=>[]);const d=await t();i("clear",{keys:await w});return d}if(r===void 0)return t();const a=c(r).catch(()=>null);const o=await t();const f=await a;if(e.method==="set")i("setItem",{key:r,value:String(e.options.value??""),prevValue:f});else i("removeItem",{key:r,prevValue:f});return o}})}function y(e,t){if(!e||!t||typeof e!=="object"||typeof t!=="object"||Array.isArray(e)||Array.isArray(t)){return t}const r={...e};for(const[a,o]of Object.entries(t)){r[a]=a in r?y(r[a],o):o}return r}function v(e){if(e===null)return null;try{return JSON.parse(e)}catch{return null}}export const preferencesAsyncStorage={getItem(e){return c(e)},async setItem(e,t){const r=c(e).catch(()=>null);await s(n,"set",{key:e,value:String(t)});i("setItem",{key:e,value:String(t),prevValue:await r})},async removeItem(e){const t=c(e).catch(()=>null);await s(n,"remove",{key:e});i("removeItem",{key:e,prevValue:await t})},async clear(){const e=await l(await m()).catch(()=>void 0);await s(n,"clear");i("clear",{prevPairs:e?.filter(t=>t[1]!==null)})},getAllKeys(){return m()},multiGet(e){return l(e)},async multiSet(e){const t=l(e.map(([r])=>r)).catch(()=>void 0);await Promise.all(e.map(([r,a])=>s(n,"set",{key:r,value:String(a)})));i("multiSet",{pairs:e.map(([r,a])=>[r,String(a)]),prevPairs:await t})},async multiRemove(e){const t=l(e).catch(()=>void 0);await Promise.all(e.map(r=>s(n,"remove",{key:r})));i("multiRemove",{keys:[...e],prevPairs:await t})},async mergeItem(e,t){const r=await c(e);await preferencesAsyncStorage.setItem(e,JSON.stringify(y(v(r),v(t))))},async multiMerge(e){for(const[t,r]of e)await preferencesAsyncStorage.mergeItem(t,r)}};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import o from"
|
|
1
|
+
"use strict";import o from"./appAsyncStorage";import{removeMany as a}from"./asyncStorageCompat";import{isDevToolsStorageKey as l}from"@buoy-gg/shared-ui";export async function clearAllAppStorage(){const e=await o.getAllKeys();if(!e||e.length===0){return}const t=e.filter(r=>!l(r));if(t.length===0){return}await a(t)}export async function clearAllStorageIncludingDevTools(){await o.clear()}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import l from"
|
|
1
|
+
"use strict";import l from"./appAsyncStorage";import{secureStoreRegistry as i}from"./SecureStoreRegistry";export function storageEditBlockedReason(e,t=[]){if(e.storageType==="mmkv"){if(e.valueType==="buffer"){return"Buffer values can't be edited \u2014 the tool only ever sees their byte length, not their contents."}const r=t.find(n=>n.id===(e.instanceId||"default"));if(r?.readOnly){return`MMKV instance "${r.id}" is registered read-only.`}}if(e.storageType==="secure"){const r=i.getAll().find(n=>n.key===e.key);if(r?.options.requireAuthentication){return"Biometric-protected keys can't be edited \u2014 writing one would fire an auth prompt."}if(!i.getModule()){return"No SecureStore module is registered."}}return null}export function validateStorageValue(e,t){if(e.storageType==="mmkv"){const r=a(e);if(r==="number"){if(t.trim()===""||Number.isNaN(Number(t))){return"Must be a number \u2014 this MMKV key is stored as a number."}}if(r==="boolean"){const n=t.trim().toLowerCase();if(n!=="true"&&n!=="false"){return'Must be "true" or "false" \u2014 this MMKV key is stored as a boolean.'}}return null}if(f(e.value)){try{JSON.parse(t)}catch(r){return`This key holds JSON \u2014 ${r instanceof Error?r.message:"invalid JSON"}`}}return null}export function storageValueToEditableText(e){if(e===void 0||e===null)return"";if(typeof e==="string"){const t=e.trim();if(t.startsWith("{")||t.startsWith("[")){try{return JSON.stringify(JSON.parse(e),null,2)}catch{return e}}return e}if(typeof e==="object")return JSON.stringify(e,null,2);return String(e)}export function structuredStorageValue(e){const{value:t}=e;if(t!==null&&typeof t==="object")return t;if(typeof t==="string"){const r=t.trim();if(!r.startsWith("{")&&!r.startsWith("["))return void 0;try{const n=JSON.parse(t);return n!==null&&typeof n==="object"?n:void 0}catch{return void 0}}return void 0}export async function setStorageValue(e,t,r=[]){const n=storageEditBlockedReason(e,r);if(n)throw new Error(n);const u=validateStorageValue(e,t);if(u)throw new Error(u);switch(e.storageType){case"async":{await l.setItem(e.key,c(e,t));return}case"secure":{await i.setValue(e.key,c(e,t));return}case"mmkv":{const o=e.instanceId||"default";const s=r.find(d=>d.id===o);if(!s){throw new Error(`MMKV instance "${o}" is not registered.`)}s.instance.set(e.key,p(e,t));return}default:{throw new Error(`Unsupported storage type "${String(e.storageType)}"`)}}}function f(e){return e!==null&&typeof e==="object"}function c(e,t){if(!f(e.value))return t;return JSON.stringify(JSON.parse(t))}function a(e){if(e.valueType)return e.valueType;if(typeof e.value==="number")return"number";if(typeof e.value==="boolean")return"boolean";return"string"}function p(e,t){switch(a(e)){case"number":return Number(t);case"boolean":return t.trim().toLowerCase()==="true";default:return t}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import R from"
|
|
1
|
+
"use strict";import R from"./appAsyncStorage";import{classifyPreviewItem as D,createRestoreScope as P,emptyRestoreResult as V,failedRestore as j,isDevToolsStorageKey as h,registerStateSnapshotProvider as x,unionKeys as w,wontApply as v}from"@buoy-gg/shared-ui";import{readMany as B,writeMany as L,removeMany as _}from"./asyncStorageCompat";import{clearAllAppStorage as C}from"./clearAllStorage";import{mmkvInstanceRegistry as $}from"./MMKVInstanceRegistry";import{detectMMKVType as W}from"./mmkvTypeDetection";import{secureStoreRegistry as m}from"./SecureStoreRegistry";function E(n,a){if(n.remove)n.remove(a);else n.delete?.(a)}function H(){return{canCapture:true,canRestore:true}}async function T(){const n=[];const a=(await R.getAllKeys()).filter(o=>!h(o));const i=(await B(a)).filter(o=>o[1]!==null);const r={};for(const{id:o,instance:y}of $.getAll()){try{r[o]=y.getAllKeys().filter(e=>!h(e)).map(e=>{const{value:f,type:l}=W(y,e);if(l==="buffer"){n.push(`mmkv "${o}"/"${e}": ArrayBuffer value not capturable`)}return{key:e,value:f,valueType:l}})}catch{n.push(`mmkv "${o}": unreadable, captured without entries`);r[o]=[]}}const u={};const s=m.getModule();for(const{key:o,options:y}of m.getAll()){if(y.requireAuthentication){n.push(`secure "${o}": biometric-protected, not capturable`);continue}let e=null;if(s){try{e=await s.getItemAsync(o,y)}catch{n.push(`secure "${o}": unreadable, captured as unset`)}}u[o]=e}return{data:{async:i,mmkv:r,secure:u},warnings:n}}async function N(){const{data:n,warnings:a}=await T();return{data:n,warnings:a}}async function U(n,a){const i=n;const r=P(a);const u=r.touch;const s=V();if(!i){return j("empty storage snapshot")}try{const e=(i.async??[]).filter(([t])=>!h(t)&&u(`async:${t}`));const f=new Set(e.map(([t])=>t));const l=(await R.getAllKeys()).filter(t=>!h(t));const g=l.filter(t=>!f.has(t)&&u(`async:${t}`));r.countExcluded((i.async??[]).length-e.length);if(g.length>0)await _(g);if(e.length>0)await L(e);s.applied+=e.length+g.length}catch(e){s.ok=false;s.warnings.push(`asyncstorage restore failed: ${String(e)}`)}for(const[e,f]of Object.entries(i.mmkv??{})){const l=$.get(e);if(!l){s.skipped.push({id:`mmkv:${e}`,reason:"instance not registered"});continue}if(l.instance.isReadOnly){s.skipped.push({id:`mmkv:${e}`,reason:"instance registered read-only"});continue}const{instance:g}=l;try{const t=new Set(f.map(c=>c.key));const d=g.getAllKeys().filter(c=>!h(c));for(const c of d){if(!r.allows(`mmkv:${e}/${c}`))continue;if(!t.has(c)){E(g,c);s.applied+=1}}for(const c of f){if(h(c.key))continue;if(!u(`mmkv:${e}/${c.key}`))continue;if(c.valueType==="buffer"){s.skipped.push({id:`mmkv:${e}/${c.key}`,reason:"ArrayBuffer values cannot be restored"});continue}g.set(c.key,c.value);s.applied+=1}}catch(t){s.ok=false;s.warnings.push(`mmkv "${e}" restore failed: ${String(t)}`)}}const o=i.secure??{};for(const{key:e,options:f}of m.getAll()){if(!r.allows(`secure:${e}`))continue;if(f.requireAuthentication){if(e in o){s.skipped.push({id:`secure:${e}`,reason:"biometric-protected keys are never written"})}continue}try{if(e in o){const l=o[e];if(l===null)await m.deleteValue(e);else await m.setValue(e,l)}else{await m.deleteValue(e)}s.applied+=1}catch(l){s.ok=false;s.warnings.push(`secure "${e}" restore failed: ${String(l)}`)}}for(const e of Object.keys(o)){if(!u(`secure:${e}`))continue;if(!m.getAll().some(f=>f.key===e)){s.skipped.push({id:`secure:${e}`,reason:"key no longer registered with registerSecureStoreKeys"})}}const y=r.excludedWarning("item(s)");if(y)s.warnings.push(y);return s}async function z(){const n=V();try{await C();n.applied+=1}catch(a){n.ok=false;n.warnings.push(`asyncstorage clear failed: ${String(a)}`)}for(const{id:a,instance:i}of $.getAll()){if(i.isReadOnly){n.skipped.push({id:`mmkv:${a}`,reason:"instance registered read-only"});continue}try{for(const r of i.getAllKeys().filter(u=>!h(u))){E(i,r);n.applied+=1}}catch(r){n.ok=false;n.warnings.push(`mmkv "${a}" clear failed: ${String(r)}`)}}for(const{key:a,options:i}of m.getAll()){if(i.requireAuthentication){n.skipped.push({id:`secure:${a}`,reason:"biometric-protected keys are never written"});continue}try{await m.deleteValue(a);n.applied+=1}catch(r){n.ok=false;n.warnings.push(`secure "${a}" clear failed: ${String(r)}`)}}return n}const F=256*1024;function M(n,a,i,r,u,s){return D({key:n,label:a,oldValue:i,newValue:r,inOld:u,inNew:s},{equal:Object.is,tooLarge:o=>typeof o==="string"&&o.length>F,tooLargeReason:"value too large to render a diff \u2014 restore still applies it"})}async function G(n,a){const i=n??{async:[],mmkv:{},secure:{}};const r=a===void 0;const u=r?(await T()).data:a??{async:[],mmkv:{},secure:{}};const s=[];const o=[];const y=new Map(u.async??[]);const e=new Map(i.async??[]);for(const t of w(y,e)){if(h(t))continue;s.push(M(`async:${t}`,t,y.get(t),e.get(t),y.has(t),e.has(t)))}for(const t of w(u.mmkv,i.mmkv)){const d=r?$.get(t):null;const c=r&&!d;const I=r&&d?.instance.isReadOnly===true;const A=new Map((u.mmkv?.[t]??[]).map(p=>[p.key,p]));const S=new Map((i.mmkv?.[t]??[]).map(p=>[p.key,p]));for(const p of w(A,S)){if(h(p))continue;const O=`mmkv:${t}/${p}`;const q=`${t} \xB7 ${p}`;const b=A.get(p);const K=S.get(p);let k=M(O,q,b?.value,K?.value,A.has(p),S.has(p));if(c){k=v(k,"MMKV instance not registered")}else if(I){k=v(k,"MMKV instance registered read-only")}else if(K?.valueType==="buffer"||b?.valueType==="buffer"){k=v(k,"ArrayBuffer values cannot be restored")}s.push(k)}}const f=u.secure??{};const l=i.secure??{};const g=r?new Map(m.getAll().map(t=>[t.key,t])):null;for(const t of w(f,l)){let d=M(`secure:${t}`,t,f[t],l[t],t in f,t in l);if(r){const c=g?.get(t);if(!c){d=v(d,"key no longer registered with registerSecureStoreKeys")}else if(c.options.requireAuthentication){d=v(d,"biometric-protected keys are never written")}}s.push(d)}return{items:s,notes:o}}x({id:"storage",label:"Storage",status:H,capture:N,restore:U,clear:z,previewItems:G});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";export const storageLabels={async:"Local",asyncFull:"localStorage",mmkv:"Session",secure:"Secure",hasSecure:false};
|
|
1
|
+
"use strict";import{usesCapacitorPreferences as e}from"./capacitorPreferences";export const storageLabels=e()?{async:"Preferences",asyncFull:"Capacitor Preferences",mmkv:"Web",secure:"Secure",hasSecure:false}:{async:"Local",asyncFull:"localStorage",mmkv:"Session",secure:"Secure",hasSecure:false};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{gameUIColors as r}from"@buoy-gg/shared-ui";export function getStorageTypeLabel(e){switch(e){case"mmkv":return
|
|
1
|
+
"use strict";import{gameUIColors as r}from"@buoy-gg/shared-ui";import{storageLabels as t}from"./storageLabels";export function getStorageTypeLabel(e){switch(e){case"mmkv":return t.mmkv;case"async":return t.async;case"secure":return"Secure";default:return e}}export function getStorageTypeHexColor(e){switch(e){case"mmkv":return r.info;case"async":return r.warning;case"secure":return r.success;default:return r.muted}}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";import{isDevToolsStorageKey as m}from"@buoy-gg/shared-ui";import l from"
|
|
1
|
+
"use strict";import{isDevToolsStorageKey as m}from"@buoy-gg/shared-ui";import l from"./appAsyncStorage";import{writeMany as f,removeMany as y}from"./asyncStorageCompat";function c(s){return!!s&&typeof s==="object"&&s.__buoyValueOnDevice===true}export async function undoOperation(s){const{action:r,data:e}=s;if(c(e?.prevValue)||c(e?.prevPairs)){throw new Error("Cannot undo: previous value is still on the device \u2014 fetch getEventDetail first")}{switch(r){case"setItem":case"mergeItem":if(e?.key){if(e.prevValue===null||e.prevValue===void 0){await l.removeItem(e.key)}else{await l.setItem(e.key,e.prevValue)}}break;case"removeItem":if(e?.key&&e.prevValue!==null&&e.prevValue!==void 0){await l.setItem(e.key,e.prevValue)}break;case"multiSet":case"multiMerge":if(e?.prevPairs&&e.prevPairs.length>0){for(const[t,a]of e.prevPairs){if(a===null){await l.removeItem(t)}else{await l.setItem(t,a)}}}break;case"multiRemove":if(e?.prevPairs&&e.prevPairs.length>0){for(const[t,a]of e.prevPairs){if(a!==null){await l.setItem(t,a)}}}break;case"clear":if(e?.prevPairs&&e.prevPairs.length>0){const t=e.prevPairs.filter(([,a])=>a!==null);if(t.length>0){await f(t)}}break;default:throw new Error(`Cannot undo unknown action type: ${r}`)}}}export async function jumpToState(s,r){if(r<0||r>=s.length){throw new Error(`Invalid event index: ${r}`)}for(const i of s){const o=i.data;if(c(o?.value)||c(o?.prevValue)||c(o?.pairs)||c(o?.prevPairs)){throw new Error("Cannot jump: some event values are still on the device \u2014 fetch getEventDetail first")}}const e=new Map;for(let i=0;i<=r;i++){k(s[i],e)}const t=new Set;for(const i of s){p(i,t)}const a=[];const n=[];for(const i of t){if(m(i))continue;const o=e.get(i);if(o===void 0||o===null){n.push(i)}else{a.push([i,o])}}if(n.length>0){await y(n)}if(a.length>0){await f(a)}}function p(s,r){const{data:e}=s;if(!e)return;if(e.key)r.add(e.key);if(e.keys)for(const t of e.keys)r.add(t);if(e.pairs)for(const[t]of e.pairs)r.add(t);if(e.prevPairs)for(const[t]of e.prevPairs)r.add(t)}function k(s,r){const{action:e,data:t}=s;switch(e){case"setItem":if(t?.key&&t?.value!==void 0){r.set(t.key,t.value)}break;case"removeItem":if(t?.key){r.set(t.key,null)}break;case"mergeItem":if(t?.key&&t?.value!==void 0){const a=r.get(t.key);if(a){try{const n=JSON.parse(a);const i=JSON.parse(t.value);const o={...n,...i};r.set(t.key,JSON.stringify(o))}catch{r.set(t.key,t.value)}}else{r.set(t.key,t.value)}}break;case"multiSet":if(t?.pairs){for(const[a,n]of t.pairs){r.set(a,n)}}break;case"multiRemove":if(t?.keys){for(const a of t.keys){r.set(a,null)}}break;case"multiMerge":if(t?.pairs){for(const[a,n]of t.pairs){const i=r.get(a);if(i){try{const o=JSON.parse(i);const u=JSON.parse(n);const v={...o,...u};r.set(a,JSON.stringify(v))}catch{r.set(a,n)}}else{r.set(a,n)}}}break;case"clear":r.clear();break}}export function canUndo(s){const{action:r,data:e}=s;switch(r){case"setItem":case"mergeItem":case"removeItem":return!!e?.key&&!c(e.prevValue);case"multiSet":case"multiRemove":case"multiMerge":case"clear":return!!e?.prevPairs&&e.prevPairs.length>0&&!c(e.prevPairs);default:return false}}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The store behind the Storage tool's "async" slot. React Native: the app's
|
|
3
|
+
* AsyncStorage. The web build swaps in appAsyncStorage.web.ts.
|
|
4
|
+
*/
|
|
5
|
+
import AsyncStorage from "@react-native-async-storage/async-storage";
|
|
6
|
+
export default AsyncStorage;
|
|
7
|
+
//# sourceMappingURL=appAsyncStorage.d.ts.map
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { AsyncStorageEvent } from "./AsyncStorageListener";
|
|
2
|
+
/** True inside a Capacitor native shell that ships `@capacitor/preferences`. */
|
|
3
|
+
export declare function usesCapacitorPreferences(): boolean;
|
|
4
|
+
type ChangeListener = (event: AsyncStorageEvent) => void;
|
|
5
|
+
/** Every Preferences change, from the app or from Buoy. Returns an unsubscribe. */
|
|
6
|
+
export declare function subscribePreferencesChanges(listener: ChangeListener): () => void;
|
|
7
|
+
/**
|
|
8
|
+
* The AsyncStorage-shaped store the Storage tool's "async" slot reads,
|
|
9
|
+
* backed by Preferences. Same contract as the browser's
|
|
10
|
+
* `@buoy-gg/shared-ui/web/asyncStorage`.
|
|
11
|
+
*/
|
|
12
|
+
export declare const preferencesAsyncStorage: {
|
|
13
|
+
getItem(key: string): Promise<string | null>;
|
|
14
|
+
setItem(key: string, value: string): Promise<void>;
|
|
15
|
+
removeItem(key: string): Promise<void>;
|
|
16
|
+
clear(): Promise<void>;
|
|
17
|
+
getAllKeys(): Promise<string[]>;
|
|
18
|
+
multiGet(keys: readonly string[]): Promise<[string, string | null][]>;
|
|
19
|
+
multiSet(pairs: readonly (readonly [string, string])[]): Promise<void>;
|
|
20
|
+
multiRemove(keys: readonly string[]): Promise<void>;
|
|
21
|
+
mergeItem(key: string, value: string): Promise<void>;
|
|
22
|
+
multiMerge(pairs: readonly (readonly [string, string])[]): Promise<void>;
|
|
23
|
+
};
|
|
24
|
+
export {};
|
|
25
|
+
//# sourceMappingURL=capacitorPreferences.d.ts.map
|