@upstash/react-redis-browser 0.2.14-rc.3 → 0.2.14-rc.4

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
@@ -1,5 +1,5 @@
1
1
  "use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { newObj[key] = obj[key]; } } } newObj.default = obj; return newObj; } } function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _nullishCoalesce(lhs, rhsFn) { if (lhs != null) { return lhs; } else { return rhsFn(); } } function _optionalChain(ops) { let lastAccessLHS = undefined; let value = ops[0]; let i = 1; while (i < ops.length) { const op = ops[i]; const fn = ops[i + 1]; i += 2; if ((op === 'optionalAccess' || op === 'optionalCall') && value == null) { return undefined; } if (op === 'access' || op === 'optionalAccess') { lastAccessLHS = value; value = fn(value); } else if (op === 'call' || op === 'optionalCall') { value = fn((...args) => value.call(lastAccessLHS, ...args)); lastAccessLHS = undefined; } } return value; }// src/components/databrowser/index.tsx
2
- var _react = require('react'); var React = _interopRequireWildcard(_react); var React2 = _interopRequireWildcard(_react); var React3 = _interopRequireWildcard(_react); var React4 = _interopRequireWildcard(_react); var React5 = _interopRequireWildcard(_react); var React6 = _interopRequireWildcard(_react); var React7 = _interopRequireWildcard(_react); var React8 = _interopRequireWildcard(_react); var React9 = _interopRequireWildcard(_react); var React10 = _interopRequireWildcard(_react); var React11 = _interopRequireWildcard(_react); var React12 = _interopRequireWildcard(_react); var React13 = _interopRequireWildcard(_react); var React14 = _interopRequireWildcard(_react);
2
+ var _react = require('react'); var React = _interopRequireWildcard(_react); var React2 = _interopRequireWildcard(_react); var React3 = _interopRequireWildcard(_react); var React4 = _interopRequireWildcard(_react); var React5 = _interopRequireWildcard(_react); var React6 = _interopRequireWildcard(_react); var React7 = _interopRequireWildcard(_react); var React8 = _interopRequireWildcard(_react); var React9 = _interopRequireWildcard(_react); var React10 = _interopRequireWildcard(_react); var React11 = _interopRequireWildcard(_react); var React12 = _interopRequireWildcard(_react); var React13 = _interopRequireWildcard(_react); var React14 = _interopRequireWildcard(_react); var React15 = _interopRequireWildcard(_react);
3
3
 
4
4
  // src/dark-mode-context.tsx
5
5
 
@@ -3179,30 +3179,21 @@ var Segmented = ({
3179
3179
  className,
3180
3180
  buttonClassName
3181
3181
  }) => {
3182
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3183
- "div",
3182
+ 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,
3183
+ "button",
3184
3184
  {
3185
3185
  className: cn(
3186
- "flex w-fit gap-[2px] rounded-lg bg-zinc-200 p-[2px] text-sm dark:bg-zinc-700",
3187
- className
3186
+ "h-7 rounded-md px-3 transition-all",
3187
+ value === option.key ? "bg-white text-zinc-950" : "text-zinc-700",
3188
+ buttonClassName
3188
3189
  ),
3189
- children: options.map((option) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
3190
- "button",
3191
- {
3192
- className: cn(
3193
- "h-7 rounded-md px-3 transition-all",
3194
- value === option.key ? "bg-white text-zinc-950 dark:bg-zinc-800 dark:text-zinc-100" : "text-zinc-700 dark:text-zinc-400",
3195
- buttonClassName
3196
- ),
3197
- onClick: () => {
3198
- _optionalChain([onChange, 'optionalCall', _25 => _25(option.key)]);
3199
- },
3200
- children: option.label
3201
- },
3202
- option.key
3203
- ))
3204
- }
3205
- );
3190
+ onClick: () => {
3191
+ _optionalChain([onChange, 'optionalCall', _25 => _25(option.key)]);
3192
+ },
3193
+ children: option.label
3194
+ },
3195
+ option.key
3196
+ )) });
3206
3197
  };
3207
3198
 
3208
3199
  // src/components/ui/toaster.tsx
@@ -3826,7 +3817,7 @@ var Spinner = ({
3826
3817
  ] }) : children });
3827
3818
  };
3828
3819
 
3829
- // src/components/databrowser/hooks/use-upsert-search-index-schema.tsx
3820
+ // src/components/databrowser/hooks/use-create-search-index-schema.tsx
3830
3821
 
3831
3822
 
3832
3823
  // src/components/databrowser/components/search/schema-parser.ts
@@ -4133,8 +4124,8 @@ function fieldToBuilder(value) {
4133
4124
  return builder;
4134
4125
  }
4135
4126
 
4136
- // src/components/databrowser/hooks/use-upsert-search-index-schema.tsx
4137
- var useUpsertSearchIndexSchema = () => {
4127
+ // src/components/databrowser/hooks/use-create-search-index-schema.tsx
4128
+ var useCreateSearchIndexSchema = () => {
4138
4129
  const { redisNoPipeline: redis } = useRedis();
4139
4130
  return _reactquery.useMutation.call(void 0, {
4140
4131
  meta: { hideToast: true },
@@ -4148,7 +4139,6 @@ var useUpsertSearchIndexSchema = () => {
4148
4139
  if (!indexName) throw new Error("Index name is required");
4149
4140
  const result = parseSchemaFromEditorValue(editorValue);
4150
4141
  if (!result.success) throw new Error(result.error);
4151
- await redis.search.index({ name: indexName }).drop();
4152
4142
  await redis.search.createIndex({
4153
4143
  name: indexName,
4154
4144
  dataType,
@@ -5240,6 +5230,236 @@ var DisplayHeader = ({
5240
5230
  ] });
5241
5231
  };
5242
5232
 
5233
+ // src/components/databrowser/components/search/save-schema-modal.tsx
5234
+
5235
+
5236
+ // src/components/ui/dialog.tsx
5237
+
5238
+ var _reactdialog = require('@radix-ui/react-dialog'); var DialogPrimitive = _interopRequireWildcard(_reactdialog);
5239
+
5240
+ var Dialog = DialogPrimitive.Root;
5241
+ var DialogTrigger = DialogPrimitive.Trigger;
5242
+ var DialogPortal = (props) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogPrimitive.Portal, { container: portalRoot, ...props });
5243
+ DialogPortal.displayName = DialogPrimitive.Portal.displayName;
5244
+ var DialogOverlay = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5245
+ DialogPrimitive.Overlay,
5246
+ {
5247
+ ref,
5248
+ className: cn(
5249
+ "data-[state=open]:animate-in data-[state=closed]:animate-out",
5250
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
5251
+ "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm",
5252
+ className
5253
+ ),
5254
+ ...props
5255
+ }
5256
+ ));
5257
+ DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
5258
+ var DialogContent = React11.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogPortal, { children: [
5259
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogOverlay, {}),
5260
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5261
+ DialogPrimitive.Content,
5262
+ {
5263
+ ref,
5264
+ className: cn(
5265
+ "antialiased",
5266
+ "data-[state=open]:animate-in data-[state=closed]:animate-out ",
5267
+ "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 ",
5268
+ "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 ",
5269
+ "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
5270
+ "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
5271
+ "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg ",
5272
+ "translate-x-[-50%] translate-y-[-50%] gap-4",
5273
+ "bg-white p-6 shadow-lg duration-200 ",
5274
+ "sm:rounded-lg md:w-full",
5275
+ className
5276
+ ),
5277
+ ...props,
5278
+ children: [
5279
+ children,
5280
+ /* @__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: [
5281
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5282
+ "svg",
5283
+ {
5284
+ width: "15",
5285
+ height: "15",
5286
+ viewBox: "0 0 15 15",
5287
+ fill: "none",
5288
+ xmlns: "http://www.w3.org/2000/svg",
5289
+ className: "h-4 w-4",
5290
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5291
+ "path",
5292
+ {
5293
+ 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",
5294
+ fill: "currentColor",
5295
+ fillRule: "evenodd",
5296
+ clipRule: "evenodd"
5297
+ }
5298
+ )
5299
+ }
5300
+ ),
5301
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Close" })
5302
+ ] })
5303
+ ]
5304
+ }
5305
+ )
5306
+ ] }));
5307
+ DialogContent.displayName = DialogPrimitive.Content.displayName;
5308
+ 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 });
5309
+ DialogHeader.displayName = "DialogHeader";
5310
+ var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5311
+ "div",
5312
+ {
5313
+ className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
5314
+ ...props
5315
+ }
5316
+ );
5317
+ DialogFooter.displayName = "DialogFooter";
5318
+ var DialogTitle = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5319
+ DialogPrimitive.Title,
5320
+ {
5321
+ ref,
5322
+ className: cn("text-lg font-semibold leading-none tracking-tight", className),
5323
+ ...props
5324
+ }
5325
+ ));
5326
+ DialogTitle.displayName = DialogPrimitive.Title.displayName;
5327
+ var DialogDescription = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5328
+ DialogPrimitive.Description,
5329
+ {
5330
+ ref,
5331
+ className: cn("text-sm text-zinc-500", className),
5332
+ ...props
5333
+ }
5334
+ ));
5335
+ DialogDescription.displayName = DialogPrimitive.Description.displayName;
5336
+
5337
+ // src/components/ui/progress.tsx
5338
+
5339
+ var _reactprogress = require('@radix-ui/react-progress'); var ProgressPrimitive = _interopRequireWildcard(_reactprogress);
5340
+
5341
+ var Progress = React12.forwardRef(({ className, value, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5342
+ ProgressPrimitive.Root,
5343
+ {
5344
+ ref,
5345
+ className: cn(
5346
+ "relative h-2 w-full overflow-hidden rounded-full bg-neutral-900/20 dark:bg-neutral-50/20",
5347
+ className
5348
+ ),
5349
+ ...props,
5350
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5351
+ ProgressPrimitive.Indicator,
5352
+ {
5353
+ className: "h-full w-full flex-1 bg-neutral-900 transition-all dark:bg-neutral-50",
5354
+ style: { transform: `translateX(-${100 - (value || 0)}%)` }
5355
+ }
5356
+ )
5357
+ }
5358
+ ));
5359
+ Progress.displayName = ProgressPrimitive.Root.displayName;
5360
+
5361
+ // src/components/databrowser/components/search/save-schema-modal.tsx
5362
+
5363
+ var SaveSchemaModal = ({
5364
+ values,
5365
+ onClose
5366
+ }) => {
5367
+ const { redisNoPipeline: redis } = useRedis();
5368
+ const [status, setStatus] = _react.useState.call(void 0, );
5369
+ const [progress, setProgress] = _react.useState.call(void 0, 0);
5370
+ const [error, setError] = _react.useState.call(void 0, );
5371
+ _react.useEffect.call(void 0, () => {
5372
+ if (!values) return;
5373
+ setProgress(0);
5374
+ setStatus(void 0);
5375
+ setError(void 0);
5376
+ }, [values]);
5377
+ const handleConfirm = async () => {
5378
+ if (!values) return;
5379
+ try {
5380
+ const result = parseSchemaFromEditorValue(values.editorValue);
5381
+ if (!result.success) throw new Error(result.error);
5382
+ setStatus("Saving index...");
5383
+ setProgress(33);
5384
+ await redis.search.index({ name: values.indexName }).drop();
5385
+ try {
5386
+ await redis.search.createIndex({
5387
+ name: values.indexName,
5388
+ dataType: values.dataType,
5389
+ prefix: values.prefixes.split(",").map((p) => p.trim()).filter(Boolean),
5390
+ language: values.language,
5391
+ schema: result.schema
5392
+ });
5393
+ } catch (txError) {
5394
+ const err = txError instanceof Error ? txError : new Error(String(txError));
5395
+ throw new Error(
5396
+ `Your index was deleted, but there was an error when trying to re-create it: ${formatUpstashErrorMessage(err)}`
5397
+ );
5398
+ }
5399
+ setStatus("Waiting for indexing...");
5400
+ setProgress(66);
5401
+ await redis.search.index({ name: values.indexName }).waitIndexing();
5402
+ setStatus("Done");
5403
+ setProgress(100);
5404
+ await new Promise((resolve) => setTimeout(resolve, 500));
5405
+ queryClient.invalidateQueries({
5406
+ queryKey: [FETCH_SEARCH_INDEX_QUERY_KEY, values.indexName]
5407
+ });
5408
+ queryClient.invalidateQueries({
5409
+ queryKey: [FETCH_SEARCH_INDEXES_QUERY_KEY]
5410
+ });
5411
+ onClose();
5412
+ } catch (catchedError) {
5413
+ setError(catchedError instanceof Error ? catchedError : new Error(String(catchedError)));
5414
+ setStatus(void 0);
5415
+ }
5416
+ };
5417
+ const isRunning = status !== void 0;
5418
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5419
+ Dialog,
5420
+ {
5421
+ open: values !== void 0,
5422
+ onOpenChange: (open) => {
5423
+ if (!open && !isRunning) onClose();
5424
+ },
5425
+ children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5426
+ DialogContent,
5427
+ {
5428
+ onInteractOutside: (e) => {
5429
+ if (isRunning) e.preventDefault();
5430
+ },
5431
+ onEscapeKeyDown: (e) => {
5432
+ if (isRunning) e.preventDefault();
5433
+ },
5434
+ children: [
5435
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogHeader, { children: [
5436
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogTitle, { children: "Save Schema Changes" }),
5437
+ !isRunning && !error && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogDescription, { children: [
5438
+ "Saving will drop and recreate the index. This will temporarily make the index unavailable.",
5439
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
5440
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "br", {}),
5441
+ "Are you sure you want to continue?"
5442
+ ] })
5443
+ ] }),
5444
+ isRunning && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex flex-col gap-2 py-4", children: [
5445
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-sm text-zinc-500", children: status }),
5446
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Progress, { value: progress })
5447
+ ] }),
5448
+ error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full break-words text-sm text-red-500", children: formatUpstashErrorMessage(error) }),
5449
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogFooter, { children: [
5450
+ !isRunning && !error && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
5451
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { onClick: onClose, children: "Cancel" }),
5452
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", onClick: handleConfirm, children: "Confirm" })
5453
+ ] }),
5454
+ error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { onClick: onClose, children: "Close" })
5455
+ ] })
5456
+ ]
5457
+ }
5458
+ )
5459
+ }
5460
+ );
5461
+ };
5462
+
5243
5463
  // src/components/databrowser/components/search/schema-editor.tsx
5244
5464
 
5245
5465
 
@@ -5625,10 +5845,11 @@ var SearchDisplay = ({
5625
5845
  });
5626
5846
  const currentIndexName = watch("indexName");
5627
5847
  const effectiveIndexName = isCreateModal ? currentIndexName : _nullishCoalesce(indexName, () => ( ""));
5848
+ const [pendingFormValues, setPendingFormValues] = _react.useState.call(void 0, );
5628
5849
  const { data, isLoading } = useFetchSearchIndex(indexName, {
5629
5850
  enabled: !isCreateModal
5630
5851
  });
5631
- const updateSchema = useUpsertSearchIndexSchema();
5852
+ const createSchema = useCreateSearchIndexSchema();
5632
5853
  _react.useEffect.call(void 0, () => {
5633
5854
  if (!data) return;
5634
5855
  reset({
@@ -5640,21 +5861,25 @@ var SearchDisplay = ({
5640
5861
  });
5641
5862
  }, [data, reset, indexName]);
5642
5863
  const onSubmit = (values) => {
5643
- updateSchema.mutate(
5644
- {
5645
- ...values,
5646
- indexName: isCreateModal ? values.indexName : indexName
5647
- },
5648
- {
5649
- onSuccess: () => {
5650
- reset();
5651
- if ((isCreateModal || isEditModal) && onClose) onClose();
5864
+ if (isCreateModal) {
5865
+ createSchema.mutate(
5866
+ {
5867
+ ...values,
5868
+ indexName: values.indexName
5869
+ },
5870
+ {
5871
+ onSuccess: () => {
5872
+ reset();
5873
+ if (onClose) onClose();
5874
+ }
5652
5875
  }
5653
- }
5654
- );
5876
+ );
5877
+ } else {
5878
+ setPendingFormValues({ ...values, indexName });
5879
+ }
5655
5880
  };
5656
5881
  const handleCancel = () => {
5657
- updateSchema.reset();
5882
+ createSchema.reset();
5658
5883
  reset();
5659
5884
  };
5660
5885
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex h-full w-full min-w-0 flex-col gap-2", children: [
@@ -5672,11 +5897,11 @@ var SearchDisplay = ({
5672
5897
  ),
5673
5898
  errors.indexName && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "text-xs text-red-500", children: errors.indexName.message })
5674
5899
  ] }),
5675
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-md border border-zinc-300 bg-white p-3 dark:border-zinc-700 dark:bg-zinc-800", children: [
5676
- /* @__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 dark:text-zinc-300", children: "Config" }) }),
5900
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "rounded-md border border-zinc-300 bg-white p-3", children: [
5901
+ /* @__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" }) }),
5677
5902
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "mt-2 grid grid-cols-4 gap-4 text-sm", children: [
5678
5903
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
5679
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mb-1.5 block text-xs font-medium text-zinc-500 dark:text-zinc-400", children: "Data Type" }),
5904
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mb-1.5 block text-xs font-medium text-zinc-500", children: "Data Type" }),
5680
5905
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5681
5906
  _reacthookform.Controller,
5682
5907
  {
@@ -5690,7 +5915,7 @@ var SearchDisplay = ({
5690
5915
  )
5691
5916
  ] }),
5692
5917
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
5693
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mb-1.5 block text-xs font-medium text-zinc-500 dark:text-zinc-400", children: "Language" }),
5918
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mb-1.5 block text-xs font-medium text-zinc-500", children: "Language" }),
5694
5919
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5695
5920
  _reacthookform.Controller,
5696
5921
  {
@@ -5704,7 +5929,7 @@ var SearchDisplay = ({
5704
5929
  )
5705
5930
  ] }),
5706
5931
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "col-span-2", children: [
5707
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mb-1.5 block text-xs font-medium text-zinc-500 dark:text-zinc-400", children: "Prefixes" }),
5932
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "mb-1.5 block text-xs font-medium text-zinc-500", children: "Prefixes" }),
5708
5933
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5709
5934
  Input,
5710
5935
  {
@@ -5717,8 +5942,8 @@ var SearchDisplay = ({
5717
5942
  ] })
5718
5943
  ] })
5719
5944
  ] }),
5720
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex min-h-0 flex-1 flex-col rounded-md border border-zinc-300 bg-white dark:border-zinc-700 dark:bg-zinc-800", children: [
5721
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "flex items-center justify-between border-b border-zinc-200 px-3 py-2 dark:border-zinc-700", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "h3", { className: "text-sm font-medium text-zinc-700 dark:text-zinc-300", children: "Schema" }) }),
5945
+ /* @__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: [
5946
+ /* @__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" }) }),
5722
5947
  /* @__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,
5723
5948
  _reacthookform.Controller,
5724
5949
  {
@@ -5735,7 +5960,7 @@ var SearchDisplay = ({
5735
5960
  }
5736
5961
  ) }) })
5737
5962
  ] }),
5738
- updateSchema.error && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "w-full break-words text-xs text-red-500", children: updateSchema.error.message.startsWith("ERR syntax error") ? "Invalid schema" : formatUpstashErrorMessage(updateSchema.error) }),
5963
+ 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) }),
5739
5964
  /* @__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: [
5740
5965
  (isDirty || isCreateModal || isEditModal) && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5741
5966
  Button,
@@ -5750,8 +5975,19 @@ var SearchDisplay = ({
5750
5975
  children: "Cancel"
5751
5976
  }
5752
5977
  ),
5753
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", onClick: handleSubmit(onSubmit), children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: updateSchema.isPending, isLoadingText: "Saving", children: isCreateModal ? "Create" : "Save" }) })
5754
- ] }) })
5978
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Button, { variant: "primary", onClick: handleSubmit(onSubmit), disabled: !isDirty, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Spinner, { isLoading: createSchema.isPending, isLoadingText: "Saving", children: isCreateModal ? "Create" : "Save..." }) })
5979
+ ] }) }),
5980
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5981
+ SaveSchemaModal,
5982
+ {
5983
+ values: pendingFormValues,
5984
+ onClose: () => {
5985
+ setPendingFormValues(void 0);
5986
+ reset();
5987
+ if (isEditModal && onClose) onClose();
5988
+ }
5989
+ }
5990
+ )
5755
5991
  ] }) })
5756
5992
  ] });
5757
5993
  };
@@ -5788,8 +6024,16 @@ var LANGUAGES = [
5788
6024
 
5789
6025
  var _reactscrollarea = require('@radix-ui/react-scroll-area'); var ScrollAreaPrimitive = _interopRequireWildcard(_reactscrollarea);
5790
6026
 
5791
- var ScrollArea = React11.forwardRef(
5792
- ({ className, scrollBarClassName, children, onScroll, disableRoundedInherit = false, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6027
+ var ScrollArea = React13.forwardRef(
6028
+ ({
6029
+ className,
6030
+ scrollBarClassName,
6031
+ scrollBarForceMount,
6032
+ children,
6033
+ onScroll,
6034
+ disableRoundedInherit = false,
6035
+ ...props
6036
+ }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5793
6037
  ScrollAreaPrimitive.Root,
5794
6038
  {
5795
6039
  ref,
@@ -5807,14 +6051,14 @@ var ScrollArea = React11.forwardRef(
5807
6051
  children
5808
6052
  }
5809
6053
  ),
5810
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, { className: scrollBarClassName }),
6054
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollBar, { className: scrollBarClassName, forceMount: scrollBarForceMount }),
5811
6055
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ScrollAreaPrimitive.Corner, {})
5812
6056
  ]
5813
6057
  }
5814
6058
  )
5815
6059
  );
5816
6060
  ScrollArea.displayName = ScrollAreaPrimitive.Root.displayName;
5817
- var ScrollBar = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6061
+ var ScrollBar = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5818
6062
  ScrollAreaPrimitive.ScrollAreaScrollbar,
5819
6063
  {
5820
6064
  ref,
@@ -5824,7 +6068,7 @@ var ScrollBar = React11.forwardRef(({ className, ...props }, ref) => /* @__PURE_
5824
6068
  children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5825
6069
  ScrollAreaPrimitive.ScrollAreaThumb,
5826
6070
  {
5827
- className: cn("relative flex-1 rounded-full bg-zinc-200/70")
6071
+ className: cn("relative flex-1 rounded-full bg-zinc-400/70")
5828
6072
  }
5829
6073
  )
5830
6074
  }
@@ -5892,7 +6136,7 @@ var _reactcontextmenu = require('@radix-ui/react-context-menu'); var ContextMenu
5892
6136
 
5893
6137
  var ContextMenu = ContextMenuPrimitive.Root;
5894
6138
  var ContextMenuTrigger = ContextMenuPrimitive.Trigger;
5895
- var ContextMenuSubTrigger = React12.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6139
+ var ContextMenuSubTrigger = React14.forwardRef(({ className, inset, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5896
6140
  ContextMenuPrimitive.SubTrigger,
5897
6141
  {
5898
6142
  ref,
@@ -5909,7 +6153,7 @@ var ContextMenuSubTrigger = React12.forwardRef(({ className, inset, children, ..
5909
6153
  }
5910
6154
  ));
5911
6155
  ContextMenuSubTrigger.displayName = ContextMenuPrimitive.SubTrigger.displayName;
5912
- var ContextMenuSubContent = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6156
+ var ContextMenuSubContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5913
6157
  ContextMenuPrimitive.SubContent,
5914
6158
  {
5915
6159
  ref,
@@ -5921,7 +6165,7 @@ var ContextMenuSubContent = React12.forwardRef(({ className, ...props }, ref) =>
5921
6165
  }
5922
6166
  ));
5923
6167
  ContextMenuSubContent.displayName = ContextMenuPrimitive.SubContent.displayName;
5924
- var ContextMenuContent = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6168
+ var ContextMenuContent = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, ContextMenuPrimitive.Portal, { container: portalRoot, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5925
6169
  ContextMenuPrimitive.Content,
5926
6170
  {
5927
6171
  ref,
@@ -5933,7 +6177,7 @@ var ContextMenuContent = React12.forwardRef(({ className, ...props }, ref) => /*
5933
6177
  }
5934
6178
  ) }));
5935
6179
  ContextMenuContent.displayName = ContextMenuPrimitive.Content.displayName;
5936
- var ContextMenuItem = React12.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6180
+ var ContextMenuItem = React14.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5937
6181
  ContextMenuPrimitive.Item,
5938
6182
  {
5939
6183
  ref,
@@ -5946,7 +6190,7 @@ var ContextMenuItem = React12.forwardRef(({ className, inset, ...props }, ref) =
5946
6190
  }
5947
6191
  ));
5948
6192
  ContextMenuItem.displayName = ContextMenuPrimitive.Item.displayName;
5949
- var ContextMenuCheckboxItem = React12.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6193
+ var ContextMenuCheckboxItem = React14.forwardRef(({ className, children, checked, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5950
6194
  ContextMenuPrimitive.CheckboxItem,
5951
6195
  {
5952
6196
  ref,
@@ -5963,7 +6207,7 @@ var ContextMenuCheckboxItem = React12.forwardRef(({ className, children, checked
5963
6207
  }
5964
6208
  ));
5965
6209
  ContextMenuCheckboxItem.displayName = ContextMenuPrimitive.CheckboxItem.displayName;
5966
- var ContextMenuRadioItem = React12.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6210
+ var ContextMenuRadioItem = React14.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
5967
6211
  ContextMenuPrimitive.RadioItem,
5968
6212
  {
5969
6213
  ref,
@@ -5979,7 +6223,7 @@ var ContextMenuRadioItem = React12.forwardRef(({ className, children, ...props }
5979
6223
  }
5980
6224
  ));
5981
6225
  ContextMenuRadioItem.displayName = ContextMenuPrimitive.RadioItem.displayName;
5982
- var ContextMenuLabel = React12.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6226
+ var ContextMenuLabel = React14.forwardRef(({ className, inset, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5983
6227
  ContextMenuPrimitive.Label,
5984
6228
  {
5985
6229
  ref,
@@ -5988,7 +6232,7 @@ var ContextMenuLabel = React12.forwardRef(({ className, inset, ...props }, ref)
5988
6232
  }
5989
6233
  ));
5990
6234
  ContextMenuLabel.displayName = ContextMenuPrimitive.Label.displayName;
5991
- var ContextMenuSeparator = React12.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6235
+ var ContextMenuSeparator = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
5992
6236
  ContextMenuPrimitive.Separator,
5993
6237
  {
5994
6238
  ref,
@@ -6809,112 +7053,9 @@ var ReloadButton = ({
6809
7053
 
6810
7054
  // src/components/databrowser/components/add-key-modal.tsx
6811
7055
 
6812
- var _reactdialog = require('@radix-ui/react-dialog'); var DialogPrimitive = _interopRequireWildcard(_reactdialog);
6813
-
6814
7056
 
6815
7057
 
6816
- // src/components/ui/dialog.tsx
6817
-
6818
-
6819
-
6820
- var Dialog = DialogPrimitive.Root;
6821
- var DialogTrigger = DialogPrimitive.Trigger;
6822
- var DialogPortal = (props) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogPrimitive.Portal, { container: portalRoot, ...props });
6823
- DialogPortal.displayName = DialogPrimitive.Portal.displayName;
6824
- var DialogOverlay = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6825
- DialogPrimitive.Overlay,
6826
- {
6827
- ref,
6828
- className: cn(
6829
- "data-[state=open]:animate-in data-[state=closed]:animate-out",
6830
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
6831
- "fixed inset-0 z-50 bg-black/50 backdrop-blur-sm",
6832
- className
6833
- ),
6834
- ...props
6835
- }
6836
- ));
6837
- DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
6838
- var DialogContent = React13.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, DialogPortal, { children: [
6839
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DialogOverlay, {}),
6840
- /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
6841
- DialogPrimitive.Content,
6842
- {
6843
- ref,
6844
- className: cn(
6845
- "antialiased",
6846
- "data-[state=open]:animate-in data-[state=closed]:animate-out ",
6847
- "data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 ",
6848
- "data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 ",
6849
- "data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
6850
- "data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
6851
- "fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg ",
6852
- "translate-x-[-50%] translate-y-[-50%] gap-4",
6853
- "bg-white p-6 shadow-lg duration-200 ",
6854
- "sm:rounded-lg md:w-full",
6855
- className
6856
- ),
6857
- ...props,
6858
- children: [
6859
- children,
6860
- /* @__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: [
6861
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6862
- "svg",
6863
- {
6864
- width: "15",
6865
- height: "15",
6866
- viewBox: "0 0 15 15",
6867
- fill: "none",
6868
- xmlns: "http://www.w3.org/2000/svg",
6869
- className: "h-4 w-4",
6870
- children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6871
- "path",
6872
- {
6873
- 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",
6874
- fill: "currentColor",
6875
- fillRule: "evenodd",
6876
- clipRule: "evenodd"
6877
- }
6878
- )
6879
- }
6880
- ),
6881
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "sr-only", children: "Close" })
6882
- ] })
6883
- ]
6884
- }
6885
- )
6886
- ] }));
6887
- DialogContent.displayName = DialogPrimitive.Content.displayName;
6888
- 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 });
6889
- DialogHeader.displayName = "DialogHeader";
6890
- var DialogFooter = ({ className, ...props }) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6891
- "div",
6892
- {
6893
- className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className),
6894
- ...props
6895
- }
6896
- );
6897
- DialogFooter.displayName = "DialogFooter";
6898
- var DialogTitle = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6899
- DialogPrimitive.Title,
6900
- {
6901
- ref,
6902
- className: cn("text-lg font-semibold leading-none tracking-tight", className),
6903
- ...props
6904
- }
6905
- ));
6906
- DialogTitle.displayName = DialogPrimitive.Title.displayName;
6907
- var DialogDescription = React13.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
6908
- DialogPrimitive.Description,
6909
- {
6910
- ref,
6911
- className: cn("text-sm text-zinc-500", className),
6912
- ...props
6913
- }
6914
- ));
6915
- DialogDescription.displayName = DialogPrimitive.Description.displayName;
6916
7058
 
6917
- // src/components/databrowser/components/add-key-modal.tsx
6918
7059
 
6919
7060
  function AddKeyModal() {
6920
7061
  const { setSelectedKey } = useTab();
@@ -7190,11 +7331,11 @@ function DataTypeSelector() {
7190
7331
 
7191
7332
  // src/components/databrowser/components/header/index.tsx
7192
7333
 
7193
- var Header = () => {
7334
+ var Header = ({ hideSearchTab = false }) => {
7194
7335
  const { isValuesSearchSelected, setIsValuesSearchSelected } = useTab();
7195
7336
  return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center justify-between gap-1.5", children: [
7196
7337
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex grow items-center gap-1.5", children: [
7197
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7338
+ !hideSearchTab && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7198
7339
  Segmented,
7199
7340
  {
7200
7341
  options: [
@@ -7388,175 +7529,371 @@ var HeaderError = () => {
7388
7529
  // src/components/databrowser/components/search/query-editor.tsx
7389
7530
 
7390
7531
 
7391
- // src/components/databrowser/components/search/generate-query-type-definitions.tsx
7392
- var generateTypeDefinitions = (schema) => {
7393
- let schemaFieldsInterface = "";
7394
- const schemaFields = _optionalChain([schema, 'optionalAccess', _89 => _89.schema]);
7395
- if (schemaFields && Object.keys(schemaFields).length > 0) {
7396
- const fieldLines = Object.entries(schemaFields).map(([fieldName, fieldDef]) => {
7397
- const fieldType = fieldDef.type;
7398
- let operationType;
7399
- switch (fieldType) {
7400
- case "TEXT": {
7401
- operationType = "StringOperations";
7402
- break;
7403
- }
7404
- case "U64":
7405
- case "I64":
7406
- case "F64": {
7407
- operationType = "NumberOperations";
7408
- break;
7409
- }
7410
- case "BOOL": {
7411
- operationType = "BooleanOperations";
7412
- break;
7413
- }
7414
- case "DATE": {
7415
- operationType = "DateOperations";
7416
- break;
7417
- }
7418
- default: {
7419
- operationType = "StringOperations";
7420
- }
7532
+ // src/components/databrowser/components/search/search-types-file.ts
7533
+ var SEARCH_TYPES = `
7534
+
7535
+ export const FIELD_TYPES = ["TEXT", "U64", "I64", "F64", "BOOL", "DATE"] as const;
7536
+ export type FieldType = (typeof FIELD_TYPES)[number];
7537
+
7538
+ export type TextField = {
7539
+ type: "TEXT";
7540
+ noTokenize?: boolean;
7541
+ noStem?: boolean;
7542
+ from?: string;
7543
+ };
7544
+
7545
+ export type NumericField = {
7546
+ type: "U64" | "I64" | "F64";
7547
+ fast: true;
7548
+ from?: string;
7549
+ };
7550
+
7551
+ export type BoolField = {
7552
+ type: "BOOL";
7553
+ fast?: boolean;
7554
+ from?: string;
7555
+ };
7556
+
7557
+ export type DateField = {
7558
+ type: "DATE";
7559
+ fast?: boolean;
7560
+ from?: string;
7561
+ };
7562
+
7563
+ export type DetailedField = TextField | NumericField | BoolField | DateField;
7564
+ export type NestedIndexSchema = {
7565
+ [key: string]: FieldType | DetailedField | NestedIndexSchema;
7566
+ };
7567
+
7568
+ export type FlatIndexSchema = {
7569
+ [key: string]: FieldType | DetailedField;
7570
+ };
7571
+
7572
+ export type SchemaPaths<T, Prefix extends string = ""> = {
7573
+ [K in keyof T]: K extends string
7574
+ ? T[K] extends FieldType | DetailedField
7575
+ ? Prefix extends ""
7576
+ ? K
7577
+ : \`\${Prefix}\${K}\`
7578
+ : T[K] extends object
7579
+ ? SchemaPaths<T[K], \`\${Prefix}\${K}.\`>
7580
+ : never
7581
+ : never;
7582
+ }[keyof T];
7583
+
7584
+ export type ExtractFieldType<T> = T extends FieldType
7585
+ ? T
7586
+ : T extends { type: infer U }
7587
+ ? U extends FieldType
7588
+ ? U
7589
+ : never
7590
+ : never;
7591
+
7592
+ export type GetFieldAtPath<
7593
+ TSchema,
7594
+ Path extends string,
7595
+ > = Path extends \`\${infer First}.\${infer Rest}\`
7596
+ ? First extends keyof TSchema
7597
+ ? GetFieldAtPath<TSchema[First], Rest>
7598
+ : never
7599
+ : Path extends keyof TSchema
7600
+ ? TSchema[Path]
7601
+ : never;
7602
+
7603
+ type FieldValueType<T extends FieldType> = T extends "TEXT"
7604
+ ? string
7605
+ : T extends "U64" | "I64" | "F64"
7606
+ ? number
7607
+ : T extends "BOOL"
7608
+ ? boolean
7609
+ : T extends "DATE"
7610
+ ? string
7611
+ : never;
7612
+
7613
+ type GetFieldValueType<TSchema, Path extends string> =
7614
+ GetFieldAtPath<TSchema, Path> extends infer Field
7615
+ ? Field extends FieldType | DetailedField
7616
+ ? FieldValueType<ExtractFieldType<Field>>
7617
+ : never
7618
+ : never;
7619
+
7620
+ // Helper type to check if a field has a 'from' property
7621
+ type HasFrom<T> = T extends { from: string } ? true : false;
7622
+
7623
+ // Distributes field inference across unions so that
7624
+ // InferSchemaData<NestedIndexSchema | FlatIndexSchema> does not collapse to never
7625
+ type InferSchemaDataField<T> = T extends FieldType
7626
+ ? FieldValueType<T>
7627
+ : T extends DetailedField
7628
+ ? FieldValueType<ExtractFieldType<T>>
7629
+ : T extends NestedIndexSchema
7630
+ ? InferSchemaData<T>
7631
+ : unknown;
7632
+
7633
+ type IsDefaultSchema<T> = [T] extends [NestedIndexSchema | FlatIndexSchema]
7634
+ ? [NestedIndexSchema | FlatIndexSchema] extends [T]
7635
+ ? true
7636
+ : false
7637
+ : false;
7638
+
7639
+ type AsAnyIfUnknown<T> = unknown extends T ? any : T;
7640
+
7641
+ export type InferSchemaData<TSchema> =
7642
+ IsDefaultSchema<TSchema> extends true
7643
+ ? any
7644
+ : {
7645
+ [K in keyof TSchema as TSchema[K] extends DetailedField
7646
+ ? HasFrom<TSchema[K]> extends true
7647
+ ? never
7648
+ : K
7649
+ : K]: AsAnyIfUnknown<InferSchemaDataField<TSchema[K]>>;
7650
+ };
7651
+
7652
+ // Query Options Types
7653
+ // These are the options that can be used for the query command
7654
+ export type QueryOptions<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
7655
+ filter?: RootQueryFilter<TSchema>;
7656
+ /** Maximum number of results to return */
7657
+ limit?: number;
7658
+ /** Number of results to skip */
7659
+ offset?: number;
7660
+ select?: Partial<{ [K in SchemaPaths<TSchema>]: true }>; // {}
7661
+ highlight?: {
7662
+ fields: SchemaPaths<TSchema>[];
7663
+ preTag?: string;
7664
+ postTag?: string;
7665
+ };
7666
+ } & QueryOrderOption<TSchema>;
7667
+
7668
+ type CombineMode = "multiply" | "sum";
7669
+ type ScoreMode = "multiply" | "sum" | "replace";
7670
+ type ScoreModifier =
7671
+ | "none"
7672
+ | "log"
7673
+ | "log1p"
7674
+ | "log2p"
7675
+ | "ln"
7676
+ | "ln1p"
7677
+ | "ln2p"
7678
+ | "square"
7679
+ | "sqrt"
7680
+ | "reciprocal";
7681
+
7682
+ export type ScoreBy<TSchemaPaths extends string> =
7683
+ | ScoreByField<false, TSchemaPaths>
7684
+ | {
7685
+ fields: ScoreByField<true, TSchemaPaths>[];
7686
+ combineMode?: CombineMode;
7687
+ scoreMode?: ScoreMode;
7688
+ };
7689
+
7690
+ type ScoreByField<TMultiple extends boolean, TSchemaPaths extends string> =
7691
+ | {
7692
+ field: TSchemaPaths;
7693
+ modifier?: ScoreModifier;
7694
+ factor?: number;
7695
+ missing?: number;
7696
+ scoreMode?: TMultiple extends true ? never : ScoreMode;
7697
+ }
7698
+ | TSchemaPaths;
7699
+
7700
+ type QueryOrderOption<TSchema extends NestedIndexSchema | FlatIndexSchema> =
7701
+ | {
7702
+ orderBy?: {
7703
+ [K in SchemaPaths<TSchema>]: { [P in K]: "ASC" | "DESC" };
7704
+ }[SchemaPaths<TSchema>];
7705
+ }
7706
+ | {
7707
+ scoreFunc?: ScoreBy<SchemaPaths<TSchema>>;
7708
+ };
7709
+
7710
+ /**
7711
+ * Converts dot notation paths to nested object structure type
7712
+ * e.g. "content.title" | "content.author" becomes { content: { title: ..., author: ... } }
7713
+ */
7714
+ type PathToNestedObject<
7715
+ TSchema,
7716
+ Path extends string,
7717
+ Value,
7718
+ > = Path extends \`\${ infer First }.\${ infer Rest }\`
7719
+ ? { [K in First]: PathToNestedObject<TSchema, Rest, Value> }
7720
+ : { [K in Path]: Value };
7721
+
7722
+ /**
7723
+ * Merges intersection of objects into a single object type with proper nesting
7724
+ */
7725
+ type DeepMerge<T> = T extends object
7726
+ ? {
7727
+ [K in keyof T]: T[K] extends object ? DeepMerge<T[K]> : T[K];
7728
+ }
7729
+ : T;
7730
+
7731
+ /**
7732
+ * Build nested result type from selected paths
7733
+ */
7734
+ type BuildNestedResult<TSchema, TFields> =
7735
+ IsDefaultSchema<TSchema> extends true
7736
+ ? DeepMerge<
7737
+ UnionToIntersection<
7738
+ {
7739
+ [Path in keyof TFields & string]: PathToNestedObject<any, Path, any>;
7740
+ }[keyof TFields & string]
7741
+ >
7742
+ >
7743
+ : DeepMerge<
7744
+ UnionToIntersection<
7745
+ {
7746
+ [Path in keyof TFields & SchemaPaths<TSchema>]: PathToNestedObject<
7747
+ TSchema,
7748
+ Path & string,
7749
+ AsAnyIfUnknown<GetFieldValueType<TSchema, Path & string>>
7750
+ >;
7751
+ }[keyof TFields & SchemaPaths<TSchema>]
7752
+ >
7753
+ >;
7754
+
7755
+ type UnionToIntersection<U> = (U extends unknown ? (k: U) => void : never) extends (
7756
+ k: infer I
7757
+ ) => void
7758
+ ? I
7759
+ : never;
7760
+
7761
+ export type QueryResult<
7762
+ TSchema extends NestedIndexSchema | FlatIndexSchema,
7763
+ TOptions extends QueryOptions<TSchema> | undefined = undefined,
7764
+ > = TOptions extends { select: infer TFields }
7765
+ ? // eslint-disable-next-line @typescript-eslint/no-empty-object-type
7766
+ {} extends TFields
7767
+ ? { key: string; score: number }
7768
+ : {
7769
+ key: string;
7770
+ score: number;
7771
+ data: BuildNestedResult<TSchema, TFields>;
7421
7772
  }
7422
- const escapedFieldName = fieldName.includes(".") ? `"${fieldName}"` : fieldName;
7423
- return ` ${escapedFieldName}?: ${operationType};`;
7424
- }).join("\n");
7425
- schemaFieldsInterface = `
7426
- /** Schema fields for the current index */
7427
- interface SchemaFields {
7428
- ${fieldLines}
7429
- }`;
7430
- } else {
7431
- schemaFieldsInterface = `
7432
- /** Schema fields - no schema available, using dynamic fields */
7433
- interface SchemaFields {
7434
- [fieldName: string]: StringOperations | NumberOperations | BooleanOperations | DateOperations;
7435
- }`;
7436
- }
7437
- return `
7438
- // String operations for TEXT fields
7439
- type StringOperationMap = {
7440
- /** Exact match */
7441
- $eq: string;
7442
- /** Not equal */
7443
- $ne: string;
7444
- /** Match any value in array */
7445
- $in: string[];
7446
- /** Fuzzy match with optional distance */
7447
- $fuzzy: string | { value: string; distance?: number; transpositionCostOne?: boolean };
7448
- /** Phrase match with optional slop or prefix */
7449
- $phrase: string | { value: string } | { value: string; slop: number; prefix?: never } | { value: string; prefix: boolean; slop?: never };
7450
- /** Regular expression match */
7451
- $regex: string;
7452
- };
7453
-
7454
- // Number operations for U64, I64, F64 fields
7455
- type NumberOperationMap = {
7456
- /** Exact match */
7457
- $eq: number;
7458
- /** Not equal */
7459
- $ne: number;
7460
- /** Match any value in array */
7461
- $in: number[];
7462
- /** Greater than */
7463
- $gt: number;
7464
- /** Greater than or equal */
7465
- $gte: number;
7466
- /** Less than */
7467
- $lt: number;
7468
- /** Less than or equal */
7469
- $lte: number;
7470
- };
7471
-
7472
- // Boolean operations for BOOL fields
7473
- type BooleanOperationMap = {
7474
- /** Exact match */
7475
- $eq: boolean;
7476
- /** Not equal */
7477
- $ne: boolean;
7478
- /** Match any value in array */
7479
- $in: boolean[];
7480
- };
7481
-
7482
- // Date operations for DATE fields
7483
- type DateOperationMap = {
7484
- /** Exact match */
7485
- $eq: string | Date;
7486
- /** Not equal */
7487
- $ne: string | Date;
7488
- /** Match any value in array */
7489
- $in: (string | Date)[];
7490
- /** Greater than */
7491
- $gt: string | Date;
7492
- /** Greater than or equal */
7493
- $gte: string | Date;
7494
- /** Less than */
7495
- $lt: string | Date;
7496
- /** Less than or equal */
7497
- $lte: string | Date;
7498
- };
7499
-
7500
- // String field operations with optional boost
7501
- type StringOperations =
7502
- | { $eq: string; $boost?: number }
7503
- | { $ne: string; $boost?: number }
7504
- | { $in: string[]; $boost?: number }
7505
- | { $fuzzy: string | { value: string; distance?: number; transpositionCostOne?: boolean }; $boost?: number }
7506
- | { $phrase: string | { value: string } | { value: string; slop: number; prefix?: never } | { value: string; prefix: boolean; slop?: never }; $boost?: number }
7507
- | { $regex: string; $boost?: number }
7508
- | string;
7509
-
7510
- // Number field operations with optional boost
7511
- type NumberOperations =
7512
- | { $eq: number; $boost?: number }
7513
- | { $ne: number; $boost?: number }
7514
- | { $in: number[]; $boost?: number }
7515
- | { $gt: number; $boost?: number }
7516
- | { $gte: number; $boost?: number }
7517
- | { $lt: number; $boost?: number }
7518
- | { $lte: number; $boost?: number }
7519
- | number;
7520
-
7521
- // Boolean field operations with optional boost
7522
- type BooleanOperations =
7523
- | { $eq: boolean; $boost?: number }
7524
- | { $ne: boolean; $boost?: number }
7525
- | { $in: boolean[]; $boost?: number }
7526
- | boolean;
7527
-
7528
- // Date field operations with optional boost
7529
- type DateOperations =
7530
- | { $eq: string | Date; $boost?: number }
7531
- | { $ne: string | Date; $boost?: number }
7532
- | { $in: (string | Date)[]; $boost?: number }
7533
- | { $gt: string | Date; $boost?: number }
7534
- | { $gte: string | Date; $boost?: number }
7535
- | { $lt: string | Date; $boost?: number }
7536
- | { $lte: string | Date; $boost?: number }
7537
- | string
7538
- | Date;
7773
+ : {
7774
+ key: string;
7775
+ score: number;
7776
+ data: InferSchemaData<TSchema>;
7777
+ };
7539
7778
 
7540
- ${schemaFieldsInterface}
7779
+ export type PublicQueryResult<
7780
+ TSchema extends NestedIndexSchema | FlatIndexSchema,
7781
+ TSelectFields extends SchemaPaths<TSchema>[] | undefined = undefined,
7782
+ > = QueryResult<
7783
+ TSchema,
7784
+ TSelectFields extends SchemaPaths<TSchema>[]
7785
+ ? {
7786
+ select: { [K in TSelectFields[number]]: true };
7787
+ }
7788
+ : undefined
7789
+ >;
7790
+
7791
+ // Query Filter Types
7792
+ // These are the operations that can be used for each field type
7793
+ type StringOperationMap<T extends string> = {
7794
+ $eq: T;
7795
+ $ne: T;
7796
+ $in: T[];
7797
+ $fuzzy: T | { value: T; distance?: number; transpositionCostOne?: boolean };
7798
+ $phrase:
7799
+ | T
7800
+ | { value: T }
7801
+ | { value: T; slop: number; prefix?: never }
7802
+ | { value: T; prefix: boolean; slop?: never };
7803
+ $regex: T;
7804
+ $smart: T;
7805
+ };
7806
+
7807
+ type NumberOperationMap<T extends number> = {
7808
+ $eq: T;
7809
+ $ne: T;
7810
+ $in: T[];
7811
+ $gt: T;
7812
+ $gte: T;
7813
+ $lt: T;
7814
+ $lte: T;
7815
+ };
7816
+
7817
+ type BooleanOperationMap<T extends boolean> = {
7818
+ $eq: T;
7819
+ $ne: T;
7820
+ $in: T[];
7821
+ };
7822
+
7823
+ type DateOperationMap<T extends string | Date> = {
7824
+ $eq: T;
7825
+ $ne: T;
7826
+ $in: T[];
7827
+ $gt: T;
7828
+ $gte: T;
7829
+ $lte: T;
7830
+ $lt: T;
7831
+ };
7832
+
7833
+ // Create union types for each field type
7834
+ type StringOperations = {
7835
+ [K in keyof StringOperationMap<string>]: { [P in K]: StringOperationMap<string>[K] } & {
7836
+ $boost?: number;
7837
+ };
7838
+ }[keyof StringOperationMap<string>];
7541
7839
 
7542
- // Query leaf - field conditions without logical operators
7543
- type QueryLeaf = SchemaFields & {
7840
+ type NumberOperations = {
7841
+ [K in keyof NumberOperationMap<number>]: { [P in K]: NumberOperationMap<number>[K] } & {
7842
+ $boost?: number;
7843
+ };
7844
+ }[keyof NumberOperationMap<number>];
7845
+
7846
+ type BooleanOperations = {
7847
+ [K in keyof BooleanOperationMap<boolean>]: { [P in K]: BooleanOperationMap<boolean>[K] } & {
7848
+ $boost?: number;
7849
+ };
7850
+ }[keyof BooleanOperationMap<boolean>];
7851
+
7852
+ type DateOperations = {
7853
+ [K in keyof DateOperationMap<string | Date>]: { [P in K]: DateOperationMap<string | Date>[K] } & {
7854
+ $boost?: number;
7855
+ };
7856
+ }[keyof DateOperationMap<string | Date>];
7857
+
7858
+ // Create a union type for all operations for a given field type
7859
+ type OperationsForFieldType<T extends FieldType> = T extends "TEXT"
7860
+ ? StringOperations
7861
+ : T extends "U64" | "I64" | "F64"
7862
+ ? NumberOperations
7863
+ : T extends "BOOL"
7864
+ ? BooleanOperations
7865
+ : T extends "DATE"
7866
+ ? DateOperations
7867
+ : never;
7868
+
7869
+ // Create a union type for all operations for a given path
7870
+ type PathOperations<TSchema, TPath extends string> =
7871
+ GetFieldAtPath<TSchema, TPath> extends infer Field
7872
+ ? Field extends FieldType | DetailedField
7873
+ ? OperationsForFieldType<ExtractFieldType<Field>> | FieldValueType<ExtractFieldType<Field>>
7874
+ : never
7875
+ : never;
7876
+
7877
+ // Create a type for a query leaf (only field paths, no boolean operators)
7878
+ type QueryLeaf<TSchema> = {
7879
+ // allowed schema paths
7880
+ [K in SchemaPaths<TSchema>]?: PathOperations<TSchema, K>;
7881
+ } & {
7544
7882
  $and?: never;
7545
7883
  $or?: never;
7546
7884
  $must?: never;
7547
7885
  $should?: never;
7548
7886
  $mustNot?: never;
7549
- $boost?: never;
7887
+ $boost?: number;
7550
7888
  };
7551
7889
 
7552
- // Base type for boolean nodes - allows field conditions
7553
- type BoolBase = SchemaFields;
7890
+ type BoolBase<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
7891
+ [P in SchemaPaths<TSchema>]?: PathOperations<TSchema, P>;
7892
+ };
7554
7893
 
7555
7894
  // $and: all conditions must match
7556
- type AndNode = BoolBase & {
7557
- /** All conditions in this array must match */
7558
- $and: QueryFilter | QueryFilter[];
7559
- /** Boost score for this node */
7895
+ type AndNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7896
+ $and: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7560
7897
  $boost?: number;
7561
7898
  $or?: never;
7562
7899
  $must?: never;
@@ -7565,10 +7902,8 @@ type AndNode = BoolBase & {
7565
7902
  };
7566
7903
 
7567
7904
  // $or: at least one condition must match
7568
- type OrNode = BoolBase & {
7569
- /** At least one condition must match */
7570
- $or: QueryFilter | QueryFilter[];
7571
- /** Boost score for this node */
7905
+ type OrNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7906
+ $or: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7572
7907
  $boost?: number;
7573
7908
  $and?: never;
7574
7909
  $must?: never;
@@ -7576,11 +7911,9 @@ type OrNode = BoolBase & {
7576
7911
  $mustNot?: never;
7577
7912
  };
7578
7913
 
7579
- // $must only (Elasticsearch-style)
7580
- type MustNode = BoolBase & {
7581
- /** All conditions must match (similar to $and) */
7582
- $must: QueryFilter | QueryFilter[];
7583
- /** Boost score for this node */
7914
+ // $must only
7915
+ type MustNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7916
+ $must: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7584
7917
  $boost?: number;
7585
7918
  $and?: never;
7586
7919
  $or?: never;
@@ -7588,11 +7921,9 @@ type MustNode = BoolBase & {
7588
7921
  $mustNot?: never;
7589
7922
  };
7590
7923
 
7591
- // $should only (Elasticsearch-style)
7592
- type ShouldNode = BoolBase & {
7593
- /** At least one should match (affects scoring) */
7594
- $should: QueryFilter | QueryFilter[];
7595
- /** Boost score for this node */
7924
+ // $should only
7925
+ type ShouldNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7926
+ $should: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7596
7927
  $boost?: number;
7597
7928
  $and?: never;
7598
7929
  $or?: never;
@@ -7601,21 +7932,16 @@ type ShouldNode = BoolBase & {
7601
7932
  };
7602
7933
 
7603
7934
  // $must + $should combined
7604
- type MustShouldNode = BoolBase & {
7605
- /** All these must match */
7606
- $must: QueryFilter | QueryFilter[];
7607
- /** At least one should match for higher score */
7608
- $should: QueryFilter | QueryFilter[];
7935
+ type MustShouldNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7936
+ $must: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7937
+ $should: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7609
7938
  $and?: never;
7610
7939
  $or?: never;
7611
- $mustNot?: never;
7612
7940
  };
7613
7941
 
7614
7942
  // $mustNot only
7615
- type NotNode = BoolBase & {
7616
- /** None of these conditions should match */
7617
- $mustNot: QueryFilter | QueryFilter[];
7618
- /** Boost score for this node */
7943
+ type NotNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7944
+ $mustNot: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7619
7945
  $boost?: number;
7620
7946
  $and?: never;
7621
7947
  $or?: never;
@@ -7623,20 +7949,18 @@ type NotNode = BoolBase & {
7623
7949
  $should?: never;
7624
7950
  };
7625
7951
 
7626
- // $and + $mustNot combined
7627
- type AndNotNode = BoolBase & {
7628
- $and: QueryFilter | QueryFilter[];
7629
- $mustNot: QueryFilter | QueryFilter[];
7952
+ type AndNotNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7953
+ $and: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7954
+ $mustNot: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7630
7955
  $boost?: number;
7631
7956
  $or?: never;
7632
7957
  $must?: never;
7633
7958
  $should?: never;
7634
7959
  };
7635
7960
 
7636
- // $or + $mustNot combined
7637
- type OrNotNode = BoolBase & {
7638
- $or: QueryFilter | QueryFilter[];
7639
- $mustNot: QueryFilter | QueryFilter[];
7961
+ type OrNotNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7962
+ $or: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7963
+ $mustNot: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7640
7964
  $boost?: number;
7641
7965
  $and?: never;
7642
7966
  $must?: never;
@@ -7644,19 +7968,18 @@ type OrNotNode = BoolBase & {
7644
7968
  };
7645
7969
 
7646
7970
  // $should + $mustNot combined
7647
- type ShouldNotNode = BoolBase & {
7648
- $should: QueryFilter | QueryFilter[];
7649
- $mustNot: QueryFilter | QueryFilter[];
7971
+ type ShouldNotNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7972
+ $should: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7973
+ $mustNot: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7650
7974
  $boost?: number;
7651
7975
  $and?: never;
7652
7976
  $or?: never;
7653
7977
  $must?: never;
7654
7978
  };
7655
7979
 
7656
- // $must + $mustNot combined
7657
- type MustNotNode = BoolBase & {
7658
- $must: QueryFilter | QueryFilter[];
7659
- $mustNot: QueryFilter | QueryFilter[];
7980
+ type MustNotNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7981
+ $must: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7982
+ $mustNot: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7660
7983
  $boost?: number;
7661
7984
  $and?: never;
7662
7985
  $or?: never;
@@ -7664,33 +7987,47 @@ type MustNotNode = BoolBase & {
7664
7987
  };
7665
7988
 
7666
7989
  // Full boolean node: $must + $should + $mustNot
7667
- type BoolNode = BoolBase & {
7668
- $must: QueryFilter | QueryFilter[];
7669
- $should: QueryFilter | QueryFilter[];
7670
- $mustNot: QueryFilter | QueryFilter[];
7990
+ type BoolNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = BoolBase<TSchema> & {
7991
+ $must: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7992
+ $should: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7993
+ $mustNot: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7671
7994
  $boost?: number;
7672
7995
  $and?: never;
7673
7996
  $or?: never;
7674
7997
  };
7675
7998
 
7676
- // Query filter - union of all node types
7677
- type QueryFilter =
7678
- | QueryLeaf
7679
- | AndNode
7680
- | OrNode
7681
- | MustNode
7682
- | ShouldNode
7683
- | MustShouldNode
7684
- | NotNode
7685
- | AndNotNode
7686
- | OrNotNode
7687
- | ShouldNotNode
7688
- | MustNotNode
7689
- | BoolNode;
7690
-
7691
- // Root-level $or restriction (no field conditions at root with $or)
7692
- type RootOrNode = {
7693
- $or: QueryFilter | QueryFilter[];
7999
+ // Create a type for a query filter
8000
+ export type QueryFilter<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8001
+ | QueryLeaf<TSchema>
8002
+ | AndNode<TSchema>
8003
+ | OrNode<TSchema>
8004
+ | MustNode<TSchema>
8005
+ | ShouldNode<TSchema>
8006
+ | MustShouldNode<TSchema>
8007
+ | NotNode<TSchema>
8008
+ | AndNotNode<TSchema>
8009
+ | OrNotNode<TSchema>
8010
+ | ShouldNotNode<TSchema>
8011
+ | MustNotNode<TSchema>
8012
+ | BoolNode<TSchema>;
8013
+
8014
+ // Create a type for root-level queries (restricts $or from mixing with fields)
8015
+ export type RootQueryFilter<TSchema extends NestedIndexSchema | FlatIndexSchema> =
8016
+ | QueryLeaf<TSchema>
8017
+ | AndNode<TSchema>
8018
+ | RootOrNode<TSchema>
8019
+ | MustNode<TSchema>
8020
+ | ShouldNode<TSchema>
8021
+ | MustShouldNode<TSchema>
8022
+ | AndNotNode<TSchema>
8023
+ | ShouldNotNode<TSchema>
8024
+ | BoolNode<TSchema>;
8025
+
8026
+ // Restricted version of OrNode that doesn't allow field operations at root level
8027
+ type RootOrNode<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
8028
+ [P in SchemaPaths<TSchema>]?: never; // No field operations at root level with $or
8029
+ } & {
8030
+ $or: QueryFilter<TSchema> | QueryFilter<TSchema>[];
7694
8031
  $boost?: number;
7695
8032
  $and?: never;
7696
8033
  $must?: never;
@@ -7698,19 +8035,96 @@ type RootOrNode = {
7698
8035
  $mustNot?: never;
7699
8036
  };
7700
8037
 
7701
- // Root query filter - restricts $or from mixing with fields at root level
7702
- type Query =
7703
- | QueryLeaf
7704
- | AndNode
7705
- | RootOrNode
7706
- | MustNode
7707
- | ShouldNode
7708
- | MustShouldNode
7709
- | NotNode
7710
- | AndNotNode
7711
- | ShouldNotNode
7712
- | MustNotNode
7713
- | BoolNode;
8038
+ export type DescribeFieldInfo = {
8039
+ type: FieldType;
8040
+ noTokenize?: boolean;
8041
+ noStem?: boolean;
8042
+ fast?: boolean;
8043
+ };
8044
+
8045
+ export type IndexDescription<TSchema extends NestedIndexSchema | FlatIndexSchema> = {
8046
+ name: string;
8047
+ dataType: "hash" | "string" | "json";
8048
+ prefixes: string[];
8049
+ language?: Language;
8050
+ schema: Record<SchemaPaths<TSchema>, DescribeFieldInfo>;
8051
+ };
8052
+
8053
+ export type Language =
8054
+ | "english"
8055
+ | "arabic"
8056
+ | "danish"
8057
+ | "dutch"
8058
+ | "finnish"
8059
+ | "french"
8060
+ | "german"
8061
+ | "greek"
8062
+ | "hungarian"
8063
+ | "italian"
8064
+ | "norwegian"
8065
+ | "portuguese"
8066
+ | "romanian"
8067
+ | "russian"
8068
+ | "spanish"
8069
+ | "swedish"
8070
+ | "tamil"
8071
+ | "turkish";
8072
+
8073
+ `;
8074
+
8075
+ // src/components/databrowser/components/search/generate-query-type-definitions.tsx
8076
+ var buildNestedSchema = (flatSchema) => {
8077
+ const nested = {};
8078
+ for (const [fieldPath, fieldDef] of Object.entries(flatSchema)) {
8079
+ const parts = fieldPath.split(".");
8080
+ let current = nested;
8081
+ for (let i = 0; i < parts.length - 1; i++) {
8082
+ const part = parts[i];
8083
+ if (!current[part] || typeof current[part] === "string") {
8084
+ current[part] = {};
8085
+ }
8086
+ current = current[part];
8087
+ }
8088
+ current[parts.at(-1)] = `"${fieldDef.type}"`;
8089
+ }
8090
+ return nested;
8091
+ };
8092
+ var generateNestedInterface = (obj, indent = " ") => {
8093
+ const lines = [];
8094
+ for (const [key, value] of Object.entries(obj)) {
8095
+ if (typeof value === "string") {
8096
+ lines.push(`${indent}${key}: ${value};`);
8097
+ } else {
8098
+ lines.push(`${indent}${key}: {`, generateNestedInterface(value, indent + " "), `${indent}};`);
8099
+ }
8100
+ }
8101
+ return lines.join("\n");
8102
+ };
8103
+ var toAmbientTypes = (types) => types.replaceAll(/export const (\w+) = (\[.*?]) as const;/g, "declare const $1: readonly $2;").replaceAll("export ", "");
8104
+ var generateTypeDefinitions = (schema) => {
8105
+ let schemaFieldsInterface = "";
8106
+ const schemaFields = _optionalChain([schema, 'optionalAccess', _89 => _89.schema]);
8107
+ if (schemaFields && Object.keys(schemaFields).length > 0) {
8108
+ const nested = buildNestedSchema(schemaFields);
8109
+ const fieldLines = generateNestedInterface(nested);
8110
+ schemaFieldsInterface = `
8111
+ /** Schema fields for the current index */
8112
+ interface SchemaFields {
8113
+ ${fieldLines}
8114
+ }`;
8115
+ } else {
8116
+ schemaFieldsInterface = `
8117
+ /** Schema fields - no schema available, using dynamic fields */
8118
+ interface SchemaFields {
8119
+ [fieldName: string]: FieldType | DetailedField | NestedIndexSchema;
8120
+ }`;
8121
+ }
8122
+ return `
8123
+ ${toAmbientTypes(SEARCH_TYPES)}
8124
+
8125
+ ${schemaFieldsInterface}
8126
+
8127
+ type Query = RootQueryFilter<SchemaFields>;
7714
8128
  `;
7715
8129
  };
7716
8130
 
@@ -7744,10 +8158,9 @@ var QueryBuilder = () => {
7744
8158
  const { valuesSearch, setValuesSearchQuery } = useTab();
7745
8159
  const { data: indexDetails } = useFetchSearchIndex(valuesSearch.index);
7746
8160
  const editorValue = PREFIX + (valuesSearch.query || "{}");
7747
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "rounded-lg border border-zinc-300 bg-white px-[6px] dark:border-zinc-700", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8161
+ return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-full rounded-lg border border-zinc-300 bg-white px-[6px]", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
7748
8162
  QueryEditor,
7749
8163
  {
7750
- height: 300,
7751
8164
  value: editorValue,
7752
8165
  onChange: (value) => {
7753
8166
  const queryPart = value.slice(PREFIX.length);
@@ -8046,9 +8459,17 @@ function Sidebar() {
8046
8459
 
8047
8460
 
8048
8461
  // src/components/databrowser/components/ui-query-builder/types.ts
8049
- var STRING_OPERATORS = ["eq", "ne", "in", "contains", "fuzzy"];
8462
+ var STRING_OPERATORS = [
8463
+ "eq",
8464
+ "ne",
8465
+ "in",
8466
+ "phrase",
8467
+ "regex",
8468
+ "fuzzy",
8469
+ "smart"
8470
+ ];
8050
8471
  var NUMBER_OPERATORS = ["eq", "ne", "gt", "gte", "lt", "lte", "in"];
8051
- var BOOLEAN_OPERATORS = ["eq", "ne"];
8472
+ var BOOLEAN_OPERATORS = ["eq", "ne", "in"];
8052
8473
  var DATE_OPERATORS = ["eq", "ne", "gt", "gte", "lt", "lte", "in"];
8053
8474
  var ALL_OPERATORS = [
8054
8475
  "eq",
@@ -8058,8 +8479,10 @@ var ALL_OPERATORS = [
8058
8479
  "lt",
8059
8480
  "lte",
8060
8481
  "in",
8061
- "contains",
8062
- "fuzzy"
8482
+ "phrase",
8483
+ "regex",
8484
+ "fuzzy",
8485
+ "smart"
8063
8486
  ];
8064
8487
  var OPERATOR_OPTIONS = [
8065
8488
  { value: "eq", label: "eq" },
@@ -8069,8 +8492,10 @@ var OPERATOR_OPTIONS = [
8069
8492
  { value: "lt", label: "lt" },
8070
8493
  { value: "lte", label: "lte" },
8071
8494
  { value: "in", label: "in" },
8072
- { value: "contains", label: "contains" },
8073
- { value: "fuzzy", label: "fuzzy" }
8495
+ { value: "phrase", label: "phrase" },
8496
+ { value: "regex", label: "regex" },
8497
+ { value: "fuzzy", label: "fuzzy" },
8498
+ { value: "smart", label: "smart" }
8074
8499
  ];
8075
8500
  var getOperatorsForFieldType = (fieldType) => {
8076
8501
  switch (fieldType) {
@@ -8152,6 +8577,8 @@ var parseFieldCondition = (field, fieldValue) => {
8152
8577
  let operator = "eq";
8153
8578
  let value = "";
8154
8579
  let fuzzyDistance;
8580
+ let phraseSlop;
8581
+ let phrasePrefix;
8155
8582
  let boost;
8156
8583
  for (const op of ALL_OPERATORS) {
8157
8584
  const key = `$${op}`;
@@ -8163,6 +8590,12 @@ var parseFieldCondition = (field, fieldValue) => {
8163
8590
  value = _nullishCoalesce(fuzzyObj.value, () => ( ""));
8164
8591
  fuzzyDistance = _nullishCoalesce(fuzzyObj.distance, () => ( 1));
8165
8592
  }
8593
+ if (op === "phrase" && typeof value === "object" && value !== null) {
8594
+ const phraseObj = value;
8595
+ value = _nullishCoalesce(phraseObj.value, () => ( ""));
8596
+ phraseSlop = phraseObj.slop;
8597
+ phrasePrefix = phraseObj.prefix;
8598
+ }
8166
8599
  break;
8167
8600
  }
8168
8601
  }
@@ -8177,6 +8610,8 @@ var parseFieldCondition = (field, fieldValue) => {
8177
8610
  operator,
8178
8611
  value,
8179
8612
  fuzzyDistance,
8613
+ phraseSlop,
8614
+ phrasePrefix,
8180
8615
  boost
8181
8616
  }
8182
8617
  };
@@ -8782,10 +9217,18 @@ var QueryCondition = ({
8782
9217
  } else if (value !== "fuzzy") {
8783
9218
  updates.fuzzyDistance = void 0;
8784
9219
  }
9220
+ if (value !== "phrase") {
9221
+ updates.phraseSlop = void 0;
9222
+ updates.phrasePrefix = void 0;
9223
+ }
8785
9224
  if (value === "in" && !Array.isArray(condition.value)) {
8786
- updates.value = condition.value ? [String(condition.value)] : [];
9225
+ if (currentFieldType === "boolean") {
9226
+ updates.value = [String(condition.value)];
9227
+ } else {
9228
+ updates.value = condition.value ? [String(condition.value)] : [];
9229
+ }
8787
9230
  } else if (value !== "in" && Array.isArray(condition.value)) {
8788
- updates.value = condition.value[0] || "";
9231
+ updates.value = currentFieldType === "boolean" ? Boolean(condition.value.includes("true")) : condition.value[0] || "";
8789
9232
  }
8790
9233
  updateNode(node.id, {
8791
9234
  ...node,
@@ -8825,6 +9268,54 @@ var QueryCondition = ({
8825
9268
  condition: { ...condition, fuzzyDistance: distance }
8826
9269
  });
8827
9270
  };
9271
+ const phraseMode = condition.phrasePrefix ? "prefix" : condition.phraseSlop === void 0 ? "exact" : "slop";
9272
+ const handlePhraseModeChange = (mode) => {
9273
+ const updates = {};
9274
+ switch (mode) {
9275
+ case "exact": {
9276
+ updates.phraseSlop = void 0;
9277
+ updates.phrasePrefix = void 0;
9278
+ break;
9279
+ }
9280
+ case "slop": {
9281
+ updates.phraseSlop = _nullishCoalesce(condition.phraseSlop, () => ( 1));
9282
+ updates.phrasePrefix = void 0;
9283
+ break;
9284
+ }
9285
+ case "prefix": {
9286
+ updates.phraseSlop = void 0;
9287
+ updates.phrasePrefix = true;
9288
+ break;
9289
+ }
9290
+ }
9291
+ updateNode(node.id, {
9292
+ ...node,
9293
+ condition: { ...condition, ...updates }
9294
+ });
9295
+ };
9296
+ const [localSlop, setLocalSlop] = _react.useState.call(void 0, String(_nullishCoalesce(condition.phraseSlop, () => ( 1))));
9297
+ const [isSlopFocused, setIsSlopFocused] = _react.useState.call(void 0, false);
9298
+ const slopStr = String(_nullishCoalesce(condition.phraseSlop, () => ( 1)));
9299
+ if (!isSlopFocused && localSlop !== slopStr) {
9300
+ setLocalSlop(slopStr);
9301
+ }
9302
+ const handlePhraseSlopChange = (value) => {
9303
+ setLocalSlop(value);
9304
+ const slop = Number(value);
9305
+ if (!Number.isNaN(slop) && value !== "" && slop >= 0) {
9306
+ updateNode(node.id, {
9307
+ ...node,
9308
+ condition: { ...condition, phraseSlop: slop }
9309
+ });
9310
+ }
9311
+ };
9312
+ const handlePhraseSlopBlur = () => {
9313
+ setIsSlopFocused(false);
9314
+ const slop = Number(localSlop);
9315
+ if (Number.isNaN(slop) || localSlop === "") {
9316
+ setLocalSlop(String(_nullishCoalesce(condition.phraseSlop, () => ( 1))));
9317
+ }
9318
+ };
8828
9319
  const handleDelete = () => {
8829
9320
  deleteNode(node.id);
8830
9321
  };
@@ -8832,7 +9323,7 @@ var QueryCondition = ({
8832
9323
  const filteredOperators = OPERATOR_OPTIONS.filter((op) => allowedOperators.includes(op.value));
8833
9324
  const isInvalidOperator = !isUnknownField && currentFieldType !== "unknown" && !allowedOperators.includes(condition.operator);
8834
9325
  const operatorError = isInvalidOperator ? `"${condition.operator}" is not valid for ${currentFieldType} fields` : void 0;
8835
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "group/condition flex items-center gap-1 px-1 py-1", children: [
9326
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "group/condition flex items-center gap-1 px-1", children: [
8836
9327
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
8837
9328
  "div",
8838
9329
  {
@@ -8885,7 +9376,46 @@ var QueryCondition = ({
8885
9376
  filteredOperators.map((op) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: op.value, children: op.label }, op.value))
8886
9377
  ] })
8887
9378
  ] }),
8888
- currentFieldType === "boolean" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
9379
+ 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: [
9380
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "flex items-center gap-1", children: [
9381
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9382
+ "input",
9383
+ {
9384
+ type: "checkbox",
9385
+ checked: Array.isArray(condition.value) && condition.value.includes("true"),
9386
+ onChange: (e) => {
9387
+ const current = Array.isArray(condition.value) ? condition.value : [];
9388
+ const next = e.target.checked ? [...current.filter((v) => v !== "true"), "true"] : current.filter((v) => v !== "true");
9389
+ updateNode(node.id, {
9390
+ ...node,
9391
+ condition: { ...condition, value: next }
9392
+ });
9393
+ },
9394
+ className: "h-3 w-3"
9395
+ }
9396
+ ),
9397
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "true" })
9398
+ ] }),
9399
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "label", { className: "flex items-center gap-1", children: [
9400
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9401
+ "input",
9402
+ {
9403
+ type: "checkbox",
9404
+ checked: Array.isArray(condition.value) && condition.value.includes("false"),
9405
+ onChange: (e) => {
9406
+ const current = Array.isArray(condition.value) ? condition.value : [];
9407
+ const next = e.target.checked ? [...current.filter((v) => v !== "false"), "false"] : current.filter((v) => v !== "false");
9408
+ updateNode(node.id, {
9409
+ ...node,
9410
+ condition: { ...condition, value: next }
9411
+ });
9412
+ },
9413
+ className: "h-3 w-3"
9414
+ }
9415
+ ),
9416
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { children: "false" })
9417
+ ] })
9418
+ ] }) : currentFieldType === "boolean" ? /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8889
9419
  Select,
8890
9420
  {
8891
9421
  value: condition.value === true || condition.value === "true" ? "true" : condition.value === false || condition.value === "false" ? "false" : "true",
@@ -8931,6 +9461,28 @@ var QueryCondition = ({
8931
9461
  ]
8932
9462
  }
8933
9463
  ),
9464
+ condition.operator === "phrase" && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, _jsxruntime.Fragment, { children: [
9465
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Select, { value: phraseMode, onValueChange: handlePhraseModeChange, children: [
9466
+ /* @__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, {}) }),
9467
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, SelectContent, { children: [
9468
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "exact", children: "exact" }),
9469
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "slop", children: "slop" }),
9470
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SelectItem, { value: "prefix", children: "prefix" })
9471
+ ] })
9472
+ ] }),
9473
+ phraseMode === "slop" && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9474
+ "input",
9475
+ {
9476
+ type: "number",
9477
+ min: 0,
9478
+ value: localSlop,
9479
+ onChange: (e) => handlePhraseSlopChange(e.target.value),
9480
+ onFocus: () => setIsSlopFocused(true),
9481
+ onBlur: handlePhraseSlopBlur,
9482
+ className: "h-[26px] w-10 appearance-none rounded-md border border-zinc-200 bg-white px-2 text-sm focus:border-zinc-400 focus:outline-none [&::-webkit-inner-spin-button]:appearance-none [&::-webkit-outer-spin-button]:appearance-none"
9483
+ }
9484
+ )
9485
+ ] }),
8934
9486
  node.boost !== void 0 && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, BoostBadge, { node }),
8935
9487
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
8936
9488
  "div",
@@ -9293,7 +9845,7 @@ var InnerGroup = ({
9293
9845
  }
9294
9846
  )
9295
9847
  ] }),
9296
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: `min-h-[20px] ${isRoot ? "" : "ml-2 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: [
9848
+ /* @__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: [
9297
9849
  node.children.map(
9298
9850
  (child) => !child.not && /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9299
9851
  ChildRow,
@@ -9308,12 +9860,8 @@ var InnerGroup = ({
9308
9860
  )
9309
9861
  ),
9310
9862
  node.children.some((child) => child.not) && /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, Tooltip, { delayDuration: 200, children: [
9311
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipTrigger, { asChild: true, children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center gap-2 px-1 py-1.5", children: [
9312
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px flex-1 bg-amber-300" }),
9313
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "span", { className: "cursor-default select-none rounded bg-amber-50 px-2 py-0.5 text-[11px] font-semibold uppercase tracking-wider text-amber-800", children: "Must Not" }),
9314
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "h-px flex-1 bg-amber-300" })
9315
- ] }) }),
9316
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipContent, { side: "top", className: "max-w-xs", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { children: [
9863
+ /* @__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" }) }),
9864
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TooltipContent, { side: "right", className: "max-w-xs", children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "p", { children: [
9317
9865
  "Keys matching any of the conditions below are excluded from the results.",
9318
9866
  " ",
9319
9867
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
@@ -9397,20 +9945,36 @@ var jsonToJsLiteral = (json) => {
9397
9945
  var toJsLiteral = (obj) => {
9398
9946
  return jsonToJsLiteral(JSON.stringify(obj, null, 2));
9399
9947
  };
9400
- var buildOperatorValue = (operator, value, fuzzyDistance) => {
9948
+ var buildOperatorValue = (operator, value, fuzzyDistance, phraseSlop, phrasePrefix) => {
9401
9949
  if (operator === "fuzzy" && fuzzyDistance) {
9402
9950
  return { value, distance: fuzzyDistance };
9403
9951
  }
9952
+ if (operator === "phrase") {
9953
+ if (phraseSlop !== void 0) {
9954
+ return { value, slop: phraseSlop };
9955
+ }
9956
+ if (phrasePrefix) {
9957
+ return { value, prefix: true };
9958
+ }
9959
+ }
9404
9960
  return value;
9405
9961
  };
9406
9962
  var conditionToObject = (node) => {
9407
- const { field, operator, value, boost: conditionBoost, fuzzyDistance } = node.condition;
9963
+ const {
9964
+ field,
9965
+ operator,
9966
+ value,
9967
+ boost: conditionBoost,
9968
+ fuzzyDistance,
9969
+ phraseSlop,
9970
+ phrasePrefix
9971
+ } = node.condition;
9408
9972
  const effectiveBoost = _nullishCoalesce(node.boost, () => ( conditionBoost));
9409
9973
  if (operator === "eq" && !effectiveBoost) {
9410
9974
  return { [field]: value };
9411
9975
  }
9412
9976
  const fieldCondition = {
9413
- [`$${operator}`]: buildOperatorValue(operator, value, fuzzyDistance)
9977
+ [`$${operator}`]: buildOperatorValue(operator, value, fuzzyDistance, phraseSlop, phrasePrefix)
9414
9978
  };
9415
9979
  const finalBoost = _nullishCoalesce(node.boost, () => ( conditionBoost));
9416
9980
  if (finalBoost && finalBoost !== 1) {
@@ -9548,7 +10112,52 @@ var UIQueryBuilder = () => {
9548
10112
  hasNormalized.current = true;
9549
10113
  setQueryState((state) => normalizeQueryState(state, fieldInfos));
9550
10114
  }, [fieldInfos, setQueryState]);
9551
- return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilderUIProvider, { fieldInfos, setQueryState, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "rounded-lg border border-zinc-200 bg-zinc-50 p-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryGroup, { node: queryState.root, isRoot: true, depth: 0 }) }) });
10115
+ const scrollAreaRef = _react.useRef.call(void 0, null);
10116
+ const viewportRef = _react.useRef.call(void 0, null);
10117
+ const [hasTopShadow, setHasTopShadow] = _react.useState.call(void 0, false);
10118
+ const [hasBottomShadow, setHasBottomShadow] = _react.useState.call(void 0, false);
10119
+ const recomputeShadows = _react.useCallback.call(void 0, () => {
10120
+ const el = viewportRef.current;
10121
+ if (!el) return;
10122
+ const { scrollTop, scrollHeight, clientHeight } = el;
10123
+ setHasTopShadow(scrollTop > 0);
10124
+ setHasBottomShadow(scrollTop + clientHeight < scrollHeight - 1);
10125
+ }, []);
10126
+ _react.useEffect.call(void 0, () => {
10127
+ viewportRef.current = _optionalChain([scrollAreaRef, 'access', _101 => _101.current, 'optionalAccess', _102 => _102.querySelector, 'call', _103 => _103(
10128
+ "[data-radix-scroll-area-viewport]"
10129
+ )]);
10130
+ recomputeShadows();
10131
+ const el = viewportRef.current;
10132
+ if (!el) return;
10133
+ const obs = new ResizeObserver(() => recomputeShadows());
10134
+ obs.observe(el);
10135
+ return () => obs.disconnect();
10136
+ }, [recomputeShadows]);
10137
+ 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: [
10138
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10139
+ "div",
10140
+ {
10141
+ className: `scroll-shadow-top pointer-events-none absolute left-0 top-0 z-10 h-6 w-full rounded-t-lg transition-opacity duration-200 ${hasTopShadow ? "opacity-100" : "opacity-0"}`
10142
+ }
10143
+ ),
10144
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10145
+ "div",
10146
+ {
10147
+ className: `scroll-shadow-bottom pointer-events-none absolute bottom-0 left-0 z-10 h-6 w-full rounded-b-lg transition-opacity duration-200 ${hasBottomShadow ? "opacity-100" : "opacity-0"}`
10148
+ }
10149
+ ),
10150
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10151
+ ScrollArea,
10152
+ {
10153
+ ref: scrollAreaRef,
10154
+ onScroll: recomputeShadows,
10155
+ className: "h-full",
10156
+ scrollBarClassName: "py-1",
10157
+ children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "p-4", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryGroup, { node: queryState.root, isRoot: true, depth: 0 }) })
10158
+ }
10159
+ )
10160
+ ] }) });
9552
10161
  };
9553
10162
  var normalizeValue = (value, fieldType) => {
9554
10163
  if (fieldType === "number" && typeof value === "string" && value !== "") {
@@ -9567,16 +10176,16 @@ var normalizeValue = (value, fieldType) => {
9567
10176
  var normalizeNode = (node, fieldInfos) => {
9568
10177
  if (node.type === "condition") {
9569
10178
  const fieldInfo = fieldInfos.find((f) => f.name === node.condition.field);
9570
- if (fieldInfo) {
9571
- return {
9572
- ...node,
9573
- condition: {
9574
- ...node.condition,
9575
- value: normalizeValue(node.condition.value, fieldInfo.type)
9576
- }
9577
- };
10179
+ const condition = { ...node.condition };
10180
+ if (fieldInfo) condition.value = normalizeValue(condition.value, fieldInfo.type);
10181
+ if (condition.phraseSlop !== void 0) {
10182
+ const num = Number(condition.phraseSlop);
10183
+ condition.phraseSlop = Number.isNaN(num) ? void 0 : num;
9578
10184
  }
9579
- return node;
10185
+ if (condition.phrasePrefix !== void 0) {
10186
+ condition.phrasePrefix = Boolean(condition.phrasePrefix);
10187
+ }
10188
+ return { ...node, condition };
9580
10189
  }
9581
10190
  if (node.type === "group") {
9582
10191
  return {
@@ -9647,24 +10256,29 @@ var SearchContent = () => {
9647
10256
  if (!hasIndexes) {
9648
10257
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchEmptyState, {});
9649
10258
  }
9650
- return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative", children: [
9651
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute right-4 top-4 z-10", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9652
- Segmented,
9653
- {
9654
- options: [
9655
- { key: "builder", label: "Query Builder" },
9656
- { key: "code", label: "Code Editor" }
9657
- ],
9658
- value: mode,
9659
- onChange: handleModeChange,
9660
- buttonClassName: "h-6"
9661
- }
9662
- ) }),
9663
- mode === "builder" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, UIQueryBuilder, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilder, {}),
10259
+ return /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { children: [
10260
+ /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "relative h-[300px] max-h-[600px] min-h-[150px] resize-y overflow-hidden", children: [
10261
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "div", { className: "absolute right-4 top-4 z-10", children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10262
+ Segmented,
10263
+ {
10264
+ options: [
10265
+ { key: "builder", label: "Query Builder" },
10266
+ { key: "code", label: "Code Editor" }
10267
+ ],
10268
+ value: mode,
10269
+ onChange: handleModeChange,
10270
+ buttonClassName: "h-6"
10271
+ }
10272
+ ) }),
10273
+ mode === "builder" ? /* @__PURE__ */ _jsxruntime.jsx.call(void 0, UIQueryBuilder, {}) : /* @__PURE__ */ _jsxruntime.jsx.call(void 0, QueryBuilder, {})
10274
+ ] }),
9664
10275
  switchError && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, "p", { className: "mt-3 text-sm text-red-500", children: switchError })
9665
10276
  ] });
9666
10277
  };
9667
- var DatabrowserInstance = ({ hidden }) => {
10278
+ var DatabrowserInstance = ({
10279
+ hidden,
10280
+ hideSearchTab = false
10281
+ }) => {
9668
10282
  const { isValuesSearchSelected } = useTab();
9669
10283
  return /* @__PURE__ */ _jsxruntime.jsx.call(void 0, KeysProvider, { children: /* @__PURE__ */ _jsxruntime.jsxs.call(void 0,
9670
10284
  "div",
@@ -9675,7 +10289,7 @@ var DatabrowserInstance = ({ hidden }) => {
9675
10289
  ),
9676
10290
  children: [
9677
10291
  /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "space-y-3 py-5", children: [
9678
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Header, {}),
10292
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, Header, { hideSearchTab }),
9679
10293
  isValuesSearchSelected && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, SearchContent, {}),
9680
10294
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, HeaderError, {})
9681
10295
  ] }),
@@ -9722,7 +10336,7 @@ var _utilities = require('@dnd-kit/utilities');
9722
10336
 
9723
10337
  var _cmdk = require('cmdk');
9724
10338
 
9725
- var Command = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10339
+ var Command = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9726
10340
  _cmdk.Command,
9727
10341
  {
9728
10342
  ref,
@@ -9734,7 +10348,7 @@ var Command = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__
9734
10348
  }
9735
10349
  ));
9736
10350
  Command.displayName = _cmdk.Command.displayName;
9737
- var CommandInput = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center border-b px-3", "cmdk-input-wrapper": "", children: [
10351
+ var CommandInput = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsxs.call(void 0, "div", { className: "flex items-center border-b px-3", "cmdk-input-wrapper": "", children: [
9738
10352
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _iconsreact.IconSearch, { className: "mr-2 h-4 w-4 shrink-0 opacity-50" }),
9739
10353
  /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9740
10354
  _cmdk.Command.Input,
@@ -9749,7 +10363,7 @@ var CommandInput = React14.forwardRef(({ className, ...props }, ref) => /* @__PU
9749
10363
  )
9750
10364
  ] }));
9751
10365
  CommandInput.displayName = _cmdk.Command.Input.displayName;
9752
- var CommandList = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10366
+ var CommandList = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9753
10367
  _cmdk.Command.List,
9754
10368
  {
9755
10369
  ref,
@@ -9758,9 +10372,9 @@ var CommandList = React14.forwardRef(({ className, ...props }, ref) => /* @__PUR
9758
10372
  }
9759
10373
  ));
9760
10374
  CommandList.displayName = _cmdk.Command.List.displayName;
9761
- var CommandEmpty = React14.forwardRef((props, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _cmdk.Command.Empty, { ref, className: "py-6 text-center text-sm", ...props }));
10375
+ var CommandEmpty = React15.forwardRef((props, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, _cmdk.Command.Empty, { ref, className: "py-6 text-center text-sm", ...props }));
9762
10376
  CommandEmpty.displayName = _cmdk.Command.Empty.displayName;
9763
- var CommandGroup = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10377
+ var CommandGroup = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9764
10378
  _cmdk.Command.Group,
9765
10379
  {
9766
10380
  ref,
@@ -9772,7 +10386,7 @@ var CommandGroup = React14.forwardRef(({ className, ...props }, ref) => /* @__PU
9772
10386
  }
9773
10387
  ));
9774
10388
  CommandGroup.displayName = _cmdk.Command.Group.displayName;
9775
- var CommandSeparator = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10389
+ var CommandSeparator = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9776
10390
  _cmdk.Command.Separator,
9777
10391
  {
9778
10392
  ref,
@@ -9781,7 +10395,7 @@ var CommandSeparator = React14.forwardRef(({ className, ...props }, ref) => /* @
9781
10395
  }
9782
10396
  ));
9783
10397
  CommandSeparator.displayName = _cmdk.Command.Separator.displayName;
9784
- var CommandItem = React14.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
10398
+ var CommandItem = React15.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0,
9785
10399
  _cmdk.Command.Item,
9786
10400
  {
9787
10401
  ref,
@@ -9820,7 +10434,7 @@ var useOverflow = () => {
9820
10434
  }
9821
10435
  if (!node) return;
9822
10436
  observerRef.current = new ResizeObserver((entries) => {
9823
- const el = _optionalChain([entries, 'access', _101 => _101.at, 'call', _102 => _102(0), 'optionalAccess', _103 => _103.target]);
10437
+ const el = _optionalChain([entries, 'access', _104 => _104.at, 'call', _105 => _105(0), 'optionalAccess', _106 => _106.target]);
9824
10438
  if (!el) return;
9825
10439
  setIsOverflow(el.scrollWidth > el.clientWidth);
9826
10440
  });
@@ -9828,7 +10442,7 @@ var useOverflow = () => {
9828
10442
  }, []);
9829
10443
  _react.useEffect.call(void 0, () => {
9830
10444
  return () => {
9831
- _optionalChain([observerRef, 'access', _104 => _104.current, 'optionalAccess', _105 => _105.disconnect, 'call', _106 => _106()]);
10445
+ _optionalChain([observerRef, 'access', _107 => _107.current, 'optionalAccess', _108 => _108.disconnect, 'call', _109 => _109()]);
9832
10446
  };
9833
10447
  }, []);
9834
10448
  return { ref, isOverflow };
@@ -9946,8 +10560,8 @@ var SortableTab = ({ id }) => {
9946
10560
  const [originalWidth, setOriginalWidth] = _react.useState.call(void 0, null);
9947
10561
  const textRef = _react.useRef.call(void 0, null);
9948
10562
  const { tabs } = useDatabrowserStore();
9949
- const tabData = _optionalChain([tabs, 'access', _107 => _107.find, 'call', _108 => _108(([tabId]) => tabId === id), 'optionalAccess', _109 => _109[1]]);
9950
- const isPinned = _optionalChain([tabData, 'optionalAccess', _110 => _110.pinned]);
10563
+ const tabData = _optionalChain([tabs, 'access', _110 => _110.find, 'call', _111 => _111(([tabId]) => tabId === id), 'optionalAccess', _112 => _112[1]]);
10564
+ const isPinned = _optionalChain([tabData, 'optionalAccess', _113 => _113.pinned]);
9951
10565
  const { attributes, listeners: listeners2, setNodeRef, transform, transition, isDragging } = _sortable.useSortable.call(void 0, {
9952
10566
  id,
9953
10567
  disabled: isPinned,
@@ -10164,7 +10778,7 @@ function AddTabButton() {
10164
10778
  const tabsId = addTab();
10165
10779
  selectTab(tabsId);
10166
10780
  setTimeout(() => {
10167
- const tab = _optionalChain([rootRef, 'optionalAccess', _111 => _111.current, 'optionalAccess', _112 => _112.querySelector, 'call', _113 => _113(`#tab-${tabsId}`)]);
10781
+ const tab = _optionalChain([rootRef, 'optionalAccess', _114 => _114.current, 'optionalAccess', _115 => _115.querySelector, 'call', _116 => _116(`#tab-${tabsId}`)]);
10168
10782
  if (!tab) return;
10169
10783
  tab.scrollIntoView({ behavior: "smooth" });
10170
10784
  }, 20);
@@ -10198,7 +10812,7 @@ function TabsListButton({
10198
10812
  onSelectTab(id);
10199
10813
  setOpen(false);
10200
10814
  setTimeout(() => {
10201
- const tab = _optionalChain([rootRef, 'optionalAccess', _114 => _114.current, 'optionalAccess', _115 => _115.querySelector, 'call', _116 => _116(`#tab-${id}`)]);
10815
+ const tab = _optionalChain([rootRef, 'optionalAccess', _117 => _117.current, 'optionalAccess', _118 => _118.querySelector, 'call', _119 => _119(`#tab-${id}`)]);
10202
10816
  if (!tab) return;
10203
10817
  tab.scrollIntoView({ behavior: "smooth" });
10204
10818
  }, 20);
@@ -10243,6 +10857,7 @@ var RedisBrowser = ({
10243
10857
  url,
10244
10858
  token,
10245
10859
  hideTabs,
10860
+ hideSearchTab,
10246
10861
  storage,
10247
10862
  disableTelemetry,
10248
10863
  onFullScreenClick,
@@ -10257,6 +10872,7 @@ var RedisBrowser = ({
10257
10872
  RedisBrowserRoot,
10258
10873
  {
10259
10874
  hideTabs,
10875
+ hideSearchTab,
10260
10876
  rootRef,
10261
10877
  onFullScreenClick
10262
10878
  }
@@ -10264,6 +10880,7 @@ var RedisBrowser = ({
10264
10880
  };
10265
10881
  var RedisBrowserRoot = ({
10266
10882
  hideTabs,
10883
+ hideSearchTab,
10267
10884
  rootRef,
10268
10885
  onFullScreenClick
10269
10886
  }) => {
@@ -10282,20 +10899,20 @@ var RedisBrowserRoot = ({
10282
10899
  ref: rootRef,
10283
10900
  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: [
10284
10901
  !hideTabs && /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserTabs, { onFullScreenClick }),
10285
- /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstances, {})
10902
+ /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstances, { hideSearchTab })
10286
10903
  ] })
10287
10904
  }
10288
10905
  )
10289
10906
  );
10290
10907
  };
10291
- var DatabrowserInstances = () => {
10908
+ var DatabrowserInstances = ({ hideSearchTab }) => {
10292
10909
  const { tabs, selectedTab, selectTab, addTab } = useDatabrowserStore();
10293
10910
  _react.useEffect.call(void 0, () => {
10294
10911
  if (tabs.length === 0) addTab();
10295
10912
  else if (!selectedTab) selectTab(tabs[0][0]);
10296
10913
  }, [tabs, selectedTab, addTab, selectTab]);
10297
10914
  if (!selectedTab) return;
10298
- return tabs.map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabIdProvider, { value: id, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstance, { hidden: id !== selectedTab }) }, id));
10915
+ return tabs.map(([id]) => /* @__PURE__ */ _jsxruntime.jsx.call(void 0, TabIdProvider, { value: id, children: /* @__PURE__ */ _jsxruntime.jsx.call(void 0, DatabrowserInstance, { hidden: id !== selectedTab, hideSearchTab }) }, id));
10299
10916
  };
10300
10917
 
10301
10918