diff --git a/bun.lockb b/bun.lockb index d7b765d..d921631 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/package.json b/package.json index b8d0021..513f4c6 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "build": "tsup", "dev": "vite", "lint": "tsc && eslint", - "fmt": "prettier --write ./src" + "fmt": "prettier --write ./src", + "prepare": "husky" }, "lint-staged": { "**/*.{js,ts,tsx}": [ @@ -49,7 +50,7 @@ "@tabler/icons-react": "^3.19.0", "@tanstack/react-query": "^5.32.0", "@types/bytes": "^3.1.4", - "@upstash/redis": "^1.35.8", + "@upstash/redis": "1.36.0-rc.4", "bytes": "^3.1.2", "cmdk": "^1.1.1", "react-hook-form": "^7.53.0", @@ -70,6 +71,8 @@ "dotenv": "^16.5.0", "eslint": "9.10.0", "eslint-plugin-unicorn": "55.0.0", + "husky": "^9.1.7", + "lint-staged": "^16.2.7", "postcss": "^8.4.31", "postcss-prefix-selector": "^2.1.0", "prettier": "^3.0.3", diff --git a/playground.ts b/playground.ts new file mode 100644 index 0000000..a91f615 --- /dev/null +++ b/playground.ts @@ -0,0 +1,154 @@ +/* eslint-disable no-console */ +import { Redis, s } from "@upstash/redis"; + +const redis = Redis.fromEnv(); + +// await redis.search.index("user-index").drop(); + +const schema = s.object({ + name: s.string(), + + age: s.number(), + isStudent: s.boolean(), + isEmployed: s.boolean(), + + // M or F + gender: s.string(), + + contact: s.object({ + email: s.string(), + phone: s.string(), + }) +}) + +const index = redis.search.index("user-index", schema) + +if (await index.describe()) { + console.log("index exists, dropping") + await index.drop(); + console.log('index dropped') +} + +console.log("creating index") +await redis.search.createIndex({ + dataType: "string", + prefix: "user:", + name: "user-index", + schema: schema, +}); + +console.log("created index") + +// await index.waitIndexing(); + +console.log("indexing done") + + +const res = await index.query({ + filter: { + $and: { + name: { + $eq: "Yusuf" + } + }, + "contact.email": "asd", + } +}) + +console.log("query result, should be empty:", res) + +// Create the data + +await redis.mset({ + "user:yusuf": JSON.stringify({ + name: "Yusuf", + age: 30, + isStudent: false, + isEmployed: true, + gender: "M", + contact: { + email: "yusuf@example.com", + phone: "1234567890", + } + }), + "user:fatima": JSON.stringify({ + name: "Fatima", + age: 35, + isStudent: true, + isEmployed: false, + gender: "F", + contact: { + email: "fatima@example.com", + phone: "0987654321", + } + }), + // josh + // arda + // ali + // sertug + "user:josh": JSON.stringify({ + name: "Josh", + age: 22, + isStudent: true, + isEmployed: false, + gender: "M", + contact: { + email: "josh@example.com", + phone: "0987654321", + } + }), + "user:arda": JSON.stringify({ + name: "Arda", + age: 20, + isStudent: true, + isEmployed: false, + gender: "M", + contact: { + email: "arda@example.com", + phone: "0987654321", + } + }), + "user:ali": JSON.stringify({ + name: "Ali", + age: 15, + isStudent: true, + isEmployed: false, + gender: "M", + contact: { + email: "ali@example.com", + phone: "0987654321", + } + }), + "user:sertug": JSON.stringify({ + name: "Sertug", + age: 5, + isStudent: true, + isEmployed: false, + gender: "M", + contact: { + email: "sertug@example.com", + phone: "0987654321", + } + }), +}) + +console.log("created data") + +// await index.waitIndexing(); + +console.log("indexing done") + +const res2 = await index.query({ + filter: { + $and: { + name: { + $eq: "Yusuf" + } + } + } +}) + +console.log("query result, should not be empty:", res2) + + +console.log(await redis.type("user-index")) diff --git a/src/components/databrowser/components/add-key-modal.tsx b/src/components/databrowser/components/add-key-modal.tsx index 75324f1..ae9636c 100644 --- a/src/components/databrowser/components/add-key-modal.tsx +++ b/src/components/databrowser/components/add-key-modal.tsx @@ -2,6 +2,7 @@ import { useState } from "react" import { useTab } from "@/tab-provider" import { DATA_TYPES, type DataType } from "@/types" import { DialogDescription } from "@radix-ui/react-dialog" +import { IconPlus } from "@tabler/icons-react" import { Controller, useForm } from "react-hook-form" import { Button } from "@/components/ui/button" @@ -22,10 +23,9 @@ import { SelectValue, } from "@/components/ui/select" import { Spinner } from "@/components/ui/spinner" +import { SimpleTooltip } from "@/components/ui/tooltip" import { TypeTag } from "@/components/databrowser/components/type-tag" import { useAddKey } from "@/components/databrowser/hooks/use-add-key" -import { SimpleTooltip } from "@/components/ui/tooltip" -import { IconPlus } from "@tabler/icons-react" export function AddKeyModal() { const { setSelectedKey } = useTab() @@ -65,8 +65,13 @@ export function AddKeyModal() { > - @@ -91,7 +96,7 @@ export function AddKeyModal() { - {DATA_TYPES.map((type) => ( + {DATA_TYPES.filter((t) => t !== "search").map((type) => ( diff --git a/src/components/databrowser/components/databrowser-instance.tsx b/src/components/databrowser/components/databrowser-instance.tsx index f8e353a..bc06fb8 100644 --- a/src/components/databrowser/components/databrowser-instance.tsx +++ b/src/components/databrowser/components/databrowser-instance.tsx @@ -1,25 +1,46 @@ +import { useTab } from "@/tab-provider" import { Panel, PanelGroup, PanelResizeHandle } from "react-resizable-panels" import { cn } from "@/lib/utils" import { Toaster } from "@/components/ui/toaster" + +import { KeysProvider } from "../hooks/use-keys" import { DataDisplay } from "./display" +import { Header } from "./header" +import { HeaderError } from "./header-error" +import { QueryBuilder } from "./query-builder" import { Sidebar } from "./sidebar" -import { KeysProvider } from "../hooks/use-keys" + +export const PREFIX = "const query: Query = " export const DatabrowserInstance = ({ hidden }: { hidden?: boolean }) => { + const { isValuesSearchSelected } = useTab() return ( -