@upstash/react-redis-browser 0.1.4 → 0.1.6-canary

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/dist/index.js CHANGED
@@ -132,9 +132,12 @@ function useToast() {
132
132
  }
133
133
 
134
134
  // src/lib/clients.ts
135
- var redisClient = (databrowser) => {
136
- const token = _optionalChain([databrowser, 'optionalAccess', _2 => _2.token]) || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN;
137
- const url = _optionalChain([databrowser, 'optionalAccess', _3 => _3.url]) || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL;
135
+ var redisClient = ({
136
+ credentials,
137
+ pipelining
138
+ }) => {
139
+ const token = _optionalChain([credentials, 'optionalAccess', _2 => _2.token]) || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN;
140
+ const url = _optionalChain([credentials, 'optionalAccess', _3 => _3.url]) || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL;
138
141
  if (!url) {
139
142
  throw new Error("Redis URL is missing!");
140
143
  }
@@ -144,7 +147,7 @@ var redisClient = (databrowser) => {
144
147
  const redis = new (0, _redis.Redis)({
145
148
  url,
146
149
  token,
147
- enableAutoPipelining: true,
150
+ enableAutoPipelining: pipelining,
148
151
  automaticDeserialization: false,
149
152
  keepAlive: false
150
153
  });
@@ -184,11 +187,12 @@ var DatabrowserProvider = ({
184
187
  children,
185
188
  redisCredentials
186
189
  }) => {
187
- const redisInstance = _react.useMemo.call(void 0, () => redisClient(redisCredentials), [redisCredentials]);
190
+ const redisInstance = _react.useMemo.call(void 0, () => redisClient({ credentials: redisCredentials, pipelining: true }), [redisCredentials]);
191
+ const redisInstanceNoPipeline = _react.useMemo.call(void 0, () => redisClient({ credentials: redisCredentials, pipelining: false }), [redisCredentials]);
188
192
  const [store] = _react.useState.call(void 0, () => {
189
193
  return createDatabrowserStore();
190
194
  });
191
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserContext.Provider, { value: { redis: redisInstance, store }, children });
195
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserContext.Provider, { value: { redis: redisInstance, redisNoPipeline: redisInstanceNoPipeline, store }, children });
192
196
  };
193
197
  var useDatabrowser = () => {
194
198
  const context = _react.useContext.call(void 0, DatabrowserContext);
@@ -2938,7 +2942,7 @@ var DATA_TYPE_NAMES = {
2938
2942
  var PAGE_SIZE = 30;
2939
2943
  var FETCH_COUNTS = [100, 200, 400, 800];
2940
2944
  var useFetchKeys = (search) => {
2941
- const { redis } = useDatabrowser();
2945
+ const { redisNoPipeline: redis } = useDatabrowser();
2942
2946
  const cache = _react.useRef.call(void 0, );
2943
2947
  const lastKey = _react.useRef.call(void 0, );
2944
2948
  const fetchKeys = _react.useCallback.call(void 0, () => {
@@ -3270,7 +3274,7 @@ var useAddKey = () => {
3270
3274
 
3271
3275
  var FETCH_SIMPLE_KEY_QUERY_KEY = "fetch-simple-key";
3272
3276
  var useFetchSimpleKey = (dataKey, type) => {
3273
- const { redis } = useDatabrowser();
3277
+ const { redisNoPipeline: redis } = useDatabrowser();
3274
3278
  const { deleteKeyCache } = useDeleteKeyCache();
3275
3279
  return _reactquery.useQuery.call(void 0, {
3276
3280
  queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey],
@@ -3279,11 +3283,21 @@ var useFetchSimpleKey = (dataKey, type) => {
3279
3283
  if (type === "string") result = await redis.get(dataKey);
3280
3284
  else if (type === "json") result = await redis.json.get(dataKey);
3281
3285
  else throw new Error(`Invalid type when fetching simple key: ${type}`);
3286
+ if (type === "json" && result !== null)
3287
+ result = JSON.stringify(sortObject(JSON.parse(result)));
3282
3288
  if (result === null) deleteKeyCache(dataKey);
3283
3289
  return result;
3284
3290
  }
3285
3291
  });
3286
3292
  };
3293
+ var sortObject = (obj) => {
3294
+ if (typeof obj !== "object" || obj === null) return obj;
3295
+ return Object.fromEntries(
3296
+ Object.entries(obj).sort((a, b) => a[0].localeCompare(b[0])).map(
3297
+ ([key, value]) => typeof value === "object" && !Array.isArray(value) && value !== null ? [key, sortObject(value)] : [key, value]
3298
+ )
3299
+ );
3300
+ };
3287
3301
 
3288
3302
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3289
3303
  var useDeleteKeyCache = () => {
@@ -3331,7 +3345,7 @@ var useDeleteKey = () => {
3331
3345
  var LIST_DISPLAY_PAGE_SIZE = 50;
3332
3346
  var FETCH_LIST_ITEMS_QUERY_KEY = "use-fetch-list-items";
3333
3347
  var useFetchListItems = ({ dataKey, type }) => {
3334
- const { redis } = useDatabrowser();
3348
+ const { redisNoPipeline: redis } = useDatabrowser();
3335
3349
  const setQuery = _reactquery.useInfiniteQuery.call(void 0, {
3336
3350
  enabled: type === "set",
3337
3351
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY, dataKey, "set"],
@@ -4591,7 +4605,7 @@ var DisplayHeader = ({
4591
4605
  }) => {
4592
4606
  const { setSelectedListItem } = useDatabrowserStore();
4593
4607
  const handleAddItem = () => {
4594
- setSelectedListItem({ key: type === "stream" ? "*" : "", value: "", isNew: true });
4608
+ setSelectedListItem({ key: type === "stream" ? "*" : "", isNew: true });
4595
4609
  };
4596
4610
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-lg bg-zinc-100 px-3 py-2", children: [
4597
4611
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-10 items-center justify-between gap-4", children: [
@@ -4613,6 +4627,7 @@ var DisplayHeader = ({
4613
4627
  // src/components/databrowser/components/display/display-list-edit.tsx
4614
4628
 
4615
4629
 
4630
+
4616
4631
  // src/components/ui/tooltip.tsx
4617
4632
 
4618
4633
 
@@ -4790,7 +4805,8 @@ var useField = ({
4790
4805
  form,
4791
4806
  height,
4792
4807
  showCopyButton,
4793
- readOnly
4808
+ readOnly,
4809
+ data
4794
4810
  }) => {
4795
4811
  const { field, fieldState } = _reacthookform.useController.call(void 0, {
4796
4812
  name,
@@ -4800,13 +4816,13 @@ var useField = ({
4800
4816
  () => checkIsValidJSON(field.value) ? "JSON" : "Text"
4801
4817
  );
4802
4818
  _react.useEffect.call(void 0, () => {
4803
- if (!checkIsValidJSON(field.value)) {
4819
+ if (!checkIsValidJSON(data)) {
4804
4820
  return;
4805
4821
  }
4806
- form.setValue(name, formatJSON(field.value), {
4822
+ form.setValue(name, formatJSON(data), {
4807
4823
  shouldDirty: false
4808
4824
  });
4809
- }, []);
4825
+ }, [data]);
4810
4826
  const handleTypeChange = (type) => {
4811
4827
  setContentType(type);
4812
4828
  if (type === "JSON") {
@@ -4856,14 +4872,32 @@ var ListEditDisplay = ({
4856
4872
  var ListEditForm = ({
4857
4873
  type,
4858
4874
  dataKey,
4859
- item: { key: itemKey, value: itemValue, isNew }
4875
+ item: { key: itemKey, isNew }
4860
4876
  }) => {
4877
+ const query = useFetchListItems({
4878
+ type,
4879
+ dataKey
4880
+ });
4881
+ const findValue = () => {
4882
+ for (const page of _nullishCoalesce(_optionalChain([query, 'access', _28 => _28.data, 'optionalAccess', _29 => _29.pages]), () => ( []))) {
4883
+ const item = page.keys.find((item2) => item2.key === itemKey);
4884
+ if (item && "value" in item) return item.value;
4885
+ }
4886
+ return;
4887
+ };
4888
+ const itemValue = findValue();
4861
4889
  const form = _reacthookform.useForm.call(void 0, {
4862
4890
  defaultValues: {
4863
4891
  key: itemKey,
4864
4892
  value: itemValue
4865
4893
  }
4866
4894
  });
4895
+ _react.useEffect.call(void 0, () => {
4896
+ form.reset({
4897
+ key: itemKey,
4898
+ value: itemValue
4899
+ });
4900
+ }, [itemKey, itemValue]);
4867
4901
  const { mutateAsync: editItem, isPending } = useEditListItem();
4868
4902
  const { setSelectedListItem } = useDatabrowserStore();
4869
4903
  const [keyLabel, valueLabel] = headerLabels[type];
@@ -4886,7 +4920,8 @@ var ListEditForm = ({
4886
4920
  readOnly: type === "stream",
4887
4921
  name: "key",
4888
4922
  height: type === "set" ? 250 : 100,
4889
- label: keyLabel
4923
+ label: keyLabel,
4924
+ data: itemKey
4890
4925
  }
4891
4926
  ),
4892
4927
  type === "zset" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NumberFormItem, { name: "value", label: valueLabel }) : type !== "set" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -4895,7 +4930,8 @@ var ListEditForm = ({
4895
4930
  readOnly: type === "stream",
4896
4931
  name: "value",
4897
4932
  height: type === "list" ? 250 : 100,
4898
- label: valueLabel
4933
+ label: valueLabel,
4934
+ data: _nullishCoalesce(itemValue, () => ( ""))
4899
4935
  }
4900
4936
  )
4901
4937
  ] }),
@@ -4951,7 +4987,8 @@ var FormItem = ({
4951
4987
  name,
4952
4988
  label,
4953
4989
  height,
4954
- readOnly
4990
+ readOnly,
4991
+ data
4955
4992
  }) => {
4956
4993
  const form = _reacthookform.useFormContext.call(void 0, );
4957
4994
  const { editor, selector } = useField({
@@ -4959,7 +4996,8 @@ var FormItem = ({
4959
4996
  form,
4960
4997
  height,
4961
4998
  showCopyButton: true,
4962
- readOnly
4999
+ readOnly,
5000
+ data
4963
5001
  });
4964
5002
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-1", children: [
4965
5003
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 text-xs", children: [
@@ -4996,7 +5034,7 @@ var ListItems = ({
4996
5034
  dataKey
4997
5035
  }) => {
4998
5036
  const { setSelectedListItem } = useDatabrowserStore();
4999
- const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _28 => _28.data, 'optionalAccess', _29 => _29.pages, 'access', _30 => _30.flatMap, 'call', _31 => _31((page) => page.keys)]), () => ( [])), [query.data]);
5037
+ const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _30 => _30.data, 'optionalAccess', _31 => _31.pages, 'access', _32 => _32.flatMap, 'call', _33 => _33((page) => page.keys)]), () => ( [])), [query.data]);
5000
5038
  const { mutate: editItem } = useEditListItem();
5001
5039
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5002
5040
  "tr",
@@ -5004,7 +5042,7 @@ var ListItems = ({
5004
5042
  "data-item-key": key,
5005
5043
  "data-item-value": value,
5006
5044
  onClick: () => {
5007
- setSelectedListItem({ key, value });
5045
+ setSelectedListItem({ key });
5008
5046
  },
5009
5047
  className: "h-10 border-b border-b-zinc-100 hover:bg-zinc-50",
5010
5048
  children: [
@@ -5083,16 +5121,16 @@ var EditorDisplayForm = ({
5083
5121
  const form = _reacthookform.useForm.call(void 0, {
5084
5122
  defaultValues: { value: data }
5085
5123
  });
5086
- const { editor, selector } = useField({ name: "value", form });
5087
- const { mutateAsync: setKey, isPending: isSettingKey } = useSetSimpleKey(dataKey, type);
5088
5124
  _react.useEffect.call(void 0, () => {
5089
5125
  form.reset(
5090
5126
  { value: data },
5091
5127
  {
5092
- keepValues: true
5128
+ keepValues: false
5093
5129
  }
5094
5130
  );
5095
5131
  }, [data]);
5132
+ const { editor, selector } = useField({ name: "value", form, data });
5133
+ const { mutateAsync: setKey, isPending: isSettingKey } = useSetSimpleKey(dataKey, type);
5096
5134
  const handleCancel = () => {
5097
5135
  form.reset();
5098
5136
  };
@@ -5254,7 +5292,7 @@ function AddKeyModal() {
5254
5292
  setSelectedKey(key);
5255
5293
  setOpen(false);
5256
5294
  setTimeout(() => {
5257
- _optionalChain([window, 'access', _32 => _32.document, 'access', _33 => _33.querySelector, 'call', _34 => _34(`[data-key="${key}"]`), 'optionalAccess', _35 => _35.scrollIntoView, 'call', _36 => _36({
5295
+ _optionalChain([window, 'access', _34 => _34.document, 'access', _35 => _35.querySelector, 'call', _36 => _36(`[data-key="${key}"]`), 'optionalAccess', _37 => _37.scrollIntoView, 'call', _38 => _38({
5258
5296
  behavior: "smooth",
5259
5297
  block: "start",
5260
5298
  inline: "nearest"
@@ -5299,7 +5337,7 @@ function AddKeyModal() {
5299
5337
  }
5300
5338
  )
5301
5339
  ] }),
5302
- formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _37 => _37.errors, 'access', _38 => _38.key, 'optionalAccess', _39 => _39.message]) }),
5340
+ formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _39 => _39.errors, 'access', _40 => _40.key, 'optionalAccess', _41 => _41.message]) }),
5303
5341
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-2 text-xs text-zinc-500", children: "After creating the key, you can edit the value" }),
5304
5342
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-6 flex justify-end gap-2", children: [
5305
5343
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5393,7 +5431,7 @@ var SidebarContextMenu = ({ children }) => {
5393
5431
 
5394
5432
  var KeysList = () => {
5395
5433
  const { keys } = useKeys();
5396
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pr-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyItem, { nextKey: _nullishCoalesce(_optionalChain([keys, 'access', _40 => _40.at, 'call', _41 => _41(i + 1), 'optionalAccess', _42 => _42[0]]), () => ( "")), data }, data[0])) }) }) });
5434
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "pr-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SidebarContextMenu, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map((data, i) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyItem, { nextKey: _nullishCoalesce(_optionalChain([keys, 'access', _42 => _42.at, 'call', _43 => _43(i + 1), 'optionalAccess', _44 => _44[0]]), () => ( "")), data }, data[0])) }) }) });
5397
5435
  };
5398
5436
  var keyStyles = {
5399
5437
  string: "border-sky-400 !bg-sky-50 text-sky-900",
@@ -5529,6 +5567,9 @@ function Sidebar() {
5529
5567
  queryClient.invalidateQueries({
5530
5568
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
5531
5569
  });
5570
+ queryClient.invalidateQueries({
5571
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY]
5572
+ });
5532
5573
  queryClient.invalidateQueries({
5533
5574
  queryKey: [FETCH_DB_SIZE_QUERY_KEY]
5534
5575
  });
package/dist/index.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  // src/components/databrowser/index.tsx
2
- import { useEffect as useEffect9, useMemo as useMemo6 } from "react";
2
+ import { useEffect as useEffect10, useMemo as useMemo6 } from "react";
3
3
 
4
4
  // src/store.tsx
5
5
  import { createContext, useContext, useMemo, useState as useState2 } from "react";
@@ -132,9 +132,12 @@ function useToast() {
132
132
  }
133
133
 
134
134
  // src/lib/clients.ts
135
- var redisClient = (databrowser) => {
136
- const token = databrowser?.token || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN;
137
- const url = databrowser?.url || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL;
135
+ var redisClient = ({
136
+ credentials,
137
+ pipelining
138
+ }) => {
139
+ const token = credentials?.token || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_TOKEN;
140
+ const url = credentials?.url || process.env.NEXT_PUBLIC_UPSTASH_REDIS_REST_URL;
138
141
  if (!url) {
139
142
  throw new Error("Redis URL is missing!");
140
143
  }
@@ -144,7 +147,7 @@ var redisClient = (databrowser) => {
144
147
  const redis = new Redis({
145
148
  url,
146
149
  token,
147
- enableAutoPipelining: true,
150
+ enableAutoPipelining: pipelining,
148
151
  automaticDeserialization: false,
149
152
  keepAlive: false
150
153
  });
@@ -184,11 +187,12 @@ var DatabrowserProvider = ({
184
187
  children,
185
188
  redisCredentials
186
189
  }) => {
187
- const redisInstance = useMemo(() => redisClient(redisCredentials), [redisCredentials]);
190
+ const redisInstance = useMemo(() => redisClient({ credentials: redisCredentials, pipelining: true }), [redisCredentials]);
191
+ const redisInstanceNoPipeline = useMemo(() => redisClient({ credentials: redisCredentials, pipelining: false }), [redisCredentials]);
188
192
  const [store] = useState2(() => {
189
193
  return createDatabrowserStore();
190
194
  });
191
- return /* @__PURE__ */ jsx(DatabrowserContext.Provider, { value: { redis: redisInstance, store }, children });
195
+ return /* @__PURE__ */ jsx(DatabrowserContext.Provider, { value: { redis: redisInstance, redisNoPipeline: redisInstanceNoPipeline, store }, children });
192
196
  };
193
197
  var useDatabrowser = () => {
194
198
  const context = useContext(DatabrowserContext);
@@ -2938,7 +2942,7 @@ var DATA_TYPE_NAMES = {
2938
2942
  var PAGE_SIZE = 30;
2939
2943
  var FETCH_COUNTS = [100, 200, 400, 800];
2940
2944
  var useFetchKeys = (search) => {
2941
- const { redis } = useDatabrowser();
2945
+ const { redisNoPipeline: redis } = useDatabrowser();
2942
2946
  const cache = useRef();
2943
2947
  const lastKey = useRef();
2944
2948
  const fetchKeys = useCallback(() => {
@@ -3270,7 +3274,7 @@ import { useCallback as useCallback3 } from "react";
3270
3274
  import { useQuery as useQuery2 } from "@tanstack/react-query";
3271
3275
  var FETCH_SIMPLE_KEY_QUERY_KEY = "fetch-simple-key";
3272
3276
  var useFetchSimpleKey = (dataKey, type) => {
3273
- const { redis } = useDatabrowser();
3277
+ const { redisNoPipeline: redis } = useDatabrowser();
3274
3278
  const { deleteKeyCache } = useDeleteKeyCache();
3275
3279
  return useQuery2({
3276
3280
  queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey],
@@ -3279,11 +3283,21 @@ var useFetchSimpleKey = (dataKey, type) => {
3279
3283
  if (type === "string") result = await redis.get(dataKey);
3280
3284
  else if (type === "json") result = await redis.json.get(dataKey);
3281
3285
  else throw new Error(`Invalid type when fetching simple key: ${type}`);
3286
+ if (type === "json" && result !== null)
3287
+ result = JSON.stringify(sortObject(JSON.parse(result)));
3282
3288
  if (result === null) deleteKeyCache(dataKey);
3283
3289
  return result;
3284
3290
  }
3285
3291
  });
3286
3292
  };
3293
+ var sortObject = (obj) => {
3294
+ if (typeof obj !== "object" || obj === null) return obj;
3295
+ return Object.fromEntries(
3296
+ Object.entries(obj).sort((a, b) => a[0].localeCompare(b[0])).map(
3297
+ ([key, value]) => typeof value === "object" && !Array.isArray(value) && value !== null ? [key, sortObject(value)] : [key, value]
3298
+ )
3299
+ );
3300
+ };
3287
3301
 
3288
3302
  // src/components/databrowser/hooks/use-delete-key-cache.ts
3289
3303
  var useDeleteKeyCache = () => {
@@ -3331,7 +3345,7 @@ import { useInfiniteQuery as useInfiniteQuery2 } from "@tanstack/react-query";
3331
3345
  var LIST_DISPLAY_PAGE_SIZE = 50;
3332
3346
  var FETCH_LIST_ITEMS_QUERY_KEY = "use-fetch-list-items";
3333
3347
  var useFetchListItems = ({ dataKey, type }) => {
3334
- const { redis } = useDatabrowser();
3348
+ const { redisNoPipeline: redis } = useDatabrowser();
3335
3349
  const setQuery = useInfiniteQuery2({
3336
3350
  enabled: type === "set",
3337
3351
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY, dataKey, "set"],
@@ -4591,7 +4605,7 @@ var DisplayHeader = ({
4591
4605
  }) => {
4592
4606
  const { setSelectedListItem } = useDatabrowserStore();
4593
4607
  const handleAddItem = () => {
4594
- setSelectedListItem({ key: type === "stream" ? "*" : "", value: "", isNew: true });
4608
+ setSelectedListItem({ key: type === "stream" ? "*" : "", isNew: true });
4595
4609
  };
4596
4610
  return /* @__PURE__ */ jsxs15("div", { className: "rounded-lg bg-zinc-100 px-3 py-2", children: [
4597
4611
  /* @__PURE__ */ jsxs15("div", { className: "flex min-h-10 items-center justify-between gap-4", children: [
@@ -4611,6 +4625,7 @@ var DisplayHeader = ({
4611
4625
  };
4612
4626
 
4613
4627
  // src/components/databrowser/components/display/display-list-edit.tsx
4628
+ import { useEffect as useEffect8 } from "react";
4614
4629
  import { Controller as Controller2, FormProvider, useForm as useForm2, useFormContext } from "react-hook-form";
4615
4630
 
4616
4631
  // src/components/ui/tooltip.tsx
@@ -4790,7 +4805,8 @@ var useField = ({
4790
4805
  form,
4791
4806
  height,
4792
4807
  showCopyButton,
4793
- readOnly
4808
+ readOnly,
4809
+ data
4794
4810
  }) => {
4795
4811
  const { field, fieldState } = useController({
4796
4812
  name,
@@ -4800,13 +4816,13 @@ var useField = ({
4800
4816
  () => checkIsValidJSON(field.value) ? "JSON" : "Text"
4801
4817
  );
4802
4818
  useEffect7(() => {
4803
- if (!checkIsValidJSON(field.value)) {
4819
+ if (!checkIsValidJSON(data)) {
4804
4820
  return;
4805
4821
  }
4806
- form.setValue(name, formatJSON(field.value), {
4822
+ form.setValue(name, formatJSON(data), {
4807
4823
  shouldDirty: false
4808
4824
  });
4809
- }, []);
4825
+ }, [data]);
4810
4826
  const handleTypeChange = (type) => {
4811
4827
  setContentType(type);
4812
4828
  if (type === "JSON") {
@@ -4856,14 +4872,32 @@ var ListEditDisplay = ({
4856
4872
  var ListEditForm = ({
4857
4873
  type,
4858
4874
  dataKey,
4859
- item: { key: itemKey, value: itemValue, isNew }
4875
+ item: { key: itemKey, isNew }
4860
4876
  }) => {
4877
+ const query = useFetchListItems({
4878
+ type,
4879
+ dataKey
4880
+ });
4881
+ const findValue = () => {
4882
+ for (const page of query.data?.pages ?? []) {
4883
+ const item = page.keys.find((item2) => item2.key === itemKey);
4884
+ if (item && "value" in item) return item.value;
4885
+ }
4886
+ return;
4887
+ };
4888
+ const itemValue = findValue();
4861
4889
  const form = useForm2({
4862
4890
  defaultValues: {
4863
4891
  key: itemKey,
4864
4892
  value: itemValue
4865
4893
  }
4866
4894
  });
4895
+ useEffect8(() => {
4896
+ form.reset({
4897
+ key: itemKey,
4898
+ value: itemValue
4899
+ });
4900
+ }, [itemKey, itemValue]);
4867
4901
  const { mutateAsync: editItem, isPending } = useEditListItem();
4868
4902
  const { setSelectedListItem } = useDatabrowserStore();
4869
4903
  const [keyLabel, valueLabel] = headerLabels[type];
@@ -4886,7 +4920,8 @@ var ListEditForm = ({
4886
4920
  readOnly: type === "stream",
4887
4921
  name: "key",
4888
4922
  height: type === "set" ? 250 : 100,
4889
- label: keyLabel
4923
+ label: keyLabel,
4924
+ data: itemKey
4890
4925
  }
4891
4926
  ),
4892
4927
  type === "zset" ? /* @__PURE__ */ jsx29(NumberFormItem, { name: "value", label: valueLabel }) : type !== "set" && /* @__PURE__ */ jsx29(
@@ -4895,7 +4930,8 @@ var ListEditForm = ({
4895
4930
  readOnly: type === "stream",
4896
4931
  name: "value",
4897
4932
  height: type === "list" ? 250 : 100,
4898
- label: valueLabel
4933
+ label: valueLabel,
4934
+ data: itemValue ?? ""
4899
4935
  }
4900
4936
  )
4901
4937
  ] }),
@@ -4951,7 +4987,8 @@ var FormItem = ({
4951
4987
  name,
4952
4988
  label,
4953
4989
  height,
4954
- readOnly
4990
+ readOnly,
4991
+ data
4955
4992
  }) => {
4956
4993
  const form = useFormContext();
4957
4994
  const { editor, selector } = useField({
@@ -4959,7 +4996,8 @@ var FormItem = ({
4959
4996
  form,
4960
4997
  height,
4961
4998
  showCopyButton: true,
4962
- readOnly
4999
+ readOnly,
5000
+ data
4963
5001
  });
4964
5002
  return /* @__PURE__ */ jsxs19("div", { className: "flex flex-col gap-1", children: [
4965
5003
  /* @__PURE__ */ jsxs19("div", { className: "flex items-center gap-1 text-xs", children: [
@@ -5004,7 +5042,7 @@ var ListItems = ({
5004
5042
  "data-item-key": key,
5005
5043
  "data-item-value": value,
5006
5044
  onClick: () => {
5007
- setSelectedListItem({ key, value });
5045
+ setSelectedListItem({ key });
5008
5046
  },
5009
5047
  className: "h-10 border-b border-b-zinc-100 hover:bg-zinc-50",
5010
5048
  children: [
@@ -5059,7 +5097,7 @@ var ListItems = ({
5059
5097
  };
5060
5098
 
5061
5099
  // src/components/databrowser/components/display/display-simple.tsx
5062
- import { useEffect as useEffect8 } from "react";
5100
+ import { useEffect as useEffect9 } from "react";
5063
5101
  import { useForm as useForm3 } from "react-hook-form";
5064
5102
  import { Fragment as Fragment6, jsx as jsx31, jsxs as jsxs21 } from "react/jsx-runtime";
5065
5103
  var EditorDisplay = ({ dataKey, type }) => {
@@ -5083,16 +5121,16 @@ var EditorDisplayForm = ({
5083
5121
  const form = useForm3({
5084
5122
  defaultValues: { value: data }
5085
5123
  });
5086
- const { editor, selector } = useField({ name: "value", form });
5087
- const { mutateAsync: setKey, isPending: isSettingKey } = useSetSimpleKey(dataKey, type);
5088
- useEffect8(() => {
5124
+ useEffect9(() => {
5089
5125
  form.reset(
5090
5126
  { value: data },
5091
5127
  {
5092
- keepValues: true
5128
+ keepValues: false
5093
5129
  }
5094
5130
  );
5095
5131
  }, [data]);
5132
+ const { editor, selector } = useField({ name: "value", form, data });
5133
+ const { mutateAsync: setKey, isPending: isSettingKey } = useSetSimpleKey(dataKey, type);
5096
5134
  const handleCancel = () => {
5097
5135
  form.reset();
5098
5136
  };
@@ -5529,6 +5567,9 @@ function Sidebar() {
5529
5567
  queryClient.invalidateQueries({
5530
5568
  queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
5531
5569
  });
5570
+ queryClient.invalidateQueries({
5571
+ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY]
5572
+ });
5532
5573
  queryClient.invalidateQueries({
5533
5574
  queryKey: [FETCH_DB_SIZE_QUERY_KEY]
5534
5575
  });
@@ -5552,7 +5593,7 @@ function Sidebar() {
5552
5593
  import { jsx as jsx42, jsxs as jsxs31 } from "react/jsx-runtime";
5553
5594
  var RedisBrowser = ({ token, url }) => {
5554
5595
  const credentials = useMemo6(() => ({ token, url }), [token, url]);
5555
- useEffect9(() => {
5596
+ useEffect10(() => {
5556
5597
  queryClient.resetQueries();
5557
5598
  }, [credentials.url]);
5558
5599
  return /* @__PURE__ */ jsx42(QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ jsx42(TooltipProvider, { children: /* @__PURE__ */ jsx42(DatabrowserProvider, { redisCredentials: credentials, children: /* @__PURE__ */ jsx42(KeysProvider, { children: /* @__PURE__ */ jsxs31("div", { className: "ups-db", style: { height: "100%" }, children: [
package/package.json CHANGED
@@ -1 +1 @@
1
- { "name": "@upstash/react-redis-browser", "version": "v0.1.4", "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.3", "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.6-canary", "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.3", "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" } }