@upstash/react-redis-browser 0.1.8 → 0.1.10

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 (3) hide show
  1. package/dist/index.js +57 -177
  2. package/dist/index.mjs +63 -183
  3. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; } var _class;// src/components/databrowser/index.tsx
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/components/databrowser/index.tsx
2
2
  var _react = require('react'); var React = _interopRequireWildcard(_react); var React2 = _interopRequireWildcard(_react); var React3 = _interopRequireWildcard(_react); var React4 = _interopRequireWildcard(_react); var React5 = _interopRequireWildcard(_react); var React6 = _interopRequireWildcard(_react); var React7 = _interopRequireWildcard(_react); var React8 = _interopRequireWildcard(_react); var React9 = _interopRequireWildcard(_react); var React10 = _interopRequireWildcard(_react); var React11 = _interopRequireWildcard(_react); var React12 = _interopRequireWildcard(_react);
3
3
 
4
4
  // src/store.tsx
@@ -2917,181 +2917,51 @@ function Toaster() {
2917
2917
 
2918
2918
 
2919
2919
 
2920
-
2921
-
2922
-
2923
-
2924
-
2925
-
2926
- // src/components/databrowser/hooks/use-fetch-key-type.tsx
2927
-
2928
- var FETCH_KEY_TYPE_QUERY_KEY = "fetch-key-type";
2929
- var useFetchKeyType = (key) => {
2930
- const { redisNoPipeline: redis } = useDatabrowser();
2931
- return _reactquery.useQuery.call(void 0, {
2932
- queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key],
2933
- queryFn: async () => {
2934
- if (!key) return "none";
2935
- return await redis.type(key);
2936
- }
2937
- });
2938
- };
2939
-
2940
- // src/components/databrowser/hooks/use-fetch-keys.ts
2941
-
2942
-
2943
- // src/types/index.ts
2944
- var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
2945
- var DATA_TYPE_NAMES = {
2946
- string: "String",
2947
- list: "List",
2948
- hash: "Hash",
2949
- set: "Set",
2950
- zset: "Sorted Set",
2951
- json: "JSON",
2952
- stream: "Stream"
2953
- };
2954
-
2955
- // src/components/databrowser/hooks/use-fetch-keys.ts
2956
- var PAGE_SIZE = 30;
2957
- var FETCH_COUNTS = [100, 200, 400, 800];
2958
- var useFetchKeys = (search) => {
2959
- const { redisNoPipeline: redis } = useDatabrowser();
2960
- const cache = _react.useRef.call(void 0, );
2961
- const lastKey = _react.useRef.call(void 0, );
2962
- const fetchKeys = _react.useCallback.call(void 0, () => {
2963
- const newKey = JSON.stringify(search);
2964
- if (!cache.current || lastKey.current !== newKey) {
2965
- cache.current = new PaginationCache(redis, search.key, search.type);
2966
- lastKey.current = newKey;
2967
- }
2968
- return cache.current.fetchNewKeys();
2969
- }, [search]);
2970
- const resetCache = _react.useCallback.call(void 0, () => {
2971
- cache.current = void 0;
2972
- lastKey.current = void 0;
2973
- }, []);
2974
- return {
2975
- fetchKeys,
2976
- resetCache
2977
- };
2978
- };
2979
- var PaginationCache = (_class = class {
2980
- constructor(redis, searchTerm, typeFilter) {;_class.prototype.__init.call(this);_class.prototype.__init2.call(this);_class.prototype.__init3.call(this);_class.prototype.__init4.call(this);
2981
- this.redis = redis;
2982
- this.searchTerm = searchTerm;
2983
- this.typeFilter = typeFilter;
2984
- if (typeFilter && !DATA_TYPES.includes(typeFilter)) {
2985
- throw new Error(`Invalid type filter: ${typeFilter}`);
2986
- }
2987
- }
2988
- // Cursor is 0 initially, then it is set to -1 when we reach the end
2989
- __init() {this.cache = Object.fromEntries(
2990
- DATA_TYPES.map((type) => [type, { cursor: "0", keys: [] }])
2991
- )}
2992
- __init2() {this.targetCount = 0}
2993
- __init3() {this.isFetching = false}
2994
- async fetchNewKeys() {
2995
- const initialKeys = new Set(this.getKeys().map(([key]) => key));
2996
- this.targetCount = this.getKeys().length + PAGE_SIZE;
2997
- void this.startFetch();
2998
- await new Promise((resolve) => {
2999
- const interval = setInterval(() => {
3000
- if (this.getLength() >= this.targetCount || this.isAllEnded()) {
3001
- clearInterval(interval);
3002
- resolve();
3003
- }
3004
- }, 100);
3005
- });
3006
- const hasNextPage = !this.isAllEnded();
3007
- return {
3008
- keys: this.getKeys().filter(([key]) => !initialKeys.has(key)),
3009
- hasNextPage
3010
- };
3011
- }
3012
- getLength() {
3013
- return Object.values(this.cache).reduce((acc, curr) => acc + curr.keys.length, 0);
3014
- }
3015
- getKeys() {
3016
- const keys = Object.entries(this.cache).flatMap(([type, { keys: keys2 }]) => {
3017
- return keys2.map((key) => [key, type]);
3018
- });
3019
- const sorted = keys.sort((a, b) => a[0].localeCompare(b[0]));
3020
- return sorted;
3021
- }
3022
- async startFetch() {
3023
- if (this.isFetching) {
3024
- return;
3025
- }
3026
- this.isFetching = true;
3027
- try {
3028
- await this.fetch();
3029
- } finally {
3030
- this.isFetching = false;
3031
- }
3032
- }
3033
- __init4() {this.fetchForType = async (type) => {
3034
- let i = 0;
3035
- while (true) {
3036
- const cursor = this.cache[type].cursor;
3037
- if (cursor === "-1" || this.getLength() >= this.targetCount) {
3038
- break;
3039
- }
3040
- const fetchCount = FETCH_COUNTS[Math.min(i, FETCH_COUNTS.length - 1)];
3041
- const [nextCursor, newKeys] = await this.redis.scan(cursor, {
3042
- count: fetchCount,
3043
- match: this.searchTerm,
3044
- type
3045
- });
3046
- this.cache[type].keys = [...this.cache[type].keys, ...newKeys];
3047
- this.cache[type].cursor = nextCursor === "0" ? "-1" : nextCursor;
3048
- i++;
3049
- }
3050
- }}
3051
- async fetch() {
3052
- const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3053
- await Promise.all(types.map(this.fetchForType));
3054
- }
3055
- isAllEnded() {
3056
- const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3057
- return types.every((type) => this.cache[type] && this.cache[type].cursor === "-1");
3058
- }
3059
- }, _class);
3060
-
3061
- // src/components/databrowser/hooks/use-keys.tsx
3062
-
3063
2920
  var KeysContext = _react.createContext.call(void 0, void 0);
3064
2921
  var FETCH_KEYS_QUERY_KEY = "use-fetch-keys";
2922
+ var SCAN_COUNT = 100;
3065
2923
  var KeysProvider = ({ children }) => {
3066
2924
  const { search } = useDatabrowserStore();
3067
- const cleanSearchKey = search.key.replace("*", "");
3068
- const { data: exactMatchType, isFetching, isLoading } = useFetchKeyType(cleanSearchKey);
3069
- const { fetchKeys, resetCache } = useFetchKeys(search);
3070
- const pageRef = _react.useRef.call(void 0, 0);
2925
+ const { redisNoPipeline: redis } = useDatabrowser();
3071
2926
  const query = _reactquery.useInfiniteQuery.call(void 0, {
3072
2927
  queryKey: [FETCH_KEYS_QUERY_KEY, search],
3073
- initialPageParam: 0,
3074
- queryFn: async ({ pageParam: page }) => {
3075
- if (pageRef.current >= page) resetCache();
3076
- pageRef.current = page;
3077
- return await fetchKeys();
2928
+ initialPageParam: "0",
2929
+ queryFn: async ({ pageParam: lastCursor }) => {
2930
+ const args = [lastCursor];
2931
+ if (search.key) {
2932
+ args.push("MATCH", search.key);
2933
+ }
2934
+ if (search.type) {
2935
+ args.push("TYPE", search.type);
2936
+ }
2937
+ args.push("COUNT", SCAN_COUNT.toString());
2938
+ if (!search.type) args.push("WITHTYPE");
2939
+ const [cursor, values] = await redis.exec(["SCAN", ...args]);
2940
+ const keys2 = [];
2941
+ let index = 0;
2942
+ while (true) {
2943
+ if (search.type) {
2944
+ if (index >= values.length) break;
2945
+ keys2.push([values[index], search.type]);
2946
+ index += 1;
2947
+ } else {
2948
+ if (index + 1 >= values.length) break;
2949
+ keys2.push([values[index], values[index + 1]]);
2950
+ index += 2;
2951
+ }
2952
+ }
2953
+ return {
2954
+ cursor: cursor === "0" ? void 0 : cursor,
2955
+ keys: keys2,
2956
+ hasNextPage: cursor !== "0"
2957
+ };
3078
2958
  },
3079
2959
  select: (data) => data,
3080
- getNextPageParam: (lastPage, __, lastPageIndex) => {
3081
- return lastPage.hasNextPage ? lastPageIndex + 1 : void 0;
3082
- },
3083
- enabled: !isFetching,
2960
+ getNextPageParam: ({ cursor }) => cursor,
3084
2961
  refetchOnMount: false
3085
2962
  });
3086
- const refetch = _react.useCallback.call(void 0, () => {
3087
- resetCache();
3088
- query.refetch();
3089
- }, [query, resetCache]);
3090
2963
  const keys = _react.useMemo.call(void 0, () => {
3091
2964
  const keys2 = _nullishCoalesce(_optionalChain([query, 'access', _10 => _10.data, 'optionalAccess', _11 => _11.pages, 'access', _12 => _12.flatMap, 'call', _13 => _13((page) => page.keys)]), () => ( []));
3092
- if (exactMatchType && exactMatchType !== "none" && (search.type === void 0 || search.type === exactMatchType)) {
3093
- keys2.push([cleanSearchKey, exactMatchType]);
3094
- }
3095
2965
  const keysSet = /* @__PURE__ */ new Set();
3096
2966
  const dedupedKeys = [];
3097
2967
  for (const key of keys2) {
@@ -3100,19 +2970,13 @@ var KeysProvider = ({ children }) => {
3100
2970
  dedupedKeys.push(key);
3101
2971
  }
3102
2972
  return dedupedKeys;
3103
- }, [query.data, cleanSearchKey, exactMatchType]);
2973
+ }, [query.data]);
3104
2974
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3105
2975
  KeysContext.Provider,
3106
2976
  {
3107
2977
  value: {
3108
2978
  keys,
3109
- // @ts-expect-error Ignore the error with spread syntax
3110
- query: {
3111
- ...query,
3112
- isLoading: isLoading || query.isLoading,
3113
- isFetching: isFetching || query.isFetching
3114
- },
3115
- refetch
2979
+ query
3116
2980
  },
3117
2981
  children
3118
2982
  }
@@ -3295,6 +3159,10 @@ var useAddKey = () => {
3295
3159
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3296
3160
 
3297
3161
 
3162
+ // src/components/databrowser/hooks/use-fetch-key-type.tsx
3163
+
3164
+ var FETCH_KEY_TYPE_QUERY_KEY = "fetch-key-type";
3165
+
3298
3166
  // src/components/databrowser/hooks/use-fetch-list-items.tsx
3299
3167
 
3300
3168
  var LIST_DISPLAY_PAGE_SIZE = 50;
@@ -3443,7 +3311,6 @@ var sortObject = (obj) => {
3443
3311
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3444
3312
  var useDeleteKeyCache = () => {
3445
3313
  const { setSelectedKey } = useDatabrowserStore();
3446
- const { refetch } = useKeys();
3447
3314
  const deleteKeyCache = _react.useCallback.call(void 0,
3448
3315
  (key) => {
3449
3316
  setSelectedKey(void 0);
@@ -3459,9 +3326,8 @@ var useDeleteKeyCache = () => {
3459
3326
  queryClient.invalidateQueries({
3460
3327
  queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key]
3461
3328
  });
3462
- refetch();
3463
3329
  },
3464
- [setSelectedKey, refetch]
3330
+ [setSelectedKey]
3465
3331
  );
3466
3332
  return { deleteKeyCache };
3467
3333
  };
@@ -4457,6 +4323,18 @@ var InfiniteScroll = ({
4457
4323
  // src/components/databrowser/components/display/display-header.tsx
4458
4324
 
4459
4325
 
4326
+ // src/types/index.ts
4327
+ var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
4328
+ var DATA_TYPE_NAMES = {
4329
+ string: "String",
4330
+ list: "List",
4331
+ hash: "Hash",
4332
+ set: "Set",
4333
+ zset: "Sorted Set",
4334
+ json: "JSON",
4335
+ stream: "Stream"
4336
+ };
4337
+
4460
4338
  // src/components/databrowser/components/type-tag.tsx
4461
4339
 
4462
4340
 
@@ -5720,7 +5598,7 @@ function DataTypeSelector() {
5720
5598
  // src/components/databrowser/components/sidebar/index.tsx
5721
5599
 
5722
5600
  function Sidebar() {
5723
- const { keys, query, refetch } = useKeys();
5601
+ const { keys, query } = useKeys();
5724
5602
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2 rounded-xl border bg-white p-1", children: [
5725
5603
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100 px-3 py-2", children: [
5726
5604
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center justify-between pl-1", children: [
@@ -5731,7 +5609,9 @@ function Sidebar() {
5731
5609
  {
5732
5610
  className: "h-7 w-7 px-0",
5733
5611
  onClick: () => {
5734
- refetch();
5612
+ queryClient.invalidateQueries({
5613
+ queryKey: [FETCH_KEYS_QUERY_KEY]
5614
+ });
5735
5615
  queryClient.invalidateQueries({
5736
5616
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
5737
5617
  });
package/dist/index.mjs CHANGED
@@ -2914,184 +2914,54 @@ function Toaster() {
2914
2914
  }
2915
2915
 
2916
2916
  // src/components/databrowser/hooks/use-keys.tsx
2917
- import {
2918
- createContext as createContext2,
2919
- useCallback as useCallback2,
2920
- useContext as useContext2,
2921
- useMemo as useMemo2,
2922
- useRef as useRef2
2923
- } from "react";
2917
+ import { createContext as createContext2, useContext as useContext2, useMemo as useMemo2 } from "react";
2924
2918
  import { useInfiniteQuery } from "@tanstack/react-query";
2925
-
2926
- // src/components/databrowser/hooks/use-fetch-key-type.tsx
2927
- import { useQuery } from "@tanstack/react-query";
2928
- var FETCH_KEY_TYPE_QUERY_KEY = "fetch-key-type";
2929
- var useFetchKeyType = (key) => {
2930
- const { redisNoPipeline: redis } = useDatabrowser();
2931
- return useQuery({
2932
- queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key],
2933
- queryFn: async () => {
2934
- if (!key) return "none";
2935
- return await redis.type(key);
2936
- }
2937
- });
2938
- };
2939
-
2940
- // src/components/databrowser/hooks/use-fetch-keys.ts
2941
- import { useCallback, useRef } from "react";
2942
-
2943
- // src/types/index.ts
2944
- var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
2945
- var DATA_TYPE_NAMES = {
2946
- string: "String",
2947
- list: "List",
2948
- hash: "Hash",
2949
- set: "Set",
2950
- zset: "Sorted Set",
2951
- json: "JSON",
2952
- stream: "Stream"
2953
- };
2954
-
2955
- // src/components/databrowser/hooks/use-fetch-keys.ts
2956
- var PAGE_SIZE = 30;
2957
- var FETCH_COUNTS = [100, 200, 400, 800];
2958
- var useFetchKeys = (search) => {
2959
- const { redisNoPipeline: redis } = useDatabrowser();
2960
- const cache = useRef();
2961
- const lastKey = useRef();
2962
- const fetchKeys = useCallback(() => {
2963
- const newKey = JSON.stringify(search);
2964
- if (!cache.current || lastKey.current !== newKey) {
2965
- cache.current = new PaginationCache(redis, search.key, search.type);
2966
- lastKey.current = newKey;
2967
- }
2968
- return cache.current.fetchNewKeys();
2969
- }, [search]);
2970
- const resetCache = useCallback(() => {
2971
- cache.current = void 0;
2972
- lastKey.current = void 0;
2973
- }, []);
2974
- return {
2975
- fetchKeys,
2976
- resetCache
2977
- };
2978
- };
2979
- var PaginationCache = class {
2980
- constructor(redis, searchTerm, typeFilter) {
2981
- this.redis = redis;
2982
- this.searchTerm = searchTerm;
2983
- this.typeFilter = typeFilter;
2984
- if (typeFilter && !DATA_TYPES.includes(typeFilter)) {
2985
- throw new Error(`Invalid type filter: ${typeFilter}`);
2986
- }
2987
- }
2988
- // Cursor is 0 initially, then it is set to -1 when we reach the end
2989
- cache = Object.fromEntries(
2990
- DATA_TYPES.map((type) => [type, { cursor: "0", keys: [] }])
2991
- );
2992
- targetCount = 0;
2993
- isFetching = false;
2994
- async fetchNewKeys() {
2995
- const initialKeys = new Set(this.getKeys().map(([key]) => key));
2996
- this.targetCount = this.getKeys().length + PAGE_SIZE;
2997
- void this.startFetch();
2998
- await new Promise((resolve) => {
2999
- const interval = setInterval(() => {
3000
- if (this.getLength() >= this.targetCount || this.isAllEnded()) {
3001
- clearInterval(interval);
3002
- resolve();
3003
- }
3004
- }, 100);
3005
- });
3006
- const hasNextPage = !this.isAllEnded();
3007
- return {
3008
- keys: this.getKeys().filter(([key]) => !initialKeys.has(key)),
3009
- hasNextPage
3010
- };
3011
- }
3012
- getLength() {
3013
- return Object.values(this.cache).reduce((acc, curr) => acc + curr.keys.length, 0);
3014
- }
3015
- getKeys() {
3016
- const keys = Object.entries(this.cache).flatMap(([type, { keys: keys2 }]) => {
3017
- return keys2.map((key) => [key, type]);
3018
- });
3019
- const sorted = keys.sort((a, b) => a[0].localeCompare(b[0]));
3020
- return sorted;
3021
- }
3022
- async startFetch() {
3023
- if (this.isFetching) {
3024
- return;
3025
- }
3026
- this.isFetching = true;
3027
- try {
3028
- await this.fetch();
3029
- } finally {
3030
- this.isFetching = false;
3031
- }
3032
- }
3033
- fetchForType = async (type) => {
3034
- let i = 0;
3035
- while (true) {
3036
- const cursor = this.cache[type].cursor;
3037
- if (cursor === "-1" || this.getLength() >= this.targetCount) {
3038
- break;
3039
- }
3040
- const fetchCount = FETCH_COUNTS[Math.min(i, FETCH_COUNTS.length - 1)];
3041
- const [nextCursor, newKeys] = await this.redis.scan(cursor, {
3042
- count: fetchCount,
3043
- match: this.searchTerm,
3044
- type
3045
- });
3046
- this.cache[type].keys = [...this.cache[type].keys, ...newKeys];
3047
- this.cache[type].cursor = nextCursor === "0" ? "-1" : nextCursor;
3048
- i++;
3049
- }
3050
- };
3051
- async fetch() {
3052
- const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3053
- await Promise.all(types.map(this.fetchForType));
3054
- }
3055
- isAllEnded() {
3056
- const types = this.typeFilter ? [this.typeFilter] : DATA_TYPES;
3057
- return types.every((type) => this.cache[type] && this.cache[type].cursor === "-1");
3058
- }
3059
- };
3060
-
3061
- // src/components/databrowser/hooks/use-keys.tsx
3062
2919
  import { jsx as jsx4 } from "react/jsx-runtime";
3063
2920
  var KeysContext = createContext2(void 0);
3064
2921
  var FETCH_KEYS_QUERY_KEY = "use-fetch-keys";
2922
+ var SCAN_COUNT = 100;
3065
2923
  var KeysProvider = ({ children }) => {
3066
2924
  const { search } = useDatabrowserStore();
3067
- const cleanSearchKey = search.key.replace("*", "");
3068
- const { data: exactMatchType, isFetching, isLoading } = useFetchKeyType(cleanSearchKey);
3069
- const { fetchKeys, resetCache } = useFetchKeys(search);
3070
- const pageRef = useRef2(0);
2925
+ const { redisNoPipeline: redis } = useDatabrowser();
3071
2926
  const query = useInfiniteQuery({
3072
2927
  queryKey: [FETCH_KEYS_QUERY_KEY, search],
3073
- initialPageParam: 0,
3074
- queryFn: async ({ pageParam: page }) => {
3075
- if (pageRef.current >= page) resetCache();
3076
- pageRef.current = page;
3077
- return await fetchKeys();
2928
+ initialPageParam: "0",
2929
+ queryFn: async ({ pageParam: lastCursor }) => {
2930
+ const args = [lastCursor];
2931
+ if (search.key) {
2932
+ args.push("MATCH", search.key);
2933
+ }
2934
+ if (search.type) {
2935
+ args.push("TYPE", search.type);
2936
+ }
2937
+ args.push("COUNT", SCAN_COUNT.toString());
2938
+ if (!search.type) args.push("WITHTYPE");
2939
+ const [cursor, values] = await redis.exec(["SCAN", ...args]);
2940
+ const keys2 = [];
2941
+ let index = 0;
2942
+ while (true) {
2943
+ if (search.type) {
2944
+ if (index >= values.length) break;
2945
+ keys2.push([values[index], search.type]);
2946
+ index += 1;
2947
+ } else {
2948
+ if (index + 1 >= values.length) break;
2949
+ keys2.push([values[index], values[index + 1]]);
2950
+ index += 2;
2951
+ }
2952
+ }
2953
+ return {
2954
+ cursor: cursor === "0" ? void 0 : cursor,
2955
+ keys: keys2,
2956
+ hasNextPage: cursor !== "0"
2957
+ };
3078
2958
  },
3079
2959
  select: (data) => data,
3080
- getNextPageParam: (lastPage, __, lastPageIndex) => {
3081
- return lastPage.hasNextPage ? lastPageIndex + 1 : void 0;
3082
- },
3083
- enabled: !isFetching,
2960
+ getNextPageParam: ({ cursor }) => cursor,
3084
2961
  refetchOnMount: false
3085
2962
  });
3086
- const refetch = useCallback2(() => {
3087
- resetCache();
3088
- query.refetch();
3089
- }, [query, resetCache]);
3090
2963
  const keys = useMemo2(() => {
3091
2964
  const keys2 = query.data?.pages.flatMap((page) => page.keys) ?? [];
3092
- if (exactMatchType && exactMatchType !== "none" && (search.type === void 0 || search.type === exactMatchType)) {
3093
- keys2.push([cleanSearchKey, exactMatchType]);
3094
- }
3095
2965
  const keysSet = /* @__PURE__ */ new Set();
3096
2966
  const dedupedKeys = [];
3097
2967
  for (const key of keys2) {
@@ -3100,19 +2970,13 @@ var KeysProvider = ({ children }) => {
3100
2970
  dedupedKeys.push(key);
3101
2971
  }
3102
2972
  return dedupedKeys;
3103
- }, [query.data, cleanSearchKey, exactMatchType]);
2973
+ }, [query.data]);
3104
2974
  return /* @__PURE__ */ jsx4(
3105
2975
  KeysContext.Provider,
3106
2976
  {
3107
2977
  value: {
3108
2978
  keys,
3109
- // @ts-expect-error Ignore the error with spread syntax
3110
- query: {
3111
- ...query,
3112
- isLoading: isLoading || query.isLoading,
3113
- isFetching: isFetching || query.isFetching
3114
- },
3115
- refetch
2979
+ query
3116
2980
  },
3117
2981
  children
3118
2982
  }
@@ -3179,7 +3043,7 @@ Button.displayName = "Button";
3179
3043
  import { useMutation } from "@tanstack/react-query";
3180
3044
 
3181
3045
  // src/components/databrowser/components/sidebar/db-size.tsx
3182
- import { useQuery as useQuery2 } from "@tanstack/react-query";
3046
+ import { useQuery } from "@tanstack/react-query";
3183
3047
 
3184
3048
  // src/components/ui/skeleton.tsx
3185
3049
  import { jsx as jsx6 } from "react/jsx-runtime";
@@ -3198,7 +3062,7 @@ import { jsx as jsx7, jsxs as jsxs2 } from "react/jsx-runtime";
3198
3062
  var FETCH_DB_SIZE_QUERY_KEY = "fetch-db-size";
3199
3063
  var DisplayDbSize = () => {
3200
3064
  const { redis } = useDatabrowser();
3201
- const { data: keyCount } = useQuery2({
3065
+ const { data: keyCount } = useQuery({
3202
3066
  queryKey: [FETCH_DB_SIZE_QUERY_KEY],
3203
3067
  queryFn: async () => {
3204
3068
  return await redis.dbsize();
@@ -3293,7 +3157,11 @@ import { useEffect as useEffect2, useState as useState3 } from "react";
3293
3157
  import { useMutation as useMutation2 } from "@tanstack/react-query";
3294
3158
 
3295
3159
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3296
- import { useCallback as useCallback3 } from "react";
3160
+ import { useCallback } from "react";
3161
+
3162
+ // src/components/databrowser/hooks/use-fetch-key-type.tsx
3163
+ import { useQuery as useQuery2 } from "@tanstack/react-query";
3164
+ var FETCH_KEY_TYPE_QUERY_KEY = "fetch-key-type";
3297
3165
 
3298
3166
  // src/components/databrowser/hooks/use-fetch-list-items.tsx
3299
3167
  import { useInfiniteQuery as useInfiniteQuery2 } from "@tanstack/react-query";
@@ -3443,8 +3311,7 @@ var sortObject = (obj) => {
3443
3311
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3444
3312
  var useDeleteKeyCache = () => {
3445
3313
  const { setSelectedKey } = useDatabrowserStore();
3446
- const { refetch } = useKeys();
3447
- const deleteKeyCache = useCallback3(
3314
+ const deleteKeyCache = useCallback(
3448
3315
  (key) => {
3449
3316
  setSelectedKey(void 0);
3450
3317
  queryClient.invalidateQueries({
@@ -3459,9 +3326,8 @@ var useDeleteKeyCache = () => {
3459
3326
  queryClient.invalidateQueries({
3460
3327
  queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key]
3461
3328
  });
3462
- refetch();
3463
3329
  },
3464
- [setSelectedKey, refetch]
3330
+ [setSelectedKey]
3465
3331
  );
3466
3332
  return { deleteKeyCache };
3467
3333
  };
@@ -4457,6 +4323,18 @@ var InfiniteScroll = ({
4457
4323
  // src/components/databrowser/components/display/display-header.tsx
4458
4324
  import { IconPlus } from "@tabler/icons-react";
4459
4325
 
4326
+ // src/types/index.ts
4327
+ var DATA_TYPES = ["string", "list", "hash", "set", "zset", "json", "stream"];
4328
+ var DATA_TYPE_NAMES = {
4329
+ string: "String",
4330
+ list: "List",
4331
+ hash: "Hash",
4332
+ set: "Set",
4333
+ zset: "Sorted Set",
4334
+ json: "JSON",
4335
+ stream: "Stream"
4336
+ };
4337
+
4460
4338
  // src/components/databrowser/components/type-tag.tsx
4461
4339
  import {
4462
4340
  IconArrowsSort,
@@ -4810,7 +4688,7 @@ var ContentTypeSelect = ({
4810
4688
  };
4811
4689
 
4812
4690
  // src/components/databrowser/components/display/input/custom-editor.tsx
4813
- import { useEffect as useEffect6, useRef as useRef3 } from "react";
4691
+ import { useEffect as useEffect6, useRef } from "react";
4814
4692
  import { Editor, useMonaco } from "@monaco-editor/react";
4815
4693
 
4816
4694
  // src/components/databrowser/copy-button.tsx
@@ -4859,7 +4737,7 @@ var CustomEditor = ({
4859
4737
  readOnly
4860
4738
  }) => {
4861
4739
  const monaco = useMonaco();
4862
- const editorRef = useRef3();
4740
+ const editorRef = useRef();
4863
4741
  useEffect6(() => {
4864
4742
  if (!monaco || !editorRef.current) {
4865
4743
  return;
@@ -5720,7 +5598,7 @@ function DataTypeSelector() {
5720
5598
  // src/components/databrowser/components/sidebar/index.tsx
5721
5599
  import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
5722
5600
  function Sidebar() {
5723
- const { keys, query, refetch } = useKeys();
5601
+ const { keys, query } = useKeys();
5724
5602
  return /* @__PURE__ */ jsxs31("div", { className: "flex h-full flex-col gap-2 rounded-xl border bg-white p-1", children: [
5725
5603
  /* @__PURE__ */ jsxs31("div", { className: "rounded-lg bg-zinc-100 px-3 py-2", children: [
5726
5604
  /* @__PURE__ */ jsxs31("div", { className: "flex h-10 items-center justify-between pl-1", children: [
@@ -5731,7 +5609,9 @@ function Sidebar() {
5731
5609
  {
5732
5610
  className: "h-7 w-7 px-0",
5733
5611
  onClick: () => {
5734
- refetch();
5612
+ queryClient.invalidateQueries({
5613
+ queryKey: [FETCH_KEYS_QUERY_KEY]
5614
+ });
5735
5615
  queryClient.invalidateQueries({
5736
5616
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
5737
5617
  });
package/package.json CHANGED
@@ -1 +1 @@
1
- { "name": "@upstash/react-redis-browser", "version": "v0.1.8", "main": "./dist/index.js", "types": "./dist/index.d.ts", "license": "MIT", "private": false, "publishConfig": { "access": "public" }, "bugs": { "url": "https://github.com/upstash/react-redis-browser/issues" }, "homepage": "https://github.com/upstash/react-redis-browser", "files": [ "./dist/**" ], "scripts": { "build": "tsup", "dev": "vite", "lint": "tsc && eslint", "fmt": "prettier --write ./src" }, "lint-staged": { "**/*.{js,ts,tsx}": [ "prettier --write", "eslint --fix" ] }, "dependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.4.0", "@monaco-editor/react": "^4.6.0", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-context-menu": "^2.2.2", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "1.3.0", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-portal": "^1.1.2", "@radix-ui/react-scroll-area": "^1.0.3", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", "@tabler/icons-react": "^3.19.0", "@tanstack/react-query": "^5.32.0", "@types/bytes": "^3.1.4", "@upstash/redis": "^1.34.8", "bytes": "^3.1.2", "react-hook-form": "^7.53.0", "react-resizable-panels": "^2.1.4", "zustand": "5.0.0" }, "devDependencies": { "postcss-prefix-selector": "^2.1.0", "@types/node": "^22.8.4", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@typescript-eslint/eslint-plugin": "8.4.0", "@typescript-eslint/parser": "8.4.0", "@vitejs/plugin-react": "^4.1.0", "autoprefixer": "^10.4.14", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "eslint": "9.10.0", "eslint-plugin-unicorn": "55.0.0", "postcss": "^8.4.31", "prettier": "^3.0.3", "prettier-plugin-tailwindcss": "^0.5.5", "react": "^18.3.1", "react-dom": "^18.3.1", "tailwind-merge": "^2.5.4", "tailwindcss": "^3.4.14", "tailwindcss-animate": "^1.0.7", "tsup": "^8.3.5", "typescript": "^5.0.4", "vite": "^5.4.10", "vite-tsconfig-paths": "^5.0.1" }, "peerDependencies": { "react": "^18.2.0 || ^19", "react-dom": "^18.2.0 || ^19" } }
1
+ { "name": "@upstash/react-redis-browser", "version": "v0.1.10", "main": "./dist/index.js", "types": "./dist/index.d.ts", "license": "MIT", "private": false, "publishConfig": { "access": "public" }, "bugs": { "url": "https://github.com/upstash/react-redis-browser/issues" }, "homepage": "https://github.com/upstash/react-redis-browser", "files": [ "./dist/**" ], "scripts": { "build": "tsup", "dev": "vite", "lint": "tsc && eslint", "fmt": "prettier --write ./src" }, "lint-staged": { "**/*.{js,ts,tsx}": [ "prettier --write", "eslint --fix" ] }, "dependencies": { "@ianvs/prettier-plugin-sort-imports": "^4.4.0", "@monaco-editor/react": "^4.6.0", "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-context-menu": "^2.2.2", "@radix-ui/react-dialog": "^1.0.5", "@radix-ui/react-dropdown-menu": "^2.1.2", "@radix-ui/react-icons": "1.3.0", "@radix-ui/react-popover": "^1.0.7", "@radix-ui/react-portal": "^1.1.2", "@radix-ui/react-scroll-area": "^1.0.3", "@radix-ui/react-select": "^2.0.0", "@radix-ui/react-slot": "^1.0.2", "@radix-ui/react-toast": "^1.1.5", "@radix-ui/react-tooltip": "^1.0.7", "@tabler/icons-react": "^3.19.0", "@tanstack/react-query": "^5.32.0", "@types/bytes": "^3.1.4", "@upstash/redis": "^1.34.8", "bytes": "^3.1.2", "react-hook-form": "^7.53.0", "react-resizable-panels": "^2.1.4", "zustand": "5.0.0" }, "devDependencies": { "postcss-prefix-selector": "^2.1.0", "@types/node": "^22.8.4", "@types/react": "^18.3.12", "@types/react-dom": "^18.3.1", "@typescript-eslint/eslint-plugin": "8.4.0", "@typescript-eslint/parser": "8.4.0", "@vitejs/plugin-react": "^4.1.0", "autoprefixer": "^10.4.14", "class-variance-authority": "^0.7.0", "clsx": "^2.0.0", "eslint": "9.10.0", "eslint-plugin-unicorn": "55.0.0", "postcss": "^8.4.31", "prettier": "^3.0.3", "prettier-plugin-tailwindcss": "^0.5.5", "react": "^18.3.1", "react-dom": "^18.3.1", "tailwind-merge": "^2.5.4", "tailwindcss": "^3.4.14", "tailwindcss-animate": "^1.0.7", "tsup": "^8.3.5", "typescript": "^5.0.4", "vite": "^5.4.10", "vite-tsconfig-paths": "^5.0.1" }, "peerDependencies": { "react": "^18.2.0 || ^19", "react-dom": "^18.2.0 || ^19" } }