Merge branch 'main' into v3

This commit is contained in:
bkellam 2025-03-16 15:24:04 -07:00
commit e8acfcca70
37 changed files with 678 additions and 749 deletions

View file

@ -0,0 +1,38 @@
name: GCP Deploy (staging)
on:
workflow_run:
workflows: ["Publish to ghcr (staging)"]
types:
- completed
jobs:
deploy:
name: Deploy staging app to GCP
runs-on: ubuntu-latest
steps:
- name: Configure SSH
run: |
mkdir -p ~/.ssh/
echo "${{ secrets.GCP_STAGING_SSH_PRIVATE_KEY }}" > ~/.ssh/private.key
chmod 600 ~/.ssh/private.key
echo "${{ secrets.GCP_STAGING_SSH_KNOWN_HOSTS }}" >> ~/.ssh/known_hosts
- name: Deploy to GCP
run: |
ssh -i ~/.ssh/private.key ${{ secrets.GCP_STAGING_USERNAME }}@${{ secrets.GCP_STAGING_HOST }} << 'EOF'
# Stop and remove any existing container
docker stop -t 60 sourcebot-staging || true
docker rm sourcebot-staging || true
# Run new container
docker run -d \
-p 80:3000 \
--rm \
--pull always \
--env-file .env.staging \
-v /mnt/data:/data \
--name sourcebot-staging \
ghcr.io/sourcebot-dev/sourcebot:staging
EOF

View file

@ -14,7 +14,7 @@ env:
jobs:
build:
runs-on: ubuntu-latest
runs-on: ${{ matrix.runs-on}}
permissions:
contents: read
packages: write
@ -23,9 +23,14 @@ jobs:
id-token: write
strategy:
matrix:
platform:
- linux/amd64
- linux/arm64
platform: [linux/amd64, linux/arm64]
include:
- platform: linux/amd64
runs-on: ubuntu-latest
- platform: linux/arm64
runs-on: ubuntu-24.04-arm
steps:
- name: Prepare
@ -76,7 +81,7 @@ jobs:
build-args: |
SOURCEBOT_VERSION=${{ github.ref_name }}
POSTHOG_PAPIK=${{ secrets.POSTHOG_PAPIK }}
- name: Export digest
run: |
mkdir -p /tmp/digests

View file

@ -70,7 +70,8 @@ jobs:
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
build-args: |
SOURCEBOT_VERSION=${{ github.ref_name }}
POSTHOG_PAPIK=${{ secrets.STAGING_POSTHOG_PAPIK }}
POSTHOG_PAPIK=${{ secrets.POSTHOG_PAPIK }}
SOURCEBOT_ENCRYPTION_KEY=${{ secrets.STAGING_SOURCEBOT_ENCRYPTION_KEY }}
- name: Export digest
run: |

View file

@ -7,6 +7,47 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [2.8.4] - 2025-03-14
### Fixed
- Fixed bug where Sourcebot Cloud card was shown to self-hosted users
## [2.8.3] - 2025-03-13
### Fixed
- Made syntax reference guide keyboard shortcut hints clickable. ([#229](https://github.com/sourcebot-dev/sourcebot/pull/229))
## [2.8.2] - 2025-02-20
### Fixed
- Remove `repo_synced` telemetry event.
## [2.8.1] - 2025-01-28
### Added
- Added `maxTrigramCount` to the config to control the maximum allowable of trigrams per document.
### Fixed
- Fixed issue with version upgrade toast not appearing without a hard refresh. ([#179](https://github.com/sourcebot-dev/sourcebot/pull/179))
## [2.8.0] - 2025-01-17
### Added
- Added a syntax reference guide. The guide can be opened using the hotkey "Cmd + /" ("Ctrl + /" on Windows). ([#169](https://github.com/sourcebot-dev/sourcebot/pull/169))
## [2.7.1] - 2025-01-15
### Fixed
- Fixed issue where we crash on startup if the install / upgrade PostHog event fails to send. ([#159](https://github.com/sourcebot-dev/sourcebot/pull/159))
- Fixed issue with broken file links. ([#161](https://github.com/sourcebot-dev/sourcebot/pull/161))
## [2.7.0] - 2025-01-10
### Added

View file

@ -46,6 +46,7 @@ ENV NEXT_TELEMETRY_DISABLED=1
# @see: https://phase.dev/blog/nextjs-public-runtime-variables/
ARG NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED=BAKED_NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED
ARG NEXT_PUBLIC_SOURCEBOT_VERSION=BAKED_NEXT_PUBLIC_SOURCEBOT_VERSION
ENV NEXT_PUBLIC_PUBLIC_SEARCH_DEMO=BAKED_NEXT_PUBLIC_PUBLIC_SEARCH_DEMO
ENV NEXT_PUBLIC_POSTHOG_PAPIK=BAKED_NEXT_PUBLIC_POSTHOG_PAPIK
ENV NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY=BAKED_NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY
ENV NEXT_PUBLIC_SENTRY_ENVIRONMENT=BAKED_NEXT_PUBLIC_SENTRY_ENVIRONMENT
@ -93,6 +94,10 @@ ARG SOURCEBOT_VERSION=unknown
ENV SOURCEBOT_VERSION=$SOURCEBOT_VERSION
RUN echo "Sourcebot Version: $SOURCEBOT_VERSION"
ARG PUBLIC_SEARCH_DEMO=false
ENV PUBLIC_SEARCH_DEMO=$PUBLIC_SEARCH_DEMO
RUN echo "Public Search Demo: $PUBLIC_SEARCH_DEMO"
# Valid values are: debug, info, warn, error
ENV SOURCEBOT_LOG_LEVEL=info

View file

@ -209,140 +209,19 @@
"atom/atom",
"Eugeny/tabby",
"lodash/lodash",
"chrislgarry/Apollo-11",
"xingshaocheng/architect-awesome",
"comfyanonymous/ComfyUI",
"h5bp/Front-end-Developer-Interview-Questions",
"adam-p/markdown-here",
"binhnguyennus/awesome-scalability",
"jquery/jquery",
"bradtraversy/design-resources-for-developers",
"danielmiessler/SecLists",
"caddyserver/caddy",
"sindresorhus/awesome-nodejs",
"rust-unofficial/awesome-rust",
"mastodon/mastodon",
"Stirling-Tools/Stirling-PDF",
"iamkun/dayjs",
"romkatv/powerlevel10k",
"algorithm-visualizer/algorithm-visualizer",
"charlax/professional-programming",
"poteto/hiring-without-whiteboards",
"FFmpeg/FFmpeg",
"laurent22/joplin",
"serverless/serverless",
"justjavac/awesome-wechat-weapp",
"minimaxir/big-list-of-naughty-strings",
"agalwood/Motrix",
"JuliaLang/julia",
"square/okhttp",
"firstcontributions/first-contributions",
"geekan/MetaGPT",
"appwrite/appwrite",
"starship/starship",
"PowerShell/PowerShell",
"Avik-Jain/100-Days-Of-ML-Code",
"ziishaned/learn-regex",
"typescript-cheatsheets/react",
"go-gitea/gitea",
"kamranahmedse/design-patterns-for-humans",
"v2ray/v2ray-core",
"karan/Projects",
"WerWolv/ImHex",
"gogs/gogs",
"x64dbg/x64dbg",
"PaddlePaddle/PaddleOCR",
"AlistGo/alist",
"android/architecture-samples",
"meteor/meteor",
"jestjs/jest",
"ColorlibHQ/AdminLTE",
"pixijs/pixijs",
"slab/quill",
"FuelLabs/fuels-ts",
"FuelLabs/fuels-rs",
"pandas-dev/pandas",
"huginn/huginn",
"type-challenges/type-challenges",
"nlohmann/json",
"parcel-bundler/parcel",
"Asabeneh/30-Days-Of-JavaScript",
"vercel/hyper",
"aymericdamien/TensorFlow-Examples",
"jakevdp/PythonDataScienceHandbook",
"astaxie/build-web-application-with-golang",
"babel/babel",
"Asabeneh/30-Days-Of-Python",
"toeverything/AFFiNE",
"google/zx",
"hashicorp/terraform",
"square/retrofit",
"dkhamsing/open-source-ios-apps",
"isocpp/CppCoreGuidelines",
"brillout/awesome-react-components",
"TanStack/query",
"dypsilon/frontend-dev-bookmarks",
"discourse/discourse",
"akullpp/awesome-java",
"skylot/jadx",
"grpc/grpc",
"streamich/react-use",
"pocketbase/pocketbase",
"serhii-londar/open-source-mac-os-apps",
"lllyasviel/Fooocus",
"k88hudson/git-flight-rules",
"react-hook-form/react-hook-form",
"yangshun/front-end-interview-handbook",
"clash-verge-rev/clash-verge-rev",
"Homebrew/brew",
"Unitech/pm2",
"Leaflet/Leaflet",
"hacksider/Deep-Live-Cam",
"kelseyhightower/kubernetes-the-hard-way",
"yarnpkg/yarn",
"Alamofire/Alamofire",
"lyswhut/lx-music-desktop",
"oobabooga/text-generation-webui",
"bailicangdu/vue2-elm",
"jeecgboot/JeecgBoot",
"GitSquared/edex-ui",
"RocketChat/Rocket.Chat",
"dbeaver/dbeaver",
"THUDM/ChatGLM-6B",
"microsoft/monaco-editor",
"faif/python-patterns",
"LeCoupa/awesome-cheatsheets",
"styled-components/styled-components",
"apache/dubbo",
"DovAmir/awesome-design-patterns",
"nwjs/nw.js",
"alex/what-happens-when",
"sudheerj/reactjs-interview-questions",
"dcloudio/uni-app",
"apache/spark",
"dotnet/aspnetcore",
"novuhq/novu",
"naptha/tesseract.js",
"babysor/MockingBird",
"freeCodeCamp/devdocs",
"SimplifyJobs/Summer2025-Internships",
"zhongyang219/TrafficMonitor",
"denysdovhan/wtfjs",
"ziglang/zig",
"expo/expo",
"lukasz-madon/awesome-remote-job",
"geekxh/hello-algorithm",
"alvarotrigo/fullPage.js",
"coollabsio/coolify",
"shadowsocks/shadowsocks-android",
"koajs/koa",
"SheetJS/sheetjs",
"trpc/trpc",
"LC044/WeChatMsg",
"rasbt/LLMs-from-scratch",
"microsoft/AI-For-Beginners",
"Kong/insomnia",
"usememos/memos",
"airbnb/lottie-android",
"huihut/interview",
"jgm/pandoc",
@ -353,39 +232,6 @@
"files-community/Files",
"sahat/hackathon-starter",
"appsmithorg/appsmith",
"formulahendry/955.WLB",
"lapce/lapce",
"jondot/awesome-react-native",
"bumptech/glide",
"carbon-app/carbon",
"unknwon/the-way-to-go_ZH_CN",
"chenfei-wu/TaskMatrix",
"typeorm/typeorm",
"gradio-app/gradio",
"google-research/google-research",
"colinhacks/zod",
"sharkdp/fd",
"saadeghi/daisyui",
"nodejs/node-v0.x-archive",
"ray-project/ray",
"rapid7/metasploit-framework",
"maybe-finance/maybe",
"OpenBB-finance/OpenBB",
"gofiber/fiber",
"junegunn/vim-plug",
"halo-dev/halo",
"DIYgod/RSSHub",
"goabstract/Awesome-Design-Tools",
"docker/compose",
"helix-editor/helix",
"penpot/penpot",
"httpie/cli",
"BVLC/caffe",
"hankcs/HanLP",
"AykutSarac/jsoncrack.com",
"zenorocha/clipboard.js",
"jaredpalmer/formik",
"testerSunshine/12306",
"ultralytics/ultralytics",
"slidevjs/slidev",
"xitu/gold-miner",
@ -395,30 +241,11 @@
"shadowsocks/shadowsocks",
"ccxt/ccxt",
"netty/netty",
"PKUanonym/REKCARC-TSC-UHT",
"tw93/Pake",
"fxsjy/jieba",
"atlassian/react-beautiful-dnd",
"ToolJet/ToolJet",
"markedjs/marked",
"Blankj/AndroidUtilCode",
"AFNetworking/AFNetworking",
"alebcay/awesome-shell",
"spacedriveapp/spacedrive",
"adobe/brackets",
"karanpratapsingh/system-design",
"xkcoding/spring-boot-demo",
"halfrost/LeetCode-Go",
"XX-net/XX-Net",
"gulpjs/gulp",
"immutable-js/immutable-js",
"nushell/nushell",
"calcom/cal.com",
"2noise/ChatTTS",
"zxing/zxing",
"alibaba/easyexcel",
"GitHubDaily/GitHubDaily",
"sqlmapproject/sqlmap",
"typicode/husky",
"laravel/framework",
"TheAlgorithms/JavaScript",
@ -428,152 +255,6 @@
"huggingface/pytorch-image-models",
"shadowsocks/ShadowsocksX-NG",
"carbon-language/carbon-lang",
"chatchat-space/Langchain-Chatchat",
"jaywcjlove/linux-command",
"FlowiseAI/Flowise",
"harness/harness",
"fengdu78/Coursera-ML-AndrewNg-Notes",
"google/material-design-lite",
"freqtrade/freqtrade",
"bayandin/awesome-awesomeness",
"KRTirtho/spotube",
"geekcomputers/Python",
"Pythagora-io/gpt-pilot",
"reworkd/AgentGPT",
"python-poetry/poetry",
"TeamNewPipe/NewPipe",
"facebookresearch/faiss",
"astral-sh/uv",
"kilimchoi/engineering-blogs",
"zhayujie/chatgpt-on-wechat",
"vllm-project/vllm",
"The-Run-Philosophy-Organization/run",
"certbot/certbot",
"upscayl/upscayl",
"beego/beego",
"zsh-users/zsh-autosuggestions",
"Trinea/android-open-project",
"Chanzhaoyu/chatgpt-web",
"CMU-Perceptual-Computing-Lab/openpose",
"hashicorp/vault",
"ryanhanwu/How-To-Ask-Questions-The-Smart-Way",
"swc-project/swc",
"portainer/portainer",
"milvus-io/milvus",
"hasura/graphql-engine",
"ibraheemdev/modern-unix",
"makeplane/plane",
"ziadoz/awesome-php",
"qishibo/AnotherRedisDesktopManager",
"ehang-io/nps",
"yewstack/yew",
"SeleniumHQ/selenium",
"mattermost/mattermost",
"blueimp/jQuery-File-Upload",
"TheAlgorithms/C-Plus-Plus",
"lllyasviel/ControlNet",
"ReactiveX/rxjs",
"pola-rs/polars",
"SerenityOS/serenity",
"amix/vimrc",
"pcottle/learnGitBranching",
"microsoft/MS-DOS",
"dockur/windows",
"mqyqingfeng/Blog",
"facebookresearch/detectron2",
"jax-ml/jax",
"jqlang/jq",
"niklasvh/html2canvas",
"geekan/HowToLiveLonger",
"veggiemonk/awesome-docker",
"vercel/swr",
"airbnb/lottie-web",
"facebookresearch/fairseq",
"lizongying/my-tv",
"gedoor/legado",
"zbezj/HEU_KMS_Activator",
"alibaba/p3c",
"karpathy/LLM101n",
"alibaba/nacos",
"lib-pku/libpku",
"explosion/spaCy",
"mathiasbynens/dotfiles",
"yunjey/pytorch-tutorial",
"huiyadanli/RevokeMsgPatcher",
"ityouknow/spring-boot-examples",
"Binaryify/NeteaseCloudMusicApi",
"floating-ui/floating-ui",
"remix-run/remix",
"cockroachdb/cockroach",
"remoteintech/remote-jobs",
"binarywang/WxJava",
"0xAX/linux-insides",
"labstack/echo",
"balena-io/etcher",
"ianstormtaylor/slate",
"myshell-ai/OpenVoice",
"ShareX/ShareX",
"pnpm/pnpm",
"joshbuchea/HEAD",
"coolsnowwolf/lede",
"qier222/YesPlayMusic",
"microsoft/calculator",
"symfony/symfony",
"aseprite/aseprite",
"SortableJS/Sortable",
"v2fly/v2ray-core",
"open-mmlab/mmdetection",
"vuejs/vue-cli",
"webtorrent/webtorrent",
"layui/layui",
"payloadcms/payload",
"foundation/foundation-sites",
"tatsu-lab/stanford_alpaca",
"sequelize/sequelize",
"donnemartin/interactive-coding-challenges",
"kubernetes/minikube",
"llvm/llvm-project",
"pbatard/rufus",
"gchq/CyberChef",
"react-boilerplate/react-boilerplate",
"parallax/jsPDF",
"ariya/phantomjs",
"zeromicro/go-zero",
"square/leakcanary",
"dokku/dokku",
"lovell/sharp",
"elsewhencode/project-guidelines",
"aosabook/500lines",
"AMAI-GmbH/AI-Expert-Roadmap",
"dromara/hutool",
"fabricjs/fabric.js",
"transloadit/uppy",
"IanLunn/Hover",
"apolloconfig/apollo",
"lukehoban/es6features",
"VincentGarreau/particles.js",
"standard/standard",
"OAI/OpenAPI-Specification",
"influxdata/influxdb",
"CSSEGISandData/COVID-19",
"apache/kafka",
"trailofbits/algo",
"JushBJJ/Mr.-Ranedeer-AI-Tutor",
"codex-team/editor.js",
"herrbischoff/awesome-macos-command-line",
"mckaywrigley/chatbot-ui",
"linexjlin/GPTs",
"mpv-player/mpv",
"refinedev/refine",
"alan2207/bulletproof-react",
"jobbole/awesome-python-cn",
"tqdm/tqdm",
"kodecocodes/swift-algorithm-club",
"outline/outline",
"qbittorrent/qBittorrent",
"facebook/rocksdb",
"xinntao/Real-ESRGAN",
"cheeriojs/cheerio",
"s0md3v/roop",
"ascoders/weekly",
"backstage/backstage",
@ -582,89 +263,6 @@
"tastejs/todomvc",
"lutzroeder/netron",
"alibaba/canal",
"Lightning-AI/pytorch-lightning",
"encode/django-rest-framework",
"postcss/postcss",
"facebook/folly",
"kenwheeler/slick",
"Ebazhanov/linkedin-skill-assessments-quizzes",
"alpinejs/alpine",
"GoogleChrome/lighthouse",
"AllThingsSmitty/css-protips",
"Mintplex-Labs/anything-llm",
"hashicorp/consul",
"charmbracelet/bubbletea",
"realpython/python-guide",
"mifi/lossless-cut",
"wuyouzhuguli/SpringAll",
"vuejs/vuex",
"microsoft/Data-Science-For-Beginners",
"usebruno/bruno",
"directus/directus",
"fastapi/full-stack-fastapi-template",
"MonitorControl/MonitorControl",
"OWASP/CheatSheetSeries",
"schollz/croc",
"codepath/android_guides",
"k3s-io/k3s",
"numpy/numpy",
"pmndrs/react-spring",
"YunaiV/ruoyi-vue-pro",
"surrealdb/surrealdb",
"ZuzooVn/machine-learning-for-software-engineers",
"caolan/async",
"google/comprehensive-rust",
"ageron/handson-ml2",
"jashkenas/backbone",
"alibaba/spring-cloud-alibaba",
"acheong08/ChatGPT",
"GorvGoyl/Clone-Wars",
"alibaba/druid",
"docsifyjs/docsify",
"jamiebuilds/the-super-tiny-compiler",
"xuxueli/xxl-job",
"iawia002/lux",
"google-ai-edge/mediapipe",
"hiroi-sora/Umi-OCR",
"ueberdosis/tiptap",
"digitalocean/nginxconfig.io",
"wesbos/JavaScript30",
"immerjs/immer",
"viraptor/reverse-interview",
"pmndrs/react-three-fiber",
"derailed/k9s",
"JedWatson/react-select",
"nextcloud/server",
"Pierian-Data/Complete-Python-3-Bootcamp",
"ChartsOrg/Charts",
"nagadomi/waifu2x",
"mobxjs/mobx",
"donnemartin/data-science-ipython-notebooks",
"DevToys-app/DevToys",
"zadam/trilium",
"cfenollosa/os-tutorial",
"google-research/tuning_playbook",
"meta-llama/llama3",
"lenve/vhr",
"mli/paper-reading",
"Advanced-Frontend/Daily-Interview-Question",
"YMFE/yapi",
"spf13/viper",
"eugeneyan/applied-ml",
"MichaelCade/90DaysOfDevOps",
"utmapp/UTM",
"jashkenas/underscore",
"vadimdemedes/ink",
"geekcompany/ResumeSample",
"tokio-rs/tokio",
"GitbookIO/gitbook",
"statelyai/xstate",
"cloudcommunity/Free-Certifications",
"google/python-fire",
"mouredev/Hello-Python",
"Tencent/weui",
"nothings/stb",
"helm/helm",
"tinygrad/tinygrad",
"ManimCommunity/manim",
"filebrowser/filebrowser",
@ -674,151 +272,26 @@
"crossoverJie/JCSprout",
"mantinedev/mantine",
"Automattic/mongoose",
"zhiwehu/Python-programming-exercises",
"michalsnik/aos",
"Homebrew/legacy-homebrew",
"mudler/LocalAI",
"HeyPuter/puter",
"mindsdb/mindsdb",
"restic/restic",
"codemirror/codemirror5",
"CamDavidsonPilon/Probabilistic-Programming-and-Bayesian-Methods-for-Hackers",
"tj/commander.js",
"rethinkdb/rethinkdb",
"dnSpy/dnSpy",
"fzaninotto/Faker",
"angular/angular-cli",
"ajaxorg/ace",
"coder2gwy/coder2gwy",
"qianguyihao/Web",
"houshanren/hangzhou_house_knowledge",
"swagger-api/swagger-ui",
"sampotts/plyr",
"IceWhaleTech/CasaOS",
"nvie/gitflow",
"go-kit/kit",
"imDazui/Tvlist-awesome-m3u-m3u8",
"exelban/stats",
"huggingface/diffusers",
"vercel/turborepo",
"AmruthPillai/Reactive-Resume",
"getredash/redash",
"python-telegram-bot/python-telegram-bot",
"telegramdesktop/tdesktop",
"mongodb/mongo",
"bvaughn/react-virtualized",
"firecracker-microvm/firecracker",
"openai/CLIP",
"fish-shell/fish-shell",
"dmlc/xgboost",
"fastai/fastai",
"tailwindlabs/headlessui",
"medusajs/medusa",
"xyflow/xyflow",
"remy/nodemon",
"hashicorp/vagrant",
"XIU2/TrackersListCollection",
"LadybirdBrowser/ladybird",
"facebookresearch/Detectron",
"dragonflydb/dragonfly",
"motiondivision/motion",
"grafana/k6",
"AvaloniaUI/Avalonia",
"qiurunze123/miaosha",
"ggreer/the_silver_searcher",
"vnpy/vnpy",
"rstacruz/nprogress",
"Asabeneh/30-Days-Of-React",
"microsoft/cascadia-code",
"rxhanson/Rectangle",
"openssl/openssl",
"spipm/Depix",
"svc-develop-team/so-vits-svc",
"XTLS/Xray-core",
"sunface/rust-course",
"quasarframework/quasar",
"deezer/spleeter",
"getcursor/cursor",
"cmderdev/cmder",
"kuchin/awesome-cto",
"Textualize/textual",
"facebookresearch/fastText",
"ossrs/srs",
"sindresorhus/awesome-electron",
"emscripten-core/emscripten",
"AdguardTeam/AdGuardHome",
"danielmiessler/fabric",
"select2/select2",
"pjreddie/darknet",
"OpenBMB/ChatDev",
"awesome-foss/awesome-sysadmin",
"airbnb/lottie-ios",
"dwmkerr/hacker-laws",
"powerline/fonts",
"vbenjs/vue-vben-admin",
"VSCodium/vscodium",
"wailsapp/wails",
"alibaba/fastjson",
"JakeChampion/fetch",
"signalapp/Signal-Android",
"t3-oss/create-t3-app",
"littlecodersh/ItChat",
"ValdikSS/GoodbyeDPI",
"jumpserver/jumpserver",
"request/request",
"chatanywhere/GPT_API_free",
"Modernizr/Modernizr",
"tmrts/go-patterns",
"taichi-dev/taichi",
"DigitalPlatDev/FreeDomain",
"haizlin/fe-interview",
"terryum/awesome-deep-learning-papers",
"DataTalksClub/data-engineering-zoomcamp",
"JakeWharton/butterknife",
"discordjs/discord.js",
"ChrisTitusTech/winutil",
"ycm-core/YouCompleteMe",
"Vision-CAIR/MiniGPT-4",
"DrKLO/Telegram",
"mozilla/DeepSpeech",
"hwdsl2/setup-ipsec-vpn",
"nginx/nginx",
"rollup/rollup",
"mbeaudru/modern-js-cheatsheet",
"ZuodaoTech/everyone-can-use-english",
"apache/incubator-seata",
"TanStack/table",
"hollischuang/toBeTopJavaer",
"fyne-io/fyne",
"sdras/awesome-actions",
"academic/awesome-datascience",
"ApolloAuto/apollo",
"zyedidia/micro",
"akveo/ngx-admin",
"kataras/iris",
"refined-github/refined-github",
"openfaas/faas",
"infiniflow/ragflow",
"ageron/handson-ml",
"locustio/locust",
"eslint/eslint",
"nextauthjs/next-auth",
"viatsko/awesome-vscode",
"flameshot-org/flameshot",
"envoyproxy/envoy",
"RVC-Project/Retrieval-based-Voice-Conversion-WebUI",
"valinet/ExplorerPatcher",
"react-native-elements/react-native-elements",
"NvChad/NvChad",
"marmelab/react-admin",
"feathericons/feather",
"datasciencemasters/go",
"OpenZeppelin/openzeppelin-contracts",
"SDWebImage/SDWebImage",
"celery/celery",
"drizzle-team/drizzle-orm",
"nsqio/nsq"
"envoyproxy/envoy"
]
},
{
"type": "gitlab",
"token": {
"env": "GITLAB_TOKEN"
},
"groups": [
"fdroid"
],
"exclude": {
"projects": [
"fdroid/wiki",
"Matrixcoffee/internal-twif-preview"
]
}
}
]
}

View file

@ -70,14 +70,16 @@ if [ ! -f "$FIRST_RUN_FILE" ]; then
# If this is our first run, send a `install` event to PostHog
# (if telemetry is enabled)
if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
curl -L -s --header "Content-Type: application/json" -d '{
if ! ( curl -L --output /dev/null --silent --fail --header "Content-Type: application/json" -d '{
"api_key": "'"$POSTHOG_PAPIK"'",
"event": "install",
"distinct_id": "'"$SOURCEBOT_INSTALL_ID"'",
"properties": {
"sourcebot_version": "'"$SOURCEBOT_VERSION"'"
}
}' https://us.i.posthog.com/capture/ > /dev/null
}' https://us.i.posthog.com/capture/ ) then
echo -e "\e[33m[Warning] Failed to send install event.\e[0m"
fi
fi
else
export SOURCEBOT_INSTALL_ID=$(cat "$FIRST_RUN_FILE" | jq -r '.install_id')
@ -88,7 +90,7 @@ else
echo -e "\e[34m[Info] Upgraded from version $PREVIOUS_VERSION to $SOURCEBOT_VERSION\e[0m"
if [ -z "$SOURCEBOT_TELEMETRY_DISABLED" ]; then
curl -L -s --header "Content-Type: application/json" -d '{
if ! ( curl -L --output /dev/null --silent --fail --header "Content-Type: application/json" -d '{
"api_key": "'"$POSTHOG_PAPIK"'",
"event": "upgrade",
"distinct_id": "'"$SOURCEBOT_INSTALL_ID"'",
@ -96,7 +98,9 @@ else
"from_version": "'"$PREVIOUS_VERSION"'",
"to_version": "'"$SOURCEBOT_VERSION"'"
}
}' https://us.i.posthog.com/capture/ > /dev/null
}' https://us.i.posthog.com/capture/ ) then
echo -e "\e[33m[Warning] Failed to send upgrade event.\e[0m"
fi
fi
fi
fi
@ -117,6 +121,11 @@ echo "{\"version\": \"$SOURCEBOT_VERSION\", \"install_id\": \"$SOURCEBOT_INSTALL
export NEXT_PUBLIC_SOURCEBOT_VERSION="$SOURCEBOT_VERSION"
fi
# Infer NEXT_PUBLIC_PUBLIC_SEARCH_DEMO if it is not set
if [ -z "$NEXT_PUBLIC_PUBLIC_SEARCH_DEMO" ] && [ ! -z "$PUBLIC_SEARCH_DEMO" ]; then
export NEXT_PUBLIC_PUBLIC_SEARCH_DEMO="$PUBLIC_SEARCH_DEMO"
fi
# Always infer NEXT_PUBLIC_POSTHOG_PAPIK
export NEXT_PUBLIC_POSTHOG_PAPIK="$POSTHOG_PAPIK"
@ -139,6 +148,7 @@ echo "{\"version\": \"$SOURCEBOT_VERSION\", \"install_id\": \"$SOURCEBOT_INSTALL
sed -i "s|BAKED_NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY|${NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY}|g" "$file"
sed -i "s|BAKED_NEXT_PUBLIC_SENTRY_ENVIRONMENT|${NEXT_PUBLIC_SENTRY_ENVIRONMENT}|g" "$file"
sed -i "s|BAKED_NEXT_PUBLIC_SENTRY_WEBAPP_DSN|${NEXT_PUBLIC_SENTRY_WEBAPP_DSN}|g" "$file"
sed -i "s|BAKED_NEXT_PUBLIC_PUBLIC_SEARCH_DEMO|${NEXT_PUBLIC_PUBLIC_SEARCH_DEMO}|g" "$file"
done
}

View file

@ -18,7 +18,7 @@
"tsc-watch": "^6.2.0",
"tsx": "^4.19.1",
"typescript": "^5.6.2",
"vitest": "^2.1.4"
"vitest": "^2.1.9"
},
"dependencies": {
"@gitbeaker/rest": "^40.5.1",

View file

@ -12,5 +12,6 @@ export const DEFAULT_SETTINGS: Settings = {
configSyncConcurrencyMultiple: 3,
gcConcurrencyMultiple: 1,
gcGracePeriodMs: 10 * 1000, // 10 seconds
repoIndexTimeoutMs: 1000 * 60 * 60 * 2 // 2 hours
repoIndexTimeoutMs: 1000 * 60 * 60 * 2, // 2 hours
maxTrigramCount: 20000,
}

View file

@ -16,9 +16,13 @@ export type AppContext = {
export type Settings = {
/**
* The maximum size of a file (in bytes) to be indexed. Files that exceed this maximum will not be inexed.
* The maximum size of a file (in bytes) to be indexed. Files that exceed this maximum will not be indexed.
*/
maxFileSize: number;
/**
* The maximum number of trigrams per document. Files that exceed this maximum will not be indexed.
*/
maxTrigramCount: number;
/**
* The interval (in milliseconds) at which the indexer should re-index all repositories.
*/

View file

@ -58,7 +58,7 @@ export const indexGitRepository = async (repo: Repo, ctx: AppContext) => {
revisions = revisions.slice(0, 64);
}
const command = `zoekt-git-index -allow_missing_branches -index ${ctx.indexPath} -file_limit ${DEFAULT_SETTINGS.maxFileSize} -branches ${revisions.join(',')} -tenant_id ${repo.orgId} -shard_prefix ${shardPrefix} ${repoPath}`;
const command = `zoekt-git-index -allow_missing_branches -index ${ctx.indexPath} -max_trigram_count ${DEFAULT_SETTINGS.maxTrigramCount} -file_limit ${DEFAULT_SETTINGS.maxFileSize} -branches ${revisions.join(',')} -tenant_id ${repo.orgId} -shard_prefix ${shardPrefix} ${repoPath}`;
return new Promise<{ stdout: string, stderr: string }>((resolve, reject) => {
exec(command, (error, stdout, stderr) => {

View file

@ -595,6 +595,17 @@ const schema = {
"default": 2097152,
"minimum": 1
},
"maxTrigramCount": {
"type": "integer",
"description": "The maximum amount of trigrams per document. Documents that exceed this maximum will not be indexed. Defaults to 20000",
"default": 20000,
"minimum": 1
},
"autoDeleteStaleRepos": {
"type": "boolean",
"description": "Automatically delete stale repositories from the index. Defaults to true.",
"default": true
},
"reindexInterval": {
"type": "integer",
"description": "The interval (in milliseconds) at which the indexer should re-index all repositories. Repositories are always indexed when first added. Defaults to 1 hour (3600000 milliseconds).",

View file

@ -40,6 +40,14 @@ export interface Settings {
* The maximum size of a file (in bytes) to be indexed. Files that exceed this maximum will not be inexed. Defaults to 2MB (2097152 bytes).
*/
maxFileSize?: number;
/**
* The maximum amount of trigrams per document. Documents that exceed this maximum will not be indexed. Defaults to 20000
*/
maxTrigramCount?: number;
/**
* Automatically delete stale repositories from the index. Defaults to true.
*/
autoDeleteStaleRepos?: boolean;
/**
* The interval (in milliseconds) at which the indexer should re-index all repositories. Repositories are always indexed when first added. Defaults to 1 hour (3600000 milliseconds).
*/

View file

@ -115,7 +115,7 @@ export const EditorContextMenu = ({
description: "✅ Copied link to selection",
});
captureEvent('share_link_created', {});
captureEvent('wa_share_link_created', {});
// Reset the selection
view.dispatch(

View file

@ -43,6 +43,7 @@ import { Separator } from "@/components/ui/separator";
import { Tooltip, TooltipTrigger, TooltipContent } from "@/components/ui/tooltip";
import { Toggle } from "@/components/ui/toggle";
import { useDomain } from "@/hooks/useDomain";
import { KeyboardShortcutHint } from "../keyboardShortcutHint";
interface SearchBarProps {
className?: string;
@ -266,6 +267,7 @@ export const SearchBar = ({
indentWithTab={false}
autoFocus={autoFocus ?? false}
/>
<KeyboardShortcutHint shortcut="/" />
<SearchSuggestionsBox
ref={suggestionBoxRef}
query={query}

View file

@ -17,6 +17,7 @@ import { VscFile, VscFilter, VscRepo, VscSymbolMisc } from "react-icons/vsc";
import { Skeleton } from "@/components/ui/skeleton";
import { Separator } from "@/components/ui/separator";
import { KeyboardShortcutHint } from "../keyboardShortcutHint";
import { useSyntaxGuide } from "@/app/[domain]/components/syntaxGuideProvider";
export type Suggestion = {
value: string;
@ -79,6 +80,7 @@ const SearchSuggestionsBox = forwardRef(({
searchHistorySuggestions,
}: SearchSuggestionsBoxProps, ref: Ref<HTMLDivElement>) => {
const [highlightedSuggestionIndex, setHighlightedSuggestionIndex] = useState(0);
const { onOpenChanged } = useSyntaxGuide();
const { suggestions, isHighlightEnabled, descriptionPlacement, DefaultIcon, onSuggestionClicked } = useMemo(() => {
if (!isEnabled) {
@ -391,7 +393,10 @@ const SearchSuggestionsBox = forwardRef(({
className="my-2"
/>
<div className="flex flex-row items-center justify-between mt-1">
<div className="flex flex-row gap-1.5 items-center">
<div
className="flex flex-row gap-1.5 items-center cursor-pointer"
onClick={() => onOpenChanged(true)}
>
<p className="text-muted-foreground text-sm">
Syntax help:
</p>

View file

@ -0,0 +1,32 @@
'use client';
import { createContext, useContext, useCallback, useState } from 'react';
interface SyntaxGuideContextType {
isOpen: boolean;
onOpenChanged: (isOpen: boolean) => void;
}
const SyntaxGuideContext = createContext<SyntaxGuideContextType | null>(null);
export const useSyntaxGuide = () => {
const context = useContext(SyntaxGuideContext);
if (!context) {
throw new Error('useSyntaxGuide must be used within a SyntaxGuideProvider');
}
return context;
};
export const SyntaxGuideProvider = ({ children }: { children: React.ReactNode }) => {
const [isOpen, setIsOpen] = useState(false);
const onOpenChanged = useCallback((isOpen: boolean) => {
setIsOpen(isOpen);
}, []);
return (
<SyntaxGuideContext.Provider value={{ isOpen, onOpenChanged }}>
{children}
</SyntaxGuideContext.Provider>
);
};

View file

@ -12,30 +12,31 @@ import {
} from "@/components/ui/table";
import clsx from "clsx";
import Link from "next/link";
import { useCallback, useRef, useState } from "react";
import { useCallback, useRef } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { useSyntaxGuide } from "./syntaxGuideProvider";
const LINGUIST_LINK = "https://github.com/github-linguist/linguist/blob/main/lib/linguist/languages.yml";
const CTAGS_LINK = "https://ctags.io/";
export const SyntaxReferenceGuide = () => {
const [isOpen, setIsOpen] = useState(false);
const { isOpen, onOpenChanged } = useSyntaxGuide();
const previousFocusedElement = useRef<HTMLElement | null>(null);
const openDialog = useCallback(() => {
previousFocusedElement.current = document.activeElement as HTMLElement;
setIsOpen(true);
}, []);
onOpenChanged(true);
}, [onOpenChanged]);
const closeDialog = useCallback(() => {
setIsOpen(false);
onOpenChanged(false);
// @note: Without requestAnimationFrame, focus was not being returned
// to codemirror elements for some reason.
requestAnimationFrame(() => {
previousFocusedElement.current?.focus();
});
}, []);
}, [onOpenChanged]);
const handleOpenChange = useCallback((isOpen: boolean) => {
if (isOpen) {

View file

@ -0,0 +1,17 @@
'use client';
import { useSyntaxGuide } from "./syntaxGuideProvider";
import { KeyboardShortcutHint } from "../../components/keyboardShortcutHint";
export const SyntaxReferenceGuideHint = () => {
const { isOpen, onOpenChanged } = useSyntaxGuide();
return (
<div
className="text-sm cursor-pointer"
onClick={() => onOpenChanged(!isOpen)}
>
<span className="dark:text-gray-300">Reference guide: </span><KeyboardShortcutHint shortcut="⌘" /> <KeyboardShortcutHint shortcut="/" />
</div>
)
}

View file

@ -2,9 +2,10 @@
import { useToast } from "@/components/hooks/use-toast";
import { ToastAction } from "@/components/ui/toast";
import { NEXT_PUBLIC_SOURCEBOT_VERSION } from "@/lib/environment.client";
import { useEffect } from "react";
import { useLocalStorage } from "usehooks-ts";
import { getVersion } from "@/app/api/(client)/client";
import { useQuery } from "@tanstack/react-query";
const GITHUB_TAGS_URL = "https://api.github.com/repos/sourcebot-dev/sourcebot/tags";
const SEMVER_REGEX = /^v(\d+)\.(\d+)\.(\d+)$/;
@ -23,8 +24,18 @@ export const UpgradeToast = () => {
new Date(0).toUTCString()
);
const { data: versionString } = useQuery({
queryKey: ["version"],
queryFn: () => getVersion(),
select: (data) => data.version,
})
useEffect(() => {
const currentVersion = getVersionFromString(NEXT_PUBLIC_SOURCEBOT_VERSION);
if (!versionString) {
return;
}
const currentVersion = getVersionFromString(versionString);
if (!currentVersion) {
return;
}
@ -71,7 +82,7 @@ export const UpgradeToast = () => {
setUpgradeToastLastShownDate(new Date().toUTCString());
});
}, [setUpgradeToastLastShownDate, toast, upgradeToastLastShownDate]);
}, [setUpgradeToastLastShownDate, toast, upgradeToastLastShownDate, versionString]);
return null;
}

View file

@ -11,6 +11,7 @@ import { getSelectorsByUserAgent } from "react-device-detect";
import { MobileUnsupportedSplashScreen } from "./components/mobileUnsupportedSplashScreen";
import { MOBILE_UNSUPPORTED_SPLASH_SCREEN_DISMISSED_COOKIE_NAME } from "@/lib/constants";
import { SyntaxReferenceGuide } from "./components/syntaxReferenceGuide";
import { SyntaxGuideProvider } from "./components/syntaxGuideProvider";
interface LayoutProps {
children: React.ReactNode,
@ -81,9 +82,9 @@ export default async function Layout({
)
}
return (
<>
<SyntaxGuideProvider>
{children}
<SyntaxReferenceGuide />
</>
</SyntaxGuideProvider>
)
}

View file

@ -8,7 +8,7 @@ import { PageNotFound } from "./components/pageNotFound";
import { Footer } from "@/app/components/footer";
import { SourcebotLogo } from "../components/sourcebotLogo";
import { RepositorySnapshot } from "./components/repositorySnapshot";
import { KeyboardShortcutHint } from "./components/keyboardShortcutHint";
import { SyntaxReferenceGuideHint } from "./components/syntaxReferenceGuideHint";
export default async function Home({ params: { domain } }: { params: { domain: string } }) {
const org = await getOrgFromDomain(domain);
@ -88,9 +88,7 @@ export default async function Home({ params: { domain } }: { params: { domain: s
</QueryExample>
</HowToSection>
</div>
<div className="text-sm">
<span className="dark:text-gray-300">Reference guide: </span><KeyboardShortcutHint shortcut="⌘" /> <KeyboardShortcutHint shortcut="/" />
</div>
<SyntaxReferenceGuideHint />
</div>
</div>
<Footer />

View file

@ -51,6 +51,7 @@ export const CodePreviewPanel = ({
if (!template || !template.match(/^{{URLJoinPath\s.*}}(\?.+)?$/)) {
return undefined;
}
const url =
template.substring("{{URLJoinPath ".length,template.indexOf("}}"))
.replace(".Version", branch ?? "HEAD")

View file

@ -22,6 +22,7 @@ import { CodePreviewPanel } from "./components/codePreviewPanel";
import { FilterPanel } from "./components/filterPanel";
import { SearchResultsPanel } from "./components/searchResultsPanel";
import { useDomain } from "@/hooks/useDomain";
import { NEXT_PUBLIC_PUBLIC_SEARCH_DEMO } from "@/lib/environment.client";
const DEFAULT_MAX_MATCH_DISPLAY_COUNT = 10000;
@ -104,6 +105,7 @@ const SearchPageInternal = () => {
const fileLanguages = searchResponse.Result.Files?.map(file => file.Language) || [];
captureEvent("search_finished", {
query: NEXT_PUBLIC_PUBLIC_SEARCH_DEMO ? searchQuery : null, // @nocheckin
contentBytesLoaded: searchResponse.Result.ContentBytesLoaded,
indexBytesLoaded: searchResponse.Result.IndexBytesLoaded,
crashes: searchResponse.Result.Crashes,
@ -126,7 +128,7 @@ const SearchPageInternal = () => {
flushReason: searchResponse.Result.FlushReason,
fileLanguages,
});
}, [captureEvent, searchResponse]);
}, [captureEvent, searchQuery, searchResponse]);
const { fileMatches, searchDurationMs, totalMatchCount, isBranchFilteringEnabled, repoUrlTemplates } = useMemo(() => {
if (!searchResponse) {

View file

@ -1,8 +1,8 @@
'use client';
import { NEXT_PUBLIC_DOMAIN_SUB_PATH } from "@/lib/environment.client";
import { fileSourceResponseSchema, listRepositoriesResponseSchema, searchResponseSchema } from "@/lib/schemas";
import { FileSourceRequest, FileSourceResponse, ListRepositoriesResponse, SearchRequest, SearchResponse } from "@/lib/types";
import { fileSourceResponseSchema, getVersionResponseSchema, listRepositoriesResponseSchema, searchResponseSchema } from "@/lib/schemas";
import { FileSourceRequest, FileSourceResponse, GetVersionResponse, ListRepositoriesResponse, SearchRequest, SearchResponse } from "@/lib/types";
import assert from "assert";
export const search = async (body: SearchRequest, domain: string): Promise<SearchResponse> => {
@ -46,6 +46,17 @@ export const getRepos = async (domain: string): Promise<ListRepositoriesResponse
return listRepositoriesResponseSchema.parse(result);
}
export const getVersion = async (): Promise<GetVersionResponse> => {
const path = resolveServerPath("/api/version");
const result = await fetch(path, {
method: "GET",
headers: {
"Content-Type": "application/json",
},
}).then(response => response.json());
return getVersionResponseSchema.parse(result);
}
/**
* Given a subpath to a api route on the server (e.g., /api/search),
* returns the full path to that route on the server, taking into account

View file

@ -0,0 +1,15 @@
import { SOURCEBOT_VERSION } from "@/lib/environment";
import { GetVersionResponse } from "@/lib/types";
// Note: In Next.JS 14, GET methods with no params are cached by default at build time.
// This creates issues since environment variables (like SOURCEBOT_VERSION) are
// not available until runtime. To work around this, we fore the route to be
// dynamic and evaluate on each request.
// @see: https://nextjs.org/docs/14/app/building-your-application/routing/route-handlers#caching
export const dynamic = "force-dynamic";
export const GET = async () => {
return Response.json({
version: SOURCEBOT_VERSION,
} satisfies GetVersionResponse);
}

View file

@ -0,0 +1,16 @@
import React from 'react'
interface KeyboardShortcutHintProps {
shortcut: string
label?: string
}
export function KeyboardShortcutHint({ shortcut, label }: KeyboardShortcutHintProps) {
return (
<div className="inline-flex items-center" aria-label={label || `Keyboard shortcut: ${shortcut}`}>
<kbd className="px-2 py-1 text-xs font-semibold border rounded-md">
{shortcut}
</kbd>
</div>
)
}

View file

@ -0,0 +1,49 @@
"use client"
import { useState } from "react"
import Link from "next/link"
import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from "@/components/ui/card"
import { Button } from "@/components/ui/button"
import { ArrowRight, Database, Search } from "lucide-react"
import useCaptureEvent from "@/hooks/useCaptureEvent"
export default function RegistrationCard() {
const [isHovered, setIsHovered] = useState(false)
const captureEvent = useCaptureEvent()
return (
<Card
className="w-full max-w-md mx-auto border shadow-lg overflow-hidden"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
>
<CardHeader className="pb-2">
<CardTitle className="text-xl font-bold mt-2">Try Sourcebot Cloud</CardTitle>
<CardDescription>Index and search your own code repositories</CardDescription>
</CardHeader>
<CardContent className="space-y-4">
<div className="space-y-3">
<div className="flex items-start">
<Search className="h-5 w-5 mr-3 text-primary" />
<p className="text-sm">Search your private and public repositories</p>
</div>
<div className="flex items-start">
<Database className="h-5 w-5 mr-3 text-primary" />
<p className="text-sm">Index your own codebase in minutes</p>
</div>
</div>
</CardContent>
<CardFooter className="flex flex-col space-y-3 pt-0">
<Link href="https://app.sourcebot.dev" className="w-full" rel="noopener noreferrer" onClick={() => captureEvent("wa_demo_try_card_pressed", {})}>
<Button className={`w-full transition-all duration-300 ${isHovered ? "translate-y-[-2px]" : ""}`}>
Try With Your Code
<ArrowRight className="ml-2 h-4 w-4" />
</Button>
</Link>
<p className="text-xs text-center text-muted-foreground">
14 day free trial. No credit card required.
</p>
</CardFooter>
</Card>
)
}

View file

@ -0,0 +1,245 @@
'use client';
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
import { Separator } from "@/components/ui/separator";
import {
Table,
TableBody,
TableCell,
TableHead,
TableHeader,
TableRow,
} from "@/components/ui/table";
import clsx from "clsx";
import Link from "next/link";
import { useCallback, useRef } from "react";
import { useHotkeys } from "react-hotkeys-hook";
import { useSyntaxGuide } from "../[domain]/components/syntaxGuideProvider";
const LINGUIST_LINK = "https://github.com/github-linguist/linguist/blob/main/lib/linguist/languages.yml";
const CTAGS_LINK = "https://ctags.io/";
export const SyntaxReferenceGuide = () => {
const { isOpen, onOpenChanged } = useSyntaxGuide();
const previousFocusedElement = useRef<HTMLElement | null>(null);
const openDialog = useCallback(() => {
previousFocusedElement.current = document.activeElement as HTMLElement;
onOpenChanged(true);
}, [onOpenChanged]);
const closeDialog = useCallback(() => {
onOpenChanged(false);
// @note: Without requestAnimationFrame, focus was not being returned
// to codemirror elements for some reason.
requestAnimationFrame(() => {
previousFocusedElement.current?.focus();
});
}, [onOpenChanged]);
const handleOpenChange = useCallback((isOpen: boolean) => {
if (isOpen) {
openDialog();
} else {
closeDialog();
}
}, [closeDialog, openDialog]);
useHotkeys("mod+/", (event) => {
event.preventDefault();
handleOpenChange(!isOpen);
}, {
enableOnFormTags: true,
enableOnContentEditable: true,
description: "Open Syntax Reference Guide",
});
return (
<Dialog
open={isOpen}
onOpenChange={handleOpenChange}
>
<DialogContent
className="max-h-[80vh] max-w-[700px] overflow-scroll"
>
<DialogHeader>
<DialogTitle>Syntax Reference Guide</DialogTitle>
<DialogDescription className="text-sm text-foreground">
Queries consist of space-seperated regular expressions. Wrapping expressions in <Code>{`""`}</Code> combines them. By default, a file must have at least one match for each expression to be included.
</DialogDescription>
</DialogHeader>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Example</TableHead>
<TableHead className="py-2">Explanation</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="py-2"><Code>foo</Code></TableCell>
<TableCell className="py-2">Match files with regex <Code>/foo/</Code></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><Code>foo bar</Code></TableCell>
<TableCell className="py-2">Match files with regex <Code>/foo/</Code> <b>and</b> <Code>/bar/</Code></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><Code>{`"foo bar"`}</Code></TableCell>
<TableCell className="py-2">Match files with regex <Code>/foo bar/</Code></TableCell>
</TableRow>
</TableBody>
</Table>
<Separator className="my-2"/>
<p className="text-sm">
{`Multiple expressions can be or'd together with `}<Code>or</Code>, negated with <Code>-</Code>, or grouped with <Code>()</Code>.
</p>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Example</TableHead>
<TableHead className="py-2">Explanation</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="py-2"><Code>foo <Highlight>or</Highlight> bar</Code></TableCell>
<TableCell className="py-2">Match files with regex <Code>/foo/</Code> <b>or</b> <Code>/bar/</Code></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><Code>foo -bar</Code></TableCell>
<TableCell className="py-2">Match files with regex <Code>/foo/</Code> but <b>not</b> <Code>/bar/</Code></TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><Code>foo (bar <Highlight>or</Highlight> baz)</Code></TableCell>
<TableCell className="py-2">Match files with regex <Code>/foo/</Code> <b>and</b> either <Code>/bar/</Code> <b>or</b> <Code>/baz/</Code></TableCell>
</TableRow>
</TableBody>
</Table>
<Separator className="my-2"/>
<p className="text-sm">
Expressions can be prefixed with certain keywords to modify search behavior. Some keywords can be negated using the <Code>-</Code> prefix.
</p>
<Table>
<TableHeader>
<TableRow>
<TableHead className="py-2">Prefix</TableHead>
<TableHead className="py-2">Description</TableHead>
<TableHead className="py-2 w-[175px]">Example</TableHead>
</TableRow>
</TableHeader>
<TableBody>
<TableRow>
<TableCell className="py-2"><Code><Highlight>file:</Highlight></Code></TableCell>
<TableCell className="py-2">Filter results from filepaths that match the regex. By default all files are searched.</TableCell>
<TableCell className="py-2">
<div className="flex flex-col gap-1">
<Code
title="Filter results to filepaths that match regex /README/"
>
<Highlight>file:</Highlight>README
</Code>
<Code
title="Filter results to filepaths that match regex /my file/"
>
<Highlight>file:</Highlight>{`"my file"`}
</Code>
<Code
title="Ignore results from filepaths match regex /test\.ts$/"
>
<Highlight>-file:</Highlight>test\.ts$
</Code>
</div>
</TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><Code><Highlight>repo:</Highlight></Code></TableCell>
<TableCell className="py-2">Filter results from repos that match the regex. By default all repos are searched.</TableCell>
<TableCell className="py-2">
<div className="flex flex-col gap-1">
<Code
title="Filter results to repos that match regex /linux/"
>
<Highlight>repo:</Highlight>linux
</Code>
<Code
title="Ignore results from repos that match regex /^web\/.*/"
>
<Highlight>-repo:</Highlight>^web/.*
</Code>
</div>
</TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><Code><Highlight>rev:</Highlight></Code></TableCell>
<TableCell className="py-2">Filter results from a specific branch or tag. By default <b>only</b> the default branch is searched.</TableCell>
<TableCell className="py-2">
<div className="flex flex-col gap-1">
<Code
title="Filter results to branches that match regex /beta/"
>
<Highlight>rev:</Highlight>beta
</Code>
</div>
</TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><Code><Highlight>lang:</Highlight></Code></TableCell>
<TableCell className="py-2">Filter results by language (as defined by <Link className="text-blue-500" href={LINGUIST_LINK}>linguist</Link>). By default all languages are searched.</TableCell>
<TableCell className="py-2">
<div className="flex flex-col gap-1">
<Code
title="Filter results to TypeScript files"
>
<Highlight>lang:</Highlight>TypeScript
</Code>
<Code
title="Ignore results from YAML files"
>
<Highlight>-lang:</Highlight>YAML
</Code>
</div>
</TableCell>
</TableRow>
<TableRow>
<TableCell className="py-2"><Code><Highlight>sym:</Highlight></Code></TableCell>
<TableCell className="py-2">Match symbol definitions created by <Link className="text-blue-500" href={CTAGS_LINK}>universal ctags</Link> at index time.</TableCell>
<TableCell className="py-2">
<div className="flex flex-col gap-1">
<Code
title="Filter results to symbols that match regex /\bmain\b/"
>
<Highlight>sym:</Highlight>\bmain\b
</Code>
</div>
</TableCell>
</TableRow>
</TableBody>
</Table>
</DialogContent>
</Dialog>
)
}
const Code = ({ children, className, title }: { children: React.ReactNode, className?: string, title?: string }) => {
return (
<code
className={clsx("bg-gray-100 dark:bg-gray-700 w-fit rounded-md font-mono px-2 py-0.5", className)}
title={title}
>
{children}
</code>
)
}
const Highlight = ({ children }: { children: React.ReactNode }) => {
return (
<span className="text-highlight">
{children}
</span>
)
}

View file

@ -1,5 +1,5 @@
'use client'
import { NEXT_PUBLIC_POSTHOG_PAPIK, NEXT_PUBLIC_POSTHOG_UI_HOST, NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED } from '@/lib/environment.client'
import { NEXT_PUBLIC_POSTHOG_PAPIK, NEXT_PUBLIC_POSTHOG_UI_HOST, NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED, NEXT_PUBLIC_PUBLIC_SEARCH_DEMO } from '@/lib/environment.client'
import posthog from 'posthog-js'
import { usePostHog } from 'posthog-js/react'
import { PostHogProvider as PHProvider } from 'posthog-js/react'
@ -45,12 +45,11 @@ export function PostHogProvider({ children }: { children: React.ReactNode }) {
posthog.init(NEXT_PUBLIC_POSTHOG_PAPIK!, {
api_host: posthogHostPath,
ui_host: NEXT_PUBLIC_POSTHOG_UI_HOST,
capture_pageview: false, // Disable automatic pageview capture
person_profiles: 'identified_only',
capture_pageview: NEXT_PUBLIC_PUBLIC_SEARCH_DEMO, // @nocheckin Disable automatic pageview capture if we're not in public demo mode
autocapture: false, // Disable automatic event capture
// eslint-disable-next-line @typescript-eslint/no-explicit-any
/* @nocheckin HANDLE SELF HOSTED CASE
person_profiles: 'identified_only',
sanitize_properties: (properties: Record<string, any>, _event: string) => {
sanitize_properties: !NEXT_PUBLIC_PUBLIC_SEARCH_DEMO ? (properties: Record<string, any>, _event: string) => {
// https://posthog.com/docs/libraries/js#config
if (properties['$current_url']) {
properties['$current_url'] = null;
@ -58,10 +57,9 @@ export function PostHogProvider({ children }: { children: React.ReactNode }) {
if (properties['$ip']) {
properties['$ip'] = null;
}
return properties;
}
*/
} : undefined
});
} else {
console.log("PostHog telemetry disabled");

View file

@ -10,4 +10,5 @@ export const NEXT_PUBLIC_SOURCEBOT_TELEMETRY_DISABLED = getEnvBoolean(process.en
export const NEXT_PUBLIC_SOURCEBOT_VERSION = getEnv(process.env.NEXT_PUBLIC_SOURCEBOT_VERSION, "unknown")!;
export const NEXT_PUBLIC_DOMAIN_SUB_PATH = getEnv(process.env.NEXT_PUBLIC_DOMAIN_SUB_PATH, "")!;
export const NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY = getEnv(process.env.NEXT_PUBLIC_STRIPE_PUBLISHABLE_KEY);
export const NEXT_PUBLIC_POLLING_INTERVAL_MS = getEnvNumber(process.env.NEXT_PUBLIC_POLLING_INTERVAL_MS, 5000);
export const NEXT_PUBLIC_POLLING_INTERVAL_MS = getEnvNumber(process.env.NEXT_PUBLIC_POLLING_INTERVAL_MS, 5000);
export const NEXT_PUBLIC_PUBLIC_SEARCH_DEMO = getEnvBoolean(process.env.NEXT_PUBLIC_PUBLIC_SEARCH_DEMO, false);

View file

@ -5,6 +5,7 @@ import { getEnv, getEnvBoolean, getEnvNumber } from "./utils";
export const ZOEKT_WEBSERVER_URL = getEnv(process.env.ZOEKT_WEBSERVER_URL, "http://localhost:6070")!;
export const SHARD_MAX_MATCH_COUNT = getEnvNumber(process.env.SHARD_MAX_MATCH_COUNT, 10000);
export const TOTAL_MAX_MATCH_COUNT = getEnvNumber(process.env.TOTAL_MAX_MATCH_COUNT, 100000);
export const SOURCEBOT_VERSION = getEnv(process.env.SOURCEBOT_VERSION, 'unknown')!;
export const NODE_ENV = process.env.NODE_ENV;
export const AUTH_SECRET = getEnv(process.env.AUTH_SECRET); // Generate using `npx auth secret`
@ -24,4 +25,5 @@ export const CONFIG_MAX_REPOS_NO_TOKEN = getEnvNumber(process.env.CONFIG_MAX_REP
export const SMTP_CONNECTION_URL = getEnv(process.env.SMTP_CONNECTION_URL);
export const EMAIL_FROM = getEnv(process.env.EMAIL_FROM);
export const SOURCEBOT_ROOT_DOMAIN = getEnv(process.env.SOURCEBOT_ROOT_DOMAIN, "localhost:3000")!;
export const SOURCEBOT_ROOT_DOMAIN = getEnv(process.env.SOURCEBOT_ROOT_DOMAIN, "localhost:3000")!;
export const PUBLIC_SEARCH_DEMO = getEnvBoolean(process.env.PUBLIC_SEARCH_DEMO, false);

View file

@ -2,6 +2,7 @@
export type PosthogEventMap = {
search_finished: {
query: string | null,
contentBytesLoaded: number,
indexBytesLoaded: number,
crashes: number,
@ -242,6 +243,8 @@ export type PosthogEventMap = {
wa_security_page_click: {},
//////////////////////////////////////////////////////////////////
wa_demo_card_click: {},
wa_demo_try_card_pressed: {},
wa_share_link_created: {},
}
export type PosthogEvent = keyof PosthogEventMap;

View file

@ -220,4 +220,8 @@ export const orgDomainSchema = z.string()
.refine(async (domain) => {
const doesDomainExist = await checkIfOrgDomainExists(domain);
return isServiceError(doesDomainExist) || !doesDomainExist;
}, "This url is already taken.");
}, "This url is already taken.");
export const getVersionResponseSchema = z.object({
version: z.string(),
});

View file

@ -1,5 +1,5 @@
import { z } from "zod";
import { fileSourceRequestSchema, fileSourceResponseSchema, listRepositoriesResponseSchema, locationSchema, rangeSchema, repositorySchema, repositoryQuerySchema, searchRequestSchema, searchResponseSchema, symbolSchema } from "./schemas";
import { fileSourceRequestSchema, fileSourceResponseSchema, listRepositoriesResponseSchema, locationSchema, rangeSchema, repositorySchema, repositoryQuerySchema, searchRequestSchema, searchResponseSchema, symbolSchema, getVersionResponseSchema } from "./schemas";
export type KeymapType = "default" | "vim";
@ -20,6 +20,8 @@ export type Repository = z.infer<typeof repositorySchema>;
export type RepositoryQuery = z.infer<typeof repositoryQuerySchema>;
export type Symbol = z.infer<typeof symbolSchema>;
export type GetVersionResponse = z.infer<typeof getVersionResponseSchema>;
export enum SearchQueryParams {
query = "query",
maxMatchDisplayCount = "maxMatchDisplayCount",

View file

@ -570,6 +570,17 @@
"default": 2097152,
"minimum": 1
},
"maxTrigramCount": {
"type": "integer",
"description": "The maximum amount of trigrams per document. Documents that exceed this maximum will not be indexed. Defaults to 20000",
"default": 20000,
"minimum": 1
},
"autoDeleteStaleRepos": {
"type": "boolean",
"description": "Automatically delete stale repositories from the index. Defaults to true.",
"default": true
},
"reindexInterval": {
"type": "integer",
"description": "The interval (in milliseconds) at which the indexer should re-index all repositories. Repositories are always indexed when first added. Defaults to 1 hour (3600000 milliseconds).",

225
yarn.lock
View file

@ -2086,7 +2086,7 @@
"@radix-ui/primitive@1.1.1":
version "1.1.1"
resolved "https://registry.npmjs.org/@radix-ui/primitive/-/primitive-1.1.1.tgz"
resolved "https://registry.yarnpkg.com/@radix-ui/primitive/-/primitive-1.1.1.tgz#fc169732d755c7fbad33ba8d0cd7fd10c90dc8e3"
integrity sha512-SJ31y+Q/zAyShtXJc8x83i9TYdbAfHZ++tUZnvjJJqFjzsdUnKsxPL6IEtBlxKkU7yzer//GQtZSV4GbldL3YA==
"@radix-ui/react-alert-dialog@^1.1.5":
@ -2169,7 +2169,7 @@
"@radix-ui/react-compose-refs@1.1.1":
version "1.1.1"
resolved "https://registry.npmjs.org/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz"
resolved "https://registry.yarnpkg.com/@radix-ui/react-compose-refs/-/react-compose-refs-1.1.1.tgz#6f766faa975f8738269ebb8a23bad4f5a8d2faec"
integrity sha512-Y9VzoRDSJtgFMUCoiZBDVo084VQ5hfpXxVE+NgkdNsjiDBByiImMZKKhxMwCbdHvhlENG6a833CbFkOQvTricw==
"@radix-ui/react-context@1.0.1":
@ -2232,7 +2232,7 @@
"@radix-ui/react-dialog@^1.1.4":
version "1.1.4"
resolved "https://registry.npmjs.org/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dialog/-/react-dialog-1.1.4.tgz#d68e977acfcc0d044b9dab47b6dd2c179d2b3191"
integrity sha512-Ur7EV1IwQGCyaAuyDRiOLA5JIUZxELJljF+MbM/2NC0BYwfuRrbpS30BiQBJrVruscgUkieKkqXYDOoByaxIoA==
dependencies:
"@radix-ui/primitive" "1.1.1"
@ -2280,7 +2280,7 @@
"@radix-ui/react-dismissable-layer@1.1.3":
version "1.1.3"
resolved "https://registry.npmjs.org/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz"
resolved "https://registry.yarnpkg.com/@radix-ui/react-dismissable-layer/-/react-dismissable-layer-1.1.3.tgz#4ee0f0f82d53bf5bd9db21665799bb0d1bad5ed8"
integrity sha512-onrWn/72lQoEucDmJnr8uczSNTujT0vJnA/X5+3AkChVPowr8n1yvIKIabhWyMQeMvvmdpsvcyDqx3X1LEXCPg==
dependencies:
"@radix-ui/primitive" "1.1.1"
@ -2357,7 +2357,7 @@
"@radix-ui/react-focus-scope@1.1.1":
version "1.1.1"
resolved "https://registry.npmjs.org/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz"
resolved "https://registry.yarnpkg.com/@radix-ui/react-focus-scope/-/react-focus-scope-1.1.1.tgz#5c602115d1db1c4fcfa0fae4c3b09bb8919853cb"
integrity sha512-01omzJAYRxXdG2/he/+xy+c8a8gCydoQ1yOxnWNcRhrrBW5W+RQJ22EK1SaO8tb3WoUsuEw7mJjBozPzihDFjA==
dependencies:
"@radix-ui/react-compose-refs" "1.1.1"
@ -2530,7 +2530,7 @@
"@radix-ui/react-portal@1.1.3":
version "1.1.3"
resolved "https://registry.npmjs.org/@radix-ui/react-portal/-/react-portal-1.1.3.tgz"
resolved "https://registry.yarnpkg.com/@radix-ui/react-portal/-/react-portal-1.1.3.tgz#b0ea5141103a1671b715481b13440763d2ac4440"
integrity sha512-NciRqhXnGojhT93RPyDaMPfLH3ZSl4jjIFbZQ1b/vxvZEdHsBZ49wP9w8L3HzUQwep01LcWtkUvm0OVB5JAHTw==
dependencies:
"@radix-ui/react-primitive" "2.0.1"
@ -2563,7 +2563,7 @@
"@radix-ui/react-presence@1.1.2":
version "1.1.2"
resolved "https://registry.npmjs.org/@radix-ui/react-presence/-/react-presence-1.1.2.tgz"
resolved "https://registry.yarnpkg.com/@radix-ui/react-presence/-/react-presence-1.1.2.tgz#bb764ed8a9118b7ec4512da5ece306ded8703cdc"
integrity sha512-18TFr80t5EVgL9x1SwF/YGtfG+l0BS0PRAlCWBDoBEiDQjeKgnNZRVJp/oVBl24sr3Gbfwc/Qpj4OcWTQMsAEg==
dependencies:
"@radix-ui/react-compose-refs" "1.1.1"
@ -2586,7 +2586,7 @@
"@radix-ui/react-primitive@2.0.1":
version "2.0.1"
resolved "https://registry.npmjs.org/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz"
resolved "https://registry.yarnpkg.com/@radix-ui/react-primitive/-/react-primitive-2.0.1.tgz#6d9efc550f7520135366f333d1e820cf225fad9e"
integrity sha512-sHCWTtxwNn3L3fH8qAfnF3WbUZycW93SM1j3NFDzXBiz8D6F5UTTy8G1+WFEaiCdvCVRJWj6N2R4Xq6HdiHmDg==
dependencies:
"@radix-ui/react-slot" "1.1.1"
@ -4016,121 +4016,62 @@
resolved "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz"
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
"@vitest/expect@2.1.4":
version "2.1.4"
resolved "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.4.tgz"
integrity sha512-DOETT0Oh1avie/D/o2sgMHGrzYUFFo3zqESB2Hn70z6QB1HrS2IQ9z5DfyTqU8sg4Bpu13zZe9V4+UTNQlUeQA==
"@vitest/expect@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-2.1.9.tgz#b566ea20d58ea6578d8dc37040d6c1a47ebe5ff8"
integrity sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==
dependencies:
"@vitest/spy" "2.1.4"
"@vitest/utils" "2.1.4"
"@vitest/spy" "2.1.9"
"@vitest/utils" "2.1.9"
chai "^5.1.2"
tinyrainbow "^1.2.0"
"@vitest/expect@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@vitest/expect/-/expect-2.1.5.tgz"
integrity sha512-nZSBTW1XIdpZvEJyoP/Sy8fUg0b8od7ZpGDkTUcfJ7wz/VoZAFzFfLyxVxGFhUjJzhYqSbIpfMtl/+k/dpWa3Q==
"@vitest/mocker@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-2.1.9.tgz#36243b27351ca8f4d0bbc4ef91594ffd2dc25ef5"
integrity sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==
dependencies:
"@vitest/spy" "2.1.5"
"@vitest/utils" "2.1.5"
chai "^5.1.2"
tinyrainbow "^1.2.0"
"@vitest/mocker@2.1.4":
version "2.1.4"
resolved "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.4.tgz"
integrity sha512-Ky/O1Lc0QBbutJdW0rqLeFNbuLEyS+mIPiNdlVlp2/yhJ0SbyYqObS5IHdhferJud8MbbwMnexg4jordE5cCoQ==
dependencies:
"@vitest/spy" "2.1.4"
"@vitest/spy" "2.1.9"
estree-walker "^3.0.3"
magic-string "^0.30.12"
"@vitest/mocker@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@vitest/mocker/-/mocker-2.1.5.tgz"
integrity sha512-XYW6l3UuBmitWqSUXTNXcVBUCRytDogBsWuNXQijc00dtnU/9OqpXWp4OJroVrad/gLIomAq9aW8yWDBtMthhQ==
dependencies:
"@vitest/spy" "2.1.5"
estree-walker "^3.0.3"
magic-string "^0.30.12"
"@vitest/pretty-format@2.1.4", "@vitest/pretty-format@^2.1.4":
version "2.1.4"
resolved "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.4.tgz"
integrity sha512-L95zIAkEuTDbUX1IsjRl+vyBSLh3PwLLgKpghl37aCK9Jvw0iP+wKwIFhfjdUtA2myLgjrG6VU6JCFLv8q/3Ww==
"@vitest/pretty-format@2.1.9", "@vitest/pretty-format@^2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-2.1.9.tgz#434ff2f7611689f9ce70cd7d567eceb883653fdf"
integrity sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==
dependencies:
tinyrainbow "^1.2.0"
"@vitest/pretty-format@2.1.5", "@vitest/pretty-format@^2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-2.1.5.tgz"
integrity sha512-4ZOwtk2bqG5Y6xRGHcveZVr+6txkH7M2e+nPFd6guSoN638v/1XQ0K06eOpi0ptVU/2tW/pIU4IoPotY/GZ9fw==
"@vitest/runner@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-2.1.9.tgz#cc18148d2d797fd1fd5908d1f1851d01459be2f6"
integrity sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==
dependencies:
tinyrainbow "^1.2.0"
"@vitest/runner@2.1.4":
version "2.1.4"
resolved "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.4.tgz"
integrity sha512-sKRautINI9XICAMl2bjxQM8VfCMTB0EbsBc/EDFA57V6UQevEKY/TOPOF5nzcvCALltiLfXWbq4MaAwWx/YxIA==
dependencies:
"@vitest/utils" "2.1.4"
"@vitest/utils" "2.1.9"
pathe "^1.1.2"
"@vitest/runner@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@vitest/runner/-/runner-2.1.5.tgz"
integrity sha512-pKHKy3uaUdh7X6p1pxOkgkVAFW7r2I818vHDthYLvUyjRfkKOU6P45PztOch4DZarWQne+VOaIMwA/erSSpB9g==
"@vitest/snapshot@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-2.1.9.tgz#24260b93f798afb102e2dcbd7e61c6dfa118df91"
integrity sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==
dependencies:
"@vitest/utils" "2.1.5"
pathe "^1.1.2"
"@vitest/snapshot@2.1.4":
version "2.1.4"
resolved "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.4.tgz"
integrity sha512-3Kab14fn/5QZRog5BPj6Rs8dc4B+mim27XaKWFWHWA87R56AKjHTGcBFKpvZKDzC4u5Wd0w/qKsUIio3KzWW4Q==
dependencies:
"@vitest/pretty-format" "2.1.4"
"@vitest/pretty-format" "2.1.9"
magic-string "^0.30.12"
pathe "^1.1.2"
"@vitest/snapshot@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-2.1.5.tgz"
integrity sha512-zmYw47mhfdfnYbuhkQvkkzYroXUumrwWDGlMjpdUr4jBd3HZiV2w7CQHj+z7AAS4VOtWxI4Zt4bWt4/sKcoIjg==
dependencies:
"@vitest/pretty-format" "2.1.5"
magic-string "^0.30.12"
pathe "^1.1.2"
"@vitest/spy@2.1.4":
version "2.1.4"
resolved "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.4.tgz"
integrity sha512-4JOxa+UAizJgpZfaCPKK2smq9d8mmjZVPMt2kOsg/R8QkoRzydHH1qHxIYNvr1zlEaFj4SXiaaJWxq/LPLKaLg==
"@vitest/spy@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-2.1.9.tgz#cb28538c5039d09818b8bfa8edb4043c94727c60"
integrity sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==
dependencies:
tinyspy "^3.0.2"
"@vitest/spy@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@vitest/spy/-/spy-2.1.5.tgz"
integrity sha512-aWZF3P0r3w6DiYTVskOYuhBc7EMc3jvn1TkBg8ttylFFRqNN2XGD7V5a4aQdk6QiUzZQ4klNBSpCLJgWNdIiNw==
"@vitest/utils@2.1.9":
version "2.1.9"
resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-2.1.9.tgz#4f2486de8a54acf7ecbf2c5c24ad7994a680a6c1"
integrity sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==
dependencies:
tinyspy "^3.0.2"
"@vitest/utils@2.1.4":
version "2.1.4"
resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.4.tgz"
integrity sha512-MXDnZn0Awl2S86PSNIim5PWXgIAx8CIkzu35mBdSApUip6RFOGXBCf3YFyeEu8n1IHk4bWD46DeYFu9mQlFIRg==
dependencies:
"@vitest/pretty-format" "2.1.4"
loupe "^3.1.2"
tinyrainbow "^1.2.0"
"@vitest/utils@2.1.5":
version "2.1.5"
resolved "https://registry.npmjs.org/@vitest/utils/-/utils-2.1.5.tgz"
integrity sha512-yfj6Yrp0Vesw2cwJbP+cl04OC+IHFsuQsrsJBL9pyGeQXE56v1UAOQco+SR55Vf1nQzfV0QJg1Qum7AaWUwwYg==
dependencies:
"@vitest/pretty-format" "2.1.5"
"@vitest/pretty-format" "2.1.9"
loupe "^3.1.2"
tinyrainbow "^1.2.0"
@ -8719,7 +8660,7 @@ react-promise-suspense@0.3.4:
react-remove-scroll-bar@^2.3.3, react-remove-scroll-bar@^2.3.7:
version "2.3.8"
resolved "https://registry.npmjs.org/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz"
resolved "https://registry.yarnpkg.com/react-remove-scroll-bar/-/react-remove-scroll-bar-2.3.8.tgz#99c20f908ee467b385b68a3469b4a3e750012223"
integrity sha512-9r+yi9+mgU33AKcj6IbT9oRCO78WriSj6t/cF8DWBZJ9aOGPOTEDvdUDz1FwKim7QXWwmHqtdHnRJfhAxEG46Q==
dependencies:
react-style-singleton "^2.2.2"
@ -8757,7 +8698,7 @@ react-remove-scroll@2.6.0:
react-remove-scroll@^2.6.1:
version "2.6.2"
resolved "https://registry.npmjs.org/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz"
resolved "https://registry.yarnpkg.com/react-remove-scroll/-/react-remove-scroll-2.6.2.tgz#2518d2c5112e71ea8928f1082a58459b5c7a2a97"
integrity sha512-KmONPx5fnlXYJQqC62Q+lwIeAk64ws/cUw6omIumRzMRPqgnYqhSSti99nbj0Ry13bv7dF+BKn7NB+OqkdZGTw==
dependencies:
react-remove-scroll-bar "^2.3.7"
@ -9458,7 +9399,7 @@ statuses@2.0.1:
resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63"
integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==
std-env@^3.7.0, std-env@^3.8.0:
std-env@^3.8.0:
version "3.8.0"
resolved "https://registry.npmjs.org/std-env/-/std-env-3.8.0.tgz"
integrity sha512-Bc3YwwCB+OzldMxOXJIIvC6cPRWr/LxOp48CdQTOkPyk/t4JWWJbrilwBd7RJzKV8QW7tJkcgAmeuLLJugl5/w==
@ -10130,7 +10071,7 @@ use-callback-ref@^1.3.0:
use-callback-ref@^1.3.3:
version "1.3.3"
resolved "https://registry.npmjs.org/use-callback-ref/-/use-callback-ref-1.3.3.tgz"
resolved "https://registry.yarnpkg.com/use-callback-ref/-/use-callback-ref-1.3.3.tgz#98d9fab067075841c5b2c6852090d5d0feabe2bf"
integrity sha512-jQL3lRnocaFtu3V00JToYz/4QkNWswxijDaCVNZRiRTO3HQDLsdu1ZtmIUvV4yPp+rvWm5j0y0TG/S61cuijTg==
dependencies:
tslib "^2.0.0"
@ -10207,20 +10148,10 @@ vfile@^6.0.0:
"@types/unist" "^3.0.0"
vfile-message "^4.0.0"
vite-node@2.1.4:
version "2.1.4"
resolved "https://registry.npmjs.org/vite-node/-/vite-node-2.1.4.tgz"
integrity sha512-kqa9v+oi4HwkG6g8ufRnb5AeplcRw8jUF6/7/Qz1qRQOXHImG8YnLbB+LLszENwFnoBl9xIf9nVdCFzNd7GQEg==
dependencies:
cac "^6.7.14"
debug "^4.3.7"
pathe "^1.1.2"
vite "^5.0.0"
vite-node@2.1.5:
version "2.1.5"
resolved "https://registry.npmjs.org/vite-node/-/vite-node-2.1.5.tgz"
integrity sha512-rd0QIgx74q4S1Rd56XIiL2cYEdyWn13cunYBIuqh9mpmQr7gGS0IxXoP8R6OaZtNQQLyXSWbd4rXKYUbhFpK5w==
vite-node@2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-2.1.9.tgz#549710f76a643f1c39ef34bdb5493a944e4f895f"
integrity sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==
dependencies:
cac "^6.7.14"
debug "^4.3.7"
@ -10238,9 +10169,9 @@ vite-tsconfig-paths@^5.1.3:
tsconfck "^3.0.3"
vite@^5.0.0:
version "5.4.11"
resolved "https://registry.npmjs.org/vite/-/vite-5.4.11.tgz"
integrity sha512-c7jFQRklXua0mTzneGW9QVyxFjUgwcihC4bXEtujIo2ouWCe1Ajt/amn2PCxYnhYfd5k09JX3SB7OYWFKYqj8Q==
version "5.4.14"
resolved "https://registry.yarnpkg.com/vite/-/vite-5.4.14.tgz#ff8255edb02134df180dcfca1916c37a6abe8408"
integrity sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==
dependencies:
esbuild "^0.21.3"
postcss "^8.4.43"
@ -10248,44 +10179,18 @@ vite@^5.0.0:
optionalDependencies:
fsevents "~2.3.3"
vitest@^2.1.4:
version "2.1.4"
resolved "https://registry.npmjs.org/vitest/-/vitest-2.1.4.tgz"
integrity sha512-eDjxbVAJw1UJJCHr5xr/xM86Zx+YxIEXGAR+bmnEID7z9qWfoxpHw0zdobz+TQAFOLT+nEXz3+gx6nUJ7RgmlQ==
vitest@^2.1.5, vitest@^2.1.9:
version "2.1.9"
resolved "https://registry.yarnpkg.com/vitest/-/vitest-2.1.9.tgz#7d01ffd07a553a51c87170b5e80fea3da7fb41e7"
integrity sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==
dependencies:
"@vitest/expect" "2.1.4"
"@vitest/mocker" "2.1.4"
"@vitest/pretty-format" "^2.1.4"
"@vitest/runner" "2.1.4"
"@vitest/snapshot" "2.1.4"
"@vitest/spy" "2.1.4"
"@vitest/utils" "2.1.4"
chai "^5.1.2"
debug "^4.3.7"
expect-type "^1.1.0"
magic-string "^0.30.12"
pathe "^1.1.2"
std-env "^3.7.0"
tinybench "^2.9.0"
tinyexec "^0.3.1"
tinypool "^1.0.1"
tinyrainbow "^1.2.0"
vite "^5.0.0"
vite-node "2.1.4"
why-is-node-running "^2.3.0"
vitest@^2.1.5:
version "2.1.5"
resolved "https://registry.npmjs.org/vitest/-/vitest-2.1.5.tgz"
integrity sha512-P4ljsdpuzRTPI/kbND2sDZ4VmieerR2c9szEZpjc+98Z9ebvnXmM5+0tHEKqYZumXqlvnmfWsjeFOjXVriDG7A==
dependencies:
"@vitest/expect" "2.1.5"
"@vitest/mocker" "2.1.5"
"@vitest/pretty-format" "^2.1.5"
"@vitest/runner" "2.1.5"
"@vitest/snapshot" "2.1.5"
"@vitest/spy" "2.1.5"
"@vitest/utils" "2.1.5"
"@vitest/expect" "2.1.9"
"@vitest/mocker" "2.1.9"
"@vitest/pretty-format" "^2.1.9"
"@vitest/runner" "2.1.9"
"@vitest/snapshot" "2.1.9"
"@vitest/spy" "2.1.9"
"@vitest/utils" "2.1.9"
chai "^5.1.2"
debug "^4.3.7"
expect-type "^1.1.0"
@ -10297,7 +10202,7 @@ vitest@^2.1.5:
tinypool "^1.0.1"
tinyrainbow "^1.2.0"
vite "^5.0.0"
vite-node "2.1.5"
vite-node "2.1.9"
why-is-node-running "^2.3.0"
vscode-languageserver-types@^3.17.1: