@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 +68 -27
- package/dist/index.mjs +68 -27
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -132,9 +132,12 @@ function useToast() {
|
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
// src/lib/clients.ts
|
|
135
|
-
var redisClient = (
|
|
136
|
-
|
|
137
|
-
|
|
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:
|
|
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" ? "*" : "",
|
|
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(
|
|
4819
|
+
if (!checkIsValidJSON(data)) {
|
|
4804
4820
|
return;
|
|
4805
4821
|
}
|
|
4806
|
-
form.setValue(name, formatJSON(
|
|
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,
|
|
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',
|
|
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
|
|
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:
|
|
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',
|
|
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',
|
|
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',
|
|
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
|
|
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 = (
|
|
136
|
-
|
|
137
|
-
|
|
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:
|
|
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" ? "*" : "",
|
|
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(
|
|
4819
|
+
if (!checkIsValidJSON(data)) {
|
|
4804
4820
|
return;
|
|
4805
4821
|
}
|
|
4806
|
-
form.setValue(name, formatJSON(
|
|
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,
|
|
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
|
|
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
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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.
|
|
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" } }
|