@upstash/react-redis-browser 0.2.14-rc.10 → 0.2.14-rc.12

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
@@ -2665,6 +2665,48 @@ function formatTime(seconds) {
2665
2665
  return parts.slice(0, 1).join(" ");
2666
2666
  }
2667
2667
  var isTest = typeof window !== "undefined" && window.__PLAYWRIGHT__ === true;
2668
+ var jsonToJsLiteral = (json) => {
2669
+ return json.replaceAll(/"([$A-Z_a-z][\w$]*)"\s*:/g, "$1:");
2670
+ };
2671
+ var MAX_INLINE_KEYS = 2;
2672
+ var isInlineable = (value) => {
2673
+ if (typeof value !== "object" || value === null) return true;
2674
+ if (Array.isArray(value)) return value.every((v) => typeof v !== "object" || v === null);
2675
+ const entries = Object.entries(value);
2676
+ return entries.length <= MAX_INLINE_KEYS && entries.every(([, v]) => typeof v !== "object" || v === null);
2677
+ };
2678
+ var prettyPrint = (value, indent) => {
2679
+ if (value === void 0 || value === null) return String(value);
2680
+ if (typeof value !== "object") return JSON.stringify(value);
2681
+ const prefix = " ".repeat(indent);
2682
+ const childPrefix = " ".repeat(indent + 1);
2683
+ if (Array.isArray(value)) {
2684
+ if (value.length === 0) return "[]";
2685
+ if (value.every((v) => isInlineable(v))) {
2686
+ const inline = `[${value.map((v) => prettyPrint(v, 0)).join(", ")}]`;
2687
+ if (!inline.includes("\n")) return inline;
2688
+ }
2689
+ const items = value.map((v) => `${childPrefix}${prettyPrint(v, indent + 1)}`);
2690
+ return `[
2691
+ ${items.join(",\n")}
2692
+ ${prefix}]`;
2693
+ }
2694
+ const entries = Object.entries(value);
2695
+ if (entries.length === 0) return "{}";
2696
+ if (indent > 0 && entries.length <= MAX_INLINE_KEYS && entries.every(([, v]) => isInlineable(v))) {
2697
+ const inline = `{ ${entries.map(([k, v]) => `${JSON.stringify(k)}: ${prettyPrint(v, 0)}`).join(", ")} }`;
2698
+ if (!inline.includes("\n")) return inline;
2699
+ }
2700
+ const parts = entries.map(
2701
+ ([k, v]) => `${childPrefix}${JSON.stringify(k)}: ${prettyPrint(v, indent + 1)}`
2702
+ );
2703
+ return `{
2704
+ ${parts.join(",\n")}
2705
+ ${prefix}}`;
2706
+ };
2707
+ var toJsLiteral = (obj) => {
2708
+ return jsonToJsLiteral(prettyPrint(obj, 0));
2709
+ };
2668
2710
  var formatUpstashErrorMessage = (error) => {
2669
2711
  if (error.name !== "UpstashError") return error.message;
2670
2712
  let message = error.message;
@@ -2795,7 +2837,7 @@ var DatabrowserProvider = ({
2795
2837
  removeItem: () => {
2796
2838
  }
2797
2839
  },
2798
- version: 7,
2840
+ version: 8,
2799
2841
  migrate: (originalState, version) => {
2800
2842
  const state = originalState;
2801
2843
  if (version <= 1) {
@@ -2827,9 +2869,12 @@ var DatabrowserProvider = ({
2827
2869
  if (version <= 6) {
2828
2870
  state.tabs = state.tabs.map(([id, data]) => [
2829
2871
  id,
2830
- { ...data, valuesSearch: { index: "", queries: {} } }
2872
+ { ...data, valuesSearch: { index: "", queries: {}, queryBuilderMode: "ui" } }
2831
2873
  ]);
2832
2874
  }
2875
+ if (version <= 7) {
2876
+ state.aiDataSharingConsent = _nullishCoalesce(state.aiDataSharingConsent, () => ( false));
2877
+ }
2833
2878
  return state;
2834
2879
  }
2835
2880
  })
@@ -2861,7 +2906,7 @@ var storeCreator = (set, get) => ({
2861
2906
  id,
2862
2907
  selectedKeys: [],
2863
2908
  search: { key: "", type: void 0 },
2864
- valuesSearch: { index: "", queries: {} },
2909
+ valuesSearch: { index: "", queries: {}, queryBuilderMode: "ui" },
2865
2910
  isValuesSearchSelected: false,
2866
2911
  pinned: false
2867
2912
  };
@@ -3078,9 +3123,29 @@ var storeCreator = (set, get) => ({
3078
3123
  return { ...old, tabs: newTabs };
3079
3124
  });
3080
3125
  },
3126
+ setQueryBuilderMode: (tabId, mode) => {
3127
+ set((old) => {
3128
+ const tabIndex = old.tabs.findIndex(([id]) => id === tabId);
3129
+ if (tabIndex === -1) return old;
3130
+ const newTabs = [...old.tabs];
3131
+ const [, tabData] = newTabs[tabIndex];
3132
+ newTabs[tabIndex] = [
3133
+ tabId,
3134
+ {
3135
+ ...tabData,
3136
+ valuesSearch: { ...tabData.valuesSearch, queryBuilderMode: mode }
3137
+ }
3138
+ ];
3139
+ return { ...old, tabs: newTabs };
3140
+ });
3141
+ },
3081
3142
  searchHistory: [],
3082
3143
  addSearchHistory: (key) => {
3083
3144
  set((old) => ({ ...old, searchHistory: [key, ...old.searchHistory] }));
3145
+ },
3146
+ aiDataSharingConsent: false,
3147
+ setAiDataSharingConsent: (consent) => {
3148
+ set({ aiDataSharingConsent: consent });
3084
3149
  }
3085
3150
  });
3086
3151
 
@@ -3111,7 +3176,8 @@ var useTab = () => {
3111
3176
  setValuesSearch,
3112
3177
  setValuesSearchIndex,
3113
3178
  setValuesSearchQuery,
3114
- setIsValuesSearchSelected
3179
+ setIsValuesSearchSelected,
3180
+ setQueryBuilderMode
3115
3181
  } = useDatabrowserStore();
3116
3182
  const tabId = useTabId();
3117
3183
  const tabData = _react.useMemo.call(void 0, () => _optionalChain([tabs, 'access', _20 => _20.find, 'call', _21 => _21(([id]) => id === tabId), 'optionalAccess', _22 => _22[1]]), [tabs, tabId]);
@@ -3130,6 +3196,7 @@ var useTab = () => {
3130
3196
  query: _nullishCoalesce(tabData.valuesSearch.queries[tabData.valuesSearch.index], () => ( ""))
3131
3197
  },
3132
3198
  isValuesSearchSelected: tabData.isValuesSearchSelected,
3199
+ queryBuilderMode: _nullishCoalesce(tabData.valuesSearch.queryBuilderMode, () => ( "ui")),
3133
3200
  pinned: tabData.pinned,
3134
3201
  setSelectedKey: (key) => setSelectedKey(tabId, key),
3135
3202
  setSelectedKeys: (keys) => setSelectedKeys(tabId, keys),
@@ -3140,7 +3207,8 @@ var useTab = () => {
3140
3207
  setValuesSearch: (search) => setValuesSearch(tabId, search),
3141
3208
  setValuesSearchIndex: (index) => setValuesSearchIndex(tabId, index),
3142
3209
  setValuesSearchQuery: (query) => setValuesSearchQuery(tabId, query),
3143
- setIsValuesSearchSelected: (isSelected) => setIsValuesSearchSelected(tabId, isSelected)
3210
+ setIsValuesSearchSelected: (isSelected) => setIsValuesSearchSelected(tabId, isSelected),
3211
+ setQueryBuilderMode: (mode) => setQueryBuilderMode(tabId, mode)
3144
3212
  }),
3145
3213
  [selectedTab, tabs, tabId]
3146
3214
  );
@@ -3170,6 +3238,29 @@ var portalWrapper = wrapper;
3170
3238
 
3171
3239
  var _reactresizablepanels = require('react-resizable-panels');
3172
3240
 
3241
+ // src/components/ui/resize-handle.tsx
3242
+
3243
+
3244
+ var ResizeHandle = ({
3245
+ direction = "horizontal"
3246
+ }) => {
3247
+ const isHorizontal = direction === "horizontal";
3248
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3249
+ _reactresizablepanels.PanelResizeHandle,
3250
+ {
3251
+ className: cn(
3252
+ "group flex items-center justify-center gap-1 rounded-md transition-colors hover:bg-zinc-300/10",
3253
+ isHorizontal ? "mx-[2px] h-full flex-col px-[8px]" : "my-[2px] w-full flex-row py-[8px]"
3254
+ ),
3255
+ children: [
3256
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" }),
3257
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" }),
3258
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" })
3259
+ ]
3260
+ }
3261
+ );
3262
+ };
3263
+
3173
3264
  // src/components/ui/segmented.tsx
3174
3265
 
3175
3266
  var Segmented = ({
@@ -3181,21 +3272,30 @@ var Segmented = ({
3181
3272
  selectedClassName,
3182
3273
  unselectedClassName
3183
3274
  }) => {
3184
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("flex w-fit gap-[2px] rounded-lg bg-zinc-200 p-[2px] text-sm", className), children: options.map((option) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3185
- "button",
3275
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3276
+ "div",
3186
3277
  {
3187
3278
  className: cn(
3188
- "h-7 rounded-md px-3 transition-all",
3189
- value === option.key ? _nullishCoalesce(selectedClassName, () => ( "bg-white text-zinc-950")) : _nullishCoalesce(unselectedClassName, () => ( "text-zinc-700")),
3190
- buttonClassName
3279
+ "flex w-fit select-none gap-[2px] rounded-lg bg-zinc-200 p-[2px] text-sm",
3280
+ className
3191
3281
  ),
3192
- onClick: () => {
3193
- _optionalChain([onChange, 'optionalCall', _25 => _25(option.key)]);
3194
- },
3195
- children: option.label
3196
- },
3197
- option.key
3198
- )) });
3282
+ children: options.map((option) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3283
+ "button",
3284
+ {
3285
+ className: cn(
3286
+ "h-7 rounded-md px-3 transition-all",
3287
+ value === option.key ? _nullishCoalesce(selectedClassName, () => ( "bg-white text-zinc-950")) : _nullishCoalesce(unselectedClassName, () => ( "text-zinc-700")),
3288
+ buttonClassName
3289
+ ),
3290
+ onClick: () => {
3291
+ _optionalChain([onChange, 'optionalCall', _25 => _25(option.key)]);
3292
+ },
3293
+ children: option.label
3294
+ },
3295
+ option.key
3296
+ ))
3297
+ }
3298
+ );
3199
3299
  };
3200
3300
 
3201
3301
  // src/components/ui/toaster.tsx
@@ -3367,6 +3467,33 @@ function Toaster() {
3367
3467
 
3368
3468
  // src/components/databrowser/hooks/use-fetch-search-indexes.tsx
3369
3469
 
3470
+
3471
+ // src/lib/scan-keys.ts
3472
+ async function scanKeys(redis, {
3473
+ match,
3474
+ type,
3475
+ count: count2 = 100,
3476
+ limit
3477
+ } = {}) {
3478
+ let cursor = "0";
3479
+ const result = [];
3480
+ while (true) {
3481
+ const [newCursor, keys] = await redis.scan(cursor, {
3482
+ count: count2,
3483
+ type,
3484
+ match
3485
+ });
3486
+ result.push(...keys);
3487
+ if (limit && result.length >= limit) {
3488
+ return result.slice(0, limit);
3489
+ }
3490
+ if (newCursor === "0") break;
3491
+ cursor = newCursor;
3492
+ }
3493
+ return result;
3494
+ }
3495
+
3496
+ // src/components/databrowser/hooks/use-fetch-search-indexes.tsx
3370
3497
  var FETCH_SEARCH_INDEXES_QUERY_KEY = "fetch-search-indexes";
3371
3498
  var useFetchSearchIndexes = ({
3372
3499
  match,
@@ -3376,21 +3503,7 @@ var useFetchSearchIndexes = ({
3376
3503
  return _reactquery.useQuery.call(void 0, {
3377
3504
  queryKey: [FETCH_SEARCH_INDEXES_QUERY_KEY],
3378
3505
  enabled: _nullishCoalesce(enabled, () => ( true)),
3379
- queryFn: async () => {
3380
- let cursor = "0";
3381
- const finalResult = [];
3382
- while (true) {
3383
- const [newCursor, results] = await redis.scan(cursor, {
3384
- count: 100,
3385
- type: "search",
3386
- match
3387
- });
3388
- finalResult.push(...results);
3389
- if (newCursor === "0") break;
3390
- cursor = newCursor;
3391
- }
3392
- return finalResult;
3393
- }
3506
+ queryFn: () => scanKeys(redis, { match, type: "search" })
3394
3507
  });
3395
3508
  };
3396
3509
 
@@ -3677,6 +3790,7 @@ Label.displayName = LabelPrimitive.Root.displayName;
3677
3790
  // src/components/ui/select.tsx
3678
3791
 
3679
3792
  var _reactselect = require('@radix-ui/react-select'); var SelectPrimitive = _interopRequireWildcard(_reactselect);
3793
+ var _reactdom = require('react-dom'); var ReactDOM = _interopRequireWildcard(_reactdom);
3680
3794
 
3681
3795
  var Select = SelectPrimitive.Root;
3682
3796
  var SelectGroup = SelectPrimitive.Group;
@@ -3732,7 +3846,7 @@ var SelectContent = React6.forwardRef(({ className, children, position = "popper
3732
3846
  SelectPrimitive.Viewport,
3733
3847
  {
3734
3848
  className: cn(
3735
- "p-1",
3849
+ "max-h-[min(var(--radix-select-content-available-height),20rem)] overflow-y-auto p-1",
3736
3850
  position === "popper" && "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]"
3737
3851
  ),
3738
3852
  children
@@ -3750,40 +3864,76 @@ var SelectLabel = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE
3750
3864
  }
3751
3865
  ));
3752
3866
  SelectLabel.displayName = SelectPrimitive.Label.displayName;
3753
- var SelectItem = React6.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3754
- SelectPrimitive.Item,
3755
- {
3756
- ref,
3757
- className: cn(
3758
- "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none hover:bg-zinc-100 focus:bg-zinc-100 focus:text-zinc-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
3759
- className
3867
+ var SelectItemTooltip = ({
3868
+ description,
3869
+ itemRef
3870
+ }) => {
3871
+ const [pos, setPos] = React6.useState();
3872
+ React6.useEffect(() => {
3873
+ const el = itemRef.current;
3874
+ if (!el) return;
3875
+ const rect = el.getBoundingClientRect();
3876
+ setPos({ top: rect.top + rect.height / 2, left: rect.right + 8 });
3877
+ }, [itemRef]);
3878
+ if (!pos) return;
3879
+ return ReactDOM.createPortal(
3880
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3881
+ "div",
3882
+ {
3883
+ className: "pointer-events-none fixed z-[100] -translate-y-1/2 whitespace-nowrap rounded-md bg-zinc-900 px-3 py-1.5 text-xs text-zinc-50 shadow-md animate-in fade-in-0",
3884
+ style: { top: pos.top, left: pos.left },
3885
+ children: description
3886
+ }
3760
3887
  ),
3761
- ...props,
3762
- children: [
3763
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3764
- "svg",
3765
- {
3766
- width: "15",
3767
- height: "15",
3768
- viewBox: "0 0 15 15",
3769
- fill: "none",
3770
- xmlns: "http://www.w3.org/2000/svg",
3771
- className: "h-4 w-4",
3772
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3773
- "path",
3774
- {
3775
- d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z",
3776
- fill: "currentColor",
3777
- fillRule: "evenodd",
3778
- clipRule: "evenodd"
3779
- }
3780
- )
3781
- }
3782
- ) }) }),
3783
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemText, { children })
3784
- ]
3785
- }
3786
- ));
3888
+ _nullishCoalesce(portalRoot, () => ( document.body))
3889
+ );
3890
+ };
3891
+ var SelectItem = React6.forwardRef(({ className, children, description, ...props }, ref) => {
3892
+ const [isHovered, setIsHovered] = React6.useState(false);
3893
+ const itemRef = React6.useRef(null);
3894
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
3895
+ SelectPrimitive.Item,
3896
+ {
3897
+ ref: (node) => {
3898
+ ;
3899
+ itemRef.current = node;
3900
+ if (typeof ref === "function") ref(node);
3901
+ else if (ref) ref.current = node;
3902
+ },
3903
+ className: cn(
3904
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-2 pr-8 text-sm outline-none hover:bg-zinc-100 focus:bg-zinc-100 focus:text-zinc-900 data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
3905
+ className
3906
+ ),
3907
+ onMouseEnter: () => setIsHovered(true),
3908
+ onMouseLeave: () => setIsHovered(false),
3909
+ ...props,
3910
+ children: [
3911
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "absolute right-2 flex h-3.5 w-3.5 items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemIndicator, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3912
+ "svg",
3913
+ {
3914
+ width: "15",
3915
+ height: "15",
3916
+ viewBox: "0 0 15 15",
3917
+ fill: "none",
3918
+ xmlns: "http://www.w3.org/2000/svg",
3919
+ className: "h-4 w-4",
3920
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3921
+ "path",
3922
+ {
3923
+ d: "M11.4669 3.72684C11.7558 3.91574 11.8369 4.30308 11.648 4.59198L7.39799 11.092C7.29783 11.2452 7.13556 11.3467 6.95402 11.3699C6.77247 11.3931 6.58989 11.3355 6.45446 11.2124L3.70446 8.71241C3.44905 8.48022 3.43023 8.08494 3.66242 7.82953C3.89461 7.57412 4.28989 7.55529 4.5453 7.78749L6.75292 9.79441L10.6018 3.90792C10.7907 3.61902 11.178 3.53795 11.4669 3.72684Z",
3924
+ fill: "currentColor",
3925
+ fillRule: "evenodd",
3926
+ clipRule: "evenodd"
3927
+ }
3928
+ )
3929
+ }
3930
+ ) }) }),
3931
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectPrimitive.ItemText, { children }),
3932
+ description && isHovered && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItemTooltip, { description, itemRef })
3933
+ ]
3934
+ }
3935
+ );
3936
+ });
3787
3937
  SelectItem.displayName = SelectPrimitive.Item.displayName;
3788
3938
  var SelectSeparator = React6.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3789
3939
  SelectPrimitive.Separator,
@@ -3890,16 +4040,22 @@ function parseFields(content, prefix, flatSchema) {
3890
4040
  if (fieldName.startsWith('"') && fieldName.endsWith('"') || fieldName.startsWith("'") && fieldName.endsWith("'")) {
3891
4041
  fieldName = fieldName.slice(1, -1);
3892
4042
  }
4043
+ if (fieldName.length === 0) {
4044
+ throw new Error("Field name cannot be empty");
4045
+ }
3893
4046
  const valueStr = entry.slice(colonIndex + 1).trim();
3894
4047
  const fullKey = prefix ? `${prefix}.${fieldName}` : fieldName;
3895
4048
  if (valueStr.startsWith("s.object(")) {
3896
4049
  const nestedContent = extractObjectContent(valueStr);
3897
- if (nestedContent !== null) {
3898
- parseFields(nestedContent, fullKey, flatSchema);
3899
- continue;
4050
+ if (nestedContent === void 0) {
4051
+ throw new Error(
4052
+ `Malformed s.object() for field "${fullKey}": missing closing brace or parenthesis`
4053
+ );
3900
4054
  }
4055
+ parseFields(nestedContent, fullKey, flatSchema);
4056
+ continue;
3901
4057
  }
3902
- const fieldValue = parseFieldBuilder(valueStr);
4058
+ const fieldValue = parseFieldBuilder(valueStr, fullKey);
3903
4059
  if (fieldValue) {
3904
4060
  flatSchema[fullKey] = fieldValue;
3905
4061
  }
@@ -3960,15 +4116,15 @@ function findColonIndex(entry) {
3960
4116
  }
3961
4117
  function extractObjectContent(str) {
3962
4118
  const match = str.match(/^s\.object\s*\(\s*{([\S\s]*)}\s*\)/);
3963
- return match ? match[1] : null;
4119
+ return match ? match[1] : void 0;
3964
4120
  }
3965
4121
  function extractFromValue(str) {
3966
4122
  const fromIndex = str.indexOf(".from(");
3967
- if (fromIndex === -1) return null;
4123
+ if (fromIndex === -1) return void 0;
3968
4124
  const start = fromIndex + 6;
3969
- if (start >= str.length) return null;
4125
+ if (start >= str.length) return void 0;
3970
4126
  const quoteChar = str[start];
3971
- if (quoteChar !== '"' && quoteChar !== "'") return null;
4127
+ if (quoteChar !== '"' && quoteChar !== "'") return void 0;
3972
4128
  let result = "";
3973
4129
  let i = start + 1;
3974
4130
  while (i < str.length) {
@@ -3984,151 +4140,61 @@ function extractFromValue(str) {
3984
4140
  result += char;
3985
4141
  i++;
3986
4142
  }
3987
- return null;
4143
+ return void 0;
3988
4144
  }
3989
- function parseFieldBuilder(str) {
4145
+ function parseFieldBuilder(str, fieldName) {
3990
4146
  str = str.trim().replace(/,\s*$/, "");
3991
4147
  if (str.startsWith("s.string()")) {
3992
4148
  const noTokenize = str.includes(".noTokenize()");
3993
4149
  const noStem = str.includes(".noStem()");
3994
4150
  const fromValue = extractFromValue(str);
3995
- if (!noTokenize && !noStem && fromValue === null) return "TEXT";
4151
+ if (!noTokenize && !noStem && fromValue === void 0) return "TEXT";
3996
4152
  return {
3997
4153
  type: "TEXT",
3998
4154
  ...noTokenize && { noTokenize: true },
3999
4155
  ...noStem && { noStem: true },
4000
- ...fromValue !== null && { from: fromValue }
4156
+ ...fromValue !== void 0 && { from: fromValue }
4001
4157
  };
4002
4158
  }
4003
4159
  if (str.startsWith("s.number(")) {
4004
4160
  const typeMatch = str.match(/s\.number\(\s*["']?(U64|I64|F64)?["']?\s*\)/);
4005
4161
  const numType = _optionalChain([typeMatch, 'optionalAccess', _31 => _31[1]]) || "F64";
4006
4162
  const fromValue = extractFromValue(str);
4007
- if (fromValue === null) return numType;
4163
+ if (fromValue === void 0) return numType;
4008
4164
  return { type: numType, from: fromValue };
4009
4165
  }
4010
4166
  if (str.startsWith("s.boolean()")) {
4011
4167
  const fast = str.includes(".fast()");
4012
4168
  const fromValue = extractFromValue(str);
4013
- if (!fast && fromValue === null) return "BOOL";
4169
+ if (!fast && fromValue === void 0) return "BOOL";
4014
4170
  return {
4015
4171
  type: "BOOL",
4016
4172
  ...fast && { fast: true },
4017
- ...fromValue !== null && { from: fromValue }
4173
+ ...fromValue !== void 0 && { from: fromValue }
4018
4174
  };
4019
4175
  }
4020
4176
  if (str.startsWith("s.date()")) {
4021
4177
  const fast = str.includes(".fast()");
4022
4178
  const fromValue = extractFromValue(str);
4023
- if (!fast && fromValue === null) return "DATE";
4179
+ if (!fast && fromValue === void 0) return "DATE";
4024
4180
  return {
4025
4181
  type: "DATE",
4026
4182
  ...fast && { fast: true },
4027
- ...fromValue !== null && { from: fromValue }
4183
+ ...fromValue !== void 0 && { from: fromValue }
4028
4184
  };
4029
4185
  }
4030
- return null;
4031
- }
4032
- function schemaToEditorValue(flatSchema) {
4033
- const nested = unflattenSchema(flatSchema);
4034
- const body = renderObject(nested, 1);
4035
- return `const schema: Schema = s.object({
4036
- ${body}})`;
4037
- }
4038
- function unflattenSchema(flat) {
4039
- const result = {};
4040
- for (const [key, value] of Object.entries(flat)) {
4041
- const parts = key.split(".");
4042
- let current = result;
4043
- for (let i = 0; i < parts.length - 1; i++) {
4044
- const part = parts[i];
4045
- if (!current[part] || typeof current[part] !== "object") {
4046
- current[part] = {};
4047
- }
4048
- current = current[part];
4049
- }
4050
- current[parts.at(-1)] = value;
4051
- }
4052
- return result;
4053
- }
4054
- function renderObject(obj, indent) {
4055
- const pad = " ".repeat(indent);
4056
- const lines = [];
4057
- for (const [key, value] of Object.entries(obj)) {
4058
- if (isFieldValue(value)) {
4059
- lines.push(`${pad}${key}: ${fieldToBuilder(value)},`);
4060
- } else {
4061
- const nested = renderObject(value, indent + 1);
4062
- lines.push(`${pad}${key}: s.object({`);
4063
- lines.push(nested.trimEnd());
4064
- lines.push(`${pad}}),`);
4065
- }
4066
- }
4067
- return lines.join("\n") + "\n";
4068
- }
4069
- function isFieldValue(value) {
4070
- if (typeof value === "string") return true;
4071
- if (typeof value === "object" && value !== null) {
4072
- return "type" in value;
4073
- }
4074
- return false;
4075
- }
4076
- function fieldToBuilder(value) {
4077
- if (typeof value === "string") {
4078
- switch (value) {
4079
- case "TEXT": {
4080
- return "s.string()";
4081
- }
4082
- case "BOOL": {
4083
- return "s.boolean()";
4084
- }
4085
- case "DATE": {
4086
- return "s.date()";
4087
- }
4088
- case "U64":
4089
- case "I64":
4090
- case "F64": {
4091
- return `s.number("${value}")`;
4092
- }
4093
- default: {
4094
- return "s.string()";
4095
- }
4096
- }
4186
+ if (str.startsWith("s.keyword()")) {
4187
+ return "KEYWORD";
4097
4188
  }
4098
- const v = value;
4099
- const type = v.type;
4100
- let builder = "";
4101
- switch (type) {
4102
- case "TEXT": {
4103
- builder = "s.string()";
4104
- if (v.noTokenize) builder += ".noTokenize()";
4105
- if (v.noStem) builder += ".noStem()";
4106
- break;
4107
- }
4108
- case "U64":
4109
- case "I64":
4110
- case "F64": {
4111
- builder = `s.number("${type}")`;
4112
- break;
4113
- }
4114
- case "BOOL": {
4115
- builder = "s.boolean()";
4116
- if (v.fast) builder += ".fast()";
4117
- break;
4118
- }
4119
- case "DATE": {
4120
- builder = "s.date()";
4121
- if (v.fast) builder += ".fast()";
4122
- break;
4123
- }
4124
- default: {
4125
- builder = "s.string()";
4126
- }
4189
+ if (str.startsWith("s.facet()")) {
4190
+ return "FACET";
4127
4191
  }
4128
- if (v.from) {
4129
- builder += `.from("${v.from}")`;
4192
+ if (str.startsWith("s.")) {
4193
+ const typeMatch = str.match(/^s\.(\w+)\(/);
4194
+ const typeName = _nullishCoalesce(_optionalChain([typeMatch, 'optionalAccess', _32 => _32[1]]), () => ( "unknown"));
4195
+ throw new Error(`Unknown field type "s.${typeName}()" for field "${fieldName}"`);
4130
4196
  }
4131
- return builder;
4197
+ return void 0;
4132
4198
  }
4133
4199
 
4134
4200
  // src/components/databrowser/hooks/use-create-search-index-schema.tsx
@@ -4168,37 +4234,113 @@ var useCreateSearchIndexSchema = () => {
4168
4234
  // src/components/databrowser/components/display/display-header.tsx
4169
4235
 
4170
4236
 
4171
- // src/components/ui/tooltip.tsx
4172
-
4237
+ // src/components/ui/scroll-area.tsx
4173
4238
 
4239
+ var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
4174
4240
 
4175
- var Tooltip = TooltipPrimitive.Root;
4176
- var TooltipTrigger = TooltipPrimitive.Trigger;
4177
- var TooltipContent = React7.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4178
- TooltipPrimitive.Content,
4179
- {
4180
- ref,
4181
- sideOffset,
4182
- className: cn(
4183
- "z-50 overflow-hidden rounded-md bg-zinc-900 px-3 py-1.5 text-xs text-zinc-50 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4184
- className
4185
- ),
4241
+ var ScrollArea = React7.forwardRef(
4242
+ ({
4243
+ className,
4244
+ scrollBarClassName,
4245
+ scrollBarForceMount,
4246
+ children,
4247
+ onScroll,
4248
+ disableRoundedInherit = false,
4249
+ orientation = "vertical",
4186
4250
  ...props
4187
- }
4188
- ) }));
4189
- TooltipContent.displayName = TooltipPrimitive.Content.displayName;
4190
- var SimpleTooltip = ({
4191
- content,
4192
- children,
4193
- variant = "default"
4194
- }) => {
4195
- if (!content) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children });
4196
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Tooltip, { delayDuration: 100, children: [
4197
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipTrigger, { asChild: true, children }),
4198
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4199
- TooltipContent,
4200
- {
4201
- side: "top",
4251
+ }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4252
+ ScrollAreaPrimitive.Root,
4253
+ {
4254
+ ref,
4255
+ className: cn("relative overflow-hidden", className),
4256
+ ...props,
4257
+ children: [
4258
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4259
+ ScrollAreaPrimitive.Viewport,
4260
+ {
4261
+ onScroll,
4262
+ className: cn(
4263
+ "h-full w-full [&>div]:!block",
4264
+ !disableRoundedInherit && "rounded-[inherit]"
4265
+ ),
4266
+ children
4267
+ }
4268
+ ),
4269
+ (orientation === "vertical" || orientation === "both") && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4270
+ ScrollBar,
4271
+ {
4272
+ className: scrollBarClassName,
4273
+ forceMount: scrollBarForceMount,
4274
+ orientation: "vertical"
4275
+ }
4276
+ ),
4277
+ (orientation === "horizontal" || orientation === "both") && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4278
+ ScrollBar,
4279
+ {
4280
+ className: scrollBarClassName,
4281
+ forceMount: scrollBarForceMount,
4282
+ orientation: "horizontal"
4283
+ }
4284
+ ),
4285
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
4286
+ ]
4287
+ }
4288
+ )
4289
+ );
4290
+ ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
4291
+ var ScrollBar = React7.forwardRef(({ className, orientation = "vertical", ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4292
+ ScrollAreaPrimitive.ScrollAreaScrollbar,
4293
+ {
4294
+ ref,
4295
+ orientation,
4296
+ className: cn(
4297
+ "flex touch-none select-none transition-colors",
4298
+ orientation === "vertical" && "mr-1 h-full w-2",
4299
+ orientation === "horizontal" && "mb-1 h-2 w-full flex-col",
4300
+ className
4301
+ ),
4302
+ ...props,
4303
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4304
+ ScrollAreaPrimitive.ScrollAreaThumb,
4305
+ {
4306
+ className: cn("relative flex-1 rounded-full bg-zinc-400/70")
4307
+ }
4308
+ )
4309
+ }
4310
+ ));
4311
+ ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
4312
+
4313
+ // src/components/ui/tooltip.tsx
4314
+
4315
+
4316
+
4317
+ var Tooltip = TooltipPrimitive.Root;
4318
+ var TooltipTrigger = TooltipPrimitive.Trigger;
4319
+ var TooltipContent = React8.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4320
+ TooltipPrimitive.Content,
4321
+ {
4322
+ ref,
4323
+ sideOffset,
4324
+ className: cn(
4325
+ "z-50 overflow-hidden rounded-md bg-zinc-900 px-3 py-1.5 text-xs text-zinc-50 animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
4326
+ className
4327
+ ),
4328
+ ...props
4329
+ }
4330
+ ) }));
4331
+ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
4332
+ var SimpleTooltip = ({
4333
+ content,
4334
+ children,
4335
+ variant = "default"
4336
+ }) => {
4337
+ if (!content) return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children });
4338
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Tooltip, { delayDuration: 100, children: [
4339
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipTrigger, { asChild: true, children }),
4340
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4341
+ TooltipContent,
4342
+ {
4343
+ side: "top",
4202
4344
  className: variant === "error" ? "bg-white text-red-500 shadow-md" : void 0,
4203
4345
  children: content
4204
4346
  }
@@ -4429,7 +4571,7 @@ var useFetchListItems = ({ dataKey, type }) => {
4429
4571
  // +1 since first message is the last one
4430
4572
  LIST_DISPLAY_PAGE_SIZE + 1
4431
4573
  );
4432
- const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _32 => _32.at, 'call', _33 => _33(-1), 'optionalAccess', _34 => _34[0]]) : void 0;
4574
+ const lastMessageId = messages.length > 0 ? _optionalChain([messages, 'access', _33 => _33.at, 'call', _34 => _34(-1), 'optionalAccess', _35 => _35[0]]) : void 0;
4433
4575
  return {
4434
4576
  cursor: messages.length < LIST_DISPLAY_PAGE_SIZE ? void 0 : lastMessageId,
4435
4577
  keys: messages.map(([id, fields]) => ({
@@ -4466,7 +4608,6 @@ function transformArray(inputArray) {
4466
4608
  var FETCH_SIMPLE_KEY_QUERY_KEY = "fetch-simple-key";
4467
4609
  var useFetchSimpleKey = (dataKey, type) => {
4468
4610
  const { redisNoPipeline: redis } = useRedis();
4469
- const { deleteKeyCache } = useDeleteKeyCache();
4470
4611
  return _reactquery.useQuery.call(void 0, {
4471
4612
  queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY, dataKey],
4472
4613
  queryFn: async () => {
@@ -4476,7 +4617,6 @@ var useFetchSimpleKey = (dataKey, type) => {
4476
4617
  else throw new Error(`Invalid type when fetching simple key: ${type}`);
4477
4618
  if (type === "json" && result !== null)
4478
4619
  result = JSON.stringify(sortObject(JSON.parse(result)));
4479
- if (result === null) deleteKeyCache(dataKey);
4480
4620
  return result;
4481
4621
  }
4482
4622
  });
@@ -4492,10 +4632,9 @@ var sortObject = (obj) => {
4492
4632
 
4493
4633
  // src/components/databrowser/hooks/use-delete-key-cache.ts
4494
4634
  var useDeleteKeyCache = () => {
4495
- const { setSelectedKey } = useTab();
4635
+ const { isValuesSearchSelected, valuesSearch } = useTab();
4496
4636
  const deleteKeyCache = _react.useCallback.call(void 0,
4497
4637
  (key) => {
4498
- setSelectedKey(void 0);
4499
4638
  queryClient.invalidateQueries({
4500
4639
  queryKey: [FETCH_KEYS_QUERY_KEY]
4501
4640
  });
@@ -4508,22 +4647,39 @@ var useDeleteKeyCache = () => {
4508
4647
  queryClient.invalidateQueries({
4509
4648
  queryKey: [FETCH_KEY_TYPE_QUERY_KEY, key]
4510
4649
  });
4650
+ queryClient.invalidateQueries({
4651
+ queryKey: [FETCH_SEARCH_INDEX_QUERY_KEY, key]
4652
+ });
4653
+ queryClient.invalidateQueries({
4654
+ queryKey: [FETCH_SEARCH_INDEXES_QUERY_KEY]
4655
+ });
4656
+ if (isValuesSearchSelected && valuesSearch.index) {
4657
+ queryClient.invalidateQueries({
4658
+ queryKey: [FETCH_SEARCH_INDEX_QUERY_KEY, valuesSearch.index]
4659
+ });
4660
+ }
4511
4661
  },
4512
- [setSelectedKey]
4662
+ [isValuesSearchSelected, valuesSearch.index]
4513
4663
  );
4514
4664
  return { deleteKeyCache };
4515
4665
  };
4516
4666
 
4517
4667
  // src/components/databrowser/hooks/use-delete-key.ts
4518
4668
  var useDeleteKey = () => {
4519
- const { redis } = useRedis();
4669
+ const { redis, redisNoPipeline } = useRedis();
4520
4670
  const { deleteKeyCache } = useDeleteKeyCache();
4671
+ const { isValuesSearchSelected, valuesSearch } = useTab();
4521
4672
  const deleteKey = _reactquery.useMutation.call(void 0, {
4522
- mutationFn: async (key) => {
4523
- return Boolean(await redis.del(key));
4673
+ mutationFn: async ({ keys, reindex }) => {
4674
+ await Promise.all(keys.map((key) => redis.del(key)));
4675
+ if (reindex && isValuesSearchSelected && valuesSearch.index) {
4676
+ await redisNoPipeline.search.index({ name: valuesSearch.index }).waitIndexing();
4677
+ }
4524
4678
  },
4525
- onSuccess: (_, key) => {
4526
- deleteKeyCache(key);
4679
+ onSuccess: (_, { keys }) => {
4680
+ for (const key of keys) {
4681
+ deleteKeyCache(key);
4682
+ }
4527
4683
  }
4528
4684
  });
4529
4685
  return deleteKey;
@@ -4590,7 +4746,7 @@ var useEditListItem = () => {
4590
4746
  }
4591
4747
  case "stream": {
4592
4748
  if (!isNew || !newKey) throw new Error("Stream data type is not mutable");
4593
- const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _35 => _35.split, 'call', _36 => _36("\n")]), () => ( []))).map(
4749
+ const opts = transformArray(_nullishCoalesce(_optionalChain([newValue, 'optionalAccess', _36 => _36.split, 'call', _37 => _37("\n")]), () => ( []))).map(
4594
4750
  ({ key, value }) => [key, value]
4595
4751
  );
4596
4752
  pipe.xadd(dataKey, newKey, Object.fromEntries(opts));
@@ -4628,7 +4784,7 @@ var _reactpopover = require('@radix-ui/react-popover'); var PopoverPrimitive = _
4628
4784
 
4629
4785
  var Popover = PopoverPrimitive.Root;
4630
4786
  var PopoverTrigger = PopoverPrimitive.Trigger;
4631
- var PopoverContent = React8.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4787
+ var PopoverContent = React9.forwardRef(({ className, align = "center", sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4632
4788
  PopoverPrimitive.Content,
4633
4789
  {
4634
4790
  ref,
@@ -4897,7 +5053,7 @@ var LengthBadge = ({
4897
5053
  content
4898
5054
  }) => {
4899
5055
  const { data, isLoading } = useFetchKeyLength({ dataKey, type });
4900
- const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _37 => _37.length]), () => ( data));
5056
+ const length = _nullishCoalesce(_optionalChain([content, 'optionalAccess', _38 => _38.length]), () => ( data));
4901
5057
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Badge, { label: "Length:", children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Skeleton, { className: "ml-1 h-3 w-10 rounded-md opacity-50" }) : length });
4902
5058
  };
4903
5059
  var SizeBadge = ({ dataKey }) => {
@@ -4933,7 +5089,7 @@ var _reactdropdownmenu = require('@radix-ui/react-dropdown-menu'); var DropdownM
4933
5089
 
4934
5090
  var DropdownMenu = DropdownMenuPrimitive.Root;
4935
5091
  var DropdownMenuTrigger = DropdownMenuPrimitive.Trigger;
4936
- var DropdownMenuSubTrigger = React9.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5092
+ var DropdownMenuSubTrigger = React10.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4937
5093
  DropdownMenuPrimitive.SubTrigger,
4938
5094
  {
4939
5095
  ref,
@@ -4950,7 +5106,7 @@ var DropdownMenuSubTrigger = React9.forwardRef(({ className, inset, children, ..
4950
5106
  }
4951
5107
  ));
4952
5108
  DropdownMenuSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName;
4953
- var DropdownMenuSubContent = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5109
+ var DropdownMenuSubContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4954
5110
  DropdownMenuPrimitive.SubContent,
4955
5111
  {
4956
5112
  ref,
@@ -4962,7 +5118,7 @@ var DropdownMenuSubContent = React9.forwardRef(({ className, ...props }, ref) =>
4962
5118
  }
4963
5119
  ));
4964
5120
  DropdownMenuSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName;
4965
- var DropdownMenuContent = React9.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5121
+ var DropdownMenuContent = React10.forwardRef(({ className, sideOffset = 4, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4966
5122
  DropdownMenuPrimitive.Content,
4967
5123
  {
4968
5124
  ref,
@@ -4976,7 +5132,7 @@ var DropdownMenuContent = React9.forwardRef(({ className, sideOffset = 4, ...pro
4976
5132
  }
4977
5133
  ) }));
4978
5134
  DropdownMenuContent.displayName = DropdownMenuPrimitive.Content.displayName;
4979
- var DropdownMenuItem = React9.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5135
+ var DropdownMenuItem = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
4980
5136
  DropdownMenuPrimitive.Item,
4981
5137
  {
4982
5138
  ref,
@@ -4989,7 +5145,7 @@ var DropdownMenuItem = React9.forwardRef(({ className, inset, ...props }, ref) =
4989
5145
  }
4990
5146
  ));
4991
5147
  DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
4992
- var DropdownMenuCheckboxItem = React9.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5148
+ var DropdownMenuCheckboxItem = React10.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
4993
5149
  DropdownMenuPrimitive.CheckboxItem,
4994
5150
  {
4995
5151
  ref,
@@ -5006,7 +5162,7 @@ var DropdownMenuCheckboxItem = React9.forwardRef(({ className, children, checked
5006
5162
  }
5007
5163
  ));
5008
5164
  DropdownMenuCheckboxItem.displayName = DropdownMenuPrimitive.CheckboxItem.displayName;
5009
- var DropdownMenuRadioItem = React9.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5165
+ var DropdownMenuRadioItem = React10.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5010
5166
  DropdownMenuPrimitive.RadioItem,
5011
5167
  {
5012
5168
  ref,
@@ -5022,7 +5178,7 @@ var DropdownMenuRadioItem = React9.forwardRef(({ className, children, ...props }
5022
5178
  }
5023
5179
  ));
5024
5180
  DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
5025
- var DropdownMenuLabel = React9.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5181
+ var DropdownMenuLabel = React10.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5026
5182
  DropdownMenuPrimitive.Label,
5027
5183
  {
5028
5184
  ref,
@@ -5031,7 +5187,7 @@ var DropdownMenuLabel = React9.forwardRef(({ className, inset, ...props }, ref)
5031
5187
  }
5032
5188
  ));
5033
5189
  DropdownMenuLabel.displayName = DropdownMenuPrimitive.Label.displayName;
5034
- var DropdownMenuSeparator = React9.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5190
+ var DropdownMenuSeparator = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5035
5191
  DropdownMenuPrimitive.Separator,
5036
5192
  {
5037
5193
  ref,
@@ -5045,80 +5201,134 @@ var DropdownMenuShortcut = ({ className, ...props }) => {
5045
5201
  };
5046
5202
  DropdownMenuShortcut.displayName = "DropdownMenuShortcut";
5047
5203
 
5048
- // src/components/ui/alert-dialog.tsx
5204
+ // src/components/databrowser/components/delete-key-modal.tsx
5205
+
5049
5206
 
5050
- var _reactalertdialog = require('@radix-ui/react-alert-dialog'); var AlertDialogPrimitive = _interopRequireWildcard(_reactalertdialog);
5207
+ // src/components/ui/dialog.tsx
5208
+
5209
+ var _reactdialog = require('@radix-ui/react-dialog'); var DialogPrimitive = _interopRequireWildcard(_reactdialog);
5051
5210
 
5052
- var AlertDialog = AlertDialogPrimitive.Root;
5053
- var AlertDialogTrigger = AlertDialogPrimitive.Trigger;
5054
- var AlertDialogPortal = ({ ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogPrimitive.Portal, { container: portalRoot, ...props });
5055
- AlertDialogPortal.displayName = AlertDialogPrimitive.Portal.displayName;
5056
- var AlertDialogOverlay = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5057
- AlertDialogPrimitive.Overlay,
5211
+ var Dialog = DialogPrimitive.Root;
5212
+ var DialogTrigger = DialogPrimitive.Trigger;
5213
+ var DialogPortal = (props) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogPrimitive.Portal, { container: portalRoot, ...props });
5214
+ DialogPortal.displayName = DialogPrimitive.Portal.displayName;
5215
+ var DialogOverlay = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5216
+ DialogPrimitive.Overlay,
5058
5217
  {
5218
+ ref,
5059
5219
  className: cn(
5060
- "fixed inset-0 z-50 bg-white/80 backdrop-blur-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
5220
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
5221
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
5222
+ "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm",
5061
5223
  className
5062
5224
  ),
5063
- ...props,
5064
- ref
5225
+ ...props
5065
5226
  }
5066
5227
  ));
5067
- AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName;
5068
- var AlertDialogContent = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogPortal, { children: [
5069
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogOverlay, {}),
5070
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5071
- AlertDialogPrimitive.Content,
5228
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
5229
+ var DialogContent = React11.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogPortal, { children: [
5230
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogOverlay, {}),
5231
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5232
+ DialogPrimitive.Content,
5072
5233
  {
5073
5234
  ref,
5074
5235
  className: cn(
5075
- "antialiased data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:slide-in-from-top-[48%]sm:rounded-lg fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border border-zinc-200 bg-white p-6 shadow-lg duration-200 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 md:w-full",
5236
+ "antialiased",
5237
+ "data-[state=open]:animate-in data-[state=closed]:animate-out ",
5238
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 ",
5239
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 ",
5240
+ "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
5241
+ "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
5242
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg ",
5243
+ "translate-x-[-50%] translate-y-[-50%] gap-4",
5244
+ "bg-white p-8 shadow-lg duration-200 ",
5245
+ "rounded-2xl md:w-full",
5076
5246
  className
5077
5247
  ),
5078
- ...props
5248
+ ...props,
5249
+ children: [
5250
+ children,
5251
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogPrimitive.Close, { className: "absolute right-4 top-4 text-zinc-400 transition-colors hover:text-zinc-600 focus:outline-none disabled:pointer-events-none", children: [
5252
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5253
+ "svg",
5254
+ {
5255
+ width: "20",
5256
+ height: "20",
5257
+ viewBox: "0 0 15 15",
5258
+ fill: "none",
5259
+ xmlns: "http://www.w3.org/2000/svg",
5260
+ className: "size-5",
5261
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5262
+ "path",
5263
+ {
5264
+ d: "M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z",
5265
+ fill: "currentColor",
5266
+ fillRule: "evenodd",
5267
+ clipRule: "evenodd"
5268
+ }
5269
+ )
5270
+ }
5271
+ ),
5272
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Close" })
5273
+ ] })
5274
+ ]
5079
5275
  }
5080
5276
  )
5081
5277
  ] }));
5082
- AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName;
5083
- var AlertDialogHeader = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("flex flex-col space-y-2 text-center sm:text-left", className), ...props });
5084
- AlertDialogHeader.displayName = "AlertDialogHeader";
5085
- var AlertDialogFooter = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5278
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
5279
+ var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
5280
+ DialogHeader.displayName = "DialogHeader";
5281
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5086
5282
  "div",
5087
5283
  {
5088
5284
  className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
5089
5285
  ...props
5090
5286
  }
5091
5287
  );
5092
- AlertDialogFooter.displayName = "AlertDialogFooter";
5093
- var AlertDialogTitle = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5094
- AlertDialogPrimitive.Title,
5288
+ DialogFooter.displayName = "DialogFooter";
5289
+ var DialogTitle = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5290
+ DialogPrimitive.Title,
5095
5291
  {
5096
5292
  ref,
5097
- className: cn("text-lg font-semibold", className),
5293
+ className: cn("text-base font-semibold text-zinc-950", className),
5098
5294
  ...props
5099
5295
  }
5100
5296
  ));
5101
- AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName;
5102
- var AlertDialogDescription = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5103
- AlertDialogPrimitive.Description,
5297
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
5298
+ var DialogDescription = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5299
+ DialogPrimitive.Description,
5104
5300
  {
5105
5301
  ref,
5106
5302
  className: cn("text-sm text-zinc-500", className),
5107
5303
  ...props
5108
5304
  }
5109
5305
  ));
5110
- AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName;
5111
- var AlertDialogAction = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogPrimitive.Action, { ref, className: cn(buttonVariants(), className), ...props }));
5112
- AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName;
5113
- var AlertDialogCancel = React10.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5114
- AlertDialogPrimitive.Cancel,
5306
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
5307
+
5308
+ // src/components/ui/switch.tsx
5309
+
5310
+ var _reactswitch = require('@radix-ui/react-switch'); var SwitchPrimitives = _interopRequireWildcard(_reactswitch);
5311
+
5312
+ var Switch = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5313
+ SwitchPrimitives.Root,
5115
5314
  {
5315
+ className: cn(
5316
+ "peer inline-flex h-5 w-9 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent shadow-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-neutral-950 focus-visible:ring-offset-2 focus-visible:ring-offset-white disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-neutral-900 data-[state=unchecked]:bg-neutral-200 dark:focus-visible:ring-neutral-300 dark:focus-visible:ring-offset-neutral-950 dark:data-[state=checked]:bg-neutral-50 dark:data-[state=unchecked]:bg-neutral-800",
5317
+ className
5318
+ ),
5319
+ ...props,
5116
5320
  ref,
5117
- className: cn(buttonVariants({ variant: "outline" }), "mt-2 sm:!mt-0", className),
5118
- ...props
5321
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5322
+ SwitchPrimitives.Thumb,
5323
+ {
5324
+ className: cn(
5325
+ "pointer-events-none block h-4 w-4 rounded-full bg-white shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-4 data-[state=unchecked]:translate-x-0 dark:bg-neutral-950"
5326
+ )
5327
+ }
5328
+ )
5119
5329
  }
5120
5330
  ));
5121
- AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName;
5331
+ Switch.displayName = SwitchPrimitives.Root.displayName;
5122
5332
 
5123
5333
  // src/components/databrowser/components/delete-key-modal.tsx
5124
5334
 
@@ -5128,17 +5338,24 @@ function DeleteKeyModal({
5128
5338
  open,
5129
5339
  onOpenChange,
5130
5340
  deletionType,
5131
- count: count2 = 1
5341
+ count: count2 = 1,
5342
+ showReindex
5132
5343
  }) {
5133
5344
  const isPlural = count2 > 1;
5134
5345
  const itemLabel = deletionType === "item" ? "Item" : "Key";
5135
5346
  const itemsLabel = deletionType === "item" ? "Items" : "Keys";
5136
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialog, { open, onOpenChange, children: [
5137
- children && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTrigger, { asChild: true, children }),
5138
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogContent, { children: [
5139
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogHeader, { children: [
5140
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogTitle, { children: isPlural ? `Delete ${count2} ${itemsLabel}` : `Delete ${itemLabel}` }),
5141
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogDescription, { className: "mt-5", children: [
5347
+ const [internalOpen, setInternalOpen] = _react.useState.call(void 0, false);
5348
+ const [reindex, setReindex] = _react.useState.call(void 0, true);
5349
+ const [isPending, setIsPending] = _react.useState.call(void 0, false);
5350
+ const isControlled = open !== void 0;
5351
+ const isOpen = isControlled ? open : internalOpen;
5352
+ const setIsOpen = isControlled ? onOpenChange : setInternalOpen;
5353
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Dialog, { open: isOpen, onOpenChange: setIsOpen, children: [
5354
+ children && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTrigger, { asChild: true, children }),
5355
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogContent, { children: [
5356
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogHeader, { children: [
5357
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: isPlural ? `Delete ${count2} ${itemsLabel}` : `Delete ${itemLabel}` }),
5358
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogDescription, { className: "mt-5", children: [
5142
5359
  "Are you sure you want to delete",
5143
5360
  " ",
5144
5361
  isPlural ? `these ${count2} ${deletionType}s` : `this ${deletionType}`,
@@ -5147,14 +5364,44 @@ function DeleteKeyModal({
5147
5364
  "This action cannot be undone."
5148
5365
  ] })
5149
5366
  ] }),
5150
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, AlertDialogFooter, { children: [
5151
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AlertDialogCancel, { type: "button", children: "Cancel" }),
5367
+ showReindex && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
5368
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5369
+ Switch,
5370
+ {
5371
+ id: "reindex",
5372
+ checked: reindex,
5373
+ onCheckedChange: setReindex,
5374
+ disabled: isPending
5375
+ }
5376
+ ),
5377
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Label, { htmlFor: "reindex", className: "cursor-pointer text-sm text-zinc-700", children: "Reindex after deletion" })
5378
+ ] }),
5379
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogFooter, { children: [
5380
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5381
+ Button,
5382
+ {
5383
+ type: "button",
5384
+ variant: "outline",
5385
+ disabled: isPending,
5386
+ onClick: () => _optionalChain([setIsOpen, 'optionalCall', _39 => _39(false)]),
5387
+ children: "Cancel"
5388
+ }
5389
+ ),
5152
5390
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5153
- AlertDialogAction,
5391
+ Button,
5154
5392
  {
5393
+ variant: "primary",
5155
5394
  className: "bg-red-500 text-zinc-50 hover:bg-red-600",
5156
- onClick: onDeleteConfirm,
5157
- children: "Yes, Delete"
5395
+ disabled: isPending,
5396
+ onClick: async (e) => {
5397
+ setIsPending(true);
5398
+ try {
5399
+ await onDeleteConfirm(e, { reindex });
5400
+ } finally {
5401
+ setIsPending(false);
5402
+ }
5403
+ },
5404
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: isPending, isLoadingText: "Deleting", children: "Yes, Delete" })
5158
5405
  }
5159
5406
  )
5160
5407
  ] })
@@ -5164,8 +5411,13 @@ function DeleteKeyModal({
5164
5411
 
5165
5412
  // src/components/databrowser/components/display/key-actions.tsx
5166
5413
 
5167
- function KeyActions({ dataKey, content }) {
5414
+ function KeyActions({
5415
+ dataKey,
5416
+ content,
5417
+ type
5418
+ }) {
5168
5419
  const { mutateAsync: deleteKey } = useDeleteKey();
5420
+ const { isValuesSearchSelected } = useTab();
5169
5421
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DropdownMenu, { modal: false, children: [
5170
5422
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { size: "icon-sm", "aria-label": "Key actions", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5171
5423
  _iconsreact.IconDotsVertical,
@@ -5196,14 +5448,24 @@ function KeyActions({ dataKey, content }) {
5196
5448
  children: "Copy key"
5197
5449
  }
5198
5450
  ),
5199
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DeleteKeyModal, { deletionType: "key", onDeleteConfirm: async () => await deleteKey(dataKey), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5200
- DropdownMenuItem,
5451
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5452
+ DeleteKeyModal,
5201
5453
  {
5202
- className: "text-red-500 focus:bg-red-500 focus:text-white",
5203
- onSelect: (e) => e.preventDefault(),
5204
- children: "Delete key"
5454
+ deletionType: "key",
5455
+ showReindex: isValuesSearchSelected && type !== "search",
5456
+ onDeleteConfirm: async (_e, options) => {
5457
+ await deleteKey({ keys: [dataKey], reindex: _optionalChain([options, 'optionalAccess', _40 => _40.reindex]) });
5458
+ },
5459
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5460
+ DropdownMenuItem,
5461
+ {
5462
+ className: "text-red-500 focus:bg-red-500 focus:text-white",
5463
+ onSelect: (e) => e.preventDefault(),
5464
+ children: "Delete key"
5465
+ }
5466
+ )
5205
5467
  }
5206
- ) })
5468
+ )
5207
5469
  ] })
5208
5470
  ] });
5209
5471
  }
@@ -5225,142 +5487,69 @@ var DisplayHeader = ({
5225
5487
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "grow truncate text-sm", children: dataKey.trim() === "" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "ml-1 text-zinc-500", children: "(Empty Key)" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium text-zinc-950", children: dataKey }) }),
5226
5488
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
5227
5489
  type !== "string" && type !== "json" && type !== "search" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Add item", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { onClick: handleAddItem, size: "icon-sm", "aria-label": "Add item", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-4 text-zinc-500 dark:text-zinc-600" }) }) }),
5228
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyActions, { dataKey, content })
5490
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyActions, { dataKey, content, type })
5229
5491
  ] })
5230
5492
  ] }),
5231
- type === "search" && hideTypeTag ? void 0 : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-10 items-center gap-1.5 overflow-scroll", children: [
5493
+ type === "search" && hideTypeTag ? void 0 : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollArea, { orientation: "horizontal", className: "w-full whitespace-nowrap", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-max items-center gap-1.5 pb-2 pt-1", children: [
5232
5494
  !hideTypeTag && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TypeTag, { variant: type, type: "badge" }),
5233
5495
  type !== "search" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SizeBadge, { dataKey }),
5234
5496
  type !== "search" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LengthBadge, { dataKey, type, content }),
5235
5497
  type !== "search" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HeaderTTLBadge, { dataKey })
5236
- ] })
5498
+ ] }) })
5237
5499
  ] });
5238
5500
  };
5239
5501
 
5502
+ // src/components/databrowser/components/display/key-deleted.tsx
5503
+
5504
+ var KeyDeleted = () => {
5505
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center rounded-md border border-dashed border-zinc-300", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: "This key has been deleted" }) });
5506
+ };
5507
+
5508
+ // src/components/databrowser/components/docs-link.tsx
5509
+
5510
+
5511
+ var DocsLink = ({ href, className }) => {
5512
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5513
+ "a",
5514
+ {
5515
+ href,
5516
+ target: "_blank",
5517
+ rel: "noopener noreferrer",
5518
+ className: cn(
5519
+ "inline-flex items-center gap-1 px-1 text-xs text-zinc-400 transition-colors hover:text-zinc-600",
5520
+ className
5521
+ ),
5522
+ children: [
5523
+ "Docs",
5524
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconExternalLink, { size: 12 })
5525
+ ]
5526
+ }
5527
+ );
5528
+ };
5529
+
5240
5530
  // src/components/databrowser/components/search/save-schema-modal.tsx
5241
5531
 
5242
5532
 
5243
- // src/components/ui/dialog.tsx
5533
+ // src/components/ui/progress.tsx
5244
5534
 
5245
- var _reactdialog = require('@radix-ui/react-dialog'); var DialogPrimitive = _interopRequireWildcard(_reactdialog);
5535
+ var _reactprogress = require('@radix-ui/react-progress'); var ProgressPrimitive = _interopRequireWildcard(_reactprogress);
5246
5536
 
5247
- var Dialog = DialogPrimitive.Root;
5248
- var DialogTrigger = DialogPrimitive.Trigger;
5249
- var DialogPortal = (props) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogPrimitive.Portal, { container: portalRoot, ...props });
5250
- DialogPortal.displayName = DialogPrimitive.Portal.displayName;
5251
- var DialogOverlay = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5252
- DialogPrimitive.Overlay,
5537
+ var Progress = React13.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5538
+ ProgressPrimitive.Root,
5253
5539
  {
5254
5540
  ref,
5255
5541
  className: cn(
5256
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
5257
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
5258
- "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm",
5542
+ "relative h-2 w-full overflow-hidden rounded-full bg-neutral-900/20 dark:bg-neutral-50/20",
5259
5543
  className
5260
5544
  ),
5261
- ...props
5262
- }
5263
- ));
5264
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
5265
- var DialogContent = React11.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogPortal, { children: [
5266
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogOverlay, {}),
5267
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5268
- DialogPrimitive.Content,
5269
- {
5270
- ref,
5271
- className: cn(
5272
- "antialiased",
5273
- "data-[state=open]:animate-in data-[state=closed]:animate-out ",
5274
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 ",
5275
- "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 ",
5276
- "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
5277
- "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
5278
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg ",
5279
- "translate-x-[-50%] translate-y-[-50%] gap-4",
5280
- "bg-white p-6 shadow-lg duration-200 ",
5281
- "sm:rounded-lg md:w-full",
5282
- className
5283
- ),
5284
- ...props,
5285
- children: [
5286
- children,
5287
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-white transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-zinc-950 focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-zinc-100 data-[state=open]:text-zinc-500", children: [
5288
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5289
- "svg",
5290
- {
5291
- width: "15",
5292
- height: "15",
5293
- viewBox: "0 0 15 15",
5294
- fill: "none",
5295
- xmlns: "http://www.w3.org/2000/svg",
5296
- className: "h-4 w-4",
5297
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5298
- "path",
5299
- {
5300
- d: "M11.7816 4.03157C12.0062 3.80702 12.0062 3.44295 11.7816 3.2184C11.5571 2.99385 11.193 2.99385 10.9685 3.2184L7.50005 6.68682L4.03164 3.2184C3.80708 2.99385 3.44301 2.99385 3.21846 3.2184C2.99391 3.44295 2.99391 3.80702 3.21846 4.03157L6.68688 7.49999L3.21846 10.9684C2.99391 11.193 2.99391 11.557 3.21846 11.7816C3.44301 12.0061 3.80708 12.0061 4.03164 11.7816L7.50005 8.31316L10.9685 11.7816C11.193 12.0061 11.5571 12.0061 11.7816 11.7816C12.0062 11.557 12.0062 11.193 11.7816 10.9684L8.31322 7.49999L11.7816 4.03157Z",
5301
- fill: "currentColor",
5302
- fillRule: "evenodd",
5303
- clipRule: "evenodd"
5304
- }
5305
- )
5306
- }
5307
- ),
5308
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Close" })
5309
- ] })
5310
- ]
5311
- }
5312
- )
5313
- ] }));
5314
- DialogContent.displayName = DialogPrimitive.Content.displayName;
5315
- var DialogHeader = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
5316
- DialogHeader.displayName = "DialogHeader";
5317
- var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5318
- "div",
5319
- {
5320
- className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
5321
- ...props
5322
- }
5323
- );
5324
- DialogFooter.displayName = "DialogFooter";
5325
- var DialogTitle = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5326
- DialogPrimitive.Title,
5327
- {
5328
- ref,
5329
- className: cn("text-lg font-semibold leading-none tracking-tight", className),
5330
- ...props
5331
- }
5332
- ));
5333
- DialogTitle.displayName = DialogPrimitive.Title.displayName;
5334
- var DialogDescription = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5335
- DialogPrimitive.Description,
5336
- {
5337
- ref,
5338
- className: cn("text-sm text-zinc-500", className),
5339
- ...props
5340
- }
5341
- ));
5342
- DialogDescription.displayName = DialogPrimitive.Description.displayName;
5343
-
5344
- // src/components/ui/progress.tsx
5345
-
5346
- var _reactprogress = require('@radix-ui/react-progress'); var ProgressPrimitive = _interopRequireWildcard(_reactprogress);
5347
-
5348
- var Progress = React12.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5349
- ProgressPrimitive.Root,
5350
- {
5351
- ref,
5352
- className: cn(
5353
- "relative h-2 w-full overflow-hidden rounded-full bg-neutral-900/20 dark:bg-neutral-50/20",
5354
- className
5355
- ),
5356
- ...props,
5357
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5358
- ProgressPrimitive.Indicator,
5359
- {
5360
- className: "h-full w-full flex-1 bg-neutral-900 transition-all dark:bg-neutral-50",
5361
- style: { transform: `translateX(-${100 - (value || 0)}%)` }
5362
- }
5363
- )
5545
+ ...props,
5546
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5547
+ ProgressPrimitive.Indicator,
5548
+ {
5549
+ className: "h-full w-full flex-1 bg-neutral-900 transition-all dark:bg-neutral-50",
5550
+ style: { transform: `translateX(-${100 - (value || 0)}%)` }
5551
+ }
5552
+ )
5364
5553
  }
5365
5554
  ));
5366
5555
  Progress.displayName = ProgressPrimitive.Root.displayName;
@@ -5491,16 +5680,18 @@ var MonacoEditorWithTypes = ({
5491
5680
  const monaco = _react2.useMonaco.call(void 0, );
5492
5681
  const editorRef = _react.useRef.call(void 0, null);
5493
5682
  const extraLibRef = _react.useRef.call(void 0, null);
5683
+ const valueRef = _react.useRef.call(void 0, value);
5684
+ valueRef.current = value;
5494
5685
  const theme = useTheme();
5495
5686
  _react.useEffect.call(void 0, () => {
5496
5687
  if (!monaco) return;
5497
- _optionalChain([extraLibRef, 'access', _38 => _38.current, 'optionalAccess', _39 => _39.dispose, 'call', _40 => _40()]);
5688
+ _optionalChain([extraLibRef, 'access', _41 => _41.current, 'optionalAccess', _42 => _42.dispose, 'call', _43 => _43()]);
5498
5689
  extraLibRef.current = monaco.languages.typescript.typescriptDefaults.addExtraLib(
5499
5690
  typeDefinitions,
5500
5691
  `file:///${filePath.replace(".ts", "-types.d.ts")}`
5501
5692
  );
5502
5693
  requestAnimationFrame(() => {
5503
- const model = _optionalChain([editorRef, 'access', _41 => _41.current, 'optionalAccess', _42 => _42.getModel, 'optionalCall', _43 => _43()]);
5694
+ const model = _optionalChain([editorRef, 'access', _44 => _44.current, 'optionalAccess', _45 => _45.getModel, 'optionalCall', _46 => _46()]);
5504
5695
  if (model) {
5505
5696
  const currentValue = model.getValue();
5506
5697
  model.setValue(currentValue);
@@ -5509,10 +5700,10 @@ var MonacoEditorWithTypes = ({
5509
5700
  }, [monaco, typeDefinitions, filePath]);
5510
5701
  _react.useEffect.call(void 0, () => {
5511
5702
  return () => {
5512
- _optionalChain([extraLibRef, 'access', _44 => _44.current, 'optionalAccess', _45 => _45.dispose, 'call', _46 => _46()]);
5703
+ _optionalChain([extraLibRef, 'access', _47 => _47.current, 'optionalAccess', _48 => _48.dispose, 'call', _49 => _49()]);
5513
5704
  if (monaco) {
5514
5705
  const model = monaco.editor.getModel(monaco.Uri.parse(filePath));
5515
- _optionalChain([model, 'optionalAccess', _47 => _47.dispose, 'call', _48 => _48()]);
5706
+ _optionalChain([model, 'optionalAccess', _50 => _50.dispose, 'call', _51 => _51()]);
5516
5707
  }
5517
5708
  };
5518
5709
  }, [monaco, filePath]);
@@ -5522,12 +5713,12 @@ var MonacoEditorWithTypes = ({
5522
5713
  } else if (newValue.trim() === "") {
5523
5714
  onChange(defaultValue);
5524
5715
  } else {
5525
- _optionalChain([editorRef, 'access', _49 => _49.current, 'optionalAccess', _50 => _50.setValue, 'optionalCall', _51 => _51(value)]);
5716
+ _optionalChain([editorRef, 'access', _52 => _52.current, 'optionalAccess', _53 => _53.setValue, 'optionalCall', _54 => _54(valueRef.current)]);
5526
5717
  }
5527
5718
  };
5528
5719
  _react.useEffect.call(void 0, () => {
5529
5720
  if (!validateValue(value)) onChange(defaultValue);
5530
- }, [value, editorRef.current, onChange, validateValue, defaultValue]);
5721
+ }, [value, onChange, validateValue, defaultValue]);
5531
5722
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5532
5723
  "div",
5533
5724
  {
@@ -5664,7 +5855,7 @@ type TextFieldBuild<TNoTokenize extends Record<"noTokenize", boolean>, TNoStem e
5664
5855
  } : {}) : TFrom["from"] extends string ? {
5665
5856
  type: "TEXT";
5666
5857
  from: TFrom["from"];
5667
- } : "TEXT";
5858
+ } : { type: "TEXT" };
5668
5859
  declare const BUILD: unique symbol;
5669
5860
  declare class TextFieldBuilder<TNoTokenize extends Record<"noTokenize", boolean> = {
5670
5861
  noTokenize: false;
@@ -5732,7 +5923,7 @@ declare class BoolFieldBuilder<Fast extends Record<"fast", boolean> = {
5732
5923
  } : TFrom["from"] extends string ? {
5733
5924
  type: "BOOL";
5734
5925
  from: TFrom["from"];
5735
- } : "BOOL";
5926
+ } : { type: "BOOL" };
5736
5927
  }
5737
5928
  declare class DateFieldBuilder<Fast extends Record<"fast", boolean> = {
5738
5929
  fast: false;
@@ -5760,7 +5951,13 @@ declare class DateFieldBuilder<Fast extends Record<"fast", boolean> = {
5760
5951
  } : TFrom["from"] extends string ? {
5761
5952
  type: "DATE";
5762
5953
  from: TFrom["from"];
5763
- } : "DATE";
5954
+ } : { type: "DATE" };
5955
+ }
5956
+ declare class KeywordFieldBuilder {
5957
+ [BUILD](): { type: "KEYWORD" };
5958
+ }
5959
+ declare class FacetFieldBuilder {
5960
+ [BUILD](): { type: "FACET" };
5764
5961
  }
5765
5962
  type FieldBuilder = TextFieldBuilder<{
5766
5963
  noTokenize: boolean;
@@ -5778,12 +5975,14 @@ type FieldBuilder = TextFieldBuilder<{
5778
5975
  fast: boolean;
5779
5976
  }, {
5780
5977
  from: string | null;
5781
- }>;
5978
+ }> | KeywordFieldBuilder | FacetFieldBuilder;
5782
5979
  declare const s: {
5783
5980
  string(): TextFieldBuilder;
5784
5981
  number<T extends NumericField["type"] = "F64">(type?: T): NumericFieldBuilder<T>;
5785
5982
  boolean(): BoolFieldBuilder;
5786
5983
  date(): DateFieldBuilder;
5984
+ keyword(): KeywordFieldBuilder;
5985
+ facet(): FacetFieldBuilder;
5787
5986
  object<T extends ObjectFieldRecord<T>>(fields: T): { [K in keyof T]: T[K] extends FieldBuilder ? ReturnType<T[K][typeof BUILD]> : T[K]; };
5788
5987
  };
5789
5988
  type ObjectFieldRecord<T> = {
@@ -5804,7 +6003,7 @@ type Schema = NestedIndexSchema | FlatIndexSchema;
5804
6003
 
5805
6004
  var SCHEMA_PREFIX = "const schema: Schema = s.object({";
5806
6005
  var SCHEMA_SUFFIX = "})";
5807
- var SCHEMA_DEFAULT = "const schema: Schema = s.object({\n \n})";
6006
+ var SCHEMA_DEFAULT = "const schema: Schema = s.object({\n name: s.string(),\n})";
5808
6007
  var isSchemaStringValid = (value) => {
5809
6008
  return value.startsWith(SCHEMA_PREFIX) && value.endsWith(SCHEMA_SUFFIX);
5810
6009
  };
@@ -5826,6 +6025,123 @@ var SchemaEditor = ({ value, onChange, height }) => {
5826
6025
  );
5827
6026
  };
5828
6027
 
6028
+ // src/components/databrowser/components/search/schema-stringify.ts
6029
+ function schemaToEditorValue(flatSchema) {
6030
+ const nested = unflattenSchema(flatSchema);
6031
+ const body = renderObject(nested, 1);
6032
+ return `const schema: Schema = s.object({
6033
+ ${body}})`;
6034
+ }
6035
+ function unflattenSchema(flat) {
6036
+ const result = {};
6037
+ for (const [key, value] of Object.entries(flat)) {
6038
+ const parts = key.split(".");
6039
+ let current = result;
6040
+ for (let i = 0; i < parts.length - 1; i++) {
6041
+ const part = parts[i];
6042
+ if (!current[part] || typeof current[part] !== "object") {
6043
+ current[part] = {};
6044
+ }
6045
+ current = current[part];
6046
+ }
6047
+ current[parts.at(-1)] = value;
6048
+ }
6049
+ return result;
6050
+ }
6051
+ function renderObject(obj, indent) {
6052
+ const pad = " ".repeat(indent);
6053
+ const lines = [];
6054
+ for (const [key, value] of Object.entries(obj)) {
6055
+ if (isFieldValue(value)) {
6056
+ lines.push(`${pad}${key}: ${fieldToBuilder(value)},`);
6057
+ } else {
6058
+ const nested = renderObject(value, indent + 1);
6059
+ lines.push(`${pad}${key}: s.object({`);
6060
+ lines.push(nested.trimEnd());
6061
+ lines.push(`${pad}}),`);
6062
+ }
6063
+ }
6064
+ return lines.join("\n") + "\n";
6065
+ }
6066
+ function isFieldValue(value) {
6067
+ if (typeof value === "string") return true;
6068
+ if (typeof value === "object" && value !== null) {
6069
+ return "type" in value;
6070
+ }
6071
+ return false;
6072
+ }
6073
+ function fieldToBuilder(value) {
6074
+ if (typeof value === "string") {
6075
+ switch (value) {
6076
+ case "TEXT": {
6077
+ return "s.string()";
6078
+ }
6079
+ case "BOOL": {
6080
+ return "s.boolean()";
6081
+ }
6082
+ case "DATE": {
6083
+ return "s.date()";
6084
+ }
6085
+ case "U64":
6086
+ case "I64":
6087
+ case "F64": {
6088
+ return `s.number("${value}")`;
6089
+ }
6090
+ case "KEYWORD": {
6091
+ return "s.keyword()";
6092
+ }
6093
+ case "FACET": {
6094
+ return "s.facet()";
6095
+ }
6096
+ default: {
6097
+ return "s.string()";
6098
+ }
6099
+ }
6100
+ }
6101
+ const v = value;
6102
+ const type = v.type;
6103
+ let builder = "";
6104
+ switch (type) {
6105
+ case "TEXT": {
6106
+ builder = "s.string()";
6107
+ if (v.noTokenize) builder += ".noTokenize()";
6108
+ if (v.noStem) builder += ".noStem()";
6109
+ break;
6110
+ }
6111
+ case "U64":
6112
+ case "I64":
6113
+ case "F64": {
6114
+ builder = `s.number("${type}")`;
6115
+ break;
6116
+ }
6117
+ case "BOOL": {
6118
+ builder = "s.boolean()";
6119
+ if (v.fast) builder += ".fast()";
6120
+ break;
6121
+ }
6122
+ case "DATE": {
6123
+ builder = "s.date()";
6124
+ if (v.fast) builder += ".fast()";
6125
+ break;
6126
+ }
6127
+ case "KEYWORD": {
6128
+ builder = "s.keyword()";
6129
+ break;
6130
+ }
6131
+ case "FACET": {
6132
+ builder = "s.facet()";
6133
+ break;
6134
+ }
6135
+ default: {
6136
+ builder = "s.string()";
6137
+ }
6138
+ }
6139
+ if (v.from) {
6140
+ builder += `.from("${v.from}")`;
6141
+ }
6142
+ return builder;
6143
+ }
6144
+
5829
6145
  // src/components/databrowser/components/search/display-search.tsx
5830
6146
 
5831
6147
  var SearchDisplay = ({
@@ -5853,6 +6169,7 @@ var SearchDisplay = ({
5853
6169
  const currentIndexName = watch("indexName");
5854
6170
  const effectiveIndexName = isCreateModal ? currentIndexName : _nullishCoalesce(indexName, () => ( ""));
5855
6171
  const [pendingFormValues, setPendingFormValues] = _react.useState.call(void 0, );
6172
+ const [parseError, setParseError] = _react.useState.call(void 0, );
5856
6173
  const { data, isLoading } = useFetchSearchIndex(indexName, {
5857
6174
  enabled: !isCreateModal
5858
6175
  });
@@ -5863,11 +6180,12 @@ var SearchDisplay = ({
5863
6180
  indexName: _nullishCoalesce(indexName, () => ( "")),
5864
6181
  editorValue: data.schema ? schemaToEditorValue(data.schema) : SCHEMA_DEFAULT,
5865
6182
  dataType: data.dataType || "string",
5866
- prefixes: _optionalChain([data, 'access', _52 => _52.prefixes, 'optionalAccess', _53 => _53.join, 'call', _54 => _54(", ")]) || "",
6183
+ prefixes: _optionalChain([data, 'access', _55 => _55.prefixes, 'optionalAccess', _56 => _56.join, 'call', _57 => _57(", ")]) || "",
5867
6184
  language: data.language || "english"
5868
6185
  });
5869
6186
  }, [data, reset, indexName]);
5870
6187
  const onSubmit = (values) => {
6188
+ setParseError(void 0);
5871
6189
  if (isCreateModal) {
5872
6190
  createSchema.mutate(
5873
6191
  {
@@ -5882,6 +6200,11 @@ var SearchDisplay = ({
5882
6200
  }
5883
6201
  );
5884
6202
  } else {
6203
+ const result = parseSchemaFromEditorValue(values.editorValue);
6204
+ if (!result.success) {
6205
+ setParseError(result.error);
6206
+ return;
6207
+ }
5885
6208
  setPendingFormValues({ ...values, indexName });
5886
6209
  }
5887
6210
  };
@@ -5889,11 +6212,14 @@ var SearchDisplay = ({
5889
6212
  createSchema.reset();
5890
6213
  reset();
5891
6214
  };
5892
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full w-full min-w-0 flex-col gap-2", children: [
6215
+ if (!isCreateModal && !isLoading && (data === null || data === void 0)) {
6216
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyDeleted, {});
6217
+ }
6218
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full min-h-0 w-full min-w-0 flex-col gap-2", children: [
5893
6219
  !isCreateModal && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey: effectiveIndexName, type: "search", hideTypeTag: isEditModal }),
5894
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full min-w-0 grow flex-col gap-2 rounded-md", children: !isCreateModal && isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoadingText: "", isLoading: true }) : !isCreateModal && (data === null || data === void 0) ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full items-center justify-center", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-zinc-500", children: "No data found" }) }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full w-full flex-col gap-3", children: [
6220
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex min-h-0 min-w-0 grow flex-col gap-2 rounded-md", children: !isCreateModal && isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoadingText: "", isLoading: true }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-0 w-full flex-1 flex-col gap-3", children: [
5895
6221
  isCreateModal && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-1.5", children: [
5896
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Label, { htmlFor: "index-name", children: "Key" }),
6222
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Label, { htmlFor: "index-name", children: "Index Key" }),
5897
6223
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5898
6224
  Input,
5899
6225
  {
@@ -5904,9 +6230,9 @@ var SearchDisplay = ({
5904
6230
  ),
5905
6231
  errors.indexName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xs text-red-500", children: errors.indexName.message })
5906
6232
  ] }),
5907
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-md border border-zinc-300 bg-white p-3", children: [
6233
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "shrink-0 rounded-md border border-zinc-300 bg-white p-3", children: [
5908
6234
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-between", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-sm font-medium text-zinc-700", children: "Config" }) }),
5909
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-2 grid grid-cols-4 gap-4 text-sm", children: [
6235
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-2 grid grid-cols-2 gap-4 text-sm lg:grid-cols-4", children: [
5910
6236
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
5911
6237
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mb-1.5 block text-xs font-medium text-zinc-500", children: "Data Type" }),
5912
6238
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -5930,7 +6256,7 @@ var SearchDisplay = ({
5930
6256
  control,
5931
6257
  render: ({ field }) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: field.value, onValueChange: field.onChange, children: [
5932
6258
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, { placeholder: "Select language" }) }),
5933
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: LANGUAGES.map((lang) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: lang, children: lang }, lang)) })
6259
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: LANGUAGES.map((lang) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: lang, children: lang.charAt(0).toUpperCase() + lang.slice(1) }, lang)) })
5934
6260
  ] })
5935
6261
  }
5936
6262
  )
@@ -5949,7 +6275,7 @@ var SearchDisplay = ({
5949
6275
  ] })
5950
6276
  ] })
5951
6277
  ] }),
5952
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-0 flex-1 flex-col rounded-md border border-zinc-300 bg-white", children: [
6278
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative flex min-h-0 flex-1 flex-col rounded-md border border-zinc-300 bg-white", children: [
5953
6279
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-between border-b border-zinc-200 px-3 py-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-sm font-medium text-zinc-700", children: "Schema" }) }),
5954
6280
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full px-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5955
6281
  _reacthookform.Controller,
@@ -5965,9 +6291,17 @@ var SearchDisplay = ({
5965
6291
  }
5966
6292
  )
5967
6293
  }
5968
- ) }) })
6294
+ ) }) }),
6295
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6296
+ DocsLink,
6297
+ {
6298
+ className: "absolute bottom-2 right-2 text-sm",
6299
+ href: "https://upstash-search.mintlify.app/redis/search/schema-definition"
6300
+ }
6301
+ )
5969
6302
  ] }),
5970
6303
  isCreateModal && createSchema.error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full break-words text-xs text-red-500", children: createSchema.error.message.startsWith("ERR syntax error") ? "Invalid schema" : formatUpstashErrorMessage(createSchema.error) }),
6304
+ parseError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full break-words text-xs text-red-500", children: parseError }),
5971
6305
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex shrink-0 items-center gap-2", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "ml-auto flex gap-2", children: [
5972
6306
  (isDirty || isCreateModal || isEditModal) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5973
6307
  Button,
@@ -5990,7 +6324,6 @@ var SearchDisplay = ({
5990
6324
  values: pendingFormValues,
5991
6325
  onClose: () => {
5992
6326
  setPendingFormValues(void 0);
5993
- reset();
5994
6327
  if (isEditModal && onClose) onClose();
5995
6328
  }
5996
6329
  }
@@ -6027,63 +6360,6 @@ var LANGUAGES = [
6027
6360
 
6028
6361
 
6029
6362
 
6030
- // src/components/ui/scroll-area.tsx
6031
-
6032
- var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
6033
-
6034
- var ScrollArea = React13.forwardRef(
6035
- ({
6036
- className,
6037
- scrollBarClassName,
6038
- scrollBarForceMount,
6039
- children,
6040
- onScroll,
6041
- disableRoundedInherit = false,
6042
- ...props
6043
- }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6044
- ScrollAreaPrimitive.Root,
6045
- {
6046
- ref,
6047
- className: cn("relative overflow-hidden", className),
6048
- ...props,
6049
- children: [
6050
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6051
- ScrollAreaPrimitive.Viewport,
6052
- {
6053
- onScroll,
6054
- className: cn(
6055
- "h-full w-full [&>div]:!block",
6056
- !disableRoundedInherit && "rounded-[inherit]"
6057
- ),
6058
- children
6059
- }
6060
- ),
6061
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, { className: scrollBarClassName, forceMount: scrollBarForceMount }),
6062
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
6063
- ]
6064
- }
6065
- )
6066
- );
6067
- ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
6068
- var ScrollBar = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6069
- ScrollAreaPrimitive.ScrollAreaScrollbar,
6070
- {
6071
- ref,
6072
- orientation: "vertical",
6073
- className: cn("mr-1 flex h-full w-2 touch-none select-none transition-colors", className),
6074
- ...props,
6075
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6076
- ScrollAreaPrimitive.ScrollAreaThumb,
6077
- {
6078
- className: cn("relative flex-1 rounded-full bg-zinc-400/70")
6079
- }
6080
- )
6081
- }
6082
- ));
6083
- ScrollBar.displayName = ScrollAreaPrimitive.ScrollAreaScrollbar.displayName;
6084
-
6085
- // src/components/common/infinite-scroll.tsx
6086
-
6087
6363
  var InfiniteScroll = ({
6088
6364
  query,
6089
6365
  children,
@@ -6121,7 +6397,7 @@ var InfiniteScroll = ({
6121
6397
  type: "always",
6122
6398
  onScroll: handleScroll,
6123
6399
  ...props,
6124
- className: cn("block h-full w-full overflow-visible transition-all", props.className),
6400
+ className: cn("block h-full min-h-0 w-full overflow-hidden transition-all", props.className),
6125
6401
  ref: scrollRef,
6126
6402
  children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { ref: contentRef, children: [
6127
6403
  children,
@@ -6277,7 +6553,7 @@ var ItemContextMenu = ({
6277
6553
  editItem({
6278
6554
  type,
6279
6555
  dataKey,
6280
- itemKey: _optionalChain([data, 'optionalAccess', _55 => _55.key]),
6556
+ itemKey: _optionalChain([data, 'optionalAccess', _58 => _58.key]),
6281
6557
  // For deletion
6282
6558
  newKey: void 0
6283
6559
  });
@@ -6312,7 +6588,7 @@ var ItemContextMenu = ({
6312
6588
  {
6313
6589
  onClick: () => {
6314
6590
  if (!data) return;
6315
- navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _56 => _56.key]));
6591
+ navigator.clipboard.writeText(_optionalChain([data, 'optionalAccess', _59 => _59.key]));
6316
6592
  toast({
6317
6593
  description: "Key copied to clipboard"
6318
6594
  });
@@ -6324,11 +6600,11 @@ var ItemContextMenu = ({
6324
6600
  ]
6325
6601
  }
6326
6602
  ),
6327
- _optionalChain([data, 'optionalAccess', _57 => _57.value]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6603
+ _optionalChain([data, 'optionalAccess', _60 => _60.value]) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6328
6604
  ContextMenuItem,
6329
6605
  {
6330
6606
  onClick: () => {
6331
- navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _58 => _58.value]), () => ( "")));
6607
+ navigator.clipboard.writeText(_nullishCoalesce(_optionalChain([data, 'optionalAccess', _61 => _61.value]), () => ( "")));
6332
6608
  toast({
6333
6609
  description: "Value copied to clipboard"
6334
6610
  });
@@ -6440,7 +6716,7 @@ var useSetHashTTL = () => {
6440
6716
  var HashFieldTTLBadge = ({ dataKey, field }) => {
6441
6717
  const { data } = useFetchHashFieldExpires({ dataKey, fields: [field] });
6442
6718
  const { mutate: setTTL, isPending } = useSetHashTTL();
6443
- const expireAt = _optionalChain([data, 'optionalAccess', _59 => _59[field]]);
6719
+ const expireAt = _optionalChain([data, 'optionalAccess', _62 => _62[field]]);
6444
6720
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6445
6721
  TTLBadge,
6446
6722
  {
@@ -6537,7 +6813,7 @@ var MonacoEditor = ({
6537
6813
  if (!active || !monaco || !editorRef.current) {
6538
6814
  return;
6539
6815
  }
6540
- _optionalChain([monaco, 'optionalAccess', _60 => _60.editor, 'access', _61 => _61.setModelLanguage, 'call', _62 => _62(editorRef.current.getModel(), language)]);
6816
+ _optionalChain([monaco, 'optionalAccess', _63 => _63.editor, 'access', _64 => _64.setModelLanguage, 'call', _65 => _65(editorRef.current.getModel(), language)]);
6541
6817
  }, [monaco, language, active]);
6542
6818
  const editor = /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6543
6819
  _react2.Editor,
@@ -6662,6 +6938,13 @@ var useField = ({
6662
6938
  }
6663
6939
  }
6664
6940
  };
6941
+ _react.useLayoutEffect.call(void 0, () => {
6942
+ if (!fieldState.isDirty && contentType === "JSON" && checkIsValidJSON(data)) {
6943
+ form.setValue(name, formatJSON(data), {
6944
+ shouldDirty: false
6945
+ });
6946
+ }
6947
+ }, [data, fieldState.isDirty]);
6665
6948
  return {
6666
6949
  selector: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContentTypeSelect, { value: contentType, onChange: handleTypeChange, data: field.value }),
6667
6950
  editor: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -6694,7 +6977,7 @@ var ListEditDisplay = ({
6694
6977
  type,
6695
6978
  item
6696
6979
  }) => {
6697
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "grow rounded-md", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditForm, { item, type, dataKey }, item.key) });
6980
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-0 grow rounded-md", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditForm, { item, type, dataKey }, item.key) });
6698
6981
  };
6699
6982
  var ListEditForm = ({
6700
6983
  type,
@@ -6706,7 +6989,7 @@ var ListEditForm = ({
6706
6989
  dataKey
6707
6990
  });
6708
6991
  const findValue = () => {
6709
- for (const page of _nullishCoalesce(_optionalChain([query, 'access', _63 => _63.data, 'optionalAccess', _64 => _64.pages]), () => ( []))) {
6992
+ for (const page of _nullishCoalesce(_optionalChain([query, 'access', _66 => _66.data, 'optionalAccess', _67 => _67.pages]), () => ( []))) {
6710
6993
  const item = page.keys.find((item2) => item2.key === itemKey);
6711
6994
  if (item && "value" in item) return item.value;
6712
6995
  }
@@ -6733,8 +7016,8 @@ var ListEditForm = ({
6733
7016
  });
6734
7017
  setSelectedListItem(void 0);
6735
7018
  });
6736
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacthookform.FormProvider, { ...form, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit, className: "flex h-full flex-col gap-2", children: [
6737
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex grow flex-col gap-2", children: [
7019
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacthookform.FormProvider, { ...form, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "form", { onSubmit, className: "flex h-full min-h-0 flex-col gap-2", children: [
7020
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-0 grow flex-col gap-2", children: [
6738
7021
  type === "zset" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NumberFormItem, { name: "value", label: valueLabel }),
6739
7022
  type !== "list" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, FormItem, { readOnly: type === "stream", name: "key", label: keyLabel, data: itemKey }),
6740
7023
  type !== "set" && type !== "zset" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -6823,7 +7106,7 @@ var FormItem = ({
6823
7106
  readOnly,
6824
7107
  data
6825
7108
  });
6826
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("flex flex-col gap-1", !height && "h-full"), children: [
7109
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: cn("flex flex-col gap-1", !height && "h-full min-h-0"), children: [
6827
7110
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 text-xs", children: [
6828
7111
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-medium text-zinc-700", children: label }),
6829
7112
  " ",
@@ -6835,7 +7118,7 @@ var FormItem = ({
6835
7118
  {
6836
7119
  className: cn(
6837
7120
  "overflow-hidden rounded-md border border-zinc-300 bg-white p-2 shadow-sm",
6838
- !height && "h-full"
7121
+ !height && "h-full min-h-0"
6839
7122
  ),
6840
7123
  children: editor
6841
7124
  }
@@ -6852,7 +7135,7 @@ var HashFieldTTLInfo = ({
6852
7135
  fields
6853
7136
  }) => {
6854
7137
  const { data } = useFetchHashFieldExpires({ dataKey, fields });
6855
- const expireAt = _optionalChain([data, 'optionalAccess', _65 => _65[field]]);
7138
+ const expireAt = _optionalChain([data, 'optionalAccess', _68 => _68[field]]);
6856
7139
  const [ttl, setTTL] = _react.useState.call(void 0, () => calculateTTL(expireAt));
6857
7140
  _react.useEffect.call(void 0, () => {
6858
7141
  setTTL(calculateTTL(expireAt));
@@ -6877,7 +7160,11 @@ var headerLabels = {
6877
7160
  var ListDisplay = ({ dataKey, type }) => {
6878
7161
  const { selectedListItem } = useTab();
6879
7162
  const query = useFetchListItems({ dataKey, type });
6880
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col gap-2", children: [
7163
+ const isEmpty = query.isFetched && _optionalChain([query, 'access', _69 => _69.data, 'optionalAccess', _70 => _70.pages, 'access', _71 => _71.every, 'call', _72 => _72((page) => page.keys.length === 0)]);
7164
+ if (isEmpty) {
7165
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyDeleted, {});
7166
+ }
7167
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full min-h-0 flex-col gap-2 overflow-hidden", children: [
6881
7168
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type }),
6882
7169
  selectedListItem && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListEditDisplay, { dataKey, type, item: selectedListItem }),
6883
7170
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: cn("min-h-0 grow", selectedListItem && "hidden"), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, InfiniteScroll, { query, className: "rounded-lg border border-zinc-200 bg-white", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "table", { className: "w-full", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ItemContextMenu, { dataKey, type, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "tbody", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ListItems, { dataKey, type, query }) }) }) }) }) })
@@ -6889,7 +7176,7 @@ var ListItems = ({
6889
7176
  dataKey
6890
7177
  }) => {
6891
7178
  const { setSelectedListItem } = useTab();
6892
- const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _66 => _66.data, 'optionalAccess', _67 => _67.pages, 'access', _68 => _68.flatMap, 'call', _69 => _69((page) => page.keys)]), () => ( [])), [query.data]);
7179
+ const keys = _react.useMemo.call(void 0, () => _nullishCoalesce(_optionalChain([query, 'access', _73 => _73.data, 'optionalAccess', _74 => _74.pages, 'access', _75 => _75.flatMap, 'call', _76 => _76((page) => page.keys)]), () => ( [])), [query.data]);
6893
7180
  const fields = _react.useMemo.call(void 0, () => keys.map((key) => key.key), [keys]);
6894
7181
  const { mutate: editItem } = useEditListItem();
6895
7182
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, { children: keys.map(({ key, value }, i) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
@@ -6971,9 +7258,12 @@ var ListItems = ({
6971
7258
 
6972
7259
  var EditorDisplay = ({ dataKey, type }) => {
6973
7260
  const { data } = useFetchSimpleKey(dataKey, type);
6974
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full w-full flex-col gap-2", children: [
7261
+ if (data === null) {
7262
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeyDeleted, {});
7263
+ }
7264
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full min-h-0 w-full flex-col gap-2 overflow-hidden", children: [
6975
7265
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DisplayHeader, { dataKey, type, content: _nullishCoalesce(data, () => ( void 0)) }),
6976
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full grow flex-col gap-2 rounded-md", children: data === void 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoadingText: "", isLoading: true }) : data === null ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _jsxruntime.Fragment, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplayForm, { dataKey, type, data }, dataKey) })
7266
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex min-h-0 grow flex-col gap-2 rounded-md", children: data === void 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoadingText: "", isLoading: true }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EditorDisplayForm, { dataKey, type, data }, dataKey) })
6977
7267
  ] });
6978
7268
  };
6979
7269
  var EditorDisplayForm = ({
@@ -6990,12 +7280,12 @@ var EditorDisplayForm = ({
6990
7280
  const { editor, selector } = useField({ name: "value", form, data });
6991
7281
  const { mutateAsync: setKey, isPending: isSettingKey } = useSetSimpleKey(dataKey, type);
6992
7282
  const handleCancel = () => {
6993
- form.reset({ value: data });
7283
+ form.reset();
6994
7284
  };
6995
7285
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
6996
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex grow flex-col gap-1", children: [
7286
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-0 grow flex-col gap-1", children: [
6997
7287
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex shrink-0 items-center gap-2", children: type === "json" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", {}) : selector }),
6998
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "grow rounded-md border border-zinc-300 bg-white p-2", children: editor })
7288
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-0 grow rounded-md border border-zinc-300 bg-white p-2", children: editor })
6999
7289
  ] }),
7000
7290
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex shrink-0 items-center gap-2", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "ml-auto flex gap-2", children: [
7001
7291
  form.formState.isDirty && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { onClick: handleCancel, children: "Cancel" }),
@@ -7036,33 +7326,6 @@ var DataDisplay = () => {
7036
7326
 
7037
7327
 
7038
7328
 
7039
- // src/components/common/reload-button.tsx
7040
-
7041
-
7042
-
7043
- var ReloadButton = ({
7044
- onClick,
7045
- isLoading: isLoadingProp
7046
- }) => {
7047
- const [isLoading, setIsLoading] = _react.useState.call(void 0, false);
7048
- const handleClick = () => {
7049
- setIsLoading(true);
7050
- onClick();
7051
- setTimeout(() => {
7052
- setIsLoading(false);
7053
- }, 350);
7054
- };
7055
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Refresh", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7056
- Button,
7057
- {
7058
- variant: "outline",
7059
- size: "icon",
7060
- onClick: handleClick,
7061
- disabled: isLoading || isLoadingProp,
7062
- children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLoader2, { className: "size-5 animate-spin text-zinc-500" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconRefresh, { className: "size-5 text-zinc-500 dark:text-zinc-600" })
7063
- }
7064
- ) }) });
7065
- };
7066
7329
 
7067
7330
  // src/components/databrowser/components/add-key-modal.tsx
7068
7331
 
@@ -7085,7 +7348,7 @@ function AddKeyModal() {
7085
7348
  setSelectedKey(key);
7086
7349
  setOpen(false);
7087
7350
  setTimeout(() => {
7088
- _optionalChain([window, 'access', _70 => _70.document, 'access', _71 => _71.querySelector, 'call', _72 => _72(`[data-key="${key}"]`), 'optionalAccess', _73 => _73.scrollIntoView, 'call', _74 => _74({
7351
+ _optionalChain([window, 'access', _77 => _77.document, 'access', _78 => _78.querySelector, 'call', _79 => _79(`[data-key="${key}"]`), 'optionalAccess', _80 => _80.scrollIntoView, 'call', _81 => _81({
7089
7352
  behavior: "smooth",
7090
7353
  block: "start",
7091
7354
  inline: "nearest"
@@ -7106,7 +7369,7 @@ function AddKeyModal() {
7106
7369
  {
7107
7370
  variant: "primary",
7108
7371
  "data-testid": "add-key-button",
7109
- className: "flex h-8 items-center gap-1 rounded-lg pl-2 pr-3 text-sm font-medium",
7372
+ className: "flex h-8 select-none items-center gap-1 rounded-lg pl-2 pr-3 text-sm font-medium",
7110
7373
  children: [
7111
7374
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-5" }),
7112
7375
  "Key"
@@ -7141,7 +7404,7 @@ function AddKeyModal() {
7141
7404
  }
7142
7405
  )
7143
7406
  ] }),
7144
- formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _75 => _75.errors, 'access', _76 => _76.key, 'optionalAccess', _77 => _77.message]) }),
7407
+ formState.errors.key && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mb-3 mt-2 text-xs text-red-500", children: _optionalChain([formState, 'access', _82 => _82.errors, 'access', _83 => _83.key, 'optionalAccess', _84 => _84.message]) }),
7145
7408
  /* @__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" }),
7146
7409
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-6 flex justify-end gap-2", children: [
7147
7410
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -7164,427 +7427,83 @@ function AddKeyModal() {
7164
7427
  );
7165
7428
  }
7166
7429
 
7167
- // src/components/databrowser/components/search/create-index-modal.tsx
7168
-
7169
- var CreateIndexModal = ({
7170
- open,
7171
- onOpenChange
7172
- }) => {
7173
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Dialog, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogContent, { className: "max-w-2xl", children: [
7174
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Create new Index" }) }),
7175
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sr-only", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogDescription, { children: "Create new search index" }) }),
7176
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchDisplay, { isCreateModal: true, onClose: () => onOpenChange(false) })
7177
- ] }) });
7178
- };
7179
-
7180
- // src/components/databrowser/components/search/edit-index-modal.tsx
7430
+ // src/components/databrowser/components/query-wizard/query-wizard-popover.tsx
7181
7431
 
7182
- var EditIndexModal = ({
7183
- open,
7184
- onOpenChange,
7185
- indexName
7186
- }) => {
7187
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Dialog, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogContent, { className: "max-w-2xl", children: [
7188
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Edit Index" }) }),
7189
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sr-only", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogDescription, { children: "Edit search index schema" }) }),
7190
- indexName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchDisplay, { indexName, isEditModal: true, onClose: () => onOpenChange(false) })
7191
- ] }) });
7192
- };
7193
7432
 
7194
- // src/components/databrowser/components/header/search-input.tsx
7195
7433
 
7434
+ // src/components/databrowser/components/query-wizard/consent-prompt.tsx
7196
7435
 
7197
7436
 
7198
- var dedupeSearchHistory = (history) => {
7199
- const seen = /* @__PURE__ */ new Set();
7200
- return history.filter((item) => {
7201
- if (!item || seen.has(item)) return false;
7202
- seen.add(item);
7203
- return true;
7204
- });
7205
- };
7206
- var SearchInput = () => {
7207
- const { setSearchKey, search } = useTab();
7208
- const { searchHistory, addSearchHistory } = useDatabrowserStore();
7209
- const [state, setState] = _react.useState.call(void 0, search.key);
7210
- const [isFocus, setIsFocus] = _react.useState.call(void 0, false);
7211
- const [focusedIndex, setFocusedIndex] = _react.useState.call(void 0, -1);
7212
- const inputRef = _react.useRef.call(void 0, null);
7213
- const historyItemRefs = _react.useRef.call(void 0, []);
7214
- const handleSubmit = (value) => {
7215
- if (value.trim() !== "" && !value.includes("*")) value = `${value}*`;
7216
- addSearchHistory(value);
7217
- setSearchKey(value);
7218
- setState(value);
7219
- };
7220
- const filteredHistory = dedupeSearchHistory(
7221
- searchHistory.filter((item) => item.trim() !== "" && item.trim() !== "*").filter((item) => item.includes(state) && item !== state)
7222
- ).slice(0, 5).map((item) => item.endsWith("*") ? item.slice(0, -1) : item);
7223
- _react.useEffect.call(void 0, () => {
7224
- setFocusedIndex(-1);
7225
- }, [filteredHistory.length]);
7226
- const handleKeyDown = (e) => {
7227
- if (e.key === "Enter") {
7228
- const text = focusedIndex >= 0 && focusedIndex < filteredHistory.length ? filteredHistory[focusedIndex] : e.currentTarget.value;
7229
- handleSubmit(text);
7230
- } else if (e.key === "Escape") {
7231
- setState("");
7232
- setFocusedIndex(-1);
7233
- _optionalChain([inputRef, 'access', _78 => _78.current, 'optionalAccess', _79 => _79.blur, 'call', _80 => _80()]);
7234
- } else if (e.key === "ArrowDown" || e.key === "Tab" && !e.shiftKey) {
7235
- e.preventDefault();
7236
- if (focusedIndex < filteredHistory.length - 1) {
7237
- setFocusedIndex(focusedIndex + 1);
7238
- } else if (filteredHistory.length > 0) {
7239
- setFocusedIndex(0);
7240
- }
7241
- } else if (e.key === "ArrowUp" || e.key === "Tab" && e.shiftKey) {
7242
- e.preventDefault();
7243
- if (focusedIndex > 0) {
7244
- setFocusedIndex(focusedIndex - 1);
7245
- } else if (filteredHistory.length > 0 && focusedIndex === 0) {
7246
- setFocusedIndex(-1);
7247
- _optionalChain([inputRef, 'access', _81 => _81.current, 'optionalAccess', _82 => _82.focus, 'call', _83 => _83()]);
7248
- } else if (filteredHistory.length > 0) {
7249
- setFocusedIndex(filteredHistory.length - 1);
7250
- }
7251
- }
7437
+ var ConsentPrompt = ({ onClose }) => {
7438
+ const store = useDatabrowserStore();
7439
+ const handleContinue = () => {
7440
+ store.setAiDataSharingConsent(true);
7252
7441
  };
7253
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative grow", children: [
7254
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Popover, { open: isFocus && filteredHistory.length > 0, children: [
7255
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-8 rounded-md border border-zinc-300 font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7256
- Input,
7442
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex max-w-[500px] flex-col gap-6 rounded-2xl p-6 shadow-lg", children: [
7443
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
7444
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-base font-semibold text-zinc-950", children: "AI Query Builder" }),
7445
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center rounded-md bg-purple-100 px-1.5 py-0.5", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm font-medium text-purple-700", children: "BETA" }) })
7446
+ ] }),
7447
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex gap-3 rounded-xl border border-yellow-300 bg-yellow-50 p-5", children: [
7448
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconAlertCircleFilled, { className: "size-5 shrink-0 text-yellow-800" }),
7449
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-1.5", children: [
7450
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm font-semibold text-yellow-800", children: "AI Query Builder requires data sharing" }),
7451
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { className: "text-sm text-yellow-800", children: [
7452
+ "To generate accurate queries, we'll send your",
7453
+ " ",
7454
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-semibold", children: "index schema" }),
7455
+ " and a",
7456
+ " ",
7457
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "font-semibold", children: "small sample of your data" }),
7458
+ " to AI models. This may include field names and example values."
7459
+ ] }),
7460
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-yellow-800", children: "Only used to generate the query you request." })
7461
+ ] })
7462
+ ] }),
7463
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-end gap-2", children: [
7464
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7465
+ "button",
7257
7466
  {
7258
- ref: inputRef,
7259
- placeholder: "Search",
7260
- className: "h-full border-none pr-6",
7261
- onKeyDown: handleKeyDown,
7262
- onChange: (e) => {
7263
- setState(e.currentTarget.value);
7264
- if (e.currentTarget.value.trim() === "") handleSubmit("");
7265
- },
7266
- value: state,
7267
- onFocus: () => {
7268
- setIsFocus(true);
7269
- setFocusedIndex(-1);
7270
- },
7271
- onBlur: () => setIsFocus(false)
7467
+ onClick: onClose,
7468
+ className: "flex h-8 items-center justify-center rounded-md border border-zinc-300 bg-white px-4 text-sm text-zinc-950 hover:bg-zinc-50",
7469
+ children: "Cancel"
7272
7470
  }
7273
- ) }) }),
7471
+ ),
7274
7472
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7275
- PopoverContent,
7473
+ "button",
7276
7474
  {
7277
- className: "w-[--radix-popover-trigger-width] divide-y px-3 py-2 text-[13px] text-zinc-900",
7278
- autoFocus: false,
7279
- onOpenAutoFocus: (e) => {
7280
- e.preventDefault();
7281
- e.stopPropagation();
7282
- },
7283
- children: filteredHistory.map((item, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full py-[3px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7284
- "button",
7285
- {
7286
- ref: (el) => {
7287
- historyItemRefs.current[index] = el;
7288
- },
7289
- onClick: () => handleSubmit(item),
7290
- onMouseEnter: () => setFocusedIndex(index),
7291
- className: `block w-full truncate rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
7292
- children: item
7293
- }
7294
- ) }, item))
7475
+ onClick: handleContinue,
7476
+ className: "flex h-8 items-center justify-center rounded-md bg-purple-500 px-4 text-sm text-white hover:bg-purple-600",
7477
+ children: "I agree & Continue"
7295
7478
  }
7296
7479
  )
7297
- ] }),
7298
- state && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7299
- Button,
7300
- {
7301
- type: "button",
7302
- variant: "link",
7303
- size: "icon",
7304
- className: "absolute right-1 top-1/2 h-5 w-5 -translate-y-1/2 text-zinc-500 hover:text-zinc-900",
7305
- onClick: () => {
7306
- setSearchKey("");
7307
- setState("");
7308
- },
7309
- children: [
7310
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 }),
7311
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Clear" })
7312
- ]
7313
- }
7314
- ),
7315
- " "
7480
+ ] })
7316
7481
  ] });
7317
7482
  };
7318
7483
 
7319
- // src/components/databrowser/components/header/type-selector.tsx
7484
+ // src/components/databrowser/components/query-wizard/use-query-wizard.tsx
7320
7485
 
7321
- var ALL_TYPES_KEY = "all";
7322
- function DataTypeSelector({ allowSearch }) {
7323
- const { search, setSearchType } = useTab();
7324
- const entries = [
7325
- [ALL_TYPES_KEY, "All Types"],
7326
- ...Object.entries(DATA_TYPE_NAMES).filter(([key]) => allowSearch || key !== "search")
7327
- ];
7328
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7329
- Select,
7330
- {
7331
- onValueChange: (type) => {
7332
- if (type === ALL_TYPES_KEY) {
7333
- setSearchType(void 0);
7334
- } else {
7335
- setSearchType(type);
7336
- }
7337
- },
7338
- value: search.type === void 0 ? ALL_TYPES_KEY : search.type,
7339
- children: [
7340
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "!w-auto shrink-0 select-none whitespace-nowrap border-zinc-300 pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
7341
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: entries.map(([key, value]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: key, children: value }, key)) }) })
7342
- ]
7343
- }
7344
- );
7345
- }
7346
7486
 
7347
- // src/components/databrowser/components/header/index.tsx
7348
7487
 
7349
- var Header = ({ tabType, allowSearch }) => {
7350
- const { isValuesSearchSelected, setIsValuesSearchSelected } = useTab();
7351
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-1.5", children: [
7352
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex grow items-center gap-1.5", children: [
7353
- tabType === "all" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7354
- Segmented,
7355
- {
7356
- options: [
7357
- {
7358
- key: "keys",
7359
- label: "Keys"
7360
- },
7361
- {
7362
- key: "values",
7363
- label: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
7364
- "Search",
7365
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-[18px] items-center rounded-md bg-emerald-100 px-[5px] text-[11px] text-emerald-700", children: "NEW" })
7366
- ] })
7367
- }
7368
- ],
7369
- value: isValuesSearchSelected ? "values" : "keys",
7370
- onChange: (value) => {
7371
- setIsValuesSearchSelected(value === "values");
7372
- },
7373
- className: "bg-emerald-800",
7374
- unselectedClassName: "text-emerald-100",
7375
- selectedClassName: "bg-emerald-50 text-emerald-800"
7376
- }
7377
- ),
7378
- isValuesSearchSelected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, IndexSelector, {}) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
7379
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataTypeSelector, { allowSearch }),
7380
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchInput, {})
7381
- ] })
7382
- ] }),
7383
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1.5", children: [
7384
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RefreshButton, {}),
7385
- isValuesSearchSelected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddIndexButton, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddKeyModal, {})
7386
- ] })
7387
- ] });
7388
- };
7389
- var IndexSelector = () => {
7390
- const {
7391
- valuesSearch: { index },
7392
- setValuesSearchIndex
7393
- } = useTab();
7394
- const { data: indexes, isLoading } = useFetchSearchIndexes();
7395
- const [open, setOpen] = _react.useState.call(void 0, false);
7396
- _react.useEffect.call(void 0, () => {
7397
- if (!indexes || isLoading) return;
7398
- if (index && !indexes.includes(index)) {
7399
- setValuesSearchIndex("");
7400
- }
7401
- }, [indexes, index, isLoading, setValuesSearchIndex]);
7402
- const [search, setSearch] = _react.useState.call(void 0, "");
7403
- const [editingIndex, setEditingIndex] = _react.useState.call(void 0, null);
7404
- const filteredIndexes = _optionalChain([indexes, 'optionalAccess', _84 => _84.filter, 'call', _85 => _85((idx) => idx.toLowerCase().includes(search.toLowerCase()))]);
7405
- const handleEditIndex = (indexName) => {
7406
- setOpen(false);
7407
- setEditingIndex(indexName);
7408
- };
7409
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex", children: [
7410
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center rounded-l-lg border border-r-0 border-zinc-300 bg-white px-3 text-sm text-zinc-700", children: "Index" }),
7411
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7412
- Popover,
7413
- {
7414
- open,
7415
- onOpenChange: (isOpen) => {
7416
- setOpen(isOpen);
7417
- if (!isOpen) setSearch("");
7418
- },
7419
- modal: false,
7420
- children: [
7421
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { className: "flex min-w-[140px] items-center justify-between gap-2 rounded-r-lg border border-zinc-300 bg-emerald-50 px-3 py-[5px] text-sm font-medium text-emerald-800 transition-colors hover:bg-emerald-100", children: [
7422
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "truncate", children: index || "Select an index" }),
7423
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronDown, { className: "size-4 shrink-0 opacity-50" })
7424
- ] }) }),
7425
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverContent, { className: "p-2", align: "center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-2", children: [
7426
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CreateIndexButton, {}),
7427
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px bg-zinc-100" }),
7428
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-9 items-center rounded-md border border-zinc-300 px-2", children: [
7429
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { className: "size-5 text-zinc-400" }),
7430
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7431
- "input",
7432
- {
7433
- value: search,
7434
- onChange: (e) => setSearch(e.target.value),
7435
- placeholder: "Search Index",
7436
- className: "flex h-full w-full bg-transparent px-2 py-3 text-sm outline-none placeholder:text-zinc-400"
7437
- }
7438
- )
7439
- ] }),
7440
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "max-h-[200px] overflow-y-auto", children: [
7441
- _optionalChain([filteredIndexes, 'optionalAccess', _86 => _86.length]) === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "py-4 text-center text-sm text-zinc-500", children: "No indexes found" }),
7442
- _optionalChain([filteredIndexes, 'optionalAccess', _87 => _87.map, 'call', _88 => _88((idx) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7443
- "div",
7444
- {
7445
- className: "flex h-9 items-center rounded-md px-2 transition-colors hover:bg-zinc-100",
7446
- children: [
7447
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7448
- "button",
7449
- {
7450
- onClick: () => {
7451
- setValuesSearchIndex(idx);
7452
- setOpen(false);
7453
- },
7454
- className: "flex flex-1 items-center gap-2 text-left text-sm",
7455
- children: [
7456
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7457
- "span",
7458
- {
7459
- className: cn(
7460
- "flex size-5 items-center justify-center",
7461
- idx === index ? "text-emerald-600" : "text-transparent"
7462
- ),
7463
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCircleCheck, { className: "size-5" })
7464
- }
7465
- ),
7466
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "truncate", children: idx })
7467
- ]
7468
- }
7469
- ),
7470
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7471
- "button",
7472
- {
7473
- onClick: (event) => {
7474
- event.stopPropagation();
7475
- event.preventDefault();
7476
- handleEditIndex(idx);
7477
- },
7478
- className: "ml-2 text-sm text-zinc-500 underline hover:text-zinc-700",
7479
- children: "Edit"
7480
- }
7481
- )
7482
- ]
7483
- },
7484
- idx
7485
- ))])
7486
- ] })
7487
- ] }) })
7488
- ]
7489
- }
7490
- ),
7491
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7492
- EditIndexModal,
7493
- {
7494
- open: Boolean(editingIndex),
7495
- onOpenChange: (isOpen) => !isOpen && setEditingIndex(null),
7496
- indexName: editingIndex
7497
- }
7498
- )
7499
- ] });
7500
- };
7501
- var CreateIndexButton = () => {
7502
- const [open, setOpen] = _react.useState.call(void 0, false);
7503
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
7504
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7505
- "button",
7506
- {
7507
- onClick: (e) => {
7508
- e.stopPropagation();
7509
- setOpen(true);
7510
- },
7511
- className: "flex h-9 w-full items-center gap-2 rounded-md px-2 text-sm text-emerald-600 transition-colors hover:bg-zinc-50",
7512
- children: [
7513
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCirclePlus, { className: "size-5" }),
7514
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "underline", children: "Create a new Index" })
7515
- ]
7516
- }
7517
- ),
7518
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CreateIndexModal, { open, onOpenChange: setOpen })
7519
- ] });
7520
- };
7521
- var AddIndexButton = () => {
7522
- const [open, setOpen] = _react.useState.call(void 0, false);
7523
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
7524
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Add index", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
7525
- Button,
7526
- {
7527
- variant: "primary",
7528
- onClick: () => setOpen(true),
7529
- className: "flex h-8 items-center gap-1 rounded-lg pl-2 pr-3 text-sm font-medium",
7530
- children: [
7531
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-5" }),
7532
- "Index"
7533
- ]
7534
- }
7535
- ) }),
7536
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CreateIndexModal, { open, onOpenChange: setOpen })
7537
- ] });
7538
- };
7539
- var RefreshButton = () => {
7540
- const { query } = useKeys();
7541
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7542
- ReloadButton,
7543
- {
7544
- onClick: () => {
7545
- queryClient.invalidateQueries({
7546
- queryKey: [FETCH_KEYS_QUERY_KEY]
7547
- });
7548
- queryClient.invalidateQueries({
7549
- queryKey: [FETCH_LIST_ITEMS_QUERY_KEY]
7550
- });
7551
- queryClient.invalidateQueries({
7552
- queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY]
7553
- });
7554
- queryClient.invalidateQueries({
7555
- queryKey: [FETCH_KEY_TYPE_QUERY_KEY]
7556
- });
7557
- },
7558
- isLoading: query.isFetching
7559
- }
7560
- );
7561
- };
7562
-
7563
- // src/components/databrowser/components/header-error.tsx
7564
-
7565
- var HeaderError = () => {
7566
- const { query } = useKeys();
7567
- if (!query.error) return null;
7568
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-red-600 dark:text-red-400", children: formatUpstashErrorMessage(query.error) });
7569
- };
7570
-
7571
- // src/components/databrowser/components/query-builder.tsx
7572
-
7573
-
7574
- // src/components/databrowser/components/search/query-editor.tsx
7575
-
7576
-
7577
- // src/components/databrowser/components/search/search-types-file.ts
7578
- var SEARCH_TYPES = `
7579
-
7580
- export const FIELD_TYPES = ["TEXT", "U64", "I64", "F64", "BOOL", "DATE"] as const;
7581
- export type FieldType = (typeof FIELD_TYPES)[number];
7582
-
7583
- export type TextField = {
7584
- type: "TEXT";
7585
- noTokenize?: boolean;
7586
- noStem?: boolean;
7587
- from?: string;
7488
+ // src/components/databrowser/components/search/search-types-file.ts
7489
+ var SEARCH_TYPES = `
7490
+ export const FIELD_TYPES = [
7491
+ "TEXT",
7492
+ "U64",
7493
+ "I64",
7494
+ "F64",
7495
+ "BOOL",
7496
+ "DATE",
7497
+ "KEYWORD",
7498
+ "FACET",
7499
+ ] as const;
7500
+ export type FieldType = (typeof FIELD_TYPES)[number];
7501
+
7502
+ export type TextField = {
7503
+ type: "TEXT";
7504
+ noTokenize?: boolean;
7505
+ noStem?: boolean;
7506
+ from?: string;
7588
7507
  };
7589
7508
 
7590
7509
  export type NumericField = {
@@ -7605,7 +7524,21 @@ export type DateField = {
7605
7524
  from?: string;
7606
7525
  };
7607
7526
 
7608
- export type DetailedField = TextField | NumericField | BoolField | DateField;
7527
+ export type KeywordField = {
7528
+ type: "KEYWORD";
7529
+ };
7530
+
7531
+ export type FacetField = {
7532
+ type: "FACET";
7533
+ };
7534
+
7535
+ export type DetailedField =
7536
+ | TextField
7537
+ | NumericField
7538
+ | BoolField
7539
+ | DateField
7540
+ | KeywordField
7541
+ | FacetField;
7609
7542
  export type NestedIndexSchema = {
7610
7543
  [key: string]: FieldType | DetailedField | NestedIndexSchema;
7611
7544
  };
@@ -7653,7 +7586,11 @@ type FieldValueType<T extends FieldType> = T extends "TEXT"
7653
7586
  ? boolean
7654
7587
  : T extends "DATE"
7655
7588
  ? string
7656
- : never;
7589
+ : T extends "KEYWORD"
7590
+ ? string
7591
+ : T extends "FACET"
7592
+ ? string
7593
+ : never;
7657
7594
 
7658
7595
  type GetFieldValueType<TSchema, Path extends string> =
7659
7596
  GetFieldAtPath<TSchema, Path> extends infer Field
@@ -7760,7 +7697,7 @@ type PathToNestedObject<
7760
7697
  TSchema,
7761
7698
  Path extends string,
7762
7699
  Value,
7763
- > = Path extends \`\${ infer First }.\${ infer Rest }\`
7700
+ > = Path extends \`\${infer First}.\${infer Rest}\`
7764
7701
  ? { [K in First]: PathToNestedObject<TSchema, Rest, Value> }
7765
7702
  : { [K in Path]: Value };
7766
7703
 
@@ -7837,7 +7774,6 @@ export type PublicQueryResult<
7837
7774
  // These are the operations that can be used for each field type
7838
7775
  type StringOperationMap<T extends string> = {
7839
7776
  $eq: T;
7840
- $ne: T;
7841
7777
  $in: T[];
7842
7778
  $fuzzy: T | { value: T; distance?: number; transpositionCostOne?: boolean };
7843
7779
  $phrase:
@@ -7851,7 +7787,15 @@ type StringOperationMap<T extends string> = {
7851
7787
 
7852
7788
  type NumberOperationMap<T extends number> = {
7853
7789
  $eq: T;
7854
- $ne: T;
7790
+ $in: T[];
7791
+ $gt: T;
7792
+ $gte: T;
7793
+ $lt: T;
7794
+ $lte: T;
7795
+ };
7796
+
7797
+ type KeywordOperationMap<T extends string> = {
7798
+ $eq: T;
7855
7799
  $in: T[];
7856
7800
  $gt: T;
7857
7801
  $gte: T;
@@ -7861,13 +7805,11 @@ type NumberOperationMap<T extends number> = {
7861
7805
 
7862
7806
  type BooleanOperationMap<T extends boolean> = {
7863
7807
  $eq: T;
7864
- $ne: T;
7865
7808
  $in: T[];
7866
7809
  };
7867
7810
 
7868
7811
  type DateOperationMap<T extends string | Date> = {
7869
7812
  $eq: T;
7870
- $ne: T;
7871
7813
  $in: T[];
7872
7814
  $gt: T;
7873
7815
  $gte: T;
@@ -7875,6 +7817,11 @@ type DateOperationMap<T extends string | Date> = {
7875
7817
  $lt: T;
7876
7818
  };
7877
7819
 
7820
+ type FacetOperationMap<T extends string> = {
7821
+ $eq: T;
7822
+ $in: T[];
7823
+ };
7824
+
7878
7825
  // Create union types for each field type
7879
7826
  type StringOperations = {
7880
7827
  [K in keyof StringOperationMap<string>]: { [P in K]: StringOperationMap<string>[K] } & {
@@ -7900,6 +7847,18 @@ type DateOperations = {
7900
7847
  };
7901
7848
  }[keyof DateOperationMap<string | Date>];
7902
7849
 
7850
+ type KeywordOperations = {
7851
+ [K in keyof KeywordOperationMap<string>]: { [P in K]: KeywordOperationMap<string>[K] } & {
7852
+ $boost?: number;
7853
+ };
7854
+ }[keyof KeywordOperationMap<string>];
7855
+
7856
+ type FacetOperations = {
7857
+ [K in keyof FacetOperationMap<string>]: { [P in K]: FacetOperationMap<string>[K] } & {
7858
+ $boost?: number;
7859
+ };
7860
+ }[keyof FacetOperationMap<string>];
7861
+
7903
7862
  // Create a union type for all operations for a given field type
7904
7863
  type OperationsForFieldType<T extends FieldType> = T extends "TEXT"
7905
7864
  ? StringOperations
@@ -7909,7 +7868,11 @@ type OperationsForFieldType<T extends FieldType> = T extends "TEXT"
7909
7868
  ? BooleanOperations
7910
7869
  : T extends "DATE"
7911
7870
  ? DateOperations
7912
- : never;
7871
+ : T extends "KEYWORD"
7872
+ ? KeywordOperations
7873
+ : T extends "FACET"
7874
+ ? FacetOperations
7875
+ : never;
7913
7876
 
7914
7877
  // Create a union type for all operations for a given path
7915
7878
  type PathOperations<TSchema, TPath extends string> =
@@ -8077,45 +8040,1020 @@ type RootOrNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
8077
8040
  $and?: never;
8078
8041
  $must?: never;
8079
8042
  $should?: never;
8080
- $mustNot?: never;
8043
+ $mustNot?: QueryFilter<TSchema> | QueryFilter<TSchema>[];
8044
+ };
8045
+
8046
+ export type DescribeFieldInfo = {
8047
+ type: FieldType;
8048
+ noTokenize?: boolean;
8049
+ noStem?: boolean;
8050
+ fast?: boolean;
8051
+ };
8052
+
8053
+ export type IndexDescription<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
8054
+ name: string;
8055
+ dataType: "hash" | "string" | "json";
8056
+ prefixes: string[];
8057
+ language?: Language;
8058
+ schema: Record<SchemaPaths<TSchema>, DescribeFieldInfo>;
8059
+ };
8060
+
8061
+ export type Language =
8062
+ | "english"
8063
+ | "arabic"
8064
+ | "danish"
8065
+ | "dutch"
8066
+ | "finnish"
8067
+ | "french"
8068
+ | "german"
8069
+ | "greek"
8070
+ | "hungarian"
8071
+ | "italian"
8072
+ | "norwegian"
8073
+ | "portuguese"
8074
+ | "romanian"
8075
+ | "russian"
8076
+ | "spanish"
8077
+ | "swedish"
8078
+ | "tamil"
8079
+ | "turkish";
8080
+
8081
+ // Helper type to extract only FACET field paths from schema
8082
+ export type FacetPaths<T, Prefix extends string = ""> = {
8083
+ [K in keyof T]: K extends string
8084
+ ? T[K] extends "FACET" | { type: "FACET" }
8085
+ ? Prefix extends ""
8086
+ ? K
8087
+ : \`\${Prefix}\${K}\`
8088
+ : T[K] extends FieldType | DetailedField
8089
+ ? never
8090
+ : T[K] extends object
8091
+ ? FacetPaths<T[K], \`\${Prefix}\${K}.\`>
8092
+ : never
8093
+ : never;
8094
+ }[keyof T];
8095
+
8096
+ // Aggregate Types
8097
+ export type AggregateOptions<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
8098
+ filter?: RootQueryFilter<TSchema>;
8099
+ aggregations: {
8100
+ [key: string]: Aggregation<TSchema>;
8101
+ };
8102
+ };
8103
+
8104
+ export type Aggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8105
+ | TermsAggregation<TSchema>
8106
+ | RangeAggregation<TSchema>
8107
+ | HistogramAggregation<TSchema>
8108
+ | StatsAggregation<TSchema>
8109
+ | AvgAggregation<TSchema>
8110
+ | SumAggregation<TSchema>
8111
+ | MinAggregation<TSchema>
8112
+ | MaxAggregation<TSchema>
8113
+ | CountAggregation<TSchema>
8114
+ | ExtendedStatsAggregation<TSchema>
8115
+ | PercentilesAggregation<TSchema>
8116
+ | CardinalityAggregation<TSchema>
8117
+ | FacetAggregation<TSchema>;
8118
+
8119
+ type BaseAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
8120
+ $aggs?: {
8121
+ [key: string]: Aggregation<TSchema>;
8122
+ };
8123
+ };
8124
+
8125
+ export type TermsAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8126
+ BaseAggregation<TSchema> & {
8127
+ $terms: {
8128
+ field: SchemaPaths<TSchema>;
8129
+ size?: number;
8130
+ };
8131
+ };
8132
+
8133
+ export type RangeAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8134
+ BaseAggregation<TSchema> & {
8135
+ $range: {
8136
+ field: SchemaPaths<TSchema>;
8137
+ ranges: { from?: number; to?: number }[];
8138
+ };
8139
+ };
8140
+
8141
+ export type HistogramAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8142
+ BaseAggregation<TSchema> & {
8143
+ $histogram: {
8144
+ field: SchemaPaths<TSchema>;
8145
+ interval: number;
8146
+ };
8147
+ };
8148
+
8149
+ export type StatsAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8150
+ BaseAggregation<TSchema> & {
8151
+ $stats: {
8152
+ field: SchemaPaths<TSchema>;
8153
+ missing?: number;
8154
+ };
8155
+ };
8156
+
8157
+ export type AvgAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8158
+ BaseAggregation<TSchema> & {
8159
+ $avg: {
8160
+ field: SchemaPaths<TSchema>;
8161
+ missing?: number;
8162
+ };
8163
+ };
8164
+
8165
+ export type SumAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8166
+ BaseAggregation<TSchema> & {
8167
+ $sum: {
8168
+ field: SchemaPaths<TSchema>;
8169
+ missing?: number;
8170
+ };
8171
+ };
8172
+
8173
+ export type MinAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8174
+ BaseAggregation<TSchema> & {
8175
+ $min: {
8176
+ field: SchemaPaths<TSchema>;
8177
+ missing?: number;
8178
+ };
8179
+ };
8180
+
8181
+ export type MaxAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8182
+ BaseAggregation<TSchema> & {
8183
+ $max: {
8184
+ field: SchemaPaths<TSchema>;
8185
+ missing?: number;
8186
+ };
8187
+ };
8188
+
8189
+ export type CountAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8190
+ BaseAggregation<TSchema> & {
8191
+ $count: {
8192
+ field: SchemaPaths<TSchema>;
8193
+ };
8194
+ };
8195
+
8196
+ export type ExtendedStatsAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8197
+ BaseAggregation<TSchema> & {
8198
+ $extendedStats: {
8199
+ field: SchemaPaths<TSchema>;
8200
+ sigma?: number;
8201
+ missing?: number;
8202
+ };
8203
+ };
8204
+
8205
+ export type PercentilesAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8206
+ BaseAggregation<TSchema> & {
8207
+ $percentiles: {
8208
+ field: SchemaPaths<TSchema>;
8209
+ percents?: number[];
8210
+ keyed?: boolean;
8211
+ missing?: number;
8212
+ };
8213
+ };
8214
+
8215
+ export type CardinalityAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8216
+ BaseAggregation<TSchema> & {
8217
+ $cardinality: {
8218
+ field: SchemaPaths<TSchema>;
8219
+ };
8220
+ };
8221
+
8222
+ export type FacetAggregation<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8223
+ BaseAggregation<TSchema> & {
8224
+ $facet: {
8225
+ field: FacetPaths<TSchema>;
8226
+ path: string;
8227
+ depth?: number;
8228
+ size?: number;
8229
+ minDocCount?: number;
8230
+ order?: { count: "desc" | "asc" };
8231
+ };
8232
+ };
8233
+
8234
+ export type AggregateResult<
8235
+ TSchema extends NestedIndexSchema | FlatIndexSchema,
8236
+ TOpts extends AggregateOptions<TSchema>,
8237
+ > = BuildAggregateResult<TSchema, TOpts["aggregations"]>;
8238
+
8239
+ type BuildAggregateResult<
8240
+ TSchema extends NestedIndexSchema | FlatIndexSchema,
8241
+ TAggs extends { [key: string]: Aggregation<TSchema> },
8242
+ > = {
8243
+ [K in keyof TAggs]: TAggs[K] extends TermsAggregation<TSchema>
8244
+ ? TermsResult<TSchema, TAggs[K]>
8245
+ : TAggs[K] extends RangeAggregation<TSchema>
8246
+ ? RangeResult<TSchema, TAggs[K]>
8247
+ : TAggs[K] extends HistogramAggregation<TSchema>
8248
+ ? HistogramResult<TSchema, TAggs[K]>
8249
+ : TAggs[K] extends StatsAggregation<TSchema>
8250
+ ? StatsResult
8251
+ : TAggs[K] extends AvgAggregation<TSchema>
8252
+ ? MetricValueResult
8253
+ : TAggs[K] extends SumAggregation<TSchema>
8254
+ ? MetricValueResult
8255
+ : TAggs[K] extends MinAggregation<TSchema>
8256
+ ? MetricValueResult
8257
+ : TAggs[K] extends MaxAggregation<TSchema>
8258
+ ? MetricValueResult
8259
+ : TAggs[K] extends CountAggregation<TSchema>
8260
+ ? MetricValueResult
8261
+ : TAggs[K] extends CardinalityAggregation<TSchema>
8262
+ ? MetricValueResult
8263
+ : TAggs[K] extends ExtendedStatsAggregation<TSchema>
8264
+ ? ExtendedStatsResult<TAggs[K]>
8265
+ : TAggs[K] extends PercentilesAggregation<TSchema>
8266
+ ? PercentilesResult<TAggs[K]>
8267
+ : TAggs[K] extends FacetAggregation<TSchema>
8268
+ ? FacetResult
8269
+ : never;
8270
+ };
8271
+
8272
+ type Bucket<T> = {
8273
+ key: T;
8274
+ docCount: number;
8275
+ from?: number;
8276
+ to?: number;
8277
+ };
8278
+
8279
+ type TermsResult<
8280
+ TSchema extends NestedIndexSchema | FlatIndexSchema,
8281
+ TAgg extends TermsAggregation<TSchema>,
8282
+ > = TAgg["$aggs"] extends { [key: string]: Aggregation<TSchema> }
8283
+ ? {
8284
+ buckets: (Bucket<GetFieldValueType<TSchema, TAgg["$terms"]["field"]>> &
8285
+ BuildAggregateResult<TSchema, TAgg["$aggs"]>)[];
8286
+ sumOtherDocCount: number;
8287
+ docCountErrorUpperBound: number;
8288
+ }
8289
+ : {
8290
+ buckets: Bucket<GetFieldValueType<TSchema, TAgg["$terms"]["field"]>>[];
8291
+ sumOtherDocCount: number;
8292
+ docCountErrorUpperBound: number;
8293
+ };
8294
+
8295
+ type RangeResult<
8296
+ TSchema extends NestedIndexSchema | FlatIndexSchema,
8297
+ TAgg extends RangeAggregation<TSchema>,
8298
+ > = TAgg["$aggs"] extends { [key: string]: Aggregation<TSchema> }
8299
+ ? {
8300
+ buckets: (Bucket<string> & BuildAggregateResult<TSchema, TAgg["$aggs"]>)[];
8301
+ }
8302
+ : {
8303
+ buckets: Bucket<string>[];
8304
+ };
8305
+
8306
+ type HistogramResult<
8307
+ TSchema extends NestedIndexSchema | FlatIndexSchema,
8308
+ TAgg extends HistogramAggregation<TSchema>,
8309
+ > = TAgg["$aggs"] extends { [key: string]: Aggregation<TSchema> }
8310
+ ? {
8311
+ buckets: (Bucket<number> & BuildAggregateResult<TSchema, TAgg["$aggs"]>)[];
8312
+ }
8313
+ : {
8314
+ buckets: Bucket<number>[];
8315
+ };
8316
+
8317
+ type MetricValueResult = {
8318
+ value: number;
8319
+ };
8320
+
8321
+ type StatsResult = {
8322
+ count: number;
8323
+ min: number;
8324
+ max: number;
8325
+ sum: number;
8326
+ avg: number;
8327
+ };
8328
+
8329
+ type ExtendedStatsResult<_TAgg> = {
8330
+ count: number;
8331
+ min: number;
8332
+ max: number;
8333
+ avg: number;
8334
+ sum: number;
8335
+ sumOfSquares: number;
8336
+ variance: number;
8337
+ variancePopulation: number;
8338
+ varianceSampling: number;
8339
+ stdDeviation: number;
8340
+ stdDeviationPopulation: number;
8341
+ stdDeviationSampling: number;
8342
+ stdDeviationBounds: {
8343
+ upper: number;
8344
+ lower: number;
8345
+ upperSampling: number;
8346
+ lowerSampling: number;
8347
+ upperPopulation: number;
8348
+ lowerPopulation: number;
8349
+ };
8350
+ };
8351
+
8352
+ type PercentilesResult<TAgg> = TAgg extends { $percentiles: { keyed: false } }
8353
+ ? {
8354
+ values: Array<{ key: number; value: number }>;
8355
+ }
8356
+ : {
8357
+ values: { [key: string]: number };
8358
+ };
8359
+
8360
+ type FacetChildNode = {
8361
+ path: string;
8362
+ docCount: number;
8363
+ sumOtherDocCount: number;
8364
+ children?: FacetChildNode[];
8365
+ };
8366
+
8367
+ type FacetResult = {
8368
+ path: string;
8369
+ sumOtherDocCount: number;
8370
+ children: FacetChildNode[];
8371
+ };
8372
+
8373
+ `;
8374
+
8375
+ // src/components/databrowser/components/query-wizard/use-query-wizard.tsx
8376
+ var QueryWizardContext = _react.createContext.call(void 0, void 0);
8377
+ var QueryWizardProvider = QueryWizardContext.Provider;
8378
+ var useQueryWizardFn = () => {
8379
+ return _react.useContext.call(void 0, QueryWizardContext);
8380
+ };
8381
+ var useGenerateQuery = () => {
8382
+ const queryWizard = useQueryWizardFn();
8383
+ return _reactquery.useMutation.call(void 0, {
8384
+ mutationFn: async ({
8385
+ prompt,
8386
+ searchIndex,
8387
+ sampleData
8388
+ }) => {
8389
+ if (!queryWizard) {
8390
+ throw new Error(
8391
+ "Query Wizard is not configured. Please provide a useQueryWizard prop to RedisBrowser component."
8392
+ );
8393
+ }
8394
+ const result = await queryWizard({
8395
+ prompt,
8396
+ searchIndex,
8397
+ sampleData,
8398
+ searchTypes: SEARCH_TYPES
8399
+ });
8400
+ return result;
8401
+ }
8402
+ });
8403
+ };
8404
+
8405
+ // src/components/databrowser/components/query-wizard/query-wizard-popover.tsx
8406
+
8407
+ var QueryWizardPopover = ({ onClose }) => {
8408
+ const { valuesSearch, setValuesSearchQuery, setQueryBuilderMode } = useTab();
8409
+ const { redisNoPipeline: redis } = useRedis();
8410
+ const [input, setInput] = _react.useState.call(void 0, "");
8411
+ const [sampleData, setSampleData] = _react.useState.call(void 0, []);
8412
+ const [showIndexFields, setShowIndexFields] = _react.useState.call(void 0, false);
8413
+ const { aiDataSharingConsent } = useDatabrowserStore();
8414
+ const { data: indexData, isLoading: isLoadingIndex } = useFetchSearchIndex(valuesSearch.index);
8415
+ const generateQuery = useGenerateQuery();
8416
+ const handleGenerate = async () => {
8417
+ if (!input.trim() || !valuesSearch.index) return;
8418
+ try {
8419
+ let samples = sampleData;
8420
+ if (samples.length === 0 && _optionalChain([indexData, 'optionalAccess', _85 => _85.prefixes, 'optionalAccess', _86 => _86[0]])) {
8421
+ try {
8422
+ const firstTenKeys = await scanKeys(redis, {
8423
+ match: `${indexData.prefixes[0]}*`,
8424
+ type: indexData.dataType,
8425
+ limit: 10
8426
+ });
8427
+ const dataPromises = firstTenKeys.map(async (key) => {
8428
+ try {
8429
+ if (indexData.dataType === "json") {
8430
+ const data = await redis.json.get(key);
8431
+ return { key, data };
8432
+ } else if (indexData.dataType === "hash") {
8433
+ const data = await redis.hgetall(key);
8434
+ return { key, data };
8435
+ } else {
8436
+ const data = await redis.get(key);
8437
+ return { key, data };
8438
+ }
8439
+ } catch (e5) {
8440
+ return null;
8441
+ }
8442
+ });
8443
+ const results = await Promise.all(dataPromises);
8444
+ samples = results.filter(Boolean);
8445
+ setSampleData(samples);
8446
+ } catch (error) {
8447
+ console.error("Error fetching sample data:", error);
8448
+ }
8449
+ }
8450
+ const result = await generateQuery.mutateAsync({
8451
+ prompt: input,
8452
+ searchIndex: _nullishCoalesce(indexData, () => ( void 0)),
8453
+ sampleData: samples
8454
+ });
8455
+ const queryString = toJsLiteral(result.query);
8456
+ setValuesSearchQuery(queryString);
8457
+ setQueryBuilderMode("code");
8458
+ _optionalChain([onClose, 'optionalCall', _87 => _87()]);
8459
+ } catch (error) {
8460
+ console.error("Error generating query:", error);
8461
+ }
8462
+ };
8463
+ if (isLoadingIndex) {
8464
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-[100px] w-[340px] items-center justify-center rounded-2xl bg-white", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: true, isLoadingText: "Loading index..." }) });
8465
+ }
8466
+ if (!valuesSearch.index) {
8467
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-[340px] flex-col items-center gap-2 rounded-2xl bg-white p-8", children: [
8468
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm font-medium text-zinc-700", children: "No index selected" }),
8469
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-center text-xs text-zinc-500", children: "Create a new index to use the Query Wizard." })
8470
+ ] });
8471
+ }
8472
+ if (aiDataSharingConsent === false) {
8473
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ConsentPrompt, { onClose });
8474
+ }
8475
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex w-[500px] flex-col gap-6 rounded-2xl bg-white p-6", children: [
8476
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2", children: [
8477
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-base font-semibold text-zinc-950", children: "AI Query Builder" }),
8478
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-center rounded-md bg-purple-100 px-1.5 py-0.5", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "!text-sm font-medium text-purple-700", children: "BETA" }) })
8479
+ ] }),
8480
+ generateQuery.error && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-2 rounded-md border border-yellow-300 bg-yellow-50 p-4", children: [
8481
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "!text-sm font-medium !text-yellow-800", children: generateQuery.error.name }),
8482
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-0.5 !text-sm !text-yellow-800 opacity-90", children: generateQuery.error.message })
8483
+ ] }),
8484
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-5", children: [
8485
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8486
+ "button",
8487
+ {
8488
+ onClick: () => setShowIndexFields(!showIndexFields),
8489
+ className: "flex h-8 items-center gap-1.5 rounded-md border border-zinc-300 bg-zinc-50 px-3 hover:bg-zinc-100",
8490
+ children: [
8491
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8492
+ _iconsreact.IconChevronRight,
8493
+ {
8494
+ className: `size-5 text-zinc-700 transition-transform ${showIndexFields ? "rotate-90" : ""}`
8495
+ }
8496
+ ),
8497
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-sm font-medium text-zinc-700", children: "Show Index fields" })
8498
+ ]
8499
+ }
8500
+ ),
8501
+ showIndexFields && indexData && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "rounded-md border border-zinc-200 bg-zinc-50 p-3", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "pre", { className: "max-h-40 overflow-auto text-xs text-zinc-700", children: JSON.stringify(indexData.schema, null, 2) }) }),
8502
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-1", children: [
8503
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Label, { htmlFor: "query-input", className: "text-sm font-medium text-zinc-950", children: "Describe" }),
8504
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8505
+ "textarea",
8506
+ {
8507
+ id: "query-input",
8508
+ value: input,
8509
+ onChange: (e) => setInput(e.target.value),
8510
+ placeholder: "",
8511
+ className: "h-[58px] w-full resize-none rounded-md border border-zinc-300 bg-white px-3 py-3 text-sm text-zinc-950 shadow-sm focus:border-purple-500 focus:outline-none focus:ring-1 focus:ring-purple-500 disabled:cursor-not-allowed disabled:opacity-50",
8512
+ disabled: generateQuery.isPending,
8513
+ autoFocus: true
8514
+ }
8515
+ ),
8516
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-0.5 pt-0.5", children: [
8517
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xs text-zinc-500", children: "Example: Find sports cars and trucks, exclude age > 100, boost sports_car" }),
8518
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8519
+ "a",
8520
+ {
8521
+ href: "https://upstash.com/docs/redis",
8522
+ target: "_blank",
8523
+ rel: "noopener noreferrer",
8524
+ className: "text-xs text-zinc-500 underline hover:text-zinc-700",
8525
+ children: "View Docs \u2192"
8526
+ }
8527
+ )
8528
+ ] })
8529
+ ] })
8530
+ ] }),
8531
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-end gap-2", children: [
8532
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8533
+ "button",
8534
+ {
8535
+ onClick: onClose,
8536
+ disabled: generateQuery.isPending,
8537
+ className: "flex h-8 items-center justify-center rounded-md border border-zinc-300 bg-white px-4 text-sm text-zinc-950 shadow-[0_1px_1px_rgba(0,0,0,0.05)] hover:bg-zinc-50 disabled:cursor-not-allowed disabled:opacity-50",
8538
+ children: "Cancel"
8539
+ }
8540
+ ),
8541
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8542
+ "button",
8543
+ {
8544
+ onClick: handleGenerate,
8545
+ disabled: !input.trim() || generateQuery.isPending,
8546
+ className: "flex h-8 items-center justify-center gap-2 rounded-md bg-purple-500 px-4 text-sm text-white shadow-[0_1px_1px_rgba(0,0,0,0.05)] hover:bg-purple-600 disabled:cursor-not-allowed disabled:opacity-50 disabled:hover:bg-purple-500",
8547
+ children: generateQuery.isPending ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
8548
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: true }),
8549
+ "Generating..."
8550
+ ] }) : "Generate Query"
8551
+ }
8552
+ )
8553
+ ] })
8554
+ ] });
8555
+ };
8556
+
8557
+ // src/components/databrowser/components/search/create-index-modal.tsx
8558
+
8559
+ var CreateIndexModal = ({
8560
+ open,
8561
+ onOpenChange
8562
+ }) => {
8563
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Dialog, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8564
+ DialogContent,
8565
+ {
8566
+ className: "max-w-2xl",
8567
+ onEscapeKeyDown: (e) => {
8568
+ const active = document.activeElement;
8569
+ if (_optionalChain([active, 'optionalAccess', _88 => _88.closest, 'call', _89 => _89(".monaco-editor")]) || _optionalChain([active, 'optionalAccess', _90 => _90.tagName]) === "TEXTAREA") {
8570
+ e.preventDefault();
8571
+ }
8572
+ },
8573
+ children: [
8574
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Create new Index" }) }),
8575
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sr-only", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogDescription, { children: "Create new search index" }) }),
8576
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchDisplay, { isCreateModal: true, onClose: () => onOpenChange(false) })
8577
+ ]
8578
+ }
8579
+ ) });
8580
+ };
8581
+
8582
+ // src/components/databrowser/components/search/edit-index-modal.tsx
8583
+
8584
+
8585
+ var EditIndexModal = ({
8586
+ open,
8587
+ onOpenChange,
8588
+ indexName
8589
+ }) => {
8590
+ const { data: indexData, isLoading: isIndexLoading } = useFetchSearchIndex(indexName, {
8591
+ enabled: open
8592
+ });
8593
+ _react.useEffect.call(void 0, () => {
8594
+ if (open && !isIndexLoading && indexData === null) {
8595
+ onOpenChange(false);
8596
+ }
8597
+ }, [indexData, onOpenChange, isIndexLoading, open]);
8598
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Dialog, { open, onOpenChange, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8599
+ DialogContent,
8600
+ {
8601
+ className: "min-h-[500px] max-w-2xl",
8602
+ onEscapeKeyDown: (e) => {
8603
+ const active = document.activeElement;
8604
+ if (_optionalChain([active, 'optionalAccess', _91 => _91.closest, 'call', _92 => _92(".monaco-editor")]) || _optionalChain([active, 'optionalAccess', _93 => _93.tagName]) === "TEXTAREA") {
8605
+ e.preventDefault();
8606
+ }
8607
+ },
8608
+ children: [
8609
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogHeader, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Edit Index" }) }),
8610
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "sr-only", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogDescription, { children: "Edit search index schema" }) }),
8611
+ indexName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchDisplay, { indexName, isEditModal: true, onClose: () => onOpenChange(false) })
8612
+ ]
8613
+ }
8614
+ ) });
8615
+ };
8616
+
8617
+ // src/components/databrowser/components/header/refresh-button.tsx
8618
+
8619
+
8620
+ // src/components/common/reload-button.tsx
8621
+
8622
+
8623
+
8624
+ var ReloadButton = ({
8625
+ onClick,
8626
+ isLoading: isLoadingProp,
8627
+ tooltip = "Refresh"
8628
+ }) => {
8629
+ const [isLoading, setIsLoading] = _react.useState.call(void 0, false);
8630
+ const handleClick = () => {
8631
+ setIsLoading(true);
8632
+ onClick();
8633
+ setTimeout(() => {
8634
+ setIsLoading(false);
8635
+ }, 350);
8636
+ };
8637
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: tooltip, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8638
+ Button,
8639
+ {
8640
+ variant: "outline",
8641
+ size: "icon",
8642
+ onClick: handleClick,
8643
+ disabled: isLoading || isLoadingProp,
8644
+ children: isLoading ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconLoader2, { className: "size-5 animate-spin text-zinc-500" }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconRefresh, { className: "size-5 text-zinc-500 dark:text-zinc-600" })
8645
+ }
8646
+ ) }) });
8647
+ };
8648
+
8649
+ // src/components/databrowser/components/header/refresh-button.tsx
8650
+
8651
+ var invalidateAll = () => {
8652
+ queryClient.invalidateQueries({ queryKey: [FETCH_KEYS_QUERY_KEY] });
8653
+ queryClient.invalidateQueries({ queryKey: [FETCH_LIST_ITEMS_QUERY_KEY] });
8654
+ queryClient.invalidateQueries({ queryKey: [FETCH_SIMPLE_KEY_QUERY_KEY] });
8655
+ queryClient.invalidateQueries({ queryKey: [FETCH_KEY_TYPE_QUERY_KEY] });
8656
+ };
8657
+ var RefreshButton = () => {
8658
+ const { query } = useKeys();
8659
+ const { isValuesSearchSelected, valuesSearch } = useTab();
8660
+ const { redisNoPipeline: redis } = useRedis();
8661
+ const reindex = _reactquery.useMutation.call(void 0, {
8662
+ mutationFn: async () => {
8663
+ if (isValuesSearchSelected && valuesSearch.index) {
8664
+ await redis.search.index({ name: valuesSearch.index }).waitIndexing();
8665
+ }
8666
+ },
8667
+ onSettled: invalidateAll
8668
+ });
8669
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8670
+ ReloadButton,
8671
+ {
8672
+ onClick: () => reindex.mutate(),
8673
+ isLoading: query.isFetching || reindex.isPending,
8674
+ tooltip: isValuesSearchSelected ? "Reindex & Refresh Query" : "Refresh Scan"
8675
+ }
8676
+ );
8677
+ };
8678
+
8679
+ // src/components/databrowser/components/header/search-input.tsx
8680
+
8681
+
8682
+
8683
+ var dedupeSearchHistory = (history) => {
8684
+ const seen = /* @__PURE__ */ new Set();
8685
+ return history.filter((item) => {
8686
+ if (!item || seen.has(item)) return false;
8687
+ seen.add(item);
8688
+ return true;
8689
+ });
8690
+ };
8691
+ var SearchInput = () => {
8692
+ const { setSearchKey, search } = useTab();
8693
+ const { searchHistory, addSearchHistory } = useDatabrowserStore();
8694
+ const [state, setState] = _react.useState.call(void 0, search.key);
8695
+ const [isFocus, setIsFocus] = _react.useState.call(void 0, false);
8696
+ const [focusedIndex, setFocusedIndex] = _react.useState.call(void 0, -1);
8697
+ const inputRef = _react.useRef.call(void 0, null);
8698
+ const historyItemRefs = _react.useRef.call(void 0, []);
8699
+ const handleSubmit = (value) => {
8700
+ if (value.trim() !== "" && !value.includes("*")) value = `${value}*`;
8701
+ addSearchHistory(value);
8702
+ setSearchKey(value);
8703
+ setState(value);
8704
+ };
8705
+ const filteredHistory = dedupeSearchHistory(
8706
+ searchHistory.filter((item) => item.trim() !== "" && item.trim() !== "*").filter((item) => item.includes(state) && item !== state)
8707
+ ).slice(0, 5).map((item) => item.endsWith("*") ? item.slice(0, -1) : item);
8708
+ _react.useEffect.call(void 0, () => {
8709
+ setFocusedIndex(-1);
8710
+ }, [filteredHistory.length]);
8711
+ const handleKeyDown = (e) => {
8712
+ if (e.key === "Enter") {
8713
+ const text = focusedIndex >= 0 && focusedIndex < filteredHistory.length ? filteredHistory[focusedIndex] : e.currentTarget.value;
8714
+ handleSubmit(text);
8715
+ } else if (e.key === "Escape") {
8716
+ setState("");
8717
+ setFocusedIndex(-1);
8718
+ _optionalChain([inputRef, 'access', _94 => _94.current, 'optionalAccess', _95 => _95.blur, 'call', _96 => _96()]);
8719
+ } else if (e.key === "ArrowDown" || e.key === "Tab" && !e.shiftKey) {
8720
+ e.preventDefault();
8721
+ if (focusedIndex < filteredHistory.length - 1) {
8722
+ setFocusedIndex(focusedIndex + 1);
8723
+ } else if (filteredHistory.length > 0) {
8724
+ setFocusedIndex(0);
8725
+ }
8726
+ } else if (e.key === "ArrowUp" || e.key === "Tab" && e.shiftKey) {
8727
+ e.preventDefault();
8728
+ if (focusedIndex > 0) {
8729
+ setFocusedIndex(focusedIndex - 1);
8730
+ } else if (filteredHistory.length > 0 && focusedIndex === 0) {
8731
+ setFocusedIndex(-1);
8732
+ _optionalChain([inputRef, 'access', _97 => _97.current, 'optionalAccess', _98 => _98.focus, 'call', _99 => _99()]);
8733
+ } else if (filteredHistory.length > 0) {
8734
+ setFocusedIndex(filteredHistory.length - 1);
8735
+ }
8736
+ }
8737
+ };
8738
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative grow", children: [
8739
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Popover, { open: isFocus && filteredHistory.length > 0, children: [
8740
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-8 rounded-md border border-zinc-300 font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8741
+ Input,
8742
+ {
8743
+ ref: inputRef,
8744
+ placeholder: "Search",
8745
+ className: "h-full border-none pr-6",
8746
+ onKeyDown: handleKeyDown,
8747
+ onChange: (e) => {
8748
+ setState(e.currentTarget.value);
8749
+ if (e.currentTarget.value.trim() === "") handleSubmit("");
8750
+ },
8751
+ value: state,
8752
+ onFocus: () => {
8753
+ setIsFocus(true);
8754
+ setFocusedIndex(-1);
8755
+ },
8756
+ onBlur: () => setIsFocus(false)
8757
+ }
8758
+ ) }) }),
8759
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8760
+ PopoverContent,
8761
+ {
8762
+ className: "w-[--radix-popover-trigger-width] divide-y px-3 py-2 text-[13px] text-zinc-900",
8763
+ autoFocus: false,
8764
+ onOpenAutoFocus: (e) => {
8765
+ e.preventDefault();
8766
+ e.stopPropagation();
8767
+ },
8768
+ children: filteredHistory.map((item, index) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full py-[3px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8769
+ "button",
8770
+ {
8771
+ ref: (el) => {
8772
+ historyItemRefs.current[index] = el;
8773
+ },
8774
+ onClick: () => handleSubmit(item),
8775
+ onMouseEnter: () => setFocusedIndex(index),
8776
+ className: `block w-full truncate rounded-sm p-1 text-left transition-colors ${focusedIndex === index ? "bg-zinc-100" : "hover:bg-zinc-100"}`,
8777
+ children: item
8778
+ }
8779
+ ) }, item))
8780
+ }
8781
+ )
8782
+ ] }),
8783
+ state && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8784
+ Button,
8785
+ {
8786
+ type: "button",
8787
+ variant: "link",
8788
+ size: "icon",
8789
+ className: "absolute right-1 top-1/2 h-5 w-5 -translate-y-1/2 text-zinc-500 hover:text-zinc-900",
8790
+ onClick: () => {
8791
+ setSearchKey("");
8792
+ setState("");
8793
+ },
8794
+ children: [
8795
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconX, { size: 16 }),
8796
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Clear" })
8797
+ ]
8798
+ }
8799
+ ),
8800
+ " "
8801
+ ] });
8802
+ };
8803
+
8804
+ // src/components/databrowser/components/header/type-selector.tsx
8805
+
8806
+ var ALL_TYPES_KEY = "all";
8807
+ function DataTypeSelector({ allowSearch }) {
8808
+ const { search, setSearchType } = useTab();
8809
+ const entries = [
8810
+ [ALL_TYPES_KEY, "All Types"],
8811
+ ...Object.entries(DATA_TYPE_NAMES).filter(([key]) => allowSearch || key !== "search")
8812
+ ];
8813
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8814
+ Select,
8815
+ {
8816
+ onValueChange: (type) => {
8817
+ if (type === ALL_TYPES_KEY) {
8818
+ setSearchType(void 0);
8819
+ } else {
8820
+ setSearchType(type);
8821
+ }
8822
+ },
8823
+ value: search.type === void 0 ? ALL_TYPES_KEY : search.type,
8824
+ children: [
8825
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "!w-auto shrink-0 select-none whitespace-nowrap border-zinc-300 pr-8", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
8826
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectContent, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectGroup, { children: entries.map(([key, value]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: key, children: value }, key)) }) })
8827
+ ]
8828
+ }
8829
+ );
8830
+ }
8831
+
8832
+ // src/components/databrowser/components/header/index.tsx
8833
+
8834
+ var Header = ({ tabType, allowSearch }) => {
8835
+ const { isValuesSearchSelected, setIsValuesSearchSelected } = useTab();
8836
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-1.5", children: [
8837
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex grow items-center gap-1.5", children: [
8838
+ tabType === "all" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8839
+ Segmented,
8840
+ {
8841
+ options: [
8842
+ {
8843
+ key: "keys",
8844
+ label: "Keys"
8845
+ },
8846
+ {
8847
+ key: "values",
8848
+ label: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
8849
+ "Search",
8850
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-[18px] items-center rounded-md bg-emerald-100 px-[5px] text-[11px] text-emerald-700", children: "NEW" })
8851
+ ] })
8852
+ }
8853
+ ],
8854
+ value: isValuesSearchSelected ? "values" : "keys",
8855
+ onChange: (value) => {
8856
+ setIsValuesSearchSelected(value === "values");
8857
+ },
8858
+ className: "bg-emerald-800",
8859
+ unselectedClassName: "text-emerald-100",
8860
+ selectedClassName: "bg-emerald-50 text-emerald-800"
8861
+ }
8862
+ ),
8863
+ isValuesSearchSelected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, IndexSelector, {}) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
8864
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataTypeSelector, { allowSearch }),
8865
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchInput, {})
8866
+ ] })
8867
+ ] }),
8868
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1.5", children: [
8869
+ isValuesSearchSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, WizardButton, {}),
8870
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RefreshButton, {}),
8871
+ isValuesSearchSelected ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddIndexButton, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddKeyModal, {})
8872
+ ] })
8873
+ ] });
8874
+ };
8875
+ var IndexSelector = () => {
8876
+ const {
8877
+ valuesSearch: { index },
8878
+ setValuesSearchIndex
8879
+ } = useTab();
8880
+ const { data: indexes, isLoading } = useFetchSearchIndexes();
8881
+ const [open, setOpen] = _react.useState.call(void 0, false);
8882
+ _react.useEffect.call(void 0, () => {
8883
+ if (!indexes || isLoading) return;
8884
+ if (index && !indexes.includes(index)) {
8885
+ setValuesSearchIndex("");
8886
+ } else if (!index && indexes.length > 0) {
8887
+ setValuesSearchIndex(indexes[0]);
8888
+ }
8889
+ }, [indexes, index, isLoading, setValuesSearchIndex]);
8890
+ const [search, setSearch] = _react.useState.call(void 0, "");
8891
+ const [editingIndex, setEditingIndex] = _react.useState.call(void 0, );
8892
+ const filteredIndexes = _optionalChain([indexes, 'optionalAccess', _100 => _100.filter, 'call', _101 => _101((idx) => idx.toLowerCase().includes(search.toLowerCase()))]);
8893
+ const handleEditIndex = (indexName) => {
8894
+ setOpen(false);
8895
+ setEditingIndex(indexName);
8896
+ };
8897
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex", children: [
8898
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center rounded-l-lg border border-r-0 border-zinc-300 bg-white px-3 text-sm text-zinc-700", children: "Index" }),
8899
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8900
+ Popover,
8901
+ {
8902
+ open,
8903
+ onOpenChange: (isOpen) => {
8904
+ setOpen(isOpen);
8905
+ if (!isOpen) setSearch("");
8906
+ },
8907
+ modal: false,
8908
+ children: [
8909
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "button", { className: "flex min-w-[140px] items-center justify-between gap-2 rounded-r-lg border border-zinc-300 bg-emerald-50 px-3 py-[5px] text-sm font-medium text-emerald-800 transition-colors hover:bg-emerald-100", children: [
8910
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "truncate", children: index || "Select an index" }),
8911
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconChevronDown, { className: "size-4 shrink-0 opacity-50" })
8912
+ ] }) }),
8913
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverContent, { className: "p-2", align: "center", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-2", children: [
8914
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CreateIndexButton, {}),
8915
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px bg-zinc-100" }),
8916
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-9 items-center rounded-md border border-zinc-300 px-2", children: [
8917
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { className: "size-5 text-zinc-400" }),
8918
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8919
+ "input",
8920
+ {
8921
+ value: search,
8922
+ onChange: (e) => setSearch(e.target.value),
8923
+ placeholder: "Search Index",
8924
+ className: "flex h-full w-full bg-transparent px-2 py-3 text-sm outline-none placeholder:text-zinc-400"
8925
+ }
8926
+ )
8927
+ ] }),
8928
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "max-h-[200px] overflow-y-auto", children: [
8929
+ _optionalChain([filteredIndexes, 'optionalAccess', _102 => _102.length]) === 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "py-4 text-center text-sm text-zinc-500", children: "No indexes found" }),
8930
+ _optionalChain([filteredIndexes, 'optionalAccess', _103 => _103.map, 'call', _104 => _104((idx) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8931
+ "div",
8932
+ {
8933
+ className: "flex h-9 items-center rounded-md px-2 transition-colors hover:bg-zinc-100 dark:hover:bg-zinc-200",
8934
+ children: [
8935
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8936
+ "button",
8937
+ {
8938
+ onClick: () => {
8939
+ setValuesSearchIndex(idx);
8940
+ setOpen(false);
8941
+ },
8942
+ className: "flex flex-1 items-center gap-2 text-left text-sm",
8943
+ children: [
8944
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8945
+ "span",
8946
+ {
8947
+ className: cn(
8948
+ "flex size-5 items-center justify-center",
8949
+ idx === index ? "text-emerald-600" : "text-transparent"
8950
+ ),
8951
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCircleCheck, { className: "size-5" })
8952
+ }
8953
+ ),
8954
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "truncate", children: idx })
8955
+ ]
8956
+ }
8957
+ ),
8958
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8959
+ "button",
8960
+ {
8961
+ onClick: (event) => {
8962
+ event.stopPropagation();
8963
+ event.preventDefault();
8964
+ handleEditIndex(idx);
8965
+ },
8966
+ className: "ml-2 text-sm text-zinc-500 underline hover:text-zinc-700",
8967
+ children: "Edit"
8968
+ }
8969
+ )
8970
+ ]
8971
+ },
8972
+ idx
8973
+ ))])
8974
+ ] })
8975
+ ] }) })
8976
+ ]
8977
+ }
8978
+ ),
8979
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8980
+ EditIndexModal,
8981
+ {
8982
+ open: Boolean(editingIndex),
8983
+ onOpenChange: (isOpen) => !isOpen && setEditingIndex(void 0),
8984
+ indexName: editingIndex
8985
+ }
8986
+ )
8987
+ ] });
8988
+ };
8989
+ var CreateIndexButton = () => {
8990
+ const [open, setOpen] = _react.useState.call(void 0, false);
8991
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
8992
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8993
+ "button",
8994
+ {
8995
+ onClick: (e) => {
8996
+ e.stopPropagation();
8997
+ setOpen(true);
8998
+ },
8999
+ className: "flex h-9 w-full items-center gap-2 rounded-md px-2 text-sm text-emerald-600 transition-colors hover:bg-zinc-100 dark:hover:bg-zinc-200",
9000
+ children: [
9001
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconCirclePlus, { className: "size-5" }),
9002
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "underline", children: "Create a new Index" })
9003
+ ]
9004
+ }
9005
+ ),
9006
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CreateIndexModal, { open, onOpenChange: setOpen })
9007
+ ] });
8081
9008
  };
8082
-
8083
- export type DescribeFieldInfo = {
8084
- type: FieldType;
8085
- noTokenize?: boolean;
8086
- noStem?: boolean;
8087
- fast?: boolean;
9009
+ var AddIndexButton = () => {
9010
+ const [open, setOpen] = _react.useState.call(void 0, false);
9011
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
9012
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Create new Index", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
9013
+ Button,
9014
+ {
9015
+ variant: "primary",
9016
+ onClick: () => setOpen(true),
9017
+ className: "flex h-8 select-none items-center gap-1 rounded-lg pl-2 pr-3 text-sm font-medium",
9018
+ children: [
9019
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { className: "size-5" }),
9020
+ "Index"
9021
+ ]
9022
+ }
9023
+ ) }),
9024
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, CreateIndexModal, { open, onOpenChange: setOpen })
9025
+ ] });
9026
+ };
9027
+ var WizardButton = () => {
9028
+ const queryWizard = useQueryWizardFn();
9029
+ const [open, setOpen] = _react.useState.call(void 0, false);
9030
+ if (!queryWizard) return null;
9031
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Popover, { open, onOpenChange: setOpen, modal: false, children: [
9032
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SimpleTooltip, { content: "Query Wizard", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, PopoverTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { size: "icon", "aria-label": "Query Wizard", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSparkles, { className: "size-4 text-zinc-500" }) }) }) }),
9033
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9034
+ PopoverContent,
9035
+ {
9036
+ side: "bottom",
9037
+ align: "end",
9038
+ alignOffset: -124,
9039
+ avoidCollisions: false,
9040
+ className: "w-auto p-0",
9041
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryWizardPopover, { onClose: () => setOpen(false) })
9042
+ }
9043
+ )
9044
+ ] });
8088
9045
  };
8089
9046
 
8090
- export type IndexDescription<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
8091
- name: string;
8092
- dataType: "hash" | "string" | "json";
8093
- prefixes: string[];
8094
- language?: Language;
8095
- schema: Record<SchemaPaths<TSchema>, DescribeFieldInfo>;
9047
+ // src/components/databrowser/components/header-error.tsx
9048
+
9049
+ var HeaderError = () => {
9050
+ const { query } = useKeys();
9051
+ if (!query.error) return null;
9052
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-red-600 dark:text-red-400", children: formatUpstashErrorMessage(query.error) });
8096
9053
  };
8097
9054
 
8098
- export type Language =
8099
- | "english"
8100
- | "arabic"
8101
- | "danish"
8102
- | "dutch"
8103
- | "finnish"
8104
- | "french"
8105
- | "german"
8106
- | "greek"
8107
- | "hungarian"
8108
- | "italian"
8109
- | "norwegian"
8110
- | "portuguese"
8111
- | "romanian"
8112
- | "russian"
8113
- | "spanish"
8114
- | "swedish"
8115
- | "tamil"
8116
- | "turkish";
9055
+ // src/components/databrowser/components/search/query-editor.tsx
8117
9056
 
8118
- `;
8119
9057
 
8120
9058
  // src/components/databrowser/components/search/generate-query-type-definitions.tsx
8121
9059
  var buildNestedSchema = (flatSchema) => {
@@ -8148,7 +9086,7 @@ var generateNestedInterface = (obj, indent = " ") => {
8148
9086
  var toAmbientTypes = (types) => types.replaceAll(/export const (\w+) = (\[.*?]) as const;/g, "declare const $1: readonly $2;").replaceAll("export ", "");
8149
9087
  var generateTypeDefinitions = (schema) => {
8150
9088
  let schemaFieldsInterface = "";
8151
- const schemaFields = _optionalChain([schema, 'optionalAccess', _89 => _89.schema]);
9089
+ const schemaFields = _optionalChain([schema, 'optionalAccess', _105 => _105.schema]);
8152
9090
  if (schemaFields && Object.keys(schemaFields).length > 0) {
8153
9091
  const nested = buildNestedSchema(schemaFields);
8154
9092
  const fieldLines = generateNestedInterface(nested);
@@ -8203,32 +9141,57 @@ var QueryBuilder = () => {
8203
9141
  const { valuesSearch, setValuesSearchQuery } = useTab();
8204
9142
  const { data: indexDetails } = useFetchSearchIndex(valuesSearch.index);
8205
9143
  const editorValue = PREFIX + (valuesSearch.query || "{}");
8206
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col rounded-lg border border-zinc-300 bg-white px-[6px]", children: [
8207
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "min-h-0 flex-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8208
- QueryEditor,
8209
- {
8210
- value: editorValue,
8211
- onChange: (value) => {
8212
- const queryPart = value.slice(PREFIX.length);
8213
- setValuesSearchQuery(queryPart);
8214
- },
8215
- schema: indexDetails
8216
- }
8217
- ) }),
8218
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-end px-2 pb-1.5", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8219
- "a",
8220
- {
8221
- href: "https://upstash-search.mintlify.app/redis/search/query-operators/boolean-operators/overview",
8222
- target: "_blank",
8223
- rel: "noopener noreferrer",
8224
- className: "flex items-center gap-1 text-xs text-zinc-400 transition-colors hover:text-zinc-600",
8225
- children: [
8226
- "Docs",
8227
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconExternalLink, { size: 12 })
8228
- ]
9144
+ if (!indexDetails) return;
9145
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full flex-col rounded-lg border border-zinc-300 bg-white px-[6px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative min-h-0 flex-1", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute inset-0", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9146
+ QueryEditor,
9147
+ {
9148
+ value: editorValue,
9149
+ onChange: (value) => {
9150
+ const queryPart = value.slice(PREFIX.length);
9151
+ setValuesSearchQuery(queryPart);
9152
+ },
9153
+ schema: indexDetails
9154
+ }
9155
+ ) }) }) });
9156
+ };
9157
+
9158
+ // src/components/databrowser/components/query-builder-error.tsx
9159
+
9160
+
9161
+ var ERROR_TIMEOUT = 5e3;
9162
+ var QueryBuilderError = ({
9163
+ error,
9164
+ autoHide
9165
+ }) => {
9166
+ const [visible, setVisible] = _react.useState.call(void 0, false);
9167
+ const [displayedError, setDisplayedError] = _react.useState.call(void 0, );
9168
+ _react.useEffect.call(void 0, () => {
9169
+ let timeout;
9170
+ if (error) {
9171
+ setDisplayedError(error);
9172
+ setVisible(true);
9173
+ if (autoHide) {
9174
+ timeout = setTimeout(() => setVisible(false), ERROR_TIMEOUT);
8229
9175
  }
8230
- ) })
8231
- ] });
9176
+ } else {
9177
+ setVisible(false);
9178
+ }
9179
+ return () => clearTimeout(timeout);
9180
+ }, [error, autoHide]);
9181
+ if (!displayedError) return;
9182
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9183
+ "p",
9184
+ {
9185
+ className: cn(
9186
+ "absolute bottom-2 left-2 z-[2] max-w-[70%] rounded-md bg-red-50 px-3 py-1.5 text-sm text-red-600 shadow-sm",
9187
+ visible ? "duration-200 animate-in fade-in slide-in-from-bottom-1" : "duration-200 animate-out fade-out slide-out-to-bottom-1 fill-mode-forwards"
9188
+ ),
9189
+ onAnimationEnd: () => {
9190
+ if (!visible) setDisplayedError(void 0);
9191
+ },
9192
+ children: displayedError
9193
+ }
9194
+ );
8232
9195
  };
8233
9196
 
8234
9197
  // src/components/databrowser/components/search-empty-state.tsx
@@ -8389,7 +9352,7 @@ var ImportSampleDatasetModal = ({
8389
9352
  if (await index.describe()) {
8390
9353
  await index.drop();
8391
9354
  }
8392
- } catch (e5) {
9355
+ } catch (e6) {
8393
9356
  }
8394
9357
  await redis.search.createIndex({
8395
9358
  dataType: "string",
@@ -8483,7 +9446,7 @@ var ImportSampleDatasetModal = ({
8483
9446
 
8484
9447
  var SearchEmptyState = () => {
8485
9448
  const [importModalOpen, setImportModalOpen] = _react.useState.call(void 0, false);
8486
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mx-auto flex h-full max-w-4xl gap-8 rounded-xl border border-zinc-200 bg-gradient-to-b from-zinc-50 to-white p-8", children: [
9449
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mx-auto flex h-full gap-8 rounded-xl border border-zinc-200 bg-gradient-to-b from-zinc-50 to-white p-8", children: [
8487
9450
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ImportSampleDatasetModal, { open: importModalOpen, onOpenChange: setImportModalOpen }),
8488
9451
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex-1", children: [
8489
9452
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h2", { className: "mb-2 text-lg font-semibold text-zinc-900", children: "Redis Search" }),
@@ -8560,7 +9523,7 @@ var Empty = () => {
8560
9523
 
8561
9524
 
8562
9525
  var SidebarContextMenu = ({ children }) => {
8563
- const { mutate: deleteKey } = useDeleteKey();
9526
+ const { mutateAsync: deleteKey } = useDeleteKey();
8564
9527
  const [isAlertOpen, setAlertOpen] = _react.useState.call(void 0, false);
8565
9528
  const [contextKeys, setContextKeys] = _react.useState.call(void 0, []);
8566
9529
  const {
@@ -8569,7 +9532,7 @@ var SidebarContextMenu = ({ children }) => {
8569
9532
  selectTab,
8570
9533
  setSearch
8571
9534
  } = useDatabrowserStore();
8572
- const { search: currentSearch, selectedKeys } = useTab();
9535
+ const { search: currentSearch, selectedKeys, isValuesSearchSelected } = useTab();
8573
9536
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
8574
9537
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8575
9538
  DeleteKeyModal,
@@ -8578,11 +9541,10 @@ var SidebarContextMenu = ({ children }) => {
8578
9541
  count: contextKeys.length,
8579
9542
  open: isAlertOpen,
8580
9543
  onOpenChange: setAlertOpen,
8581
- onDeleteConfirm: (e) => {
9544
+ showReindex: isValuesSearchSelected,
9545
+ onDeleteConfirm: async (e, options) => {
8582
9546
  e.stopPropagation();
8583
- for (const key of contextKeys) {
8584
- deleteKey(key);
8585
- }
9547
+ await deleteKey({ keys: contextKeys, reindex: _optionalChain([options, 'optionalAccess', _106 => _106.reindex]) });
8586
9548
  setAlertOpen(false);
8587
9549
  }
8588
9550
  }
@@ -8745,14 +9707,14 @@ var LoadingSkeleton = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div",
8745
9707
 
8746
9708
  function Sidebar() {
8747
9709
  const { keys, query } = useKeys();
8748
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex h-full flex-col gap-2", children: query.isLoading && keys.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSkeleton, {}) : keys.length > 0 ? (
9710
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative flex h-full flex-col gap-2", children: query.isLoading && keys.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, LoadingSkeleton, {}) : keys.length > 0 ? (
8749
9711
  // Infinite scroll already has a loader at the bottom
8750
9712
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8751
9713
  InfiniteScroll,
8752
9714
  {
8753
9715
  query,
8754
9716
  disableRoundedInherit: true,
8755
- className: "min-h-0 rounded-xl bg-zinc-100 px-2 py-5 pr-4 dark:bg-zinc-200",
9717
+ className: "h-full min-h-0 rounded-xl bg-zinc-100 px-2 py-5 pr-4 dark:bg-zinc-200",
8756
9718
  scrollBarClassName: "py-5",
8757
9719
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysList, {})
8758
9720
  }
@@ -8767,21 +9729,13 @@ function Sidebar() {
8767
9729
 
8768
9730
 
8769
9731
  // src/components/databrowser/components/ui-query-builder/types.ts
8770
- var STRING_OPERATORS = [
8771
- "eq",
8772
- "ne",
8773
- "in",
8774
- "phrase",
8775
- "regex",
8776
- "fuzzy",
8777
- "smart"
8778
- ];
8779
- var NUMBER_OPERATORS = ["eq", "ne", "gt", "gte", "lt", "lte", "in"];
8780
- var BOOLEAN_OPERATORS = ["eq", "ne", "in"];
8781
- var DATE_OPERATORS = ["eq", "ne", "gt", "gte", "lt", "lte", "in"];
9732
+ var STRING_OPERATORS = ["smart", "eq", "in", "phrase", "regex", "fuzzy"];
9733
+ var NUMBER_OPERATORS = ["eq", "gt", "gte", "lt", "lte"];
9734
+ var BOOLEAN_OPERATORS = ["eq"];
9735
+ var DATE_OPERATORS = NUMBER_OPERATORS;
8782
9736
  var ALL_OPERATORS = [
9737
+ "smart",
8783
9738
  "eq",
8784
- "ne",
8785
9739
  "gt",
8786
9740
  "gte",
8787
9741
  "lt",
@@ -8789,12 +9743,23 @@ var ALL_OPERATORS = [
8789
9743
  "in",
8790
9744
  "phrase",
8791
9745
  "regex",
8792
- "fuzzy",
8793
- "smart"
9746
+ "fuzzy"
8794
9747
  ];
9748
+ var OPERATOR_DESCRIPTIONS = {
9749
+ eq: "Equals",
9750
+ gt: "Greater than",
9751
+ gte: "Greater than or equal",
9752
+ lt: "Less than",
9753
+ lte: "Less than or equal",
9754
+ in: "Matches any of the given values, comma separated",
9755
+ phrase: "Matches an exact phrase",
9756
+ regex: "Matches a regular expression pattern",
9757
+ fuzzy: "Approximate match with custom edit distance",
9758
+ smart: "Default opinionated matching algorithm"
9759
+ };
8795
9760
  var OPERATOR_OPTIONS = [
9761
+ { value: "smart", label: "smart" },
8796
9762
  { value: "eq", label: "eq" },
8797
- { value: "ne", label: "ne" },
8798
9763
  { value: "gt", label: "gt" },
8799
9764
  { value: "gte", label: "gte" },
8800
9765
  { value: "lt", label: "lt" },
@@ -8802,8 +9767,7 @@ var OPERATOR_OPTIONS = [
8802
9767
  { value: "in", label: "in" },
8803
9768
  { value: "phrase", label: "phrase" },
8804
9769
  { value: "regex", label: "regex" },
8805
- { value: "fuzzy", label: "fuzzy" },
8806
- { value: "smart", label: "smart" }
9770
+ { value: "fuzzy", label: "fuzzy" }
8807
9771
  ];
8808
9772
  var getOperatorsForFieldType = (fieldType) => {
8809
9773
  switch (fieldType) {
@@ -8845,7 +9809,7 @@ var hasMustShouldCombination = (queryString) => {
8845
9809
  const obj = parseJSObjectLiteral(queryString);
8846
9810
  if (!obj) return false;
8847
9811
  return hasMustShouldCombinationInObject(obj);
8848
- } catch (e6) {
9812
+ } catch (e7) {
8849
9813
  return false;
8850
9814
  }
8851
9815
  };
@@ -8871,12 +9835,13 @@ var isFieldConditionObject = (obj) => {
8871
9835
  };
8872
9836
  var parseFieldCondition = (field, fieldValue) => {
8873
9837
  if (!isFieldConditionObject(fieldValue)) {
9838
+ const operator2 = typeof fieldValue === "boolean" || typeof fieldValue === "number" ? "eq" : "smart";
8874
9839
  return {
8875
9840
  id: generateId(),
8876
9841
  type: "condition",
8877
9842
  condition: {
8878
9843
  field,
8879
- operator: "eq",
9844
+ operator: operator2,
8880
9845
  value: fieldValue
8881
9846
  }
8882
9847
  };
@@ -8907,20 +9872,23 @@ var parseFieldCondition = (field, fieldValue) => {
8907
9872
  break;
8908
9873
  }
8909
9874
  }
9875
+ if (operator === "smart" && (typeof value === "boolean" || typeof value === "number")) {
9876
+ operator = "eq";
9877
+ }
8910
9878
  if ("$boost" in fieldObj) {
8911
9879
  boost = fieldObj.$boost;
8912
9880
  }
8913
9881
  return {
8914
9882
  id: generateId(),
8915
9883
  type: "condition",
9884
+ boost,
8916
9885
  condition: {
8917
9886
  field,
8918
9887
  operator,
8919
9888
  value,
8920
9889
  fuzzyDistance,
8921
9890
  phraseSlop,
8922
- phrasePrefix,
8923
- boost
9891
+ phrasePrefix
8924
9892
  }
8925
9893
  };
8926
9894
  };
@@ -8930,6 +9898,10 @@ var parseMultiFieldObject = (obj, operator) => {
8930
9898
  for (const [key, value] of Object.entries(obj)) {
8931
9899
  if (key === "$boost") {
8932
9900
  boost = value;
9901
+ } else if (key === "$and" || key === "$or") {
9902
+ const nestedOp = key === "$and" ? "and" : "or";
9903
+ const nestedGroup = parseGroup(value, nestedOp);
9904
+ if (nestedGroup) children.push(nestedGroup);
8933
9905
  } else if (!isOperatorKey(key)) {
8934
9906
  children.push(parseFieldCondition(key, value));
8935
9907
  }
@@ -9000,11 +9972,29 @@ var objectToQueryNode = (obj) => {
9000
9972
  const operator = "$and" in obj ? "and" : "or";
9001
9973
  const groupValue = _nullishCoalesce(obj["$and"], () => ( obj["$or"]));
9002
9974
  const boost = "$boost" in obj ? obj.$boost : void 0;
9003
- const groupNode = parseGroup(groupValue, operator, boost);
9975
+ const groupNode = parseGroup(
9976
+ groupValue,
9977
+ operator,
9978
+ nonOperatorKeys.length === 0 ? boost : void 0
9979
+ );
9004
9980
  if (groupNode && groupNode.type === "group" && hasMustNot) {
9005
9981
  addMustNotChildren(groupNode, obj.$mustNot);
9006
9982
  }
9007
- return groupNode;
9983
+ if (!groupNode || nonOperatorKeys.length === 0) {
9984
+ return groupNode;
9985
+ }
9986
+ const fieldChildren = nonOperatorKeys.map((key) => parseFieldCondition(key, obj[key]));
9987
+ const group = {
9988
+ id: generateId(),
9989
+ type: "group",
9990
+ groupOperator: "and",
9991
+ children: [...fieldChildren, groupNode],
9992
+ boost
9993
+ };
9994
+ if (hasMustNot) {
9995
+ addMustNotChildren(group, obj.$mustNot);
9996
+ }
9997
+ return group;
9008
9998
  }
9009
9999
  if (hasMustNot) {
9010
10000
  if (nonOperatorKeys.length > 0) {
@@ -9053,7 +10043,7 @@ var parseQueryStringWithError = (queryString) => {
9053
10043
  }
9054
10044
  return { success: true, state: { root: root2 } };
9055
10045
  }
9056
- } catch (e7) {
10046
+ } catch (e8) {
9057
10047
  }
9058
10048
  return { success: false, error: "Failed to parse query" };
9059
10049
  };
@@ -9240,8 +10230,7 @@ var moveNodeInTree = (root2, nodeId, newParentId, newIndex) => {
9240
10230
 
9241
10231
 
9242
10232
 
9243
- // src/components/databrowser/components/ui-query-builder/condition-common.tsx
9244
-
10233
+ // src/components/databrowser/components/ui-query-builder/boost-badge.tsx
9245
10234
 
9246
10235
 
9247
10236
  // src/components/databrowser/components/ui-query-builder/dynamic-width-input.tsx
@@ -9294,7 +10283,7 @@ var DynamicWidthInput = ({
9294
10283
  );
9295
10284
  };
9296
10285
 
9297
- // src/components/databrowser/components/ui-query-builder/condition-common.tsx
10286
+ // src/components/databrowser/components/ui-query-builder/boost-badge.tsx
9298
10287
 
9299
10288
  var BoostBadge = ({
9300
10289
  node,
@@ -9325,7 +10314,13 @@ var BoostBadge = ({
9325
10314
  const labelBg = isNegative ? "bg-red-50" : "bg-purple-50";
9326
10315
  const textColor = isNegative ? "text-red-800" : "text-purple-800";
9327
10316
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "span", { className: "relative flex h-[26px] items-center overflow-hidden rounded-md border border-zinc-300 text-sm font-medium", children: [
9328
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `flex h-full items-center px-2 ${labelBg} ${textColor}`, children: isNegative ? "Demote" : "Boost" }),
10317
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Tooltip, { delayDuration: 200, children: [
10318
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `flex h-full cursor-default items-center px-2 ${labelBg} ${textColor}`, children: isNegative ? "Demote" : "Boost" }) }),
10319
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, TooltipContent, { side: "bottom", className: "max-w-xs", children: [
10320
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: isNegative ? `Multiplies this condition's score by ${_nullishCoalesce(node.boost, () => ( 0))}, subtracting from the total.` : `Multiplies this condition's score by ${_nullishCoalesce(node.boost, () => ( 0))}.` }),
10321
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DocsLink, { href: "https://upstash-search.mintlify.app/redis/search/query-operators/boolean-operators/boost" })
10322
+ ] })
10323
+ ] }),
9329
10324
  isStatic ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: `px-2 ${textColor}`, children: node.boost }) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "flex h-full items-center bg-white px-2", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9330
10325
  DynamicWidthInput,
9331
10326
  {
@@ -9339,7 +10334,33 @@ var BoostBadge = ({
9339
10334
  ) })
9340
10335
  ] });
9341
10336
  };
10337
+
10338
+ // src/components/databrowser/components/ui-query-builder/dnd-context.tsx
10339
+
10340
+
10341
+
10342
+
10343
+
10344
+
10345
+
10346
+ var _core = require('@dnd-kit/core');
10347
+
10348
+ // src/components/databrowser/components/ui-query-builder/drag-overlay.tsx
10349
+
10350
+
10351
+
10352
+ // src/components/databrowser/components/ui-query-builder/not-badge.tsx
10353
+
9342
10354
  var NotBadge = () => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "flex h-[26px] items-center rounded-md border border-zinc-300 bg-amber-50 px-2 text-sm font-medium text-amber-800", children: "Not" });
10355
+
10356
+ // src/components/databrowser/components/ui-query-builder/query-condition.tsx
10357
+
10358
+
10359
+
10360
+ // src/components/databrowser/components/ui-query-builder/node-actions-menu.tsx
10361
+
10362
+
10363
+
9343
10364
  var NodeActionsMenu = ({ node }) => {
9344
10365
  const { updateNode } = useQueryBuilderUI();
9345
10366
  const [open, setOpen] = _react.useState.call(void 0, false);
@@ -9393,24 +10414,8 @@ var NodeActionsMenu = ({ node }) => {
9393
10414
  ] });
9394
10415
  };
9395
10416
 
9396
- // src/components/databrowser/components/ui-query-builder/dnd-context.tsx
9397
-
9398
-
9399
-
9400
-
9401
-
9402
-
9403
-
9404
- var _core = require('@dnd-kit/core');
9405
-
9406
- // src/components/databrowser/components/ui-query-builder/drag-overlay.tsx
9407
-
9408
-
9409
-
9410
10417
  // src/components/databrowser/components/ui-query-builder/query-condition.tsx
9411
10418
 
9412
-
9413
-
9414
10419
  var formatValueForDisplay = (value) => {
9415
10420
  if (Array.isArray(value)) {
9416
10421
  return value.join(", ");
@@ -9435,7 +10440,7 @@ var QueryCondition = ({
9435
10440
  setLocalValue(formattedConditionValue);
9436
10441
  }
9437
10442
  const currentFieldInfo = fieldInfos.find((f) => f.name === condition.field);
9438
- const currentFieldType = _nullishCoalesce(_optionalChain([currentFieldInfo, 'optionalAccess', _90 => _90.type]), () => ( "unknown"));
10443
+ const currentFieldType = _nullishCoalesce(_optionalChain([currentFieldInfo, 'optionalAccess', _107 => _107.type]), () => ( "unknown"));
9439
10444
  const isUnknownField = condition.field && !fieldNames.includes(condition.field);
9440
10445
  const getValueTypeError = () => {
9441
10446
  if (isUnknownField || currentFieldType === "unknown" || currentFieldType === "string") {
@@ -9493,8 +10498,8 @@ var QueryCondition = ({
9493
10498
  }
9494
10499
  }, [currentFieldType, condition.value]);
9495
10500
  const handleFieldChange = (value) => {
9496
- const newFieldInfo = _optionalChain([fieldInfos, 'optionalAccess', _91 => _91.find, 'call', _92 => _92((f) => f.name === value)]);
9497
- const newFieldType = _nullishCoalesce(_optionalChain([newFieldInfo, 'optionalAccess', _93 => _93.type]), () => ( "unknown"));
10501
+ const newFieldInfo = _optionalChain([fieldInfos, 'optionalAccess', _108 => _108.find, 'call', _109 => _109((f) => f.name === value)]);
10502
+ const newFieldType = _nullishCoalesce(_optionalChain([newFieldInfo, 'optionalAccess', _110 => _110.type]), () => ( "unknown"));
9498
10503
  const validOperators = getOperatorsForFieldType(newFieldType);
9499
10504
  const isOperatorValid = validOperators.includes(condition.operator);
9500
10505
  let newValue = condition.value;
@@ -9635,10 +10640,10 @@ var QueryCondition = ({
9635
10640
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9636
10641
  "div",
9637
10642
  {
9638
- ref: _optionalChain([dragHandleProps, 'optionalAccess', _94 => _94.ref]),
10643
+ ref: _optionalChain([dragHandleProps, 'optionalAccess', _111 => _111.ref]),
9639
10644
  className: "flex cursor-grab items-center px-1 text-zinc-400 hover:text-zinc-600",
9640
- ..._optionalChain([dragHandleProps, 'optionalAccess', _95 => _95.attributes]),
9641
- ..._optionalChain([dragHandleProps, 'optionalAccess', _96 => _96.listeners]),
10645
+ ..._optionalChain([dragHandleProps, 'optionalAccess', _112 => _112.attributes]),
10646
+ ..._optionalChain([dragHandleProps, 'optionalAccess', _113 => _113.listeners]),
9642
10647
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconGripVertical, { size: 16 })
9643
10648
  }
9644
10649
  ),
@@ -9681,7 +10686,15 @@ var QueryCondition = ({
9681
10686
  },
9682
10687
  condition.operator
9683
10688
  ),
9684
- filteredOperators.map((op) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: op.value, children: op.label }, op.value))
10689
+ filteredOperators.map((op) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10690
+ SelectItem,
10691
+ {
10692
+ value: op.value,
10693
+ description: OPERATOR_DESCRIPTIONS[op.value],
10694
+ children: op.label
10695
+ },
10696
+ op.value
10697
+ ))
9685
10698
  ] })
9686
10699
  ] }),
9687
10700
  currentFieldType === "boolean" && condition.operator === "in" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-[26px] items-center gap-2 rounded-none rounded-r-md border border-zinc-200 bg-white px-2 text-sm", children: [
@@ -9763,8 +10776,15 @@ var QueryCondition = ({
9763
10776
  children: [
9764
10777
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-[26px] w-16 gap-3 border-zinc-200 bg-white px-2 text-sm", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
9765
10778
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, SelectContent, { children: [
9766
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "1", children: "1" }),
9767
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "2", children: "2" })
10779
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10780
+ SelectItem,
10781
+ {
10782
+ value: "1",
10783
+ description: "Matches words with 1 character edit (e.g. 'teh' \u2192 'the')",
10784
+ children: "1"
10785
+ }
10786
+ ),
10787
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "2", description: "Matches words with up to 2 character edits", children: "2" })
9768
10788
  ] })
9769
10789
  ]
9770
10790
  }
@@ -9773,9 +10793,23 @@ var QueryCondition = ({
9773
10793
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: phraseMode, onValueChange: handlePhraseModeChange, children: [
9774
10794
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectTrigger, { className: "h-[26px] w-20 gap-3 border-zinc-200 bg-white px-2 text-sm font-normal", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectValue, {}) }),
9775
10795
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, SelectContent, { children: [
9776
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "exact", children: "exact" }),
9777
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "slop", children: "slop" }),
9778
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "prefix", children: "prefix" })
10796
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "exact", description: "Terms must appear adjacent to each other", children: "exact" }),
10797
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10798
+ SelectItem,
10799
+ {
10800
+ value: "slop",
10801
+ description: "Allow custom number of intervening words between terms",
10802
+ children: "slop"
10803
+ }
10804
+ ),
10805
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10806
+ SelectItem,
10807
+ {
10808
+ value: "prefix",
10809
+ description: "Last term matches as a prefix (e.g. 'wireless head' \u2192 'headphones')",
10810
+ children: "prefix"
10811
+ }
10812
+ )
9779
10813
  ] })
9780
10814
  ] }),
9781
10815
  phraseMode === "slop" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -9791,6 +10825,7 @@ var QueryCondition = ({
9791
10825
  }
9792
10826
  )
9793
10827
  ] }),
10828
+ node.not && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NotBadge, {}),
9794
10829
  node.boost !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BoostBadge, { node }),
9795
10830
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
9796
10831
  "div",
@@ -10027,6 +11062,7 @@ var DraggableItem = ({
10027
11062
  // src/components/databrowser/components/ui-query-builder/drop-zone.tsx
10028
11063
 
10029
11064
 
11065
+
10030
11066
  var DropIndicator = ({ id, isOver }) => {
10031
11067
  const { setNodeRef } = _core.useDroppable.call(void 0, { id });
10032
11068
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { ref: setNodeRef, className: `relative flex h-2 items-center`, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -10039,14 +11075,26 @@ var DropIndicator = ({ id, isOver }) => {
10039
11075
  }
10040
11076
  ) });
10041
11077
  };
10042
- var EmptyGroupDropZone = ({ groupId, isOver }) => {
11078
+ var EmptyGroupDropZone = ({
11079
+ groupId,
11080
+ isOver,
11081
+ onAddCondition
11082
+ }) => {
10043
11083
  const { setNodeRef } = _core.useDroppable.call(void 0, { id: `drop-${groupId}-end` });
10044
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10045
- "div",
11084
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
11085
+ "button",
10046
11086
  {
11087
+ type: "button",
10047
11088
  ref: setNodeRef,
10048
- className: `mt-2 flex h-8 items-center justify-center rounded-md border border-dashed text-sm transition-all ${isOver ? "border-blue-500 bg-blue-50 text-blue-600" : "border-zinc-300 text-zinc-400"}`,
10049
- children: "Add a condition to start"
11089
+ onClick: onAddCondition,
11090
+ className: cn(
11091
+ "mt-2 flex h-8 w-full items-center justify-center gap-1.5 rounded-md border border-dashed text-sm transition-all",
11092
+ isOver ? "border-blue-500 bg-blue-50 text-blue-600" : "border-zinc-300 text-zinc-400 hover:border-zinc-400 hover:bg-zinc-50 hover:text-zinc-500"
11093
+ ),
11094
+ children: [
11095
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconPlus, { size: 14 }),
11096
+ "Add a condition"
11097
+ ]
10050
11098
  }
10051
11099
  );
10052
11100
  };
@@ -10093,9 +11141,7 @@ var InnerGroup = ({
10093
11141
  addChildToGroup(node.id, createEmptyCondition(fieldInfos));
10094
11142
  };
10095
11143
  const handleAddGroup = () => {
10096
- const newGroup = createEmptyGroup("and");
10097
- newGroup.children = [createEmptyCondition(fieldInfos)];
10098
- addChildToGroup(node.id, newGroup);
11144
+ addChildToGroup(node.id, createEmptyGroup("and"));
10099
11145
  };
10100
11146
  const handleDeleteGroup = () => {
10101
11147
  deleteNode(node.id);
@@ -10105,10 +11151,10 @@ var InnerGroup = ({
10105
11151
  !isRoot && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10106
11152
  "div",
10107
11153
  {
10108
- ref: _optionalChain([dragHandleProps, 'optionalAccess', _97 => _97.ref]),
11154
+ ref: _optionalChain([dragHandleProps, 'optionalAccess', _114 => _114.ref]),
10109
11155
  className: "flex cursor-grab items-center px-1 text-zinc-400",
10110
- ..._optionalChain([dragHandleProps, 'optionalAccess', _98 => _98.attributes]),
10111
- ..._optionalChain([dragHandleProps, 'optionalAccess', _99 => _99.listeners]),
11156
+ ..._optionalChain([dragHandleProps, 'optionalAccess', _115 => _115.attributes]),
11157
+ ..._optionalChain([dragHandleProps, 'optionalAccess', _116 => _116.listeners]),
10112
11158
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconGripVertical, { size: 16 })
10113
11159
  }
10114
11160
  ),
@@ -10134,6 +11180,7 @@ var InnerGroup = ({
10134
11180
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DropdownMenuItem, { onClick: handleAddGroup, children: "Add Group" })
10135
11181
  ] })
10136
11182
  ] }),
11183
+ node.not && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, NotBadge, {}),
10137
11184
  node.boost !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BoostBadge, { node }),
10138
11185
  !isRoot && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
10139
11186
  "div",
@@ -10154,7 +11201,14 @@ var InnerGroup = ({
10154
11201
  }
10155
11202
  )
10156
11203
  ] }),
10157
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `min-h-[20px] ${isRoot ? "" : "ml-[15px] border-l-2 border-zinc-200 pl-3"}`, children: node.children.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, EmptyGroupDropZone, { groupId: node.id, isOver: activeOverId === `drop-${node.id}-end` }) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
11204
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `min-h-[20px] ${isRoot ? "" : "ml-[15px] border-l-2 border-zinc-200 pl-3"}`, children: node.children.length === 0 ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
11205
+ EmptyGroupDropZone,
11206
+ {
11207
+ groupId: node.id,
11208
+ isOver: activeOverId === `drop-${node.id}-end`,
11209
+ onAddCondition: fieldInfos.length > 0 ? handleAddCondition : void 0
11210
+ }
11211
+ ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
10158
11212
  node.children.map(
10159
11213
  (child) => !child.not && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10160
11214
  ChildRow,
@@ -10170,20 +11224,10 @@ var InnerGroup = ({
10170
11224
  ),
10171
11225
  node.children.some((child) => child.not) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Tooltip, { delayDuration: 200, children: [
10172
11226
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "ml-2 mt-2 flex h-[26px] w-fit cursor-default select-none items-center rounded-md border border-zinc-300 bg-amber-50 px-2 text-sm font-medium capitalize text-amber-800", children: "Must Not" }) }),
10173
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipContent, { side: "right", className: "max-w-xs", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { children: [
10174
- "Keys matching any of the conditions below are excluded from the results.",
10175
- " ",
10176
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10177
- "a",
10178
- {
10179
- href: "https://upstash-search.mintlify.app/redis/search/query-operators/boolean-operators/must-not",
10180
- target: "_blank",
10181
- rel: "noopener noreferrer",
10182
- className: "underline",
10183
- children: "Learn more"
10184
- }
10185
- )
10186
- ] }) })
11227
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, TooltipContent, { side: "right", className: "max-w-xs", children: [
11228
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "Keys matching any of the conditions below are excluded from the results." }),
11229
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DocsLink, { href: "https://upstash-search.mintlify.app/redis/search/query-operators/boolean-operators/must-not" })
11230
+ ] })
10187
11231
  ] }),
10188
11232
  node.children.map(
10189
11233
  (child) => child.not && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -10248,12 +11292,6 @@ var QueryGroup = ({ node, isRoot = false, depth }) => {
10248
11292
 
10249
11293
 
10250
11294
  // src/components/databrowser/components/ui-query-builder/query-stringify.ts
10251
- var jsonToJsLiteral = (json) => {
10252
- return json.replaceAll(/"([$A-Z_a-z][\w$]*)"\s*:/g, "$1:");
10253
- };
10254
- var toJsLiteral = (obj) => {
10255
- return jsonToJsLiteral(JSON.stringify(obj, null, 2));
10256
- };
10257
11295
  var buildOperatorValue = (operator, value, fuzzyDistance, phraseSlop, phrasePrefix) => {
10258
11296
  if (operator === "fuzzy" && fuzzyDistance) {
10259
11297
  return { value, distance: fuzzyDistance };
@@ -10279,7 +11317,8 @@ var conditionToObject = (node) => {
10279
11317
  phrasePrefix
10280
11318
  } = node.condition;
10281
11319
  const effectiveBoost = _nullishCoalesce(node.boost, () => ( conditionBoost));
10282
- if (operator === "eq" && !effectiveBoost) {
11320
+ const isCollapsibleEq = operator === "eq" && (typeof value === "boolean" || typeof value === "number");
11321
+ if ((operator === "smart" || isCollapsibleEq) && !effectiveBoost) {
10283
11322
  return { [field]: value };
10284
11323
  }
10285
11324
  const fieldCondition = {
@@ -10292,15 +11331,15 @@ var conditionToObject = (node) => {
10292
11331
  return { [field]: fieldCondition };
10293
11332
  };
10294
11333
  var canMergeChildren = (children) => {
10295
- return children.every(
10296
- (child) => child.type === "condition" && !child.not && !child.boost && child.condition.operator === "eq" && !child.condition.boost
10297
- );
11334
+ if (!children.every((child) => child.type === "condition" && !child.not)) return false;
11335
+ const fields = children.map((c) => c.condition.field);
11336
+ return new Set(fields).size === fields.length;
10298
11337
  };
10299
11338
  var mergeConditions = (children, boost) => {
10300
11339
  const merged = {};
10301
11340
  for (const child of children) {
10302
11341
  if (child.type === "condition") {
10303
- merged[child.condition.field] = child.condition.value;
11342
+ Object.assign(merged, conditionToObject(child));
10304
11343
  }
10305
11344
  }
10306
11345
  if (boost && boost !== 1) {
@@ -10308,7 +11347,14 @@ var mergeConditions = (children, boost) => {
10308
11347
  }
10309
11348
  return merged;
10310
11349
  };
10311
- var groupToObject = (node, isRoot) => {
11350
+ var buildMustNot = (negatedChildren) => {
11351
+ const negatedObjects = negatedChildren.map((child) => {
11352
+ const withoutNot = { ...child, not: void 0 };
11353
+ return queryNodeToObject(withoutNot, false);
11354
+ });
11355
+ return negatedObjects.length === 1 ? negatedObjects[0] : negatedObjects;
11356
+ };
11357
+ var groupToObject = (node, isRoot, forArray = false) => {
10312
11358
  const { groupOperator, children, boost, not } = node;
10313
11359
  const normalChildren = children.filter((c) => !c.not);
10314
11360
  const negatedChildren = children.filter((c) => c.not);
@@ -10324,41 +11370,84 @@ var groupToObject = (node, isRoot) => {
10324
11370
  }
10325
11371
  return { $mustNot: [inner] };
10326
11372
  }
10327
- if (isRoot && groupOperator === "and" && normalChildren.length === 1 && negatedChildren.length === 0 && !boost) {
10328
- return queryNodeToObject(normalChildren[0], false);
11373
+ if (isRoot && groupOperator === "and" && negatedChildren.length === 0) {
11374
+ if (normalChildren.length === 1) {
11375
+ const result2 = queryNodeToObject(normalChildren[0], false);
11376
+ if (boost && boost !== 1) result2.$boost = boost;
11377
+ return result2;
11378
+ }
11379
+ const conditionChildren = normalChildren.filter((c) => c.type === "condition");
11380
+ const groupChildren = normalChildren.filter((c) => c.type === "group");
11381
+ const hasConflictingGroupChild = groupChildren.some(
11382
+ (c) => c.groupOperator === groupOperator && c.children.length > 1 && c.boost
11383
+ );
11384
+ if (!hasConflictingGroupChild) {
11385
+ const fields = conditionChildren.map(
11386
+ (c) => c.condition.field
11387
+ );
11388
+ const groupOps = groupChildren.map((c) => `$${c.groupOperator}`);
11389
+ const allKeys = [...fields, ...groupOps];
11390
+ const hasConflicts = new Set(allKeys).size !== allKeys.length;
11391
+ if (!hasConflicts) {
11392
+ const result2 = {};
11393
+ for (const child of conditionChildren) {
11394
+ Object.assign(result2, conditionToObject(child));
11395
+ }
11396
+ for (const child of groupChildren) {
11397
+ Object.assign(result2, groupToObject(child, false));
11398
+ }
11399
+ if (boost && boost !== 1) result2.$boost = boost;
11400
+ return result2;
11401
+ }
11402
+ }
10329
11403
  }
10330
- if (normalChildren.length > 0 && negatedChildren.length === 0 && canMergeChildren(normalChildren)) {
10331
- const merged = mergeConditions(normalChildren, boost);
10332
- if (isRoot && groupOperator === "and") {
10333
- return merged;
11404
+ if (normalChildren.length > 0 && canMergeChildren(normalChildren)) {
11405
+ if (isRoot && groupOperator === "and" && negatedChildren.length === 0) {
11406
+ return mergeConditions(normalChildren, boost);
11407
+ }
11408
+ const result2 = {};
11409
+ if (forArray) {
11410
+ result2[`$${groupOperator}`] = mergeConditions(normalChildren);
11411
+ if (boost && boost !== 1) result2.$boost = boost;
11412
+ } else {
11413
+ result2[`$${groupOperator}`] = mergeConditions(normalChildren, boost);
10334
11414
  }
10335
- const result2 = { [`$${groupOperator}`]: merged };
10336
- if (boost && boost !== 1) {
10337
- result2.$boost = boost;
11415
+ if (negatedChildren.length > 0) {
11416
+ result2.$mustNot = buildMustNot(negatedChildren);
10338
11417
  }
10339
11418
  return result2;
10340
11419
  }
10341
11420
  const result = {};
10342
11421
  if (normalChildren.length > 0) {
10343
- result[`$${groupOperator}`] = normalChildren.map((child) => queryNodeToObject(child, false));
11422
+ result[`$${groupOperator}`] = normalChildren.map((child) => {
11423
+ if (child.type === "group") {
11424
+ const groupChild = child;
11425
+ const gc = groupChild.children;
11426
+ const gcNormal = gc.filter((c) => !c.not);
11427
+ const gcNegated = gc.filter((c) => c.not);
11428
+ if (groupChild.groupOperator === groupOperator && gc.length > 1 && gcNegated.length === 0 && canMergeChildren(gcNormal)) {
11429
+ return mergeConditions(gcNormal, groupChild.boost);
11430
+ }
11431
+ }
11432
+ return queryNodeToObject(child, false, true);
11433
+ });
11434
+ } else if (negatedChildren.length > 0) {
11435
+ result[`$${groupOperator}`] = {};
10344
11436
  }
10345
11437
  if (negatedChildren.length > 0) {
10346
- result.$mustNot = negatedChildren.map((child) => {
10347
- const withoutNot = { ...child, not: void 0 };
10348
- return queryNodeToObject(withoutNot, false);
10349
- });
11438
+ result.$mustNot = buildMustNot(negatedChildren);
10350
11439
  }
10351
11440
  if (boost && boost !== 1) {
10352
11441
  result.$boost = boost;
10353
11442
  }
10354
11443
  return result;
10355
11444
  };
10356
- var queryNodeToObject = (node, isRoot = false) => {
11445
+ var queryNodeToObject = (node, isRoot = false, forArray = false) => {
10357
11446
  if (node.type === "condition") {
10358
11447
  return conditionToObject(node);
10359
11448
  }
10360
11449
  if (node.type === "group") {
10361
- return groupToObject(node, isRoot);
11450
+ return groupToObject(node, isRoot, forArray);
10362
11451
  }
10363
11452
  return {};
10364
11453
  };
@@ -10414,7 +11503,7 @@ var UIQueryBuilder = () => {
10414
11503
  const { valuesSearch } = useTab();
10415
11504
  const { data: indexDetails } = useFetchSearchIndex(valuesSearch.index);
10416
11505
  const { queryState, setQueryState } = useQueryStateSync();
10417
- const fieldInfos = _optionalChain([indexDetails, 'optionalAccess', _100 => _100.schema]) ? extractFieldInfo(indexDetails.schema) : [];
11506
+ const fieldInfos = _optionalChain([indexDetails, 'optionalAccess', _117 => _117.schema]) ? extractFieldInfo(indexDetails.schema) : [];
10418
11507
  const hasNormalized = _react.useRef.call(void 0, false);
10419
11508
  _react.useEffect.call(void 0, () => {
10420
11509
  if (hasNormalized.current || fieldInfos.length === 0) return;
@@ -10433,7 +11522,7 @@ var UIQueryBuilder = () => {
10433
11522
  setHasBottomShadow(scrollTop + clientHeight < scrollHeight - 1);
10434
11523
  }, []);
10435
11524
  _react.useEffect.call(void 0, () => {
10436
- viewportRef.current = _optionalChain([scrollAreaRef, 'access', _101 => _101.current, 'optionalAccess', _102 => _102.querySelector, 'call', _103 => _103(
11525
+ viewportRef.current = _optionalChain([scrollAreaRef, 'access', _118 => _118.current, 'optionalAccess', _119 => _119.querySelector, 'call', _120 => _120(
10437
11526
  "[data-radix-scroll-area-viewport]"
10438
11527
  )]);
10439
11528
  recomputeShadows();
@@ -10443,7 +11532,7 @@ var UIQueryBuilder = () => {
10443
11532
  obs.observe(el);
10444
11533
  return () => obs.disconnect();
10445
11534
  }, [recomputeShadows]);
10446
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilderUIProvider, { fieldInfos, setQueryState, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative h-full rounded-lg bg-zinc-50", children: [
11535
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilderUIProvider, { fieldInfos, setQueryState, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative h-full min-h-0 rounded-lg bg-zinc-50 dark:bg-zinc-50/40", children: [
10447
11536
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10448
11537
  "div",
10449
11538
  {
@@ -10539,41 +11628,47 @@ var extractFieldInfo = (schema) => {
10539
11628
 
10540
11629
  var PREFIX = "const query: Query = ";
10541
11630
  var QueryBuilderContent = () => {
10542
- const { valuesSearch } = useTab();
10543
- const [mode, setMode] = _react.useState.call(void 0, "builder");
10544
- const [switchError, setSwitchError] = _react.useState.call(void 0, null);
11631
+ const { valuesSearch, queryBuilderMode, setQueryBuilderMode } = useTab();
11632
+ const { query } = useKeys();
11633
+ const [switchError, setSwitchError] = _react.useState.call(void 0, );
10545
11634
  const handleModeChange = (value) => {
10546
11635
  const newMode = value;
10547
- if (newMode === "builder") {
11636
+ if (newMode === "ui") {
10548
11637
  if (hasMustShouldCombination(valuesSearch.query)) {
10549
11638
  setSwitchError(
10550
11639
  "Queries using both $must and $should are not supported in the UI query builder"
10551
11640
  );
10552
11641
  return;
10553
11642
  }
10554
- setSwitchError(null);
11643
+ setSwitchError(void 0);
10555
11644
  } else {
10556
- setSwitchError(null);
11645
+ setSwitchError(void 0);
10557
11646
  }
10558
- setMode(newMode);
11647
+ setQueryBuilderMode(newMode);
10559
11648
  };
10560
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
10561
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative h-[200px] max-h-[40vh] min-h-[150px] resize-y overflow-hidden", children: [
10562
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute right-4 top-4 z-10", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10563
- Segmented,
10564
- {
10565
- options: [
10566
- { key: "builder", label: "Query Builder" },
10567
- { key: "code", label: "Code Editor" }
10568
- ],
10569
- value: mode,
10570
- onChange: handleModeChange,
10571
- buttonClassName: "h-6"
10572
- }
10573
- ) }),
10574
- mode === "builder" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, UIQueryBuilder, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilder, {})
10575
- ] }),
10576
- switchError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-3 text-sm text-red-500", children: switchError })
11649
+ const errorMessage = _nullishCoalesce(switchError, () => ( (query.error ? formatUpstashErrorMessage(query.error) : void 0)));
11650
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative flex h-full min-h-0 flex-col", children: [
11651
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute right-4 top-4 z-[2]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
11652
+ Segmented,
11653
+ {
11654
+ options: [
11655
+ { key: "ui", label: "Query Builder" },
11656
+ { key: "code", label: "Code Editor" }
11657
+ ],
11658
+ value: queryBuilderMode,
11659
+ onChange: handleModeChange,
11660
+ buttonClassName: "h-6"
11661
+ }
11662
+ ) }),
11663
+ queryBuilderMode === "ui" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, UIQueryBuilder, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilder, {}),
11664
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilderError, { error: errorMessage, autoHide: Boolean(switchError) }),
11665
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
11666
+ DocsLink,
11667
+ {
11668
+ className: "absolute bottom-2 right-2 text-sm",
11669
+ href: "https://upstash-search.mintlify.app/redis/search/query-operators/boolean-operators/overview"
11670
+ }
11671
+ )
10577
11672
  ] });
10578
11673
  };
10579
11674
  var SearchContent = () => {
@@ -10590,7 +11685,7 @@ var DatabrowserInstance = ({
10590
11685
  tabType,
10591
11686
  allowSearch
10592
11687
  }) => {
10593
- const { isValuesSearchSelected, setIsValuesSearchSelected } = useTab();
11688
+ const { isValuesSearchSelected, queryBuilderMode, setIsValuesSearchSelected } = useTab();
10594
11689
  const { data: indexes, isLoading } = useFetchSearchIndexes({
10595
11690
  enabled: tabType === "search"
10596
11691
  });
@@ -10606,16 +11701,40 @@ var DatabrowserInstance = ({
10606
11701
  "div",
10607
11702
  {
10608
11703
  className: cn(
10609
- "flex min-h-0 grow flex-col rounded-md bg-white px-5 pb-5",
11704
+ "flex min-h-0 grow flex-col rounded-[10px] bg-white px-5 pb-5",
10610
11705
  hidden && "hidden"
10611
11706
  ),
10612
11707
  children: [
10613
11708
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-3 py-5", children: [
10614
11709
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Header, { tabType, allowSearch }),
10615
- isValuesSearchSelected && !showEmptyState && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchContent, {}),
10616
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HeaderError, {})
11710
+ !isValuesSearchSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HeaderError, {})
10617
11711
  ] }),
10618
- showEmptyState ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchEmptyState, {}) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
11712
+ showEmptyState ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchEmptyState, {}) : isValuesSearchSelected ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
11713
+ _reactresizablepanels.PanelGroup,
11714
+ {
11715
+ autoSaveId: "search-layout",
11716
+ direction: "vertical",
11717
+ className: "h-full w-full !overflow-visible text-sm antialiased",
11718
+ children: [
11719
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
11720
+ _reactresizablepanels.Panel,
11721
+ {
11722
+ defaultSize: 30,
11723
+ minSize: 15,
11724
+ maxSize: 60,
11725
+ className: queryBuilderMode === "code" ? "!overflow-visible" : "",
11726
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchContent, {})
11727
+ }
11728
+ ),
11729
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ResizeHandle, { direction: "vertical" }),
11730
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _reactresizablepanels.PanelGroup, { autoSaveId: "persistence", direction: "horizontal", className: "h-full w-full", children: [
11731
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, {}) }),
11732
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ResizeHandle, {}),
11733
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 40, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataDisplay, {}) })
11734
+ ] }) })
11735
+ ]
11736
+ }
11737
+ ) : /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
10619
11738
  _reactresizablepanels.PanelGroup,
10620
11739
  {
10621
11740
  autoSaveId: "persistence",
@@ -10623,11 +11742,7 @@ var DatabrowserInstance = ({
10623
11742
  className: "h-full w-full text-sm antialiased",
10624
11743
  children: [
10625
11744
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { defaultSize: 30, minSize: 30, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Sidebar, {}) }),
10626
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _reactresizablepanels.PanelResizeHandle, { className: "group mx-[2px] flex h-full flex-col items-center justify-center gap-1 rounded-md px-[8px] transition-colors hover:bg-zinc-300/10", children: [
10627
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" }),
10628
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" }),
10629
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-[3px] w-[3px] rounded-full bg-zinc-300" })
10630
- ] }),
11745
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ResizeHandle, {}),
10631
11746
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactresizablepanels.Panel, { minSize: 40, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DataDisplay, {}) })
10632
11747
  ]
10633
11748
  }
@@ -10756,7 +11871,7 @@ var useOverflow = () => {
10756
11871
  }
10757
11872
  if (!node) return;
10758
11873
  observerRef.current = new ResizeObserver((entries) => {
10759
- const el = _optionalChain([entries, 'access', _104 => _104.at, 'call', _105 => _105(0), 'optionalAccess', _106 => _106.target]);
11874
+ const el = _optionalChain([entries, 'access', _121 => _121.at, 'call', _122 => _122(0), 'optionalAccess', _123 => _123.target]);
10760
11875
  if (!el) return;
10761
11876
  setIsOverflow(el.scrollWidth > el.clientWidth);
10762
11877
  });
@@ -10764,7 +11879,7 @@ var useOverflow = () => {
10764
11879
  }, []);
10765
11880
  _react.useEffect.call(void 0, () => {
10766
11881
  return () => {
10767
- _optionalChain([observerRef, 'access', _107 => _107.current, 'optionalAccess', _108 => _108.disconnect, 'call', _109 => _109()]);
11882
+ _optionalChain([observerRef, 'access', _124 => _124.current, 'optionalAccess', _125 => _125.disconnect, 'call', _126 => _126()]);
10768
11883
  };
10769
11884
  }, []);
10770
11885
  return { ref, isOverflow };
@@ -10882,8 +11997,8 @@ var SortableTab = ({ id }) => {
10882
11997
  const [originalWidth, setOriginalWidth] = _react.useState.call(void 0, null);
10883
11998
  const textRef = _react.useRef.call(void 0, null);
10884
11999
  const { tabs } = useDatabrowserStore();
10885
- const tabData = _optionalChain([tabs, 'access', _110 => _110.find, 'call', _111 => _111(([tabId]) => tabId === id), 'optionalAccess', _112 => _112[1]]);
10886
- const isPinned = _optionalChain([tabData, 'optionalAccess', _113 => _113.pinned]);
12000
+ const tabData = _optionalChain([tabs, 'access', _127 => _127.find, 'call', _128 => _128(([tabId]) => tabId === id), 'optionalAccess', _129 => _129[1]]);
12001
+ const isPinned = _optionalChain([tabData, 'optionalAccess', _130 => _130.pinned]);
10887
12002
  const { attributes, listeners: listeners2, setNodeRef, transform, transition, isDragging } = _sortable.useSortable.call(void 0, {
10888
12003
  id,
10889
12004
  disabled: isPinned,
@@ -11028,7 +12143,7 @@ var DatabrowserTabs = ({ onFullScreenClick }) => {
11028
12143
  reorderTabs(oldIndex, newIndex);
11029
12144
  }
11030
12145
  };
11031
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative shrink-0 overflow-hidden rounded-t-lg bg-zinc-300", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
12146
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "relative shrink-0 overflow-hidden rounded-t-[10px] bg-zinc-300", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1", children: [
11032
12147
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative min-w-0 flex-1", children: [
11033
12148
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
11034
12149
  "div",
@@ -11076,7 +12191,7 @@ var DatabrowserTabs = ({ onFullScreenClick }) => {
11076
12191
  }
11077
12192
  )
11078
12193
  ] }),
11079
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 pl-1", children: [
12194
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-1 px-1", children: [
11080
12195
  isOverflow && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, AddTabButton, {}),
11081
12196
  tabs.length > 1 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabsListButton, { tabs, onSelectTab: selectTab }),
11082
12197
  onFullScreenClick && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -11084,9 +12199,8 @@ var DatabrowserTabs = ({ onFullScreenClick }) => {
11084
12199
  {
11085
12200
  "aria-label": "Toggle fullscreen",
11086
12201
  variant: "secondary",
11087
- size: "icon-sm",
11088
12202
  onClick: onFullScreenClick,
11089
- className: "flex-shrink-0 bg-white text-zinc-500 dark:bg-zinc-100",
12203
+ className: "h-[34px] w-[34px] flex-shrink-0 rounded-lg bg-white text-zinc-500 dark:bg-zinc-100",
11090
12204
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconWindowMaximize, { size: 16 })
11091
12205
  }
11092
12206
  )
@@ -11100,7 +12214,7 @@ function AddTabButton() {
11100
12214
  const tabsId = addTab();
11101
12215
  selectTab(tabsId);
11102
12216
  setTimeout(() => {
11103
- const tab = _optionalChain([rootRef, 'optionalAccess', _114 => _114.current, 'optionalAccess', _115 => _115.querySelector, 'call', _116 => _116(`#tab-${tabsId}`)]);
12217
+ const tab = _optionalChain([rootRef, 'optionalAccess', _131 => _131.current, 'optionalAccess', _132 => _132.querySelector, 'call', _133 => _133(`#tab-${tabsId}`)]);
11104
12218
  if (!tab) return;
11105
12219
  tab.scrollIntoView({ behavior: "smooth" });
11106
12220
  }, 20);
@@ -11134,7 +12248,7 @@ function TabsListButton({
11134
12248
  onSelectTab(id);
11135
12249
  setOpen(false);
11136
12250
  setTimeout(() => {
11137
- const tab = _optionalChain([rootRef, 'optionalAccess', _117 => _117.current, 'optionalAccess', _118 => _118.querySelector, 'call', _119 => _119(`#tab-${id}`)]);
12251
+ const tab = _optionalChain([rootRef, 'optionalAccess', _134 => _134.current, 'optionalAccess', _135 => _135.querySelector, 'call', _136 => _136(`#tab-${id}`)]);
11138
12252
  if (!tab) return;
11139
12253
  tab.scrollIntoView({ behavior: "smooth" });
11140
12254
  }, 20);
@@ -11144,8 +12258,7 @@ function TabsListButton({
11144
12258
  Button,
11145
12259
  {
11146
12260
  variant: "secondary",
11147
- size: "sm",
11148
- className: "gap-1 bg-white px-2",
12261
+ className: "h-[34px] gap-1 rounded-lg bg-white px-2",
11149
12262
  "aria-label": "Search in tabs",
11150
12263
  children: [
11151
12264
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "text-xs text-zinc-600", children: tabs.length }),
@@ -11184,14 +12297,15 @@ var RedisBrowser = ({
11184
12297
  disableTelemetry,
11185
12298
  onFullScreenClick,
11186
12299
  theme = "light",
11187
- allowSearch = false
12300
+ allowSearch = false,
12301
+ useQueryWizard
11188
12302
  }) => {
11189
12303
  const credentials = _react.useMemo.call(void 0, () => ({ token, url }), [token, url]);
11190
12304
  const rootRef = _react.useRef.call(void 0, null);
11191
12305
  _react.useEffect.call(void 0, () => {
11192
12306
  queryClient.resetQueries();
11193
12307
  }, [credentials.url]);
11194
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactquery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RedisProvider, { redisCredentials: credentials, telemetry: !disableTelemetry, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DarkModeProvider, { theme, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserProvider, { storage, rootRef, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacttooltip.TooltipProvider, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
12308
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reactquery.QueryClientProvider, { client: queryClient, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, RedisProvider, { redisCredentials: credentials, telemetry: !disableTelemetry, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DarkModeProvider, { theme, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserProvider, { storage, rootRef, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryWizardProvider, { value: useQueryWizard, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _reacttooltip.TooltipProvider, { children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
11195
12309
  RedisBrowserRoot,
11196
12310
  {
11197
12311
  allowSearch,
@@ -11200,7 +12314,7 @@ var RedisBrowser = ({
11200
12314
  rootRef,
11201
12315
  onFullScreenClick
11202
12316
  }
11203
- ) }) }) }) }) });
12317
+ ) }) }) }) }) }) });
11204
12318
  };
11205
12319
  var RedisBrowserRoot = ({
11206
12320
  hideTabs,
@@ -11222,7 +12336,7 @@ var RedisBrowserRoot = ({
11222
12336
  className: `ups-db ${theme === "dark" ? "dark" : ""}`,
11223
12337
  style: { height: "100%" },
11224
12338
  ref: rootRef,
11225
- children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col overflow-hidden rounded-[14px] border-[4px] border-zinc-300 text-zinc-700", children: [
12339
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full flex-col rounded-[14px] border-[4px] border-zinc-300 text-zinc-700", children: [
11226
12340
  !hideTabs && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserTabs, { onFullScreenClick }),
11227
12341
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstances, { tabType, allowSearch })
11228
12342
  ] })