@choksheak/react-utils 0.2.2 → 0.2.3

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.
Files changed (39) hide show
  1. package/docs/assets/highlight.css +49 -0
  2. package/docs/assets/search.js +1 -1
  3. package/docs/classes/sharedQuery.SharedQuery.html +11 -6
  4. package/docs/classes/sharedState.SharedState.html +2 -2
  5. package/docs/classes/utils_storage.InMemoryStorageAdapter.html +2 -2
  6. package/docs/classes/utils_storage.IndexedDbAdapter.html +2 -2
  7. package/docs/classes/utils_storage.LocalStorageAdapter.html +2 -2
  8. package/docs/functions/sharedQuery.sharedQuery.html +5 -1
  9. package/docs/functions/sharedQuery.useSharedQuery.html +5 -3
  10. package/docs/functions/sharedState.sharedState.html +1 -1
  11. package/docs/functions/sharedState.useSharedState.html +1 -1
  12. package/docs/functions/sharedState.useSharedStateSetter.html +1 -1
  13. package/docs/functions/sharedState.useSharedStateValue.html +1 -1
  14. package/docs/functions/utils_storage.getStorageAdapter.html +1 -1
  15. package/docs/functions/utils_stringify.stringifyDeterministicForKeys.html +1 -1
  16. package/docs/types/sharedQuery.FetchFn.html +1 -1
  17. package/docs/types/sharedQuery.PersistTo.html +1 -1
  18. package/docs/types/sharedQuery.QueryStateValue.html +5 -2
  19. package/docs/types/sharedQuery.SharedQueryOptions.html +1 -1
  20. package/docs/types/sharedQuery.SharedQueryState.html +1 -1
  21. package/docs/types/sharedQuery.UseQueryResult.html +1 -1
  22. package/docs/types/sharedState.SharedStateOptions.html +1 -1
  23. package/docs/types/utils_storage.StorageAdapter.html +2 -2
  24. package/docs/types/utils_storage.StorageOptions.html +2 -2
  25. package/docs/variables/fetcher.fetcher.html +1 -1
  26. package/docs/variables/fetcher.fetcherWithRetries.html +1 -1
  27. package/docs/variables/sharedQuery.SharedQueryDefaults.html +2 -2
  28. package/docs/variables/sharedState.SharedStateDefaults.html +1 -1
  29. package/package.json +33 -32
  30. package/sharedQuery.d.mts +30 -1
  31. package/sharedQuery.d.ts +30 -1
  32. package/sharedQuery.js +105 -4
  33. package/sharedQuery.mjs +95 -4
  34. package/src/sharedQuery.ts +159 -5
  35. package/src/utils/stringify.test.ts +0 -46
  36. package/utils/stringify.test.d.mts +0 -2
  37. package/utils/stringify.test.d.ts +0 -2
  38. package/utils/stringify.test.js +0 -69
  39. package/utils/stringify.test.mjs +0 -86
@@ -1,2 +1,2 @@
1
1
  <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>fetcher | Chok’s React Utilities</title><meta name="description" content="Documentation for Chok’s React Utilities"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">Chok’s React Utilities</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/fetcher.html">fetcher</a></li><li><a href="" aria-current="page">fetcher</a></li></ul><h1>Variable fetcher<code class="tsd-tag">Const</code></h1></div><div class="tsd-signature"><span class="tsd-kind-variable">fetcher</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Wretch</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol"> = ...</span></div><div class="tsd-comment tsd-typography"><p>Name this as &quot;fetcher&quot; to make it easier to understand.</p>
2
- </div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/choksheak/react-utils/blob/ad41baddd972618a95ea449a56501b128648cf9a/src/fetcher.ts#L5">fetcher.ts:5</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Chok’s React Utilities</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
2
+ </div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/choksheak/react-utils/blob/6e51f83891b45c4e9690241acb26557b1dbcce3f/src/fetcher.ts#L5">fetcher.ts:5</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Chok’s React Utilities</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
@@ -1,2 +1,2 @@
1
1
  <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>fetcherWithRetries | Chok’s React Utilities</title><meta name="description" content="Documentation for Chok’s React Utilities"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">Chok’s React Utilities</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/fetcher.html">fetcher</a></li><li><a href="" aria-current="page">fetcherWithRetries</a></li></ul><h1>Variable fetcherWithRetries<code class="tsd-tag">Const</code></h1></div><div class="tsd-signature"><span class="tsd-kind-variable">fetcherWithRetries</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">Wretch</span><span class="tsd-signature-symbol">&lt;</span><span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">unknown</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">,</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">&gt;</span><span class="tsd-signature-symbol"> = ...</span></div><div class="tsd-comment tsd-typography"><p>Fetcher with default short retries.</p>
2
- </div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/choksheak/react-utils/blob/ad41baddd972618a95ea449a56501b128648cf9a/src/fetcher.ts#L8">fetcher.ts:8</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Chok’s React Utilities</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
2
+ </div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/choksheak/react-utils/blob/6e51f83891b45c4e9690241acb26557b1dbcce3f/src/fetcher.ts#L8">fetcher.ts:8</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Chok’s React Utilities</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
@@ -1,2 +1,2 @@
1
- <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>SharedQueryDefaults | Chok’s React Utilities</title><meta name="description" content="Documentation for Chok’s React Utilities"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">Chok’s React Utilities</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/sharedQuery.html">sharedQuery</a></li><li><a href="" aria-current="page">SharedQueryDefaults</a></li></ul><h1>Variable SharedQueryDefaults<code class="tsd-tag">Const</code></h1></div><div class="tsd-signature"><span class="tsd-kind-variable">SharedQueryDefaults</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{</span><br/>    <span class="tsd-kind-property">expiryMs</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br/>    <span class="tsd-kind-property">persistTo</span><span class="tsd-signature-symbol">:</span> <a href="../types/sharedQuery.PersistTo.html" class="tsd-signature-type tsd-kind-type-alias">PersistTo</a> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">;</span><br/>    <span class="tsd-kind-property">staleMs</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br/><span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol"> = ...</span></div><div class="tsd-comment tsd-typography"><p>Users can override these values globally.</p>
2
- </div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter"><h5 id="expiryms"><span class="tsd-kind-property">expiryMs</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5></li><li class="tsd-parameter"><h5 id="persistto"><span class="tsd-kind-property">persistTo</span><span class="tsd-signature-symbol">: </span><a href="../types/sharedQuery.PersistTo.html" class="tsd-signature-type tsd-kind-type-alias">PersistTo</a> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h5></li><li class="tsd-parameter"><h5 id="stalems"><span class="tsd-kind-property">staleMs</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/choksheak/react-utils/blob/ad41baddd972618a95ea449a56501b128648cf9a/src/sharedQuery.ts#L62">sharedQuery.ts:62</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Chok’s React Utilities</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
1
+ <!DOCTYPE html><html class="default" lang="en" data-base="../"><head><meta charset="utf-8"/><meta http-equiv="x-ua-compatible" content="IE=edge"/><title>SharedQueryDefaults | Chok’s React Utilities</title><meta name="description" content="Documentation for Chok’s React Utilities"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="stylesheet" href="../assets/style.css"/><link rel="stylesheet" href="../assets/highlight.css"/><script defer src="../assets/main.js"></script><script async src="../assets/icons.js" id="tsd-icons-script"></script><script async src="../assets/search.js" id="tsd-search-script"></script><script async src="../assets/navigation.js" id="tsd-nav-script"></script></head><body><script>document.documentElement.dataset.theme = localStorage.getItem("tsd-theme") || "os";document.body.style.display="none";setTimeout(() => window.app?app.showPage():document.body.style.removeProperty("display"),500)</script><header class="tsd-page-toolbar"><div class="tsd-toolbar-contents container"><a href="../index.html" class="title">Chok’s React Utilities</a><div id="tsd-toolbar-links"></div><button id="tsd-search-trigger" class="tsd-widget" aria-label="Search"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-search"></use></svg></button><dialog id="tsd-search" aria-label="Search"><input role="combobox" id="tsd-search-input" aria-controls="tsd-search-results" aria-autocomplete="list" aria-expanded="true" autocapitalize="off" autocomplete="off" placeholder="Search the docs" maxLength="100"/><ul role="listbox" id="tsd-search-results"></ul><div id="tsd-search-status" aria-live="polite" aria-atomic="true"><div>Preparing search index...</div></div></dialog><a href="#" class="tsd-widget menu" id="tsd-toolbar-menu-trigger" data-toggle="menu" aria-label="Menu"><svg width="16" height="16" viewBox="0 0 16 16" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-menu"></use></svg></a></div></header><div class="container container-main"><div class="col-content"><div class="tsd-page-title"><ul class="tsd-breadcrumb" aria-label="Breadcrumb"><li><a href="../modules/sharedQuery.html">sharedQuery</a></li><li><a href="" aria-current="page">SharedQueryDefaults</a></li></ul><h1>Variable SharedQueryDefaults<code class="tsd-tag">Const</code></h1></div><div class="tsd-signature"><span class="tsd-kind-variable">SharedQueryDefaults</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-symbol">{</span><br/>    <span class="tsd-kind-property">expiryMs</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br/>    <span class="tsd-kind-property">maxBytes</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br/>    <span class="tsd-kind-property">maxSize</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br/>    <span class="tsd-kind-property">persistTo</span><span class="tsd-signature-symbol">:</span> <a href="../types/sharedQuery.PersistTo.html" class="tsd-signature-type tsd-kind-type-alias">PersistTo</a> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span><span class="tsd-signature-symbol">;</span><br/>    <span class="tsd-kind-property">staleMs</span><span class="tsd-signature-symbol">:</span> <span class="tsd-signature-type">number</span><span class="tsd-signature-symbol">;</span><br/><span class="tsd-signature-symbol">}</span><span class="tsd-signature-symbol"> = ...</span></div><div class="tsd-comment tsd-typography"><p>Users can override these values globally.</p>
2
+ </div><div class="tsd-type-declaration"><h4>Type Declaration</h4><ul class="tsd-parameters"><li class="tsd-parameter"><h5 id="expiryms"><span class="tsd-kind-property">expiryMs</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5></li><li class="tsd-parameter"><h5 id="maxbytes"><span class="tsd-kind-property">maxBytes</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5></li><li class="tsd-parameter"><h5 id="maxsize"><span class="tsd-kind-property">maxSize</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5></li><li class="tsd-parameter"><h5 id="persistto"><span class="tsd-kind-property">persistTo</span><span class="tsd-signature-symbol">: </span><a href="../types/sharedQuery.PersistTo.html" class="tsd-signature-type tsd-kind-type-alias">PersistTo</a> <span class="tsd-signature-symbol">|</span> <span class="tsd-signature-type">undefined</span></h5></li><li class="tsd-parameter"><h5 id="stalems"><span class="tsd-kind-property">staleMs</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/choksheak/react-utils/blob/6e51f83891b45c4e9690241acb26557b1dbcce3f/src/sharedQuery.ts#L77">sharedQuery.ts:77</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Chok’s React Utilities</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
@@ -3,4 +3,4 @@
3
3
  the top level scope when the shared state is defined.</p>
4
4
  </div></li><li class="tsd-parameter"><h5 id="storeexpiryms"><span class="tsd-kind-property">storeExpiryMs</span><span class="tsd-signature-symbol">: </span><span class="tsd-signature-type">number</span></h5><div class="tsd-comment tsd-typography"><p>Default duration for storage expiration in milliseconds. Initial value
5
5
  is 30 days, but can be changed to anything.</p>
6
- </div></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/choksheak/react-utils/blob/ad41baddd972618a95ea449a56501b128648cf9a/src/sharedState.ts#L28">sharedState.ts:28</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Chok’s React Utilities</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
6
+ </div></li></ul></div><aside class="tsd-sources"><ul><li>Defined in <a href="https://github.com/choksheak/react-utils/blob/6e51f83891b45c4e9690241acb26557b1dbcce3f/src/sharedState.ts#L28">sharedState.ts:28</a></li></ul></aside></div><div class="col-sidebar"><div class="page-menu"><div class="tsd-navigation settings"><details class="tsd-accordion"><summary class="tsd-accordion-summary"><svg width="20" height="20" viewBox="0 0 24 24" fill="none" aria-hidden="true"><use href="../assets/icons.svg#icon-chevronDown"></use></svg><h3>Settings</h3></summary><div class="tsd-accordion-details"><div class="tsd-filter-visibility"><span class="settings-label">Member Visibility</span><ul id="tsd-filter-options"><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-protected" name="protected"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Protected</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-inherited" name="inherited" checked/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>Inherited</span></label></li><li class="tsd-filter-item"><label class="tsd-filter-input"><input type="checkbox" id="tsd-filter-external" name="external"/><svg width="32" height="32" viewBox="0 0 32 32" aria-hidden="true"><rect class="tsd-checkbox-background" width="30" height="30" x="1" y="1" rx="6" fill="none"></rect><path class="tsd-checkbox-checkmark" d="M8.35422 16.8214L13.2143 21.75L24.6458 10.25" stroke="none" stroke-width="3.5" stroke-linejoin="round" fill="none"></path></svg><span>External</span></label></li></ul></div><div class="tsd-theme-toggle"><label class="settings-label" for="tsd-theme">Theme</label><select id="tsd-theme"><option value="os">OS</option><option value="light">Light</option><option value="dark">Dark</option></select></div></div></details></div></div><div class="site-menu"><nav class="tsd-navigation"><a href="../modules.html">Chok’s React Utilities</a><ul class="tsd-small-nested-navigation" id="tsd-nav-container"><li>Loading...</li></ul></nav></div></div></div><footer><p class="tsd-generator">Generated using <a href="https://typedoc.org/" target="_blank">TypeDoc</a></p></footer><div class="overlay"></div></body></html>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@choksheak/react-utils",
3
3
  "license": "The Unlicense",
4
- "version": "0.2.2",
4
+ "version": "0.2.3",
5
5
  "description": "Miscellaneous React+TypeScript utilities with support for full tree-shaking.",
6
6
  "private": false,
7
7
  "main": "index.js",
@@ -10,34 +10,6 @@
10
10
  "files": [
11
11
  "**/*"
12
12
  ],
13
- "exports": {
14
- "./package.json": "./package.json",
15
- "./fetcher": {
16
- "types": "./fetcher.d.ts",
17
- "import": "./fetcher.js"
18
- },
19
- "./sharedQuery": {
20
- "types": "./sharedQuery.d.ts",
21
- "import": "./sharedQuery.js"
22
- },
23
- "./sharedState": {
24
- "types": "./sharedState.d.ts",
25
- "import": "./sharedState.js"
26
- }
27
- },
28
- "typesVersions": {
29
- "*": {
30
- "fetcher": [
31
- "fetcher.d.ts"
32
- ],
33
- "sharedQuery": [
34
- "sharedQuery.d.ts"
35
- ],
36
- "sharedState": [
37
- "sharedState.d.ts"
38
- ]
39
- }
40
- },
41
13
  "scripts": {
42
14
  "lint": "eslint .",
43
15
  "fix": "eslint . --fix",
@@ -50,6 +22,7 @@
50
22
  "ls": "lint-staged",
51
23
  "docs": "rm -rf docs && typedoc `find src -name '*.ts' ! -name '*.test.ts'` --out docs --name 'Chok’s React Utilities'",
52
24
  "gen-types": "tsc --emitDeclarationOnly --declaration",
25
+ "gen-exports": "tsx scripts/gen-exports.ts",
53
26
  "bump": "tsx scripts/bump-version.ts",
54
27
  "bump:patch": "tsx scripts/bump-version.ts --patch",
55
28
  "bump:minor": "tsx scripts/bump-version.ts --minor",
@@ -57,7 +30,7 @@
57
30
  "pkg": "scripts/package.sh",
58
31
  "pub": "npm publish dist/ --access=public",
59
32
  "commit": "scripts/commit-release.sh",
60
- "release": "npm run ci && npm run bump && npm run pkg && npm run pub && npm run commit",
33
+ "release": "npm run ci && npm run bump && npm i && npm run pkg && npm run pub && npm run commit",
61
34
  "postinstall": "simple-git-hooks"
62
35
  },
63
36
  "simple-git-hooks": {
@@ -90,7 +63,6 @@
90
63
  "devDependencies": {
91
64
  "@eslint/compat": "^1.4.0",
92
65
  "@eslint/js": "^9.38.0",
93
- "@tanstack/react-query": "^5.90.5",
94
66
  "@types/jest": "^30.0.0",
95
67
  "@types/react": "^19.2.2",
96
68
  "@types/react-dom": "^19.2.2",
@@ -107,6 +79,7 @@
107
79
  "globals": "^16.4.0",
108
80
  "jiti": "^2.6.1",
109
81
  "lint-staged": "^16.2.6",
82
+ "object-sizeof": "^2.6.5",
110
83
  "prettier": "^3.6.2",
111
84
  "react": "^19.2.0",
112
85
  "react-dom": "^19.2.0",
@@ -121,8 +94,36 @@
121
94
  },
122
95
  "peerDependencies": {
123
96
  "@choksheak/ts-utils": ">=0.2.9",
124
- "@tanstack/react-query": ">=5",
97
+ "object-sizeof": ">=2.6.5",
125
98
  "react": ">=16",
126
99
  "wretch": ">=3"
100
+ },
101
+ "exports": {
102
+ "./package.json": "./package.json",
103
+ "./fetcher": {
104
+ "types": "./fetcher.d.ts",
105
+ "import": "./fetcher.js"
106
+ },
107
+ "./sharedQuery": {
108
+ "types": "./sharedQuery.d.ts",
109
+ "import": "./sharedQuery.js"
110
+ },
111
+ "./sharedState": {
112
+ "types": "./sharedState.d.ts",
113
+ "import": "./sharedState.js"
114
+ }
115
+ },
116
+ "typesVersions": {
117
+ "*": {
118
+ "fetcher": [
119
+ "./fetcher.d.ts"
120
+ ],
121
+ "sharedQuery": [
122
+ "./sharedQuery.d.ts"
123
+ ],
124
+ "sharedState": [
125
+ "./sharedState.d.ts"
126
+ ]
127
+ }
127
128
  }
128
129
  }
package/sharedQuery.d.mts CHANGED
@@ -3,6 +3,11 @@ import './utils/storage.mjs';
3
3
 
4
4
  type FetchFn<TArgs extends unknown[], TData> = (...args: TArgs) => Promise<TData> | TData;
5
5
  type QueryStateValue<TData> = {
6
+ /**
7
+ * When this record was last updated. Used for LRU determination. If you want
8
+ * the data age, please use `dataUpdatedMs` instead.
9
+ */
10
+ lastUpdatedMs: number;
6
11
  loading: boolean;
7
12
  data?: TData;
8
13
  dataUpdatedMs?: number;
@@ -27,12 +32,16 @@ type SharedQueryOptions<TArgs extends unknown[], TData> = {
27
32
  expiryMs?: number;
28
33
  refetchOnStale?: boolean;
29
34
  persistTo?: PersistTo;
35
+ maxSize?: number;
36
+ maxBytes?: number;
30
37
  } & SharedStateOptions<SharedQueryState<TData>>;
31
38
  /** Users can override these values globally. */
32
39
  declare const SharedQueryDefaults: {
33
40
  staleMs: number;
34
41
  expiryMs: number;
35
42
  persistTo: PersistTo | undefined;
43
+ maxSize: number;
44
+ maxBytes: number;
36
45
  };
37
46
  declare class SharedQuery<TArgs extends unknown[], TData> {
38
47
  private readonly inflightPromises;
@@ -42,6 +51,8 @@ declare class SharedQuery<TArgs extends unknown[], TData> {
42
51
  readonly expiryMs: number;
43
52
  readonly staleMs: number;
44
53
  readonly refetchOnStale: boolean;
54
+ readonly maxSize: number;
55
+ readonly maxBytes: number;
45
56
  constructor(options: SharedQueryOptions<TArgs, TData>);
46
57
  getQueryKey(args: TArgs): string;
47
58
  private isStale;
@@ -57,6 +68,11 @@ declare class SharedQuery<TArgs extends unknown[], TData> {
57
68
  deleteData(args: TArgs): void;
58
69
  /** Delete all currently cached data & all inflight promises. */
59
70
  clear(): void;
71
+ /**
72
+ * Discard the oldest entries if the size exceeds the limit. The last
73
+ * remaining record cannot be deleted no matter what the limit is.
74
+ */
75
+ enforceSizeLimit(): void;
60
76
  }
61
77
  /**
62
78
  * Create a reusable shared query object that can be used to auto de-duplicate
@@ -64,12 +80,25 @@ declare class SharedQuery<TArgs extends unknown[], TData> {
64
80
  *
65
81
  * Each `queryName` must be unique, and can only be declared once, most often
66
82
  * in the top level scope. The queryName is used for logging only.
83
+ *
84
+ * Example:
85
+ * ```
86
+ * export const usersQuery = sharedQuery({
87
+ * queryName: "users",
88
+ * queryFn: listUsers,
89
+ * persistTo: "indexedDb",
90
+ * staleMs: MS_PER_DAY,
91
+ * });
92
+ * ```
67
93
  */
68
94
  declare function sharedQuery<TArgs extends unknown[], TData>(options: SharedQueryOptions<TArgs, TData>): SharedQuery<TArgs, TData>;
69
95
  /**
70
96
  * React hook to make use of a shared query inside any React component.
71
97
  *
72
- * const users = useSharedQuery(usersQuery, ["123"]);
98
+ * Example:
99
+ * ```
100
+ * const users = useSharedQuery(usersQuery, ["123"]);
101
+ * ```
73
102
  */
74
103
  declare function useSharedQuery<TArgs extends unknown[], TData>(query: SharedQuery<TArgs, TData>, args?: TArgs): UseQueryResult<TData>;
75
104
 
package/sharedQuery.d.ts CHANGED
@@ -1,6 +1,11 @@
1
1
  import { SharedState, SharedStateOptions } from "./sharedState";
2
2
  export type FetchFn<TArgs extends unknown[], TData> = (...args: TArgs) => Promise<TData> | TData;
3
3
  export type QueryStateValue<TData> = {
4
+ /**
5
+ * When this record was last updated. Used for LRU determination. If you want
6
+ * the data age, please use `dataUpdatedMs` instead.
7
+ */
8
+ lastUpdatedMs: number;
4
9
  loading: boolean;
5
10
  data?: TData;
6
11
  dataUpdatedMs?: number;
@@ -25,12 +30,16 @@ export type SharedQueryOptions<TArgs extends unknown[], TData> = {
25
30
  expiryMs?: number;
26
31
  refetchOnStale?: boolean;
27
32
  persistTo?: PersistTo;
33
+ maxSize?: number;
34
+ maxBytes?: number;
28
35
  } & SharedStateOptions<SharedQueryState<TData>>;
29
36
  /** Users can override these values globally. */
30
37
  export declare const SharedQueryDefaults: {
31
38
  staleMs: number;
32
39
  expiryMs: number;
33
40
  persistTo: PersistTo | undefined;
41
+ maxSize: number;
42
+ maxBytes: number;
34
43
  };
35
44
  export declare class SharedQuery<TArgs extends unknown[], TData> {
36
45
  private readonly inflightPromises;
@@ -40,6 +49,8 @@ export declare class SharedQuery<TArgs extends unknown[], TData> {
40
49
  readonly expiryMs: number;
41
50
  readonly staleMs: number;
42
51
  readonly refetchOnStale: boolean;
52
+ readonly maxSize: number;
53
+ readonly maxBytes: number;
43
54
  constructor(options: SharedQueryOptions<TArgs, TData>);
44
55
  getQueryKey(args: TArgs): string;
45
56
  private isStale;
@@ -55,6 +66,11 @@ export declare class SharedQuery<TArgs extends unknown[], TData> {
55
66
  deleteData(args: TArgs): void;
56
67
  /** Delete all currently cached data & all inflight promises. */
57
68
  clear(): void;
69
+ /**
70
+ * Discard the oldest entries if the size exceeds the limit. The last
71
+ * remaining record cannot be deleted no matter what the limit is.
72
+ */
73
+ enforceSizeLimit(): void;
58
74
  }
59
75
  /**
60
76
  * Create a reusable shared query object that can be used to auto de-duplicate
@@ -62,11 +78,24 @@ export declare class SharedQuery<TArgs extends unknown[], TData> {
62
78
  *
63
79
  * Each `queryName` must be unique, and can only be declared once, most often
64
80
  * in the top level scope. The queryName is used for logging only.
81
+ *
82
+ * Example:
83
+ * ```
84
+ * export const usersQuery = sharedQuery({
85
+ * queryName: "users",
86
+ * queryFn: listUsers,
87
+ * persistTo: "indexedDb",
88
+ * staleMs: MS_PER_DAY,
89
+ * });
90
+ * ```
65
91
  */
66
92
  export declare function sharedQuery<TArgs extends unknown[], TData>(options: SharedQueryOptions<TArgs, TData>): SharedQuery<TArgs, TData>;
67
93
  /**
68
94
  * React hook to make use of a shared query inside any React component.
69
95
  *
70
- * const users = useSharedQuery(usersQuery, ["123"]);
96
+ * Example:
97
+ * ```
98
+ * const users = useSharedQuery(usersQuery, ["123"]);
99
+ * ```
71
100
  */
72
101
  export declare function useSharedQuery<TArgs extends unknown[], TData>(query: SharedQuery<TArgs, TData>, args?: TArgs): UseQueryResult<TData>;
package/sharedQuery.js CHANGED
@@ -1,7 +1,9 @@
1
1
  "use strict";
2
+ var __create = Object.create;
2
3
  var __defProp = Object.defineProperty;
3
4
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
5
  var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
5
7
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
8
  var __export = (target, all) => {
7
9
  for (var name in all)
@@ -15,6 +17,14 @@ var __copyProps = (to, from, except, desc) => {
15
17
  }
16
18
  return to;
17
19
  };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
18
28
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
29
 
20
30
  // src/sharedQuery.ts
@@ -27,6 +37,7 @@ __export(sharedQuery_exports, {
27
37
  });
28
38
  module.exports = __toCommonJS(sharedQuery_exports);
29
39
  var import_timeConstants2 = require("@choksheak/ts-utils/timeConstants");
40
+ var import_object_sizeof = __toESM(require("object-sizeof"));
30
41
  var import_react2 = require("react");
31
42
 
32
43
  // src/sharedState.ts
@@ -296,7 +307,11 @@ function stringifyDeterministicForKeys(params) {
296
307
  var SharedQueryDefaults = {
297
308
  staleMs: 0,
298
309
  expiryMs: 30 * import_timeConstants2.MS_PER_DAY,
299
- persistTo: void 0
310
+ persistTo: void 0,
311
+ maxSize: 100,
312
+ // 100 is not too large, but please tweak accordingly
313
+ maxBytes: 1e5
314
+ // 100kb before GC
300
315
  };
301
316
  var SharedQuery = class {
302
317
  inflightPromises = /* @__PURE__ */ new Map();
@@ -306,6 +321,8 @@ var SharedQuery = class {
306
321
  expiryMs;
307
322
  staleMs;
308
323
  refetchOnStale;
324
+ maxSize;
325
+ maxBytes;
309
326
  constructor(options) {
310
327
  this.queryName = options.queryName;
311
328
  this.queryFn = options.queryFn;
@@ -318,6 +335,8 @@ var SharedQuery = class {
318
335
  } else if (persistTo === "indexedDb") {
319
336
  options.indexedDbKey = options.queryName;
320
337
  }
338
+ this.maxSize = options?.maxSize ?? SharedQueryDefaults.maxSize;
339
+ this.maxBytes = options?.maxBytes ?? SharedQueryDefaults.maxBytes;
321
340
  this.queryState = sharedState(
322
341
  {},
323
342
  {
@@ -386,11 +405,13 @@ var SharedQuery = class {
386
405
  /** Set the data directly if the user obtained it from somewhere else. */
387
406
  async setData(queryKey, data, dataUpdatedMs = Date.now()) {
388
407
  const entry = {
408
+ lastUpdatedMs: Date.now(),
389
409
  loading: false,
390
410
  data,
391
411
  dataUpdatedMs
392
412
  };
393
413
  this.queryState.setValue((prev) => ({ ...prev, [queryKey]: entry }));
414
+ this.enforceSizeLimit();
394
415
  }
395
416
  /** Do a new fetch even when the data is already cached. */
396
417
  async updateFromSource(...args) {
@@ -411,6 +432,78 @@ var SharedQuery = class {
411
432
  this.queryState.delete();
412
433
  this.inflightPromises.clear();
413
434
  }
435
+ /**
436
+ * Discard the oldest entries if the size exceeds the limit. The last
437
+ * remaining record cannot be deleted no matter what the limit is.
438
+ */
439
+ enforceSizeLimit() {
440
+ if (!this.maxSize && !this.maxBytes) {
441
+ return;
442
+ }
443
+ const oldState = this.queryState.getSnapshot();
444
+ const oldSize = Object.keys(oldState).length;
445
+ if (oldSize <= 1) {
446
+ return;
447
+ }
448
+ const oldByteSize = (0, import_object_sizeof.default)(oldState);
449
+ let newState = oldState;
450
+ let needUpdate = false;
451
+ if (this.maxSize) {
452
+ const numToCut = oldSize - this.maxSize;
453
+ if (numToCut > 0) {
454
+ console.log(
455
+ `enforceSizeLimit for ${this.queryName} needed due to size ${oldSize} > ${this.maxSize}`
456
+ );
457
+ newState = { ...newState };
458
+ needUpdate = true;
459
+ Object.entries(newState).sort(
460
+ (entry1, entry2) => (
461
+ // Sort descending.
462
+ entry2[1].lastUpdatedMs - entry1[1].lastUpdatedMs
463
+ )
464
+ ).slice(-numToCut).forEach(([key]) => {
465
+ delete newState[key];
466
+ });
467
+ }
468
+ }
469
+ if (this.maxBytes && Object.keys(newState).length > 1) {
470
+ const currentByteSize = needUpdate ? (0, import_object_sizeof.default)(newState) : oldByteSize;
471
+ let bytesToCut = currentByteSize - this.maxBytes;
472
+ if (bytesToCut > 0) {
473
+ console.log(
474
+ `enforceSizeLimit for ${this.queryName} needed due to byte size ${currentByteSize.toLocaleString()} > ${this.maxBytes.toLocaleString()}`
475
+ );
476
+ if (!needUpdate) {
477
+ newState = { ...newState };
478
+ needUpdate = true;
479
+ }
480
+ const entriesByTimeAscending = Object.entries(newState).sort(
481
+ (entry1, entry2) => entry1[1].lastUpdatedMs - entry2[1].lastUpdatedMs
482
+ );
483
+ for (
484
+ let i = 0;
485
+ // Leave the last record entriesByTimeAscending[len-1] untouched.
486
+ i < entriesByTimeAscending.length - 1 && bytesToCut > 0;
487
+ i++
488
+ ) {
489
+ const key = entriesByTimeAscending[i][0];
490
+ const thisSize = (0, import_object_sizeof.default)(key) + (0, import_object_sizeof.default)(newState[key]);
491
+ delete newState[key];
492
+ bytesToCut -= thisSize;
493
+ }
494
+ }
495
+ }
496
+ if (needUpdate) {
497
+ this.queryState.setValue(newState);
498
+ console.log(
499
+ `Trimmed data for ${this.queryName}: size=(${oldSize} -> ${Object.keys(newState).length}) (limit=${this.maxSize}), byteSize=(${oldByteSize.toLocaleString()} -> ${(0, import_object_sizeof.default)(newState).toLocaleString()}) (limit=${this.maxBytes.toLocaleString()})`
500
+ );
501
+ return;
502
+ }
503
+ console.log(
504
+ `No need to trim data for ${this.queryName}: size=${oldSize} (limit=${this.maxSize}), byteSize=${oldByteSize.toLocaleString()} (limit=${this.maxBytes.toLocaleString()})`
505
+ );
506
+ }
414
507
  };
415
508
  var seenQueryNames = /* @__PURE__ */ new Set();
416
509
  function sharedQuery(options) {
@@ -420,7 +513,10 @@ function sharedQuery(options) {
420
513
  seenQueryNames.add(options.queryName);
421
514
  return new SharedQuery(options);
422
515
  }
423
- var DEFAULT_QUERY_STATE_ENTRY = { loading: true };
516
+ var DEFAULT_QUERY_STATE_ENTRY = {
517
+ lastUpdatedMs: 0,
518
+ loading: true
519
+ };
424
520
  function useSharedQuery(query, args = []) {
425
521
  const [queryState, setQueryState] = useSharedState(query.queryState);
426
522
  const isMounted = (0, import_react2.useRef)(true);
@@ -431,6 +527,7 @@ function useSharedQuery(query, args = []) {
431
527
  const clone = { ...prev };
432
528
  clone[queryKey] = {
433
529
  ...clone[queryKey] ?? {},
530
+ lastUpdatedMs: Date.now(),
434
531
  loading: true
435
532
  };
436
533
  return clone;
@@ -440,11 +537,13 @@ function useSharedQuery(query, args = []) {
440
537
  if (isMounted.current) {
441
538
  setQueryState((prev) => {
442
539
  const clone = { ...prev };
540
+ const now = Date.now();
443
541
  clone[queryKey] = {
444
542
  // Don't keep old error.
543
+ lastUpdatedMs: now,
445
544
  loading: false,
446
545
  data,
447
- dataUpdatedMs: Date.now()
546
+ dataUpdatedMs: now
448
547
  };
449
548
  return clone;
450
549
  });
@@ -454,12 +553,14 @@ function useSharedQuery(query, args = []) {
454
553
  if (isMounted.current) {
455
554
  setQueryState((prev) => {
456
555
  const clone = { ...prev };
556
+ const now = Date.now();
457
557
  clone[queryKey] = {
458
558
  // Keep old data.
459
559
  ...clone[queryKey] ?? {},
560
+ lastUpdatedMs: now,
460
561
  loading: false,
461
562
  error,
462
- errorUpdatedMs: Date.now()
563
+ errorUpdatedMs: now
463
564
  };
464
565
  return clone;
465
566
  });