├── .gitignore ├── posts ├── 2024 │ ├── sqlite-lembed-init │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── package.json │ │ ├── styles.css │ │ ├── index.js │ │ ├── index.md │ │ └── package-lock.json │ ├── sqlite-rembed-init │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── package.json │ │ ├── styles.css │ │ ├── index.js │ │ ├── index.md │ │ └── package-lock.json │ ├── sqlite-vec-metadata-release │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── package.json │ │ ├── styles.css │ │ ├── index.js │ │ ├── package-lock.json │ │ └── index.md │ ├── sqlite-vec-stable-release │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── package.json │ │ ├── styles.css │ │ ├── index.js │ │ └── package-lock.json │ ├── sqlite-vec-hybrid-search │ │ ├── .gitignore │ │ ├── Makefile │ │ ├── package.json │ │ ├── styles.css │ │ ├── index.js │ │ └── package-lock.json │ ├── sql-vector-search-languages │ │ ├── .gitignore │ │ ├── package.json │ │ ├── styles.css │ │ ├── Makefile │ │ ├── index.js │ │ └── package-lock.json │ ├── blog-intro.md │ └── building-new-vector-search-sqlite │ │ ├── .gitignore │ │ ├── index.js │ │ ├── package.json │ │ ├── Makefile │ │ ├── hero.js │ │ ├── styles.css │ │ ├── sqlite.js │ │ └── index.md ├── 2025 │ └── introducing-libfec │ │ ├── Makefile │ │ ├── index.mjs │ │ └── index.md └── sqlite │ ├── pointer-names.md │ └── subtypes.md ├── static ├── 1.png ├── MonaspaceNeon-Regular.otf ├── theme.js └── base.css ├── Makefile ├── .github └── workflows │ └── site.yaml ├── Home.tsx ├── Post.tsx └── page.css /.gitignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | .vscode/ 3 | -------------------------------------------------------------------------------- /posts/2024/sqlite-lembed-init/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /posts/2024/sqlite-rembed-init/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-metadata-release/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-stable-release/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-hybrid-search/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist/ 3 | -------------------------------------------------------------------------------- /static/1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asg017/blog/main/static/1.png -------------------------------------------------------------------------------- /posts/2024/sql-vector-search-languages/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | demos 3 | -------------------------------------------------------------------------------- /posts/2024/blog-intro.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Blog intro 3 | created_at: 9999-12-31 4 | skip: true 5 | --- 6 | -------------------------------------------------------------------------------- /static/MonaspaceNeon-Regular.otf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/asg017/blog/main/static/MonaspaceNeon-Regular.otf -------------------------------------------------------------------------------- /posts/2024/building-new-vector-search-sqlite/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | 3 | 4 | movies.bit.db 5 | sqlite3.mjs 6 | sqlite3.wasm 7 | -------------------------------------------------------------------------------- /posts/2025/introducing-libfec/Makefile: -------------------------------------------------------------------------------- 1 | dist: index.mjs 2 | rm -rf $@ || true 3 | mkdir $@ 4 | deno bundle --minify $< -o $@/index.js -------------------------------------------------------------------------------- /posts/sqlite/pointer-names.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: An unofficial list of SQLite "pointer names" in the wild 3 | created_at: 9999-12-31 4 | skip: true 5 | --- 6 | -------------------------------------------------------------------------------- /posts/2024/building-new-vector-search-sqlite/index.js: -------------------------------------------------------------------------------- 1 | import "./node_modules/@alex.garcia/sqlite-wasm-toolkit/dist/plugin.css"; 2 | import "./styles.css"; 3 | 4 | import { hero } from "./hero.js"; 5 | 6 | function main() { 7 | hero(); 8 | import("./sqlite.js").then(({ load }) => load()); 9 | } 10 | 11 | addEventListener("DOMContentLoaded", main); 12 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-hybrid-search/Makefile: -------------------------------------------------------------------------------- 1 | node_modules: package.json 2 | npm i 3 | touch $@ 4 | 5 | dist: index.js node_modules $@ 6 | rm -rf $@ || true 7 | mkdir $@ 8 | ./node_modules/.bin/esbuild \ 9 | --minify --bundle --format=esm --splitting \ 10 | --out-extension:.js=.min.js \ 11 | --out-extension:.css=.min.css \ 12 | $< --outdir=$@ 13 | touch $@ 14 | 15 | clean: 16 | rm -rf demos/ 17 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-metadata-release/Makefile: -------------------------------------------------------------------------------- 1 | node_modules: package.json 2 | npm i 3 | touch $@ 4 | 5 | dist: index.js node_modules $@ 6 | rm -rf $@ || true 7 | mkdir $@ 8 | ./node_modules/.bin/esbuild \ 9 | --minify --bundle --format=esm --splitting \ 10 | --out-extension:.js=.min.js \ 11 | --out-extension:.css=.min.css \ 12 | $< --outdir=$@ 13 | touch $@ 14 | 15 | clean: 16 | rm -rf demos/ 17 | -------------------------------------------------------------------------------- /posts/2024/sqlite-lembed-init/Makefile: -------------------------------------------------------------------------------- 1 | node_modules: package.json package-lock.json 2 | npm i 3 | touch $@ 4 | 5 | dist: index.js node_modules 6 | rm -rf $@ || true 7 | mkdir $@ 8 | ./node_modules/.bin/esbuild \ 9 | --minify --bundle --format=esm --splitting \ 10 | --out-extension:.js=.min.js \ 11 | --out-extension:.css=.min.css \ 12 | $< --outdir=$@ 13 | touch $@ 14 | 15 | clean: 16 | rm -rf demos/ 17 | -------------------------------------------------------------------------------- /posts/2024/sqlite-rembed-init/Makefile: -------------------------------------------------------------------------------- 1 | node_modules: package.json package-lock.json 2 | npm i 3 | touch $@ 4 | 5 | dist: index.js node_modules 6 | rm -rf $@ || true 7 | mkdir $@ 8 | ./node_modules/.bin/esbuild \ 9 | --minify --bundle --format=esm --splitting \ 10 | --out-extension:.js=.min.js \ 11 | --out-extension:.css=.min.css \ 12 | $< --outdir=$@ 13 | touch $@ 14 | 15 | clean: 16 | rm -rf demos/ 17 | -------------------------------------------------------------------------------- /posts/2024/sqlite-lembed-init/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "d3-selection": "^3.0.0", 14 | "d3-transition": "^3.0.1", 15 | "esbuild": "^0.21.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /posts/2024/sqlite-rembed-init/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "d3-selection": "^3.0.0", 14 | "d3-transition": "^3.0.1", 15 | "esbuild": "^0.21.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-hybrid-search/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "d3-selection": "^3.0.0", 14 | "d3-transition": "^3.0.1", 15 | "esbuild": "^0.21.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRC_DIR := posts/2024 2 | DIST_DIR := dist/2024 3 | 4 | serve: 5 | open http://localhost:8000 6 | uv run -m http.server -d dist 7 | site: 8 | deno run \ 9 | --allow-read=.,../sqlite-vec/dist/.wasm/sqlite3.wasm \ 10 | --allow-write=. \ 11 | --allow-env=VSCODE_TEXTMATE_DEBUG \ 12 | --allow-run \ 13 | build.tsx 14 | 15 | site-watch: 16 | watchexec --ignore dist/ --ignore '**/node_modules/**' -- make site 17 | 18 | clean: 19 | rm -f $(DIST_DIR)/*.html 20 | -------------------------------------------------------------------------------- /posts/2024/sql-vector-search-languages/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "d3-selection": "^3.0.0", 14 | "d3-transition": "^3.0.1", 15 | "esbuild": "^0.21.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-metadata-release/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "d3-selection": "^3.0.0", 14 | "d3-transition": "^3.0.1", 15 | "esbuild": "^0.21.3" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-stable-release/Makefile: -------------------------------------------------------------------------------- 1 | node_modules: package.json package-lock.json 2 | npm i 3 | touch $@ 4 | 5 | dist: index.js node_modules $@ 6 | rm -rf $@ || true 7 | mkdir $@ 8 | ./node_modules/.bin/esbuild \ 9 | --minify --bundle --format=esm --splitting \ 10 | --out-extension:.js=.min.js \ 11 | --out-extension:.css=.min.css \ 12 | $< --outdir=$@ 13 | cp node_modules/lite-youtube-embed/src/lite-yt-embed.css $@ 14 | touch $@ 15 | 16 | clean: 17 | rm -rf demos/ 18 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-stable-release/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "scripts": { 6 | "test": "echo \"Error: no test specified\" && exit 1" 7 | }, 8 | "keywords": [], 9 | "author": "", 10 | "license": "ISC", 11 | "description": "", 12 | "dependencies": { 13 | "d3-selection": "^3.0.0", 14 | "d3-transition": "^3.0.1", 15 | "esbuild": "^0.21.3", 16 | "lite-youtube-embed": "^0.3.2" 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /posts/2024/sqlite-rembed-init/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --svg-bg: var(--ctp-crust); 3 | --hero-c1: var(--ctp-flamingo); 4 | --hero-c2: var(--ctp-pink); 5 | --hero-c3: var(--ctp-mauve); 6 | --hero-c4: var(--ctp-red); 7 | --hero-c5: var(--ctp-maroon); 8 | --hero-c6: var(--ctp-peach); 9 | --hero-c7: var(--ctp-yellow); 10 | --hero-c8: var(--ctp-green); 11 | --hero-c9: var(--ctp-teal); 12 | --hero-c10: var(--ctp-sky); 13 | --hero-c11: var(--ctp-sapphire); 14 | --hero-c12: var(--ctp-blue); 15 | --hero-c13: var(--ctp-lavender); 16 | } 17 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-hybrid-search/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --svg-bg: var(--ctp-crust); 3 | --hero-c1: var(--ctp-flamingo); 4 | --hero-c2: var(--ctp-pink); 5 | --hero-c3: var(--ctp-mauve); 6 | --hero-c4: var(--ctp-red); 7 | --hero-c5: var(--ctp-maroon); 8 | --hero-c6: var(--ctp-peach); 9 | --hero-c7: var(--ctp-yellow); 10 | --hero-c8: var(--ctp-green); 11 | --hero-c9: var(--ctp-teal); 12 | --hero-c10: var(--ctp-sky); 13 | --hero-c11: var(--ctp-sapphire); 14 | --hero-c12: var(--ctp-blue); 15 | --hero-c13: var(--ctp-lavender); 16 | } 17 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-metadata-release/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --svg-bg: var(--ctp-crust); 3 | --hero-c1: var(--ctp-flamingo); 4 | --hero-c2: var(--ctp-pink); 5 | --hero-c3: var(--ctp-mauve); 6 | --hero-c4: var(--ctp-red); 7 | --hero-c5: var(--ctp-maroon); 8 | --hero-c6: var(--ctp-peach); 9 | --hero-c7: var(--ctp-yellow); 10 | --hero-c8: var(--ctp-green); 11 | --hero-c9: var(--ctp-teal); 12 | --hero-c10: var(--ctp-sky); 13 | --hero-c11: var(--ctp-sapphire); 14 | --hero-c12: var(--ctp-blue); 15 | --hero-c13: var(--ctp-lavender); 16 | } 17 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-stable-release/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --svg-bg: var(--ctp-crust); 3 | --hero-c1: var(--ctp-flamingo); 4 | --hero-c2: var(--ctp-pink); 5 | --hero-c3: var(--ctp-mauve); 6 | --hero-c4: var(--ctp-red); 7 | --hero-c5: var(--ctp-maroon); 8 | --hero-c6: var(--ctp-peach); 9 | --hero-c7: var(--ctp-yellow); 10 | --hero-c8: var(--ctp-green); 11 | --hero-c9: var(--ctp-teal); 12 | --hero-c10: var(--ctp-sky); 13 | --hero-c11: var(--ctp-sapphire); 14 | --hero-c12: var(--ctp-blue); 15 | --hero-c13: var(--ctp-lavender); 16 | } 17 | -------------------------------------------------------------------------------- /posts/2024/building-new-vector-search-sqlite/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "new-vector-search-sqlite", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "keywords": [], 10 | "author": "", 11 | "license": "ISC", 12 | "dependencies": { 13 | "@alex.garcia/sqlite-wasm-toolkit": "^0.0.1-alpha.12", 14 | "@observablehq/inputs": "^0.10.6", 15 | "d3-selection": "^3.0.0", 16 | "d3-transition": "^3.0.1", 17 | "esbuild": "^0.20.2" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /.github/workflows/site.yaml: -------------------------------------------------------------------------------- 1 | name: Deploy Site 2 | on: 3 | workflow_dispatch: {} 4 | push: 5 | branches: 6 | - main 7 | jobs: 8 | deploy: 9 | runs-on: ubuntu-latest 10 | permissions: 11 | pages: write 12 | id-token: write 13 | environment: 14 | name: github-pages 15 | url: ${{ steps.deployment.outputs.page_url }} 16 | steps: 17 | - uses: actions/checkout@v5 18 | - uses: denoland/setup-deno@v2 19 | with: 20 | deno-version: v2.x 21 | - run: make site 22 | - uses: actions/configure-pages@v5 23 | - uses: actions/upload-pages-artifact@v3 24 | with: 25 | path: dist 26 | - id: deployment 27 | uses: actions/deploy-pages@v4 28 | -------------------------------------------------------------------------------- /static/theme.js: -------------------------------------------------------------------------------- 1 | function main() { 2 | const btn = document.querySelector("button.theme"); 3 | const root = document.documentElement; 4 | 5 | // initial theme'ing 6 | if (localStorage.getItem("theme") === "dark") { 7 | root.classList.add("dark"); 8 | localStorage.setItem("theme", "dark"); 9 | } else { 10 | localStorage.setItem("theme", "light"); 11 | } 12 | 13 | // enable the 'Change theme' button 14 | btn.textContent = "Change theme"; 15 | btn.addEventListener("click", () => { 16 | if (root.classList.toggle("dark")) { 17 | localStorage.setItem("theme", "dark"); 18 | } else { 19 | localStorage.setItem("theme", "light"); 20 | } 21 | }); 22 | } 23 | 24 | addEventListener("DOMContentLoaded", main); 25 | -------------------------------------------------------------------------------- /posts/2024/building-new-vector-search-sqlite/Makefile: -------------------------------------------------------------------------------- 1 | site: dist 2 | 3 | sqlite3.wasm: 4 | curl -L -o $@ https://github.com/asg017/blog/releases/download/blobs/sqlite3.wasm 5 | 6 | sqlite3.mjs: 7 | curl -L -o $@ https://github.com/asg017/blog/releases/download/blobs/sqlite3.mjs 8 | 9 | movies.bit.db: 10 | curl -L -o $@ https://github.com/asg017/blog/releases/download/blobs/movies.bit.db 11 | 12 | 13 | node_modules: package.json package-lock.json 14 | npm i 15 | touch $@ 16 | 17 | dist: index.js hero.js sqlite.js styles.css node_modules Makefile movies.bit.db sqlite3.wasm sqlite3.mjs 18 | rm -rf $@ || true 19 | mkdir $@ 20 | ./node_modules/.bin/esbuild \ 21 | --minify --bundle --format=esm --splitting \ 22 | --out-extension:.js=.min.js \ 23 | --out-extension:.css=.min.css \ 24 | $< --outdir=$@ 25 | cp sqlite3.wasm $@ 26 | cp movies.bit.db $@ 27 | touch $@ 28 | 29 | clean: 30 | rm -rf node_modules/ dist/ movies.bit.db sqlite3.wasm sqlite3.mjs 31 | 32 | .PHONY: site clean 33 | -------------------------------------------------------------------------------- /posts/2024/sqlite-lembed-init/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --svg-bg: var(--ctp-crust); 3 | --hero-c1: var(--ctp-flamingo); 4 | --hero-c2: var(--ctp-pink); 5 | --hero-c3: var(--ctp-mauve); 6 | --hero-c4: var(--ctp-red); 7 | --hero-c5: var(--ctp-maroon); 8 | --hero-c6: var(--ctp-peach); 9 | --hero-c7: var(--ctp-yellow); 10 | --hero-c8: var(--ctp-green); 11 | --hero-c9: var(--ctp-teal); 12 | --hero-c10: var(--ctp-sky); 13 | --hero-c11: var(--ctp-sapphire); 14 | --hero-c12: var(--ctp-blue); 15 | --hero-c13: var(--ctp-lavender); 16 | } 17 | 18 | .swt-editor { 19 | --swt-code-bg: var(--ctp-base); 20 | --swt-code-comment: var(--ctp-subtext1); /*#5f6368;*/ 21 | --swt-code-keyword: var(--ctp-mauve); 22 | --swt-code-identifier: var(--ctp-blue); 23 | --swt-code-string: var(--ctp-green); 24 | --swt-code-types: var(--ctp-yellow); 25 | --swt-code-literal: var(--ctp-peach); 26 | --swt-code-params: var(--ctp-pink); 27 | 28 | --swt-widget-border: var(--ctp-overlay2); 29 | 30 | --swt-result-th-bg: var(--ctp-crust); 31 | --swt-result-td-bg: var(--ctp-mantle); 32 | --swt-result-cell-border-color: #1b1b1b; 33 | } 34 | 35 | .cm-activeLine { 36 | background-color: var(--ctp-mantle) !important; 37 | } 38 | -------------------------------------------------------------------------------- /posts/2024/sql-vector-search-languages/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --svg-bg: var(--ctp-crust); 3 | --hero-c1: var(--ctp-flamingo); 4 | --hero-c2: var(--ctp-pink); 5 | --hero-c3: var(--ctp-mauve); 6 | --hero-c4: var(--ctp-red); 7 | --hero-c5: var(--ctp-maroon); 8 | --hero-c6: var(--ctp-peach); 9 | --hero-c7: var(--ctp-yellow); 10 | --hero-c8: var(--ctp-green); 11 | --hero-c9: var(--ctp-teal); 12 | --hero-c10: var(--ctp-sky); 13 | --hero-c11: var(--ctp-sapphire); 14 | --hero-c12: var(--ctp-blue); 15 | --hero-c13: var(--ctp-lavender); 16 | } 17 | 18 | .swt-editor { 19 | --swt-code-bg: var(--ctp-base); 20 | --swt-code-comment: var(--ctp-subtext1); /*#5f6368;*/ 21 | --swt-code-keyword: var(--ctp-mauve); 22 | --swt-code-identifier: var(--ctp-blue); 23 | --swt-code-string: var(--ctp-green); 24 | --swt-code-types: var(--ctp-yellow); 25 | --swt-code-literal: var(--ctp-peach); 26 | --swt-code-params: var(--ctp-pink); 27 | 28 | --swt-widget-border: var(--ctp-overlay2); 29 | 30 | --swt-result-th-bg: var(--ctp-crust); 31 | --swt-result-td-bg: var(--ctp-mantle); 32 | --swt-result-cell-border-color: #1b1b1b; 33 | } 34 | 35 | .cm-activeLine { 36 | background-color: var(--ctp-mantle) !important; 37 | } 38 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-hybrid-search/index.js: -------------------------------------------------------------------------------- 1 | import "./styles.css"; 2 | import * as d3 from "d3-selection"; 3 | import "d3-transition"; 4 | 5 | const colors = Array.from({ length: 12 }, (_, i) => `var(--hero-c${i + 1})`); 6 | 7 | export async function hero() { 8 | const hero = document.querySelector("#hero"); 9 | const width = hero.parentElement.clientWidth; 10 | const height = (width * 9) / 16 / 2; 11 | hero.setAttribute("width", width); 12 | hero.setAttribute("height", height); 13 | 14 | d3.select(hero) 15 | .append("rect") 16 | .attr("width", width) 17 | .attr("height", height) 18 | .attr("rx", 8) 19 | .attr("ry", 8) 20 | .attr("fill", "var(--svg-bg)"); 21 | 22 | const rects = d3 23 | .select(hero) 24 | .selectAll("g") 25 | .data(Array.from({ length: 64 }, (_, i) => i)) 26 | .join((enter) => 27 | enter.append("g").call((g) => 28 | g 29 | .attr( 30 | "transform", 31 | (d, i) => 32 | `translate(${20 + Math.floor(i / 4) * 40}, ${20 + (i % 4) * 40})` 33 | ) 34 | .append("rect") 35 | .attr("width", 20) 36 | .attr("height", 20) 37 | .attr("fill", (d, i) => colors[i % colors.length]) 38 | .attr("fill-opacity", 0.8) 39 | ) 40 | ); 41 | 42 | while (true) { 43 | await rects 44 | .transition() 45 | .delay((d, i) => (i / 12) * 750) 46 | .duration(() => 2500 + Math.random() * 1000) 47 | .select("rect") 48 | .attrTween("transform", () => (t) => `rotate(${t * 360}, 10, 10)`) 49 | //.call((g) => ) 50 | .end(); 51 | } 52 | } 53 | 54 | hero(); 55 | -------------------------------------------------------------------------------- /posts/2024/sqlite-lembed-init/index.js: -------------------------------------------------------------------------------- 1 | import "./styles.css"; 2 | import * as d3 from "d3-selection"; 3 | import "d3-transition"; 4 | 5 | const colors = Array.from({ length: 12 }, (_, i) => `var(--hero-c${i + 1})`); 6 | 7 | export async function hero() { 8 | const hero = document.querySelector("#hero"); 9 | const width = hero.parentElement.clientWidth; 10 | const height = (width * 9) / 16 / 2; 11 | hero.setAttribute("width", width); 12 | hero.setAttribute("height", height); 13 | 14 | d3.select(hero) 15 | .append("rect") 16 | .attr("width", width) 17 | .attr("height", height) 18 | .attr("rx", 8) 19 | .attr("ry", 8) 20 | .attr("fill", "var(--svg-bg)"); 21 | 22 | const rects = d3 23 | .select(hero) 24 | .selectAll("g") 25 | .data(Array.from({ length: 60 }, (_, i) => i)) 26 | .join((enter) => 27 | enter.append("g").call((g) => 28 | g 29 | .attr("transform", (d, i) => `translate(${i * 12}, ${(i % 12) * 20})`) 30 | .append("rect") 31 | //.attr("x", (d, i) => i * 16) 32 | .attr("width", 20) 33 | //.attr("y", (d, i) => (i % 12) * 20) 34 | .attr("height", 20) 35 | .attr("fill", (d, i) => colors[i % colors.length]) 36 | .attr("fill-opacity", 0.4) 37 | ) 38 | ); 39 | 40 | const minWidth = 100; 41 | while (true) { 42 | await rects 43 | .transition() 44 | .delay((d, i) => (i % 12) * 750) 45 | .duration(() => 1200) 46 | .select("rect") 47 | .attrTween("transform", () => (t) => `rotate(${t * 360}, 10, 10)`) 48 | //.call((g) => ) 49 | .end(); 50 | } 51 | } 52 | 53 | hero(); 54 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-metadata-release/index.js: -------------------------------------------------------------------------------- 1 | import "./styles.css"; 2 | import * as d3 from "d3-selection"; 3 | import "d3-transition"; 4 | 5 | const colors = Array.from({ length: 12 }, (_, i) => `var(--hero-c${i + 1})`); 6 | 7 | export async function hero() { 8 | const hero = document.querySelector("#hero"); 9 | const width = hero.parentElement.clientWidth; 10 | const height = (width * 9) / 16 / 2; 11 | hero.setAttribute("width", width); 12 | hero.setAttribute("height", height); 13 | 14 | d3.select(hero) 15 | .append("rect") 16 | .attr("width", width) 17 | .attr("height", height) 18 | .attr("rx", 8) 19 | .attr("ry", 8) 20 | .attr("fill", "var(--svg-bg)"); 21 | 22 | const rects = d3 23 | .select(hero) 24 | .selectAll("g") 25 | .data(Array.from({ length: 256 }, (_, i) => i)) 26 | .join((enter) => 27 | enter.append("g").call((g) => 28 | g 29 | .attr( 30 | "transform", 31 | (d, i) => 32 | `translate(${20 + Math.floor(i / 8) * 24}, ${20 + (i % 8) * 24})` 33 | ) 34 | .append("rect") 35 | .attr("width", 10) 36 | .attr("height", 10) 37 | .attr("fill", (d, i) => colors[i % colors.length]) 38 | .attr("fill-opacity", 0.8) 39 | ) 40 | ); 41 | 42 | while (true) { 43 | await rects 44 | .transition() 45 | .delay((d, i) => (i / 12) * 250) 46 | .duration(() => 1000 + Math.random() * 500) 47 | .select("rect") 48 | .attrTween("transform", () => (t) => `rotate(${t * 360}, 6, 6)`) 49 | //.call((g) => ) 50 | .end(); 51 | } 52 | } 53 | 54 | hero(); 55 | -------------------------------------------------------------------------------- /posts/2024/sqlite-rembed-init/index.js: -------------------------------------------------------------------------------- 1 | import "./styles.css"; 2 | import * as d3 from "d3-selection"; 3 | import "d3-transition"; 4 | 5 | const colors = Array.from({ length: 12 }, (_, i) => `var(--hero-c${i + 1})`); 6 | 7 | export async function hero() { 8 | const hero = document.querySelector("#hero"); 9 | const width = hero.parentElement.clientWidth; 10 | const height = (width * 9) / 16 / 2; 11 | hero.setAttribute("width", width); 12 | hero.setAttribute("height", height); 13 | 14 | d3.select(hero) 15 | .append("rect") 16 | .attr("width", width) 17 | .attr("height", height) 18 | .attr("rx", 8) 19 | .attr("ry", 8) 20 | .attr("fill", "var(--svg-bg)"); 21 | 22 | const rects = d3 23 | .select(hero) 24 | .selectAll("g") 25 | .data(Array.from({ length: 48 }, (_, i) => i)) 26 | .join((enter) => 27 | enter.append("g").call((g) => 28 | g 29 | .attr( 30 | "transform", 31 | (d, i) => 32 | `translate(${6 + (Math.random() * width - 12)}, ${ 33 | Math.random() * height 34 | })` 35 | ) 36 | .append("ellipse") 37 | .attr("cx", 12) 38 | .attr("cy", 8) 39 | .attr("rx", 21) 40 | .attr("ry", 8) 41 | .attr("fill", (d, i) => colors[i % colors.length]) 42 | .attr("fill-opacity", 0.4) 43 | ) 44 | ); 45 | 46 | const minWidth = 100; 47 | while (true) { 48 | await rects 49 | .transition() 50 | .delay((d, i) => (i % 12) * 750) 51 | .duration(() => 1200) 52 | .select("ellipse") 53 | .attrTween("transform", () => (t) => `rotate(${t * 360}, 6, 4)`) 54 | //.call((g) => ) 55 | .end(); 56 | } 57 | } 58 | 59 | hero(); 60 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-stable-release/index.js: -------------------------------------------------------------------------------- 1 | import "./styles.css"; 2 | import * as d3 from "d3-selection"; 3 | import "d3-transition"; 4 | import "lite-youtube-embed"; 5 | 6 | const colors = Array.from({ length: 12 }, (_, i) => `var(--hero-c${i + 1})`); 7 | 8 | export async function hero() { 9 | const hero = document.querySelector("#hero"); 10 | const width = hero.parentElement.clientWidth; 11 | const height = (width * 9) / 16 / 2; 12 | hero.setAttribute("width", width); 13 | hero.setAttribute("height", height); 14 | 15 | d3.select(hero) 16 | .append("rect") 17 | .attr("width", width) 18 | .attr("height", height) 19 | .attr("rx", 8) 20 | .attr("ry", 8) 21 | .attr("fill", "var(--svg-bg)"); 22 | 23 | const rects = d3 24 | .select(hero) 25 | .selectAll("g") 26 | .data(Array.from({ length: 48 }, (_, i) => i)) 27 | .join((enter) => 28 | enter.append("g").call((g) => 29 | g 30 | .attr( 31 | "transform", 32 | (d, i) => 33 | `translate(${ 34 | 10 + (Math.floor(Math.random() * width - 20) / 20) * 20 35 | }, ${20 + Math.floor((Math.random() * height) / 20) * 20})` 36 | ) 37 | .append("rect") 38 | .attr("width", 20) 39 | .attr("height", 20) 40 | .attr("fill", (d, i) => colors[i % colors.length]) 41 | .attr("fill-opacity", 0.8) 42 | ) 43 | ); 44 | 45 | while (true) { 46 | await rects 47 | .transition() 48 | .delay((d, i) => (i / 12) * 750) 49 | .duration(() => 2500 + Math.random() * 1000) 50 | .select("rect") 51 | .attrTween("transform", () => (t) => `rotate(${t * 360}, 10, 10)`) 52 | //.call((g) => ) 53 | .end(); 54 | } 55 | } 56 | 57 | hero(); 58 | -------------------------------------------------------------------------------- /posts/2024/building-new-vector-search-sqlite/hero.js: -------------------------------------------------------------------------------- 1 | import * as d3 from "d3-selection"; 2 | import "d3-transition"; 3 | 4 | const colors = Array.from({ length: 13 }, (_, i) => `var(--hero-c${i + 1})`); 5 | 6 | export async function hero() { 7 | const hero = document.querySelector("#hero"); 8 | const width = hero.parentElement.clientWidth; 9 | const height = (width * 9) / 16 / 2; 10 | hero.setAttribute("width", width); 11 | hero.setAttribute("height", height); 12 | 13 | d3.select(hero) 14 | .append("rect") 15 | .attr("width", width) 16 | .attr("height", height) 17 | .attr("rx", 8) 18 | .attr("ry", 8) 19 | .attr("fill", "var(--svg-bg)"); 20 | 21 | const arrows = d3 22 | .select(hero) 23 | .selectAll("g") 24 | .data(Array.from({ length: 20 }, (_, i) => i)) 25 | .join((enter) => 26 | enter.append("g").call((g) => 27 | g 28 | .append("line") 29 | .attr("y1", (d, i) => 10 + i * 10) 30 | .attr("y2", (d, i) => 10 + i * 10) 31 | .attr("stroke", (d, i) => colors[i % colors.length]) 32 | .attr("stroke-width", 4) 33 | ) 34 | ); 35 | 36 | const minWidth = 100; 37 | while (true) { 38 | const positions = arrows.data().map((d) => { 39 | const min = Math.random() * (width - minWidth); 40 | const max = Math.random() * (width - (min + minWidth)) + (min + minWidth); 41 | return [min, max]; 42 | }); 43 | 44 | await arrows 45 | .transition() 46 | .delay(() => Math.random() * 750) 47 | .duration(() => 2000 + Math.random() * 3000) 48 | .call((g) => 49 | g 50 | .selectAll("line") 51 | .attr("x1", (d, i) => positions[d][0]) 52 | .attr("x2", (d, i) => positions[d][1]) 53 | ) 54 | .end(); 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /posts/2024/sql-vector-search-languages/Makefile: -------------------------------------------------------------------------------- 1 | demos: 2 | mkdir -p $@ 3 | 4 | demos/demo.bun.ts: demos 5 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-bun/demo.ts 6 | demos/demo.deno.ts: demos 7 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-deno/demo.ts 8 | demos/demo.mjs: demos 9 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-node/demo.mjs 10 | demos/demo.py: demos 11 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-python/demo.py 12 | demos/demo.c: demos 13 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-c/demo.c 14 | demos/demo.go: demos 15 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-go/demo.go 16 | demos/demo.rb: demos 17 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-ruby/demo.rb 18 | demos/demo.rs: demos 19 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-rust/demo.rs 20 | demos/demo.sql: demos 21 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-sqlite/demo.sql 22 | demos/index.html: demos 23 | curl -L -o $@ https://github.com/asg017/sqlite-vec/raw/main/examples/simple-wasm/index.html 24 | 25 | all: demos/demo.bun.ts demos/demo.deno.ts demos/demo.mjs demos/demo.py demos/demo.c demos/demo.go demos/demo.rb demos/demo.rs demos/demo.sql demos/demo.py demos/index.html 26 | 27 | 28 | node_modules: package.json package-lock.json 29 | npm i 30 | touch $@ 31 | 32 | dist: index.js all node_modules 33 | rm -rf $@ || true 34 | mkdir $@ 35 | ./node_modules/.bin/esbuild \ 36 | --minify --bundle --format=esm --splitting \ 37 | --out-extension:.js=.min.js \ 38 | --out-extension:.css=.min.css \ 39 | $< --outdir=$@ 40 | touch $@ 41 | 42 | clean: 43 | rm -rf demos/ 44 | -------------------------------------------------------------------------------- /static/base.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: MonaspaceNeon; 3 | font-weight: bold; 4 | src: url("MonaspaceNeon-Regular.otf") format("opentype"); 5 | } 6 | 7 | :root { 8 | --blog-link-color: #7287fd; 9 | --text-color: black; 10 | --bg-color: white; 11 | } 12 | 13 | html.dark { 14 | --blog-link-color: #b4befe; 15 | --text-color: white; 16 | --bg-color: #181825; 17 | } 18 | 19 | html { 20 | background-color: var(--bg-color); 21 | } 22 | 23 | main { 24 | max-width: 48rem; 25 | margin: 0 auto; 26 | } 27 | 28 | * { 29 | color: var(--text-color); 30 | /*font-family: "Inter", sans-serif;*/ 31 | font-family: "Helvetica Neue", helvetica, sans-serif; 32 | font-optical-sizing: auto; 33 | /*font-weight: ;*/ 34 | font-style: normal; 35 | font-variation-settings: "slnt" 0; 36 | } 37 | 38 | a { 39 | color: var(--blog-link-color); /*#cba6f7;*/ 40 | } 41 | 42 | h1, 43 | h2 { 44 | margin-bottom: 0.5rem; 45 | } 46 | 47 | li::marker { 48 | margin: 0; 49 | } 50 | 51 | code { 52 | font-family: MonaspaceNeon; 53 | } 54 | 55 | pre { 56 | padding: 0.75rem; 57 | border-radius: 0.25rem; 58 | overflow: auto; 59 | } 60 | 61 | .header { 62 | display: flex; 63 | justify-content: space-between; 64 | align-items: center; 65 | } 66 | 67 | button.theme::before { 68 | content: "⏼"; 69 | } 70 | button.theme { 71 | cursor: pointer; 72 | background: none; 73 | border: none; 74 | text-decoration: underline; 75 | color: var(--blog-link-color); 76 | } 77 | 78 | /* 79 | 80 | html.dark .shiki, 81 | html.dark .shiki span { 82 | color: var(--shiki-dark) !important; 83 | background-color: var(--shiki-dark-bg) !important; 84 | 85 | font-style: var(--shiki-dark-font-style) !important; 86 | font-weight: var(--shiki-dark-font-weight) !important; 87 | text-decoration: var(--shiki-dark-text-decoration) !important; 88 | } 89 | 90 | */ 91 | -------------------------------------------------------------------------------- /posts/2024/building-new-vector-search-sqlite/styles.css: -------------------------------------------------------------------------------- 1 | :root { 2 | --svg-bg: var(--ctp-crust); 3 | --hero-c1: var(--ctp-flamingo); 4 | --hero-c2: var(--ctp-pink); 5 | --hero-c3: var(--ctp-mauve); 6 | --hero-c4: var(--ctp-red); 7 | --hero-c5: var(--ctp-maroon); 8 | --hero-c6: var(--ctp-peach); 9 | --hero-c7: var(--ctp-yellow); 10 | --hero-c8: var(--ctp-green); 11 | --hero-c9: var(--ctp-teal); 12 | --hero-c10: var(--ctp-sky); 13 | --hero-c11: var(--ctp-sapphire); 14 | --hero-c12: var(--ctp-blue); 15 | --hero-c13: var(--ctp-lavender); 16 | } 17 | 18 | .swt-editor { 19 | --swt-code-bg: var(--ctp-base); 20 | --swt-code-comment: var(--ctp-subtext1); /*#5f6368;*/ 21 | --swt-code-keyword: var(--ctp-mauve); 22 | --swt-code-identifier: var(--ctp-blue); 23 | --swt-code-string: var(--ctp-green); 24 | --swt-code-types: var(--ctp-yellow); 25 | --swt-code-literal: var(--ctp-peach); 26 | --swt-code-params: var(--ctp-pink); 27 | 28 | --swt-widget-border: var(--ctp-overlay2); 29 | 30 | --swt-result-th-bg: var(--ctp-crust); 31 | --swt-result-td-bg: var(--ctp-mantle); 32 | --swt-result-cell-border-color: #1b1b1b; 33 | } 34 | 35 | .cm-activeLine { 36 | background-color: var(--ctp-mantle) !important; 37 | } 38 | 39 | #movie-select-table { 40 | overflow: auto; 41 | font-family: "Roboto-Mono"; 42 | } 43 | #movie-select-table table { 44 | margin: 0 auto; 45 | border-collapse: collapse; 46 | max-width: initial; 47 | } 48 | #movie-select-table table th { 49 | background: var(--swt-result-th-bg); 50 | } 51 | #movie-select-table table td { 52 | background: var(--swt-result-td-bg); 53 | } 54 | 55 | #movie-select-table table td:first-child { 56 | max-width: 40px; 57 | } 58 | #movie-select-table th, 59 | #movie-select-table td { 60 | border: 1px solid var(--swt-result-cell-border-color); 61 | } 62 | 63 | 64 | .swt-table td { 65 | max-width: 66 | } -------------------------------------------------------------------------------- /posts/2024/sql-vector-search-languages/index.js: -------------------------------------------------------------------------------- 1 | import "./styles.css"; 2 | import * as d3 from "d3-selection"; 3 | import "d3-transition"; 4 | 5 | const colors = Array.from({ length: 12 }, (_, i) => `var(--hero-c${i + 1})`); 6 | 7 | export async function hero() { 8 | const hero = document.querySelector("#hero"); 9 | const width = hero.parentElement.clientWidth; 10 | const height = (width * 9) / 16 / 2; 11 | hero.setAttribute("width", width); 12 | hero.setAttribute("height", height); 13 | 14 | d3.select(hero) 15 | .append("rect") 16 | .attr("width", width) 17 | .attr("height", height) 18 | .attr("rx", 8) 19 | .attr("ry", 8) 20 | .attr("fill", "var(--svg-bg)"); 21 | 22 | const arrows = d3 23 | .select(hero) 24 | .selectAll("g") 25 | .data(Array.from({ length: 24 }, (_, i) => i)) 26 | .join((enter) => 27 | enter.append("g").call((g) => 28 | g 29 | .append("line") 30 | .attr("x1", (d, i) => 10 + (i * width) / 6) 31 | .attr("x2", (d, i) => 10 + (i * width) / 6) 32 | .attr("y1", 0) 33 | .attr("y2", height) 34 | .attr("stroke", (d, i) => colors[i % colors.length]) 35 | .attr("stroke-width", 4) 36 | .attr("stroke-opacity", 0.4) 37 | ) 38 | ); 39 | 40 | const minWidth = 100; 41 | while (true) { 42 | const positions = arrows.data().map((d) => { 43 | const min = Math.random() * (width - minWidth); 44 | const max = Math.random() * (width - (min + minWidth)) + (min + minWidth); 45 | return [min, max]; 46 | }); 47 | 48 | await arrows 49 | .transition() 50 | .delay(() => Math.random() * 750) 51 | .duration(() => 2000 + Math.random() * 3000) 52 | .call((g) => 53 | g 54 | .selectAll("line") 55 | .attr("x1", (d, i) => -positions[d][0]) 56 | .attr("x2", (d, i) => positions[d][1]) 57 | ) 58 | .end(); 59 | } 60 | } 61 | 62 | hero(); 63 | -------------------------------------------------------------------------------- /Home.tsx: -------------------------------------------------------------------------------- 1 | /** @jsx h */ 2 | import { h } from "https://esm.sh/preact@10.5.15"; 3 | import { Post } from "./build.tsx"; 4 | 5 | export function HomePage({ posts }: { posts: Post[] }) { 6 | return ( 7 | 8 | 9 | 10 | 11 | 12 | Alex Garcia's Blog 13 | 14 | 15 | 20 | 21 | 22 |
23 |
24 |
25 |
26 | 27 |
28 |
29 |
30 |

Alex Garcia's Blog

31 |

32 | I'm Alex Garcia, a software 33 | engineer based out of Los Angeles. 34 |
35 |
This is my new blog approach I'm trying out. I have older 36 | writings on my{" "} 37 | Observable account 38 | . 39 |

40 |

41 |
42 |
43 |

All posts

44 | {posts 45 | .sort( 46 | (a, b) => a.frontmatter.created_at - b.frontmatter.created_at 47 | ) 48 | .map((post) => ( 49 |
50 |
  • 51 | 52 | {post.frontmatter.created_at 53 | .toISOString() 54 | .substring(0, "YYYY-MM-DD".length)} 55 | 56 | : {post.frontmatter.title} 57 |
  • 58 |
    59 | ))} 60 |
    61 |
    62 | 63 | 64 | ); 65 | } 66 | -------------------------------------------------------------------------------- /posts/sqlite/subtypes.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: An unofficial list of SQLite subtypes in the wild 3 | created_at: 9999-12-31 4 | skip: true 5 | --- 6 | 7 | | Subtype value | Source | Usage | 8 | | ------------- | --------------------- | ---------------- | 9 | | 74 (`'J'`) | SQLite JSON extension | JSON values | 10 | | 88 (`'X'`) | `sqlite-xml` | XML | 11 | | 112 (`'p'`) | | | 12 | | 221 | `sqlite-html` | HTML elements | 13 | | 223 | `sqlite-vec` | float32 vectors | 14 | | 224 | `sqlite-vec` | binary vectors | 15 | | 225 | `sqlite-vec` | integer8 vectors | 16 | 17 | ## JSON subtype 18 | 19 | https://github.com/sqlite/sqlite/blob/b11daa50f9ea11c332bb5913a071c5a0fd6c9993/src/json.c#L268 20 | 21 | ```c 22 | /* The "subtype" set for text JSON values passed through using 23 | ** sqlite3_result_subtype() and sqlite3_value_subtype(). 24 | */ 25 | #define JSON_SUBTYPE 74 /* Ascii for "J" */ 26 | ``` 27 | 28 | https://github.com/sqlite/sqlite/blob/b11daa50f9ea11c332bb5913a071c5a0fd6c9993/src/vdbemem.c#L971 29 | 30 | ```c 31 | void sqlite3VdbeMemSetPointer( 32 | Mem *pMem, 33 | void *pPtr, 34 | const char *zPType, 35 | void (*xDestructor)(void*) 36 | ){ 37 | assert( pMem->flags==MEM_Null ); 38 | vdbeMemClear(pMem); 39 | pMem->u.zPType = zPType ? zPType : ""; 40 | pMem->z = pPtr; 41 | pMem->flags = MEM_Null|MEM_Dyn|MEM_Subtype|MEM_Term; 42 | pMem->eSubtype = 'p'; 43 | pMem->xDel = xDestructor ? xDestructor : sqlite3NoopDestructor; 44 | } 45 | ``` 46 | 47 | https://github.com/asg017/sqlite-html/blob/d3b1d77f2a0c1383349babed26fb8a196beab445/elements.go#L18 48 | 49 | ```go 50 | var HTML_SUBTYPE = 0xdd 51 | ``` 52 | 53 | https://github.com/asg017/sqlite-vec/blob/e5b0f4c0c5ee69aa5746b0c64ab881e1fc6d9d70/sqlite-vec.c#L88-L92 54 | 55 | ```c 56 | enum VectorElementType { 57 | SQLITE_VEC_ELEMENT_TYPE_FLOAT32 = 223 + 0, 58 | SQLITE_VEC_ELEMENT_TYPE_BIT = 223 + 1, 59 | SQLITE_VEC_ELEMENT_TYPE_INT8 = 223 + 2, 60 | }; 61 | ``` 62 | 63 | https://github.com/asg017/sqlite-xml/blob/acb1894bcfed3c6f2abc54650c4fce5817c4b522/src/scalar.rs#L38 64 | 65 | ```rust 66 | fn result_xml(context: *mut sqlite3_context, doc: &Document, node: &RoNode) -> Result<()> { 67 | api::result_text(context, doc.ronode_to_string(node).as_str())?; 68 | api::result_subtype(context, b'X'); 69 | Ok(()) 70 | } 71 | ``` 72 | -------------------------------------------------------------------------------- /posts/2025/introducing-libfec/index.mjs: -------------------------------------------------------------------------------- 1 | import * as d3 from "npm:d3-selection"; 2 | import "npm:d3-transition"; 3 | 4 | export function hero() { 5 | const hero = document.querySelector("#hero"); 6 | const width = hero.parentElement.clientWidth; 7 | const height = (width * 9) / 16 / 2; 8 | hero.setAttribute("width", width); 9 | hero.setAttribute("height", height); 10 | 11 | d3.select(hero) 12 | .append("rect") 13 | .attr("width", width) 14 | .attr("height", height) 15 | .attr("fill", "var(--svg-bg)"); 16 | 17 | const circleData = Array.from({ length: 32 }, (_, i) => ({ 18 | id: i, 19 | x: Math.random() * (width - 40) + 20, 20 | y: Math.random() * (height - 40) + 20, 21 | color: 'var(--ctp-green)' 22 | })); 23 | 24 | const linkData = []; 25 | const numLinks = Math.floor(circleData.length * 0.8); 26 | 27 | for (let i = 0; i < numLinks; i++) { 28 | const source = circleData[Math.floor(Math.random() * circleData.length)]; 29 | const target = circleData[Math.floor(Math.random() * circleData.length)]; 30 | 31 | // Avoid self-links and duplicate links 32 | if (source.id !== target.id) { 33 | const existingLink = linkData.find(link => 34 | (link.source.id === source.id && link.target.id === target.id) || 35 | (link.source.id === target.id && link.target.id === source.id) 36 | ); 37 | 38 | if (!existingLink) { 39 | linkData.push({ source, target }); 40 | } 41 | } 42 | } 43 | 44 | d3 45 | .select(hero) 46 | .selectAll("line.link") 47 | .data(linkData) 48 | .join("line") 49 | .attr("class", "link") 50 | .attr("x1", d => d.source.x) 51 | .attr("y1", d => d.source.y) 52 | .attr("x2", d => d.target.x) 53 | .attr("y2", d => d.target.y) 54 | .attr("stroke", 'var(--ctp-green)') 55 | .attr("stroke-width", 4) 56 | .attr("stroke-opacity", 0.3); 57 | 58 | const circles = d3 59 | .select(hero) 60 | .selectAll("circle.animated") 61 | .data(circleData) 62 | .join("circle") 63 | .attr("class", "animated") 64 | .attr("cx", d => d.x) 65 | .attr("cy", d => d.y) 66 | .attr("r", 8) 67 | .attr("fill", d => d.color) 68 | .attr("fill-opacity", 0.7); 69 | 70 | function animate() { 71 | circles 72 | .transition() 73 | .duration(3000 + Math.random() * 2000) 74 | .attr("r", () => 6 + Math.random() * 12) 75 | .on("end", animate); 76 | } 77 | 78 | animate(); 79 | } 80 | 81 | hero(); 82 | -------------------------------------------------------------------------------- /posts/2024/building-new-vector-search-sqlite/sqlite.js: -------------------------------------------------------------------------------- 1 | import { attach } from "@alex.garcia/sqlite-wasm-toolkit/plugin"; 2 | import { default as init } from "./sqlite3.mjs"; 3 | import { table } from "@observablehq/inputs"; 4 | 5 | const initialCode = `select 6 | rowid, 7 | distance, 8 | movies.title 9 | from vec_movies 10 | left join movies on movies.rowid = vec_movies.rowid 11 | where overview_embeddings match 12 | ( 13 | select overview_embeddings 14 | from vec_movies 15 | where rowid = :selected_movie 16 | ) 17 | and k = 10 18 | order by distance; 19 | `; 20 | 21 | export async function load() { 22 | const sqlite3 = await init(); 23 | const target = document.body.querySelector("#target-code"); 24 | const v = new sqlite3.oo1.DB(":memory:").selectValue("select vec_version()"); 25 | 26 | const db = await fetch("./movies.bit.db") 27 | .then((r) => r.arrayBuffer()) 28 | .then((buffer) => { 29 | const p = sqlite3.wasm.allocFromTypedArray(buffer); 30 | const db = new sqlite3.oo1.DB(); 31 | const rc = sqlite3.capi.sqlite3_deserialize( 32 | db.pointer, 33 | "main", 34 | p, 35 | buffer.byteLength, 36 | buffer.byteLength, 37 | sqlite3.capi.SQLITE_DESERIALIZE_FREEONCLOSE 38 | ); 39 | db.checkRc(rc); 40 | return db; 41 | }); 42 | 43 | let selected_movie = 69; 44 | function prepareStatement(stmt) { 45 | if (stmt.getParamIndex(":selected_movie") !== undefined) { 46 | stmt.bind({ ":selected_movie": selected_movie }); 47 | } 48 | } 49 | 50 | class MyClass extends EventTarget { 51 | doSomething() { 52 | this.dispatchEvent(new Event("something")); 53 | } 54 | } 55 | const m = new MyClass(); 56 | attach({ 57 | db, 58 | target, 59 | sqlite3, 60 | prepareStatement, 61 | initialCode, 62 | footerExtra: `, with sqlite-vec ${v}`, 63 | refresh: m, 64 | }); 65 | attach({ 66 | db, 67 | target: document.querySelector("#target1"), 68 | sqlite3, 69 | initialCode: `select 70 | movies.title, 71 | movies.release_date, 72 | substr(movies.overview, 0, 20) || '...' as overview_start, 73 | vec_movies.overview_embeddings 74 | from movies 75 | left join vec_movies on vec_movies.rowid = movies.rowid 76 | limit 10;`, 77 | footerExtra: `, with sqlite-vec ${v}`, 78 | }); 79 | 80 | const movies = db.selectObjects( 81 | "select rowid, title, release_date from movies limit 40" 82 | ); 83 | const moviesTable = table(movies, { 84 | multiple: false, 85 | value: movies[0], 86 | columns: ["title", "release_date"], 87 | }); 88 | moviesTable.addEventListener("input", (e) => { 89 | selected_movie = movies[e.target.value].rowid; 90 | console.log(selected_movie); 91 | m.dispatchEvent(new CustomEvent("refresh")); 92 | }); 93 | document.querySelector("#target-table").appendChild(moviesTable); 94 | moviesTable.setAttribute("id", "movie-select-table"); 95 | } 96 | -------------------------------------------------------------------------------- /Post.tsx: -------------------------------------------------------------------------------- 1 | /** @jsx h */ 2 | import { h } from "https://esm.sh/preact@10.5.15"; 3 | import { Post } from "./build.tsx"; 4 | 5 | const pageCss = Deno.readTextFileSync("page.css"); 6 | 7 | export function PostPage({ post }: { post: Post }): h.JSX.Element { 8 | return ( 9 | 10 | 11 | 12 | 13 | 14 | {post.frontmatter.title} | Alex Garcia's Blog 15 | 16 | 17 | 18 | 19 | 20 | 21 | 25 | 26 | 27 | 28 | 32 | 39 | 40 | 41 | 42 | 47 | 51 | 52 | 57 | 58 | 59 |
    60 |
    61 |
    62 | Alex Garcia's Blog 63 |
    64 |
    65 | 66 |
    67 |
    68 |

    {post.frontmatter.title}

    69 |

    70 | {post.frontmatter.created_at 71 | .toISOString() 72 | .substring(0, "yyyy-mm-dd".length)}{" "} 73 | by Alex Garcia 74 |

    75 |
    78 |
    79 | 80 | 81 | ); 82 | } 83 | -------------------------------------------------------------------------------- /posts/2024/sqlite-rembed-init/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introducing sqlite-rembed: A SQLite extension for generating text embeddings from remote APIs" 3 | description: Generate embeddings with pure SQL from OpenAI, Cohere, Nomic, llamafile, Ollama, ... 4 | created_at: 2024-07-25 5 | build: make dist 6 | share_photo_url: https://blog-static.alxg.xyz/Screen%20Shot%202024-07-24%20at%2010.42.43%20PM.png 7 | --- 8 | 9 | 10 | 11 | 12 | 13 | 14 |
    15 | 16 | > \_tl;dr — [`sqlite-rembed`](https://github.com/asg017/sqlite-rembed) is a new 17 | > SQLite extension for generating text embeddings from remote APIs — like OpenAI, Nomic, Cohere, llamafile, Ollama, and more! It bundles its own HTTP client, so it can be used in small environments like the official SQLite CLI. It doesn't support batch embeddings yet, but can still be useful in many cases. 18 | 19 | 24 |
    25 | 26 | --- 27 | 28 | `sqlite-rembed` is a new SQLite extension I've been experimenting with, as a sister project to [`sqlite-vec`](https://github.com/asg017/sqlite-vec). It connects to various 3rd party APIs to generate text embeddings. 29 | 30 | For example, to use [OpenAI's embedding service](https://platform.openai.com/docs/guides/embeddings), this is all you need: 31 | 32 | ```sql 33 | INSERT INTO temp.rembed_clients(name, options) 34 | VALUES ('text-embedding-3-small', 'openai'); 35 | 36 | select rembed( 37 | 'text-embedding-3-small', 38 | 'The United States Postal Service is an independent agency...' 39 | ); -- X'A452...01FC', Blob<6144 bytes> 40 | ``` 41 | 42 | Here we register a new rembed "client" named `text-embedding-3-small`, using the special `openai` option. By default, The `openai` option will source your API key from the `OPENAI_API_KEY` environment variable, and use the client name (`text-embedding-3-small`) as the model name. 43 | 44 | Now, we can use the `rembed()` SQL function to generate embeddings from OpenAI! It returns the embeddings in a compact BLOB format, the same format that `sqlite-vec` uses. In this case, `text-embedding-3-small` returns 1536 dimensions, so a `1536 * 4 = 6144` length BLOB is returned. 45 | 46 | And `sqlite-rembed` has support for other providers! Here's an example that uses [Nomic's embedding API](https://docs.nomic.ai/reference/endpoints/nomic-embed-text): 47 | 48 | ```sql 49 | INSERT INTO temp.rembed_clients(name, options) 50 | VALUES ('nomic-embed-text-v1.5', 'nomic'); 51 | 52 | select rembed( 53 | 'nomic-embed-text-v1.5', 54 | 'The United States Postal Service is an independent agency...' 55 | ); 56 | ``` 57 | 58 | And with [Cohere's embedding API](https://docs.cohere.com/reference/embed): 59 | 60 | ```sql 61 | INSERT INTO temp.rembed_clients(name, options) 62 | VALUES ('embed-english-v3.0', 'cohere'); 63 | 64 | select rembed( 65 | 'embed-english-v3.0', 66 | 'The United States Postal Service is an independent agency...' 67 | ); 68 | ``` 69 | 70 | Notice how you can have multiple clients, all with different names and using different API providers. Secrets are sourced from places you expect: `NOMIC_API_KEY`, `CO_API_KEY`, and so on. 71 | 72 | If you want to manually configure which API keys to use, or change the "base URL" of a provider, you can do so with `rembed_client_options()`: 73 | 74 | ```sql 75 | INSERT INTO temp.rembed_clients(name, options) VALUES 76 | ( 77 | 'text-embedding-3-small', 78 | rembed_client_options( 79 | 'format', 'openai', 80 | 'key', :OPENAI_API_KEY -- SQL parameter to bind an API key 81 | ) 82 | ); 83 | ``` 84 | 85 | In total, `sqlite-rembed` currently has support for the following embedding providers: 86 | 87 | - OpenAI 88 | - Nomic 89 | - Cohere 90 | - Jina 91 | - MixedBread 92 | - Llamafile 93 | - Ollama 94 | 95 | ## "Remote" embeddings can still be local! 96 | 97 | `sqlite-rembed` stands for "**SQLite** **r**emote **embed**dings," in contrast to its sister project [`sqlite-lembed`](https://github.com/asg017/sqlite-lembed) that stands for "**SQLite** **l**ocal **embed**dings." For `sqlite-lembed`, "local" means inside the same process, no external process or server needed. "Remote" in `sqlite-rembed` just means "outside the current process", which isn't always an outside `https://...` server. 98 | 99 | You can totally run a embeddings model locally with llamafile, Ollama, or some other "OpenAI compatible" service, and point `sqlite-rembed` to a `http://localhost:...` endpoint. 100 | 101 | Let's take llamafile as an example: follow the ["Getting Started with LLaMAfiler"](https://github.com/Mozilla-Ocho/llamafile/blob/main/llamafile/server/doc/getting_started.md) guide. Once up, you'll have a local embeddings server available to you at `http://127.0.0.1:8080/`. To use it from `sqlite-rembed`, register with the `llamafile` option: 102 | 103 | ```sql 104 | INSERT INTO temp.rembed_clients(name, options) 105 | VALUES ('llamafile', 'llamafile'); 106 | 107 | .mode quote 108 | 109 | select rembed('llamafile', 'Tennis star Coco Gauff will carry the U.S. flag...'); 110 | ``` 111 | 112 | And that's it! Not a single byte of your data will leave your computer. 113 | 114 | Another option is [Ollama's embeddings support](https://ollama.com/blog/embedding-models). Once installed, Ollama will have a constantly running server at `http://localhost:11434`. To use from `sqlite-rembed`, register a `ollama` client like so: 115 | 116 | ```sql 117 | INSERT INTO temp.rembed_clients(name, options) 118 | VALUES ('snowflake-arctic-embed:s', 'ollama'); 119 | 120 | select rembed('ollama', 'LeVar Burton talks about his changing...'); 121 | ``` 122 | 123 | Where the [`snowflake-arctic-embed:s`](https://ollama.com/library/snowflake-arctic-embed:s) model I downloaded with `ollama pull snowflake-arctic-embed:s`. This approach is nice because the Ollama service will be constantly running in the background, and will "wake up" embedding models into memory on first request (and will unload after 5 minutes of inactivity). Again, not a single byte of your data leaves your computer. 124 | 125 | --- 126 | 127 | So try out `sqlite-rembed` today! There are pre-compiled binaries on Github releases, or you can `pip install sqlite-rembed` or `npm install sqlite-remebed`. 128 | -------------------------------------------------------------------------------- /posts/2024/sqlite-lembed-init/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "Introducing sqlite-lembed: A SQLite extension for generating text embeddings locally" 3 | description: Generate text embeddings in SQL with GGUF models! 4 | created_at: 2024-07-24 5 | build: make dist 6 | share_photo_url: https://blog-static.alxg.xyz/Screen%20Shot%202024-07-23%20at%2011.37.14%20PM.png 7 | --- 8 | 9 | 10 | 11 | 12 | 13 | 14 |
    15 | 16 | > _tl;dr — [`sqlite-lembed`](https://github.com/asg017/sqlite-lembed) is a SQLite extension for generating text embeddings, meant to work alongside [`sqlite-vec`](https://github.com/asg017/sqlite-vec). With a single embeddings model file provided in the `.gguf` format, you can generate embeddings using regular SQL functions, and store them directly inside your SQLite database. No extra server, process, or configuration needed!_ 17 | 18 | --- 19 | 20 |
    21 | 22 | 27 | 28 | I've been working on [`sqlite-vec`](https://github.com/asg017/sqlite-vec) for quite some time now - 3 months [since I first announced it](https://alexgarcia.xyz/blog/2024/building-new-vector-search-sqlite/index.html), More than 7 months since my first prototype, and more than 2 years since [my first SQLite vector search attempt](https://github.com/asg017/sqlite-vss). And the initial stable version coming soon, I promise! `v0.1.0` is scheduled for next week. 29 | 30 | But one weakness of `sqlite-vec` compared to other vector storage tools is that **you must generate embeddings yourself**. Some vector databases have helper functions and wrappers that automatically generate embeddings for you when inserting text. 31 | 32 | But this feature never made sense for `sqlite-vec`. It's a [single C file](https://github.com/asg017/sqlite-vec/blob/main/sqlite-vec.c) with no external dependencies. Adding embedding model inference would drastically add scope and make things too complicated. 33 | 34 | At the same time, I don't want to `pip install openai` or `pip install sentence-transformers` every time I want to generate embeddings on some text. I want something that is lightweight, a single binary, and works with SQLite. 35 | 36 | So, with the help of [`llama.cpp`'s embeddings support](https://github.com/ggerganov/llama.cpp/pull/5796), `sqlite-lembed` is born! 37 | 38 | ## Usage 39 | 40 | There are a few ways to install `sqlite-lembed` - `npm install sqlite-lembed`, `pip install sqlite-lembed`, `gem install sqlite-lembed`, or grabbing pre-compiled extension from [the Releases page](https://github.com/asg017/sqlite-lembed/releases). Or if you want to directly install and give your IT admins a scare, install with: 41 | 42 | ```bash 43 | curl -L https://github.com/asg017/sqlite-lembed/releases/download/v0.0.1-alpha.4/install.sh | sh 44 | ``` 45 | 46 | You now have a `lembed0.dylib` (MacOS) or `lembed0.so` (Linux) file in your current directory! 47 | 48 | Now you'll need an embeddings models in [`.gguf` format](https://huggingface.co/docs/hub/en/gguf). A few open source options include [`nomic-embed-text-v1.5`](https://huggingface.co/nomic-ai/nomic-embed-text-v1.5-GGUF) and [`mxbai-embed-large-v1`](https://huggingface.co/mixedbread-ai/mxbai-embed-large-v1), but here we will download the smaller and older [`all-MiniLM-L6-v2`](https://huggingface.co/sentence-transformers/all-MiniLM-L6-v2) model like so: 49 | 50 | ```bash 51 | curl -L -o all-MiniLM-L6-v2.e4ce9877.q8_0.gguf https://huggingface.co/asg017/sqlite-lembed-model-examples/resolve/main/all-MiniLM-L6-v2/all-MiniLM-L6-v2.e4ce9877.q8_0.gguf 52 | ``` 53 | 54 | Now we can generate some embeddings! Fire up the `sqlite3` CLI and run these setup commands. 55 | 56 | ```sql 57 | .load ./lembed0 58 | 59 | INSERT INTO temp.lembed_models(name, model) 60 | select 'all-MiniLM-L6-v2', lembed_model_from_file('all-MiniLM-L6-v2.e4ce9877.q8_0.gguf'); 61 | ``` 62 | 63 | The `temp.lembed_model` virtual table lets you "register" models with pure `INSERT INTO` statements. The `name` field is a unique identifier for a given model, and `model` is provided as a path to the `.gguf` model, on disk, with the `lembed_model_from_file()` function. 64 | 65 | Let's try out this new `'all-MiniLM-L6-v2'` model with the `lembed()` function. 66 | 67 | ```sql 68 | 69 | select lembed( 70 | 'all-MiniLM-L6-v2', 71 | 'The United States Postal Service is an independent agency...' 72 | ); -- X'A402...09C3' (1536 bytes) 73 | ``` 74 | 75 | That's out first embedding! A 384 dimensional floating point vector (defined as part of the `all-MiniLM-L6-v2` model), taking up 1,536 bytes of space with 4 bytes per element. 76 | 77 | Now a single embedding of a single sentence isn't that exciting — let's try a larger sample. Since we will be comparing multiple vectors together, let's bring in `sqlite-vec` into our project. Again you can `npm install` or `gem install` or `pip install` `sqlite-vec`, but if you live dangerously you can install with: 78 | 79 | ```bash 80 | curl -L https://github.com/asg017/sqlite-vec/releases/download/0.0.1-alpha.37/install.sh | sh 81 | ``` 82 | 83 | Let's create a corpus of some random news headlines and store that in a "regular" SQLite table. 84 | 85 | ```sql 86 | create table articles( 87 | headline text 88 | ); 89 | 90 | -- Random NPR headlines from 2024-06-04 91 | insert into articles VALUES 92 | ('Shohei Ohtani''s ex-interpreter pleads guilty to charges related to gambling and theft'), 93 | ('The jury has been selected in Hunter Biden''s gun trial'), 94 | ('Larry Allen, a Super Bowl champion and famed Dallas Cowboy, has died at age 52'), 95 | ('After saying Charlotte, a lone stingray, was pregnant, aquarium now says she''s sick'), 96 | ('An Epoch Times executive is facing money laundering charge'); 97 | ``` 98 | 99 | Ok now let's generate some embeddings! We will store the embedding directly into a new `vec0` virtual table. We can always join this new table back with the `articles` table for metadata. 100 | 101 | ```sql 102 | 103 | .load ./vec0 104 | 105 | -- Build a vector table with embeddings of article headlines 106 | create virtual table vec_articles using vec0( 107 | headline_embeddings float[384] 108 | ); 109 | 110 | insert into vec_articles(rowid, headline_embeddings) 111 | select rowid, lembed('all-MiniLM-L6-v2', headline) 112 | from articles; 113 | 114 | ``` 115 | 116 | Now every `headline` in `articles` has been embed and stored in `vec_articles`. To perform a KNN-style search, we can do: 117 | 118 | ```sql 119 | param set :query 'firearm courtroom' 120 | 121 | with matches as ( 122 | select 123 | rowid, 124 | distance 125 | from vec_articles 126 | where headline_embeddings match lembed('all-MiniLM-L6-v2', :query) 127 | order by distance 128 | limit 3 129 | ) 130 | select 131 | headline, 132 | distance 133 | from matches 134 | left join articles on articles.rowid = matches.rowid; 135 | 136 | /* 137 | +--------------------------------------------------------------+------------------+ 138 | | headline | distance | 139 | +--------------------------------------------------------------+------------------+ 140 | | Shohei Ohtani's ex-interpreter pleads guilty to charges rela | 1.14812409877777 | 141 | | ted to gambling and theft | | 142 | +--------------------------------------------------------------+------------------+ 143 | | The jury has been selected in Hunter Biden's gun trial | 1.18380105495453 | 144 | +--------------------------------------------------------------+------------------+ 145 | | An Epoch Times executive is facing money laundering charge | 1.27715671062469 | 146 | +--------------------------------------------------------------+------------------+ 147 | */ 148 | ``` 149 | 150 | And there we go! Notice how "firearm courtroom" doesn't appear in any of these headlines, but it can still figure out that "Hunter Biden's gun trial" is related, and the other two justice-related articles appear on top. 151 | 152 | So there you have it - text embeddings and vector search, all with the `sqlite3` CLI, two extensions, and a single `.gguf` file. 153 | 154 | ## Last notes 155 | 156 | **It is not required to use `sqlite-lembed` with `sqlite-vec`**, or vice-versa. You can use any embeddings provider with `sqlite-vec` — the OpenAI API, other JSON endpoints, PyTorch models, etc. As long as your embeddings can be provided as JSON or a compact BLOG format, you're good to go. 157 | 158 | Similarly, **it is not required to use `sqlite-vec` with `sqlite-lembed`**. You can dump embeddings generated by `sqlite-lembed` into any other vector store you like, or in regular SQLite tables with `sqlite-vec`. 159 | 160 | Also, Windows isn't supported yet. Sorry! Hopefully soon, `llama.cpp` does support Windows, but Github Actions can be quite a nightmare. WASM is also not supported yet, but hoping to figure that out in the near future. 161 | 162 | And lastly — **`sqlite-lembed` is still in beta**! While `sqlite-vec` stabilized on v0.1.0 next week, `sqlite-lembed` will be actively developed for the near future. Mostly because the `llama.cpp` dependency is also under active deveopment, but I hope that the main SQL API won't change much. 163 | -------------------------------------------------------------------------------- /posts/2024/building-new-vector-search-sqlite/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: I'm writing a new vector search SQLite Extension 3 | description: sqlite-vec is an new vector search SQLite extension, coming soon! 4 | created_at: 2024-05-02 5 | build: make dist 6 | share_photo_url: https://alexgarcia.xyz/blog/1.png 7 | --- 8 | 9 | 10 | 11 | 12 | 13 | 14 |
    15 | 16 | > _tl;dr — [`sqlite-vec`](https://github.com/asg017/sqlite-vec) will be a new 17 | > SQLite extension for vector search, replacing `sqlite-vss`. It will be an 18 | > embeddable "fast enough" vector search tool, that can run anywhere SQLite 19 | > runs - including WASM! It's still in active development, but 20 | > [check out the repo](https://github.com/asg017/sqlite-vec) to learn when it 21 | > will be ready!_ 22 | 23 | --- 24 | 25 |
    26 | 27 | 32 | 33 | I'm working on a new SQLite extension! It's called 34 | [`sqlite-vec`](https://github.com/asg017/sqlite-vec), an extension for vector 35 | search, written purely in C. It's meant to replace 36 | [`sqlite-vss`](https://github.com/asg017/sqlite-vss), another vector search 37 | SQLite extension I released in February 2023, which 38 | [has a number of problems](#wrong-sqlite-vss). I believe the approach I'm taking 39 | with `sqlite-vec` solves a number of problem it's predecessor has, will have a 40 | much nicer and performant SQL API, and is a better fit for all applications who 41 | want an embed vector search solution! 42 | 43 | ## What `sqlite-vec` will be 44 | 45 | `sqlite-vec` will be a SQLite extension written purely in C with no 46 | dependencies. It will provide custom SQL functions and virtual tables for fast 47 | vector search, as well as other tools and utilities for working with vectors 48 | (quantization, JSON/BLOB/numpy conversions, vector arithmetic, etc.). 49 | 50 | A quick sample of what vector search will look like with `sqlite-vec`, in pure 51 | SQL: 52 | 53 | ```sqlite 54 | .load ./vec0 55 | 56 | -- a "vector store" for 8-dimensional floating point numbers 57 | create virtual table vec_examples using vec0( 58 | sample_embedding float[8] 59 | ); 60 | 61 | -- vectors can be provided as JSON or in a compact binary format 62 | insert into vec_examples(rowid, sample_embedding) 63 | values 64 | (1, '[-0.200, 0.250, 0.341, -0.211, 0.645, 0.935, -0.316, -0.924]'), 65 | (2, X'E5D0E23E894100BF8FC2B53E426045BFF4FD343F7D3F35BFA4703DBE1058B93E'), 66 | (3, '[0.716, -0.927, 0.134, 0.052, -0.669, 0.793, -0.634, -0.162]'), 67 | (4, X'8FC235BFC3F5A83E9EEF273F9EEF273DA4707DBF23DB393FB81EC53E7D3F75BF'); 68 | 69 | 70 | -- KNN style query goes brrrr 71 | select 72 | rowid, 73 | distance 74 | from vec_examples 75 | where sample_embedding match '[0.890, 0.544, 0.825, 0.961, 0.358, 0.0196, 0.521, 0.175]' 76 | order by distance 77 | limit 2; 78 | 79 | /* 80 | rowid,distance 81 | 2,2.38687372207642 82 | 1,2.38978505134583 83 | */ 84 | ``` 85 | 86 | Using `sqlite-vec` means using pure SQL, just `CREATE VIRTUAL TABLE`, 87 | `INSERT INTO`, and `SELECT` statements. 88 | 89 | This work is exciting - for many reasons! First off, "written in pure C" means 90 | it will be able to run anywhere. The previous `sqlite-vss` extension, which had 91 | some cumbersome C++ dependencies, was only able to reliably run on Linux and 92 | MacOS machines, with binaries in the `3MB`-`5MB` range. By contrast, 93 | `sqlite-vec` will run on all platforms (Linux/MacOS/Windows), in the browser 94 | with WebAssembly, and even smaller devices like mobile phones and Raspberry Pis! 95 | Smaller binaries too, in the few 100's of KB range. 96 | 97 | Additionally, `sqlite-vec` has more control over memory usage. By default, 98 | vectors are stored in 'chunks' in shadow tables, and are read chunk-by-chunk 99 | during KNN searches. This means you don't need to store everything in RAM! 100 | Though if you do want in-memory speed, you could use the 101 | [`PRAGMA mmap_size`](https://www.sqlite.org/pragma.html#pragma_mmap_size) 102 | command to make KNN searches much faster. 103 | 104 | And finally, `sqlite-vec` is built in a new "era" of vector search tooling and 105 | research. There will be better support for "adative-length embeddings" (aka 106 | [Matryoshka embeddings](https://huggingface.co/blog/matryoshka)), and 107 | `int8`/`bit` vector support for 108 | [binary and scalar quantization](https://huggingface.co/blog/embedding-quantization). 109 | This means more control over the speed, accuracy, and disk space that your 110 | vectors take up. 111 | 112 | Though initially, `sqlite-vec` will only support exhaustive full-scan vector 113 | search. There will be no "approximate nearest neighbors" (ANN) options. But I 114 | hope to add IVF + HNSW in the future! 115 | 116 | ## Demo 117 | 118 | Enough yappin' let's see a demo 119 | 120 | `sqlite-vec` is running right now in your browser! If you open up devtools, 121 | you'll see an (un-optimized) `5.9MB` `sqlite3.wasm` file, which is the 122 | [official SQLite WASM build](https://sqlite.org/wasm/doc/trunk/about.md) with 123 | `sqlite-vec` compiled in. There is a `movies.bit.db` SQLite database also 124 | loaded, which is a `2.6MB` SQLite database, which has 125 | [this movies dataset](https://www.kaggle.com/datasets/tmdb/tmdb-movie-metadata?select=tmdb_5000_movies.csv) 126 | with 4,800 movie overviews in the `articles` table. The separate `vec_movies` 127 | virtual table is a vector index of those "overviews" embedded, with 128 | [Nomic's 1.5 embeddings model](https://blog.nomic.ai/posts/nomic-embed-matryoshka), 129 | quantized to binary vectors. 130 | 131 | Here's a quick sample of what the data looks like: 132 | 133 |
    134 | 135 | Here we see the `articles` table has columns like `title`, `release_date`, and 136 | `overview`. The `overview` column here is important - it's a very short sentence 137 | describing the plot of the movie. We also have the `vec_articles` virtual table, 138 | which stores embeddings of the `articles.overview` as the `overview_embeddings` 139 | column. Thy are binary vectors with 768 dimensions, which takes up 96 bytes 140 | (`768 / 8 = 96`). 141 | 142 | Now let's see how a KNN-style search works! Here's a lil' table select 143 | component. Select a movie with the radio button on the left-hand side. 144 | 145 |
    146 | 147 | The movie ID you selected will now pre-populate the `:selected_movie` SQL 148 | parameter in this KNN SQL query! 149 | 150 |
    151 | 152 | Those are the 10 closest movies to the one you selected! The "closest" one 153 | (using hamming distance, because it's a binary vector) will always be the same 154 | movie, with a distance of 0. Keep in mind, embedding a single-sentence plot 155 | description of a small movie dataset doesn't give the best results (and binary 156 | quantization sacrifices even more quality), but the core idea remains. Fast, 157 | "good enough" vector search, in your browser! 158 | 159 | More docs about this KNN-style query will come soon, but in case you wanted to 160 | poke around at the internals, try adding a `EXPLAIN QUERY PLAN` to the beginning 161 | of the `SELECT` statement. You'll see the `0:knn` "index" that `vec_movies` 162 | uses. 163 | 164 |

    But what's wrong with sqlite-vss?

    165 | 166 | I won't go into all the details, but there were a number of roadblocks in the 167 | development and adoption of `sqlite-vss`, including: 168 | 169 | - Only worked on Linux + MacOS machines (no Windows, WASM, mobile devices, etc.) 170 | - Stored vectors all in-memory 171 | - Various transaction-related bugs and issues 172 | - Extremely hard and time-consuming to compile 173 | - Missing common vector operations (scalar/binary quantization) 174 | 175 | Nearly all of these are because `sqlite-vss` depended on 176 | [Faiss](https://github.com/facebookresearch/faiss). With a lot of time and 177 | energy, some of these issues could _maybe_ be solved, but many of them would be 178 | blocked by Faiss. 179 | 180 | Given all this, a no-dependency and low-level solution seemed really enticing. 181 | Turns out, vector search isn't too complicated, so `sqlite-vec` was born! 182 | 183 | ## Still not ready, but soon! 184 | 185 | The core features of `sqlite-vec` work, but I have very little error handling + 186 | testing. I have 246 TODOs in the `sqlite-vec.c` file, which I'm tracking with a 187 | lil script: 188 | 189 | ``` 190 | $ make progress 191 | deno run --allow-read=sqlite-vec.c scripts/progress.ts 192 | Number of todo_assert()'s: 191 193 | Number of "// TODO" comments: 41 194 | Number of todo panics: 14 195 | Total TODOs: 246 196 | 197 | ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░ (0/246) 198 | 199 | 0% complete to sqlite-vec v0 200 | ``` 201 | 202 | Once those 246 TODOs are completed, then the first `v0.1.0` of `sqlite-vec` will 203 | be released, with documentation, demos, bindings, and more! I'm aiming for a 204 | month or so, but we shall see! 205 | 206 | ## I'm looking for sponsors! 207 | 208 | Is your company interested in the success of `sqlite-vec`? I'd love to chat! 209 | [Email me](https://alexgarcia.xyz/) for more information. 210 | -------------------------------------------------------------------------------- /page.css: -------------------------------------------------------------------------------- 1 | /* https://unpkg.com/@catppuccin/palette@1.1.1/css/catppuccin.css */ 2 | :root { 3 | --ctp-latte-rosewater: #dc8a78; 4 | --ctp-latte-flamingo: #dd7878; 5 | --ctp-latte-pink: #ea76cb; 6 | --ctp-latte-mauve: #8839ef; 7 | --ctp-latte-red: #d20f39; 8 | --ctp-latte-maroon: #e64553; 9 | --ctp-latte-peach: #fe640b; 10 | --ctp-latte-yellow: #df8e1d; 11 | --ctp-latte-green: #40a02b; 12 | --ctp-latte-teal: #179299; 13 | --ctp-latte-sky: #04a5e5; 14 | --ctp-latte-sapphire: #209fb5; 15 | --ctp-latte-blue: #1e66f5; 16 | --ctp-latte-lavender: #7287fd; 17 | --ctp-latte-text: #4c4f69; 18 | --ctp-latte-subtext1: #5c5f77; 19 | --ctp-latte-subtext0: #6c6f85; 20 | --ctp-latte-overlay2: #7c7f93; 21 | --ctp-latte-overlay1: #8c8fa1; 22 | --ctp-latte-overlay0: #9ca0b0; 23 | --ctp-latte-surface2: #acb0be; 24 | --ctp-latte-surface1: #bcc0cc; 25 | --ctp-latte-surface0: #ccd0da; 26 | --ctp-latte-base: #eff1f5; 27 | --ctp-latte-mantle: #e6e9ef; 28 | --ctp-latte-crust: #dce0e8; 29 | } 30 | 31 | :root { 32 | --ctp-frappe-rosewater: #f2d5cf; 33 | --ctp-frappe-flamingo: #eebebe; 34 | --ctp-frappe-pink: #f4b8e4; 35 | --ctp-frappe-mauve: #ca9ee6; 36 | --ctp-frappe-red: #e78284; 37 | --ctp-frappe-maroon: #ea999c; 38 | --ctp-frappe-peach: #ef9f76; 39 | --ctp-frappe-yellow: #e5c890; 40 | --ctp-frappe-green: #a6d189; 41 | --ctp-frappe-teal: #81c8be; 42 | --ctp-frappe-sky: #99d1db; 43 | --ctp-frappe-sapphire: #85c1dc; 44 | --ctp-frappe-blue: #8caaee; 45 | --ctp-frappe-lavender: #babbf1; 46 | --ctp-frappe-text: #c6d0f5; 47 | --ctp-frappe-subtext1: #b5bfe2; 48 | --ctp-frappe-subtext0: #a5adce; 49 | --ctp-frappe-overlay2: #949cbb; 50 | --ctp-frappe-overlay1: #838ba7; 51 | --ctp-frappe-overlay0: #737994; 52 | --ctp-frappe-surface2: #626880; 53 | --ctp-frappe-surface1: #51576d; 54 | --ctp-frappe-surface0: #414559; 55 | --ctp-frappe-base: #303446; 56 | --ctp-frappe-mantle: #292c3c; 57 | --ctp-frappe-crust: #232634; 58 | } 59 | 60 | :root { 61 | --ctp-macchiato-rosewater: #f4dbd6; 62 | --ctp-macchiato-flamingo: #f0c6c6; 63 | --ctp-macchiato-pink: #f5bde6; 64 | --ctp-macchiato-mauve: #c6a0f6; 65 | --ctp-macchiato-red: #ed8796; 66 | --ctp-macchiato-maroon: #ee99a0; 67 | --ctp-macchiato-peach: #f5a97f; 68 | --ctp-macchiato-yellow: #eed49f; 69 | --ctp-macchiato-green: #a6da95; 70 | --ctp-macchiato-teal: #8bd5ca; 71 | --ctp-macchiato-sky: #91d7e3; 72 | --ctp-macchiato-sapphire: #7dc4e4; 73 | --ctp-macchiato-blue: #8aadf4; 74 | --ctp-macchiato-lavender: #b7bdf8; 75 | --ctp-macchiato-text: #cad3f5; 76 | --ctp-macchiato-subtext1: #b8c0e0; 77 | --ctp-macchiato-subtext0: #a5adcb; 78 | --ctp-macchiato-overlay2: #939ab7; 79 | --ctp-macchiato-overlay1: #8087a2; 80 | --ctp-macchiato-overlay0: #6e738d; 81 | --ctp-macchiato-surface2: #5b6078; 82 | --ctp-macchiato-surface1: #494d64; 83 | --ctp-macchiato-surface0: #363a4f; 84 | --ctp-macchiato-base: #24273a; 85 | --ctp-macchiato-mantle: #1e2030; 86 | --ctp-macchiato-crust: #181926; 87 | } 88 | 89 | :root { 90 | --ctp-mocha-rosewater: #f5e0dc; 91 | --ctp-mocha-flamingo: #f2cdcd; 92 | --ctp-mocha-pink: #f5c2e7; 93 | --ctp-mocha-mauve: #cba6f7; 94 | --ctp-mocha-red: #f38ba8; 95 | --ctp-mocha-maroon: #eba0ac; 96 | --ctp-mocha-peach: #fab387; 97 | --ctp-mocha-yellow: #f9e2af; 98 | --ctp-mocha-green: #a6e3a1; 99 | --ctp-mocha-teal: #94e2d5; 100 | --ctp-mocha-sky: #89dceb; 101 | --ctp-mocha-sapphire: #74c7ec; 102 | --ctp-mocha-blue: #89b4fa; 103 | --ctp-mocha-lavender: #b4befe; 104 | --ctp-mocha-text: #cdd6f4; 105 | --ctp-mocha-subtext1: #bac2de; 106 | --ctp-mocha-subtext0: #a6adc8; 107 | --ctp-mocha-overlay2: #9399b2; 108 | --ctp-mocha-overlay1: #7f849c; 109 | --ctp-mocha-overlay0: #6c7086; 110 | --ctp-mocha-surface2: #585b70; 111 | --ctp-mocha-surface1: #45475a; 112 | --ctp-mocha-surface0: #313244; 113 | --ctp-mocha-base: #1e1e2e; 114 | --ctp-mocha-mantle: #181825; 115 | --ctp-mocha-crust: #11111b; 116 | } 117 | 118 | :root { 119 | --ctp-rosewater: var(--ctp-latte-rosewater); 120 | --ctp-flamingo: var(--ctp-latte-flamingo); 121 | --ctp-pink: var(--ctp-latte-pink); 122 | --ctp-mauve: var(--ctp-latte-mauve); 123 | --ctp-red: var(--ctp-latte-red); 124 | --ctp-maroon: var(--ctp-latte-maroon); 125 | --ctp-peach: var(--ctp-latte-peach); 126 | --ctp-yellow: var(--ctp-latte-yellow); 127 | --ctp-green: var(--ctp-latte-green); 128 | --ctp-teal: var(--ctp-latte-teal); 129 | --ctp-sky: var(--ctp-latte-sky); 130 | --ctp-sapphire: var(--ctp-latte-sapphire); 131 | --ctp-blue: var(--ctp-latte-blue); 132 | --ctp-lavender: var(--ctp-latte-lavender); 133 | --ctp-text: var(--ctp-latte-text); 134 | --ctp-subtext1: var(--ctp-latte-subtext1); 135 | --ctp-subtext0: var(--ctp-latte-subtext0); 136 | --ctp-overlay2: var(--ctp-latte-overlay2); 137 | --ctp-overlay1: var(--ctp-latte-overlay1); 138 | --ctp-overlay0: var(--ctp-latte-overlay0); 139 | --ctp-surface2: var(--ctp-latte-surface2); 140 | --ctp-surface1: var(--ctp-latte-surface1); 141 | --ctp-surface0: var(--ctp-latte-surface0); 142 | --ctp-base: var(--ctp-latte-base); 143 | --ctp-mantle: var(--ctp-latte-mantle); 144 | --ctp-crust: var(--ctp-latte-crust); 145 | } 146 | html.dark { 147 | --ctp-rosewater: var(--ctp-mocha-rosewater); 148 | --ctp-flamingo: var(--ctp-mocha-flamingo); 149 | --ctp-pink: var(--ctp-mocha-pink); 150 | --ctp-mauve: var(--ctp-mocha-mauve); 151 | --ctp-red: var(--ctp-mocha-red); 152 | --ctp-maroon: var(--ctp-mocha-maroon); 153 | --ctp-peach: var(--ctp-mocha-peach); 154 | --ctp-yellow: var(--ctp-mocha-yellow); 155 | --ctp-green: var(--ctp-mocha-green); 156 | --ctp-teal: var(--ctp-mocha-teal); 157 | --ctp-sky: var(--ctp-mocha-sky); 158 | --ctp-sapphire: var(--ctp-mocha-sapphire); 159 | --ctp-blue: var(--ctp-mocha-blue); 160 | --ctp-lavender: var(--ctp-mocha-lavender); 161 | --ctp-text: var(--ctp-mocha-text); 162 | --ctp-subtext1: var(--ctp-mocha-subtext1); 163 | --ctp-subtext0: var(--ctp-mocha-subtext0); 164 | --ctp-overlay2: var(--ctp-mocha-overlay2); 165 | --ctp-overlay1: var(--ctp-mocha-overlay1); 166 | --ctp-overlay0: var(--ctp-mocha-overlay0); 167 | --ctp-surface2: var(--ctp-mocha-surface2); 168 | --ctp-surface1: var(--ctp-mocha-surface1); 169 | --ctp-surface0: var(--ctp-mocha-surface0); 170 | --ctp-base: var(--ctp-mocha-base); 171 | --ctp-mantle: var(--ctp-mocha-mantle); 172 | --ctp-crust: var(--ctp-mocha-crust); 173 | } 174 | html { 175 | background-color: var(--ctp-base); 176 | } 177 | /* 178 | * { 179 | color: var(--ctp-text); 180 | }*/ 181 | 182 | * { 183 | color: black; 184 | } 185 | html.dark * { 186 | color: white; 187 | } 188 | 189 | h1 { 190 | margin-bottom: 0rem; 191 | } 192 | /* 193 | h2, 194 | h3, 195 | h4 { 196 | color: var(--ctp-subtext0); 197 | }*/ 198 | 199 | .header { 200 | display: flex; 201 | justify-content: space-between; 202 | align-items: center; 203 | } 204 | 205 | hr { 206 | border: 0.5px solid var(--ctp-subtext0); 207 | } 208 | 209 | button.theme::before { 210 | content: "⏼"; 211 | } 212 | 213 | .header a { 214 | color: var(--blog-link-color); 215 | } 216 | button.theme { 217 | cursor: pointer; 218 | background: none; 219 | border: none; 220 | text-decoration: underline; 221 | color: var(--blog-link-color); 222 | } 223 | 224 | main { 225 | max-width: 48rem; 226 | margin: 0 auto; 227 | padding: 2rem 1rem; 228 | padding-bottom: 6rem; 229 | 230 | } 231 | 232 | summary { 233 | cursor: pointer; 234 | margin-left: 1rem; 235 | } 236 | 237 | p, 238 | li, 239 | h1, 240 | h2, 241 | h3, 242 | h4, 243 | h5, 244 | h6, 245 | details, 246 | summary { 247 | /*font-family: "Helvetica Neue", helvetica, sans-serif;*/ 248 | font-family: "Inter", sans-serif; 249 | font-optical-sizing: auto; 250 | /*font-weight: ;*/ 251 | font-style: normal; 252 | font-variation-settings: "slnt" 0; 253 | } 254 | 255 | p { 256 | line-height: 22px; 257 | } 258 | 259 | a { 260 | color: var(--ctp-blue); 261 | } 262 | a:visited { 263 | color: var(--ctp-lavender); 264 | } 265 | code { 266 | font-family: MonaspaceNeon; 267 | background: var(--ctp-crust); 268 | padding: 2px 4px; 269 | border-radius: 4px; 270 | } 271 | html.dark code { 272 | background: unset; 273 | padding: unset; 274 | } 275 | a code { 276 | color: var(--ctp-blue); 277 | } 278 | pre code { 279 | background: unset; 280 | padding: unset; 281 | } 282 | pre { 283 | padding: 0.75rem; 284 | border-radius: 0.25rem; 285 | overflow: auto; 286 | background: var(--ctp-crust); 287 | } 288 | @font-face { 289 | font-family: MonaspaceNeon; 290 | font-weight: bold; 291 | src: url("../../MonaspaceNeon-Regular.otf") format("opentype"); 292 | } 293 | 294 | html .shiki, 295 | html .shiki span { 296 | color: var(--shiki-light); 297 | /*background-color: var(--shiki-light-bg);*/ 298 | } 299 | 300 | html.dark .shiki, 301 | html.dark .shiki span { 302 | color: var(--shiki-dark); 303 | /*background-color: var(--shiki-dark-bg);*/ 304 | } 305 | 306 | .shiki .line.highlighted { 307 | background-color: #ccd0da; 308 | transition: background-color 0.5s; 309 | margin: 0 -0.75rem; 310 | padding: 0 0.75rem; 311 | width: calc(100% + 0.1px); 312 | display: inline-block; 313 | } 314 | .shiki .line.highlighted span { 315 | background-color: #ccd0da; 316 | transition: background-color 0.5s; 317 | } 318 | 319 | html.dark .shiki .line.highlighted { 320 | background-color: #313244; 321 | transition: background-color 0.5s; 322 | margin: 0 -0.75rem; 323 | padding: 0 0.75rem; 324 | width: calc(100% + 0.1px); 325 | display: inline-block; 326 | } 327 | html.dark .shiki .line.highlighted span { 328 | background-color: #313244; 329 | transition: background-color 0.5s; 330 | } 331 | -------------------------------------------------------------------------------- /posts/2025/introducing-libfec/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: I'm working on libfec, a new FEC file parser and CLI tool 3 | description: Parse federal campaign filings 4 | created_at: 2025-10-13 5 | build: make dist 6 | share_photo_url: https://blog-static.alxg.xyz/Screenshot%202025-10-13%20at%2010.22.10%20PM.png 7 | --- 8 | 9 | 10 | 11 | 12 | 30 | 31 |
    32 | 33 | > *tl;dr — [`libfec`](https://github.com/asg017/libfec) is a new tool for working with Federal Election Committee (FEC) data, for exploring and analyzing federal campaign finance reports. It's reminiscent of past tools like [FastFEC](https://github.com/washingtonpost/FastFEC) and [fecfile](https://github.com/esonderegger/fecfile), but is faster, supports exporting to CSV/JSON/ SQLite/Excel, and works directly with the [OpenFEC API](https://api.open.fec.gov/developers/) to simplify common operations. Try it today!* 34 | 35 | 40 |
    41 | 42 | --- 43 | 44 | Building a tool for working with FEC data is a rite of passage for data journalists and newsroom engineers. 45 | 46 | The earliest open-source FEC parser I could find is 47 | [FEC-Scraper](https://github.com/cschnaars/FEC-Scraper), 48 | created 14 years ago — a collection of Python scripts published by journalists at USA Today. Then a year later 49 | [Fech](https://github.com/nytimes/Fech) 50 | (Ruby) from the New York Times, followed by 51 | [fec-parse](https://github.com/PublicI/fec-parse) 52 | (Node.js) in 2015, 53 | [fecfile](https://github.com/esonderegger/fecfile) 54 | (Python) in 2018, and 55 | [FastFEC](https://github.com/washingtonpost/FastFEC) 56 | (C) from the Washington Post in 2021. 57 | 58 | 59 | All these tools perform a similar task — converting the FEC's 60 | [custom `.fec` file format](https://www.fec.gov/introduction-campaign-finance/data-tutorials/) 61 | into more usable formats like CSV or JSON. 62 | 63 | And `libfec` is no different! It's fast, easy to install, and works directly with the [OpenFEC API](https://api.open.fec.gov/developers/) to make your life easier. 64 | 65 | 66 | 67 | ## Introducing `libfec` 68 | 69 | `libfec` is a single-binary CLI tool written in Rust, with [a variety of ways to install](https://alexgarcia.xyz/libfec/getting-started/installation). 70 | 71 | The `libfec export` command allows you to export filing itemizations to CSVs/JSON/SQLite/Excel for easier analysis. Let's try it with [`FEC-1903265`](https://docquery.fec.gov/cgi-bin/forms/C00765164/1903265), the 2025 Q2 financial report for Alex Padilla, senator from California. To export the receipt itemizations from that filing, we can run: 72 | 73 | 74 | ```bash 75 | libfec export \ 76 | --target receipts \ 77 | FEC-1903265 \ 78 | -o padilla_contributors-2025-Q2.csv 79 | ``` 80 | 81 | 82 | Behind the scenes, `libfec` will download and cache the [raw `1903265.fec` file](https://docquery.fec.gov/dcdev/posted/1781583.fec) for this filing, and export all receipt itemizations (contributions, incoming transfers) into a CSV file at `padilla_contributors-2025-Q2.csv`. 83 | 84 | Now we can use other tools for further analysis. For example, let's get all individual contributors from California who donated to Alex Padilla in this reporting period, using [`csvkit`](https://csvkit.readthedocs.io/en/latest/): 85 | 86 | ```bash 87 | csvgrep padilla_contributors-2025-Q2.csv -c entity_type -m IND \ 88 | | csvgrep -c contributor_state -m CA \ 89 | | csvcut -c contributor_first_name,contributor_last_name,contributor_city,contribution_amount \ 90 | | head -10 91 | ``` 92 | ``` 93 | contributor_first_name,contributor_last_name,contributor_city,contribution_amount 94 | David,Alexander,Carlsbad,2000.00 95 | Jan,Altemus,Los Angeles,250.00 96 | L Sue,Alza,Los Angeles,250.00 97 | Cynthia,Amador Diaz,Monrovia,50.00 98 | Gilberto,Amparo,Northridge,250.00 99 | John H,Anderson,San Diego,20.00 100 | John H,Anderson,San Diego,20.00 101 | John H,Anderson,San Diego,20.00 102 | Olle,Andersson,Carlsbad,25.00 103 | ``` 104 | 105 | Or you can use Python, R, Node.js, DuckDB, Excel — any tool that works with CSVs! 106 | 107 | Another example: [this Politico article from Jessica Piper](https://www.politico.com/news/2023/01/25/george-santos-199-expenses-00079334) (January 2023) details how George Santos, former New York Congressman, reported 40 expenditure transactions that were valued between $199.00 and $199.99. Campaigns are required to keep receipts for expenses greater than $200, so having multiple expenditures *right below* the cutoff is a bit suspicous. 108 | 109 | To get a list of all expenditures reported by George Santos' campaign committee [`C00721365`](https://www.fec.gov/data/committee/C00721365/?cycle=2022) in 2022, we could run: 110 | 111 | 112 | ```bash 113 | $ libfec export C00721365 \ 114 | --target disbursements \ 115 | --cycle 2022 \ 116 | -o santos22.csv 117 | ✓ Cached 15 filings, 1.04 MiB 118 | Exported 1558 rows to santos22.csv in 1s 977ms 586µs 119 | ``` 120 | 121 | Now `santos22.csv` contains all Schedule B disbursements from all FEC reports filed by the Santos campaign! Including the 40 suspicous transactions, which we can confirm with a DuckDB query: 122 | 123 | ```bash 124 | $ duckdb :memory: 'SELECT count(*) FROM "santos22.csv" WHERE expenditure_amount BETWEEN 199.0 AND 199.99' 125 | ``` 126 | 127 |
    128 | ┌──────────────┐
    129 | │ count_star() │
    130 | │    int64     │
    131 | ├──────────────┤
    132 | │      40      │
    133 | └──────────────┘
    134 | 
    135 | 136 | ## `libfec` on commitees & contests 137 | 138 | Look at the above example a little closer — all we provided was a committee ID for Santos (`libfec export C00721365 ...`). With just the committee ID, `libfec` was able to resolve the 15 relevant filings that `C00721365` filed for the 2022 cycle, even accounting for amended filings. 139 | 140 | This is powerful! Previous open-source FEC tooling required you to supply individual FEC filing IDs, which often meant searching up a committee's filing history, copy+pasting FEC IDs, and manually accounting for amended filings. With `libfec`, it's handled for you! 141 | 142 | Let's try another sample. I'm tracking the near-to-me 2026 California 40th district, where incumbent Young Kim is runnings to hold onto her seat. If I want to get filings for all candidates running in that race, I can run: 143 | 144 | ```bash 145 | $ libfec export \ 146 | --election 2026 \ 147 | CA40 \ 148 | -o ca40-2026.db 149 | Exporting filings to SQLite database at "ca40-2026.db" 150 | Finished exporting 18 filings into ca40-2026.db, in 3 seconds 151 | ``` 152 | 153 | `libfec` found all the candidates running in CA40 and exported their filinings into a SQLite database at `ca40-2026.db`. 154 | 155 | 156 | ## SQLite as a first-class target 157 | 158 | `libfec` was built with SQLite in mind, for many reasons! 159 | 160 | For one, FEC filings are not just 1 clean CSV file. A single "filing" can have multiple tabular datasets. A "receipt" itemization has columns like `contributor_first_name` and `contribution_amount`, while a "disbursement" itemization has columns like `payee_first_name` and `expenditure_amount`. 161 | 162 | With SQLite, `libfec` stores these different itemization types into different tables, meaning we can store all itemizations from multiple filings all in a single database file. 163 | 164 | Also with SQLite, you can write SQL! Let's find the top 10 cities where individuals contributed to any candidate from the CA40 race: 165 | 166 | ```sql 167 | select 168 | contributor_state, 169 | contributor_city, 170 | sum(contribution_amount) 171 | from libfec_schedule_a 172 | where form_type = 'SA11AI' 173 | and entity_type = 'IND' 174 | group by 1, 2 175 | order by 3 desc 176 | limit 10; 177 | ``` 178 | 179 | ``` 180 | contributor_state contributor_city sum(contribution_amount) 181 | ------------------- ------------------ -------------------------- 182 | CA Los Angeles 233757 183 | NY New York 111062 184 | DC Washington 79642.7 185 | CA Beverly Hills 64100 186 | CA San Francisco 52590.4 187 | MN Minneapolis 35657.3 188 | TX Dallas 33362.7 189 | TX Houston 31549.2 190 | CA Santa Monica 29218.5 191 | NY Manhattan 28000 192 | ``` 193 | 194 | I was not expecting so many non-California cities... 195 | 196 | Now let's find which candidate raised the most from small individual donors compared to large donors: 197 | 198 | ```sql 199 | select 200 | committee_name, 201 | format( 202 | '%f%%', 203 | 100.0 * col_a_individual_contributions_unitemized / 204 | ( 205 | col_a_individual_contributions_itemized 206 | + col_a_individual_contributions_unitemized 207 | ) 208 | ) as percent_small_donor_raised, 209 | format('$%,.2f', col_a_cash_on_hand_close) as cash_on_hand_close 210 | from libfec_F3 211 | where report_code = 'Q2' 212 | order by 2 desc 213 | ``` 214 | 215 | ``` 216 | committee_name percent_small_donor_raised cash_on_hand_close 217 | ------------------------------ ---------------------------- -------------------- 218 | Esther Kim Varet for Congress 62.068472% $1,308,999.98 219 | Young Kim for Congress 39.489178% $3,938,779.72 220 | Christina Gagnier for Congress 34.705837% $306,572.33 221 | Joe Kerr for California 29.493767% $11,838.09 222 | NINA LINH FOR CONGRESS 1.394278% $104,300.06 223 | ``` 224 | 225 | And finally, SQLite is great because every programming language already has a great client library for SQLite! 226 | Python has the [`sqlite3` module](https://docs.python.org/3/library/sqlite3.html), 227 | Node.js now has the builtin [`node:sqlite3`](https://nodejs.org/api/sqlite.html) module, 228 | [RSQLite](https://cran.r-project.org/web/packages/RSQLite/vignettes/RSQLite.html) for R users, [`sqlite3-ruby`](https://github.com/sparklemotion/sqlite3-ruby) for Ruby, even [SQLite WASM](https://sqlite.org/wasm/doc/trunk/index.md) for in-browser options! 229 | 230 | This means that even if you personally use Python but your coworkers likes R, you can use `libfec` as a lingua franca to work together: `libfec export` to a SQLite database, write SQL to analyze, then whatever language you like for your own visualizations or analysis work. 231 | 232 | 233 | ## `libfec` is *fast* 234 | 235 | The previous fastest FEC parsing tool was [FastFEC](https://github.com/washingtonpost/FastFEC/) from the Washington Post. While `libfec` and FastFEC do different things, there is a [FastFEC compatible `libfec fastfec`](https://alexgarcia.xyz/libfec/guides/fastfec) command that runs ~1.8x to ~10x faster than FastFEC, depending on the FastFEC installation. 236 | 237 | The `libfec export` command is fast too! It can parse [`FEC-1909062`](https://docquery.fec.gov/cgi-bin/forms/C00401224/1909062/), the `10GB` Mid-Year 2025 report for ActBlue, in ~30 seconds: 238 | 239 | ```bash 240 | libfec export 1909062.fec \ 241 | --target receipts \ 242 | -o ab-2025-h1.csv 243 | ``` 244 | 245 | On my machine (2024 MacBook Pro M4 Pro) this takes 31 seconds, exporting a `5.8 GB` CSV with 25 million rows! 246 | 247 | `libfec` also caches filing files by default, so subsequent exports on the same filings will be even faster. See [The `libfec` Cache](https://alexgarcia.xyz/libfec/guides/cache.html) for more details. 248 | 249 | ## A big thanks 250 | 251 | Federal campaign finance data is extremely complex and not well documented. `libfec` would not be possible for the countless newsroom developers and volunteers who contributed to dozens of open source projects and resources. I am grateful to all who have contributed to these initiatives, and also to these specific folks in no particular order: 252 | 253 | 254 | - [Chris Zubak-Skees](https://zubak-skees.dev/), creator of `fec-parser`, advisor on the FastFEC project 255 | - [Dylan Freedman](https://github.com/freedmand), creator of the FastFEC project 256 | - [Evan Sonderegger](https://github.com/esonderegger), creator of the fecfile project, maintains the most up-to-fec FEC version mappings 257 | - [Derek Willis](https://github.com/dwillis), creator of the Fech project 258 | - [Rachel Shorey](https://github.com/rshorey), creator oof the fec2json project 259 | 260 | And *many* other contributors, maintainers, and other journalist who have put in countless hours digging into the weird intricacies and nuances of federal campaign finance. 261 | 262 | 263 | ## I need help finishing `libfec`! 264 | 265 | I've been working on `libfec` for a long time, but it's nowhere near complete! For example: 266 | 267 | - Only FEC filings version `8.1+` are supported, so only filings from the last ~10 years years are supported. See [issue #1](https://github.com/asg017/libfec/issues/1) for more info. 268 | - I want to add bindings for other programming languages (Python, WASM, Node.js, Ruby, etc). 269 | - A "watch" feature that can automically sync newly filed reports, using the FEC RSS feeds or APIs 270 | 271 | But most importantly, I need people to use it! If you currently use other FEC parsers, give `libfec` a try and let me know how it goes! 272 | 273 | A rough roadmap of what I'm planning for the near future: 274 | 275 | - Support for all FEC versions ([#1](https://github.com/asg017/libfec/issues/1)) 276 | - Python + WASM support 277 | - *Extensive* examples, recipes, and story re-creations 278 | 279 | Want to get involved? Drop a post [in the `libfec` forum on GitHub](https://github.com/asg017/libfec/discussions), tell us how you want to use `libfec`, and try it out today! -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-hybrid-search/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sql-vector-search-languages", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "d3-selection": "^3.0.0", 13 | "d3-transition": "^3.0.1", 14 | "esbuild": "^0.21.3" 15 | } 16 | }, 17 | "node_modules/@esbuild/aix-ppc64": { 18 | "version": "0.21.5", 19 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 20 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 21 | "cpu": [ 22 | "ppc64" 23 | ], 24 | "optional": true, 25 | "os": [ 26 | "aix" 27 | ], 28 | "engines": { 29 | "node": ">=12" 30 | } 31 | }, 32 | "node_modules/@esbuild/android-arm": { 33 | "version": "0.21.5", 34 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 35 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 36 | "cpu": [ 37 | "arm" 38 | ], 39 | "optional": true, 40 | "os": [ 41 | "android" 42 | ], 43 | "engines": { 44 | "node": ">=12" 45 | } 46 | }, 47 | "node_modules/@esbuild/android-arm64": { 48 | "version": "0.21.5", 49 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 50 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 51 | "cpu": [ 52 | "arm64" 53 | ], 54 | "optional": true, 55 | "os": [ 56 | "android" 57 | ], 58 | "engines": { 59 | "node": ">=12" 60 | } 61 | }, 62 | "node_modules/@esbuild/android-x64": { 63 | "version": "0.21.5", 64 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 65 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 66 | "cpu": [ 67 | "x64" 68 | ], 69 | "optional": true, 70 | "os": [ 71 | "android" 72 | ], 73 | "engines": { 74 | "node": ">=12" 75 | } 76 | }, 77 | "node_modules/@esbuild/darwin-arm64": { 78 | "version": "0.21.5", 79 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 80 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 81 | "cpu": [ 82 | "arm64" 83 | ], 84 | "optional": true, 85 | "os": [ 86 | "darwin" 87 | ], 88 | "engines": { 89 | "node": ">=12" 90 | } 91 | }, 92 | "node_modules/@esbuild/darwin-x64": { 93 | "version": "0.21.5", 94 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 95 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 96 | "cpu": [ 97 | "x64" 98 | ], 99 | "optional": true, 100 | "os": [ 101 | "darwin" 102 | ], 103 | "engines": { 104 | "node": ">=12" 105 | } 106 | }, 107 | "node_modules/@esbuild/freebsd-arm64": { 108 | "version": "0.21.5", 109 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 110 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 111 | "cpu": [ 112 | "arm64" 113 | ], 114 | "optional": true, 115 | "os": [ 116 | "freebsd" 117 | ], 118 | "engines": { 119 | "node": ">=12" 120 | } 121 | }, 122 | "node_modules/@esbuild/freebsd-x64": { 123 | "version": "0.21.5", 124 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 125 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 126 | "cpu": [ 127 | "x64" 128 | ], 129 | "optional": true, 130 | "os": [ 131 | "freebsd" 132 | ], 133 | "engines": { 134 | "node": ">=12" 135 | } 136 | }, 137 | "node_modules/@esbuild/linux-arm": { 138 | "version": "0.21.5", 139 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 140 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 141 | "cpu": [ 142 | "arm" 143 | ], 144 | "optional": true, 145 | "os": [ 146 | "linux" 147 | ], 148 | "engines": { 149 | "node": ">=12" 150 | } 151 | }, 152 | "node_modules/@esbuild/linux-arm64": { 153 | "version": "0.21.5", 154 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 155 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 156 | "cpu": [ 157 | "arm64" 158 | ], 159 | "optional": true, 160 | "os": [ 161 | "linux" 162 | ], 163 | "engines": { 164 | "node": ">=12" 165 | } 166 | }, 167 | "node_modules/@esbuild/linux-ia32": { 168 | "version": "0.21.5", 169 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 170 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 171 | "cpu": [ 172 | "ia32" 173 | ], 174 | "optional": true, 175 | "os": [ 176 | "linux" 177 | ], 178 | "engines": { 179 | "node": ">=12" 180 | } 181 | }, 182 | "node_modules/@esbuild/linux-loong64": { 183 | "version": "0.21.5", 184 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 185 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 186 | "cpu": [ 187 | "loong64" 188 | ], 189 | "optional": true, 190 | "os": [ 191 | "linux" 192 | ], 193 | "engines": { 194 | "node": ">=12" 195 | } 196 | }, 197 | "node_modules/@esbuild/linux-mips64el": { 198 | "version": "0.21.5", 199 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 200 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 201 | "cpu": [ 202 | "mips64el" 203 | ], 204 | "optional": true, 205 | "os": [ 206 | "linux" 207 | ], 208 | "engines": { 209 | "node": ">=12" 210 | } 211 | }, 212 | "node_modules/@esbuild/linux-ppc64": { 213 | "version": "0.21.5", 214 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 215 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 216 | "cpu": [ 217 | "ppc64" 218 | ], 219 | "optional": true, 220 | "os": [ 221 | "linux" 222 | ], 223 | "engines": { 224 | "node": ">=12" 225 | } 226 | }, 227 | "node_modules/@esbuild/linux-riscv64": { 228 | "version": "0.21.5", 229 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 230 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 231 | "cpu": [ 232 | "riscv64" 233 | ], 234 | "optional": true, 235 | "os": [ 236 | "linux" 237 | ], 238 | "engines": { 239 | "node": ">=12" 240 | } 241 | }, 242 | "node_modules/@esbuild/linux-s390x": { 243 | "version": "0.21.5", 244 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 245 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 246 | "cpu": [ 247 | "s390x" 248 | ], 249 | "optional": true, 250 | "os": [ 251 | "linux" 252 | ], 253 | "engines": { 254 | "node": ">=12" 255 | } 256 | }, 257 | "node_modules/@esbuild/linux-x64": { 258 | "version": "0.21.5", 259 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 260 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 261 | "cpu": [ 262 | "x64" 263 | ], 264 | "optional": true, 265 | "os": [ 266 | "linux" 267 | ], 268 | "engines": { 269 | "node": ">=12" 270 | } 271 | }, 272 | "node_modules/@esbuild/netbsd-x64": { 273 | "version": "0.21.5", 274 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 275 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 276 | "cpu": [ 277 | "x64" 278 | ], 279 | "optional": true, 280 | "os": [ 281 | "netbsd" 282 | ], 283 | "engines": { 284 | "node": ">=12" 285 | } 286 | }, 287 | "node_modules/@esbuild/openbsd-x64": { 288 | "version": "0.21.5", 289 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 290 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 291 | "cpu": [ 292 | "x64" 293 | ], 294 | "optional": true, 295 | "os": [ 296 | "openbsd" 297 | ], 298 | "engines": { 299 | "node": ">=12" 300 | } 301 | }, 302 | "node_modules/@esbuild/sunos-x64": { 303 | "version": "0.21.5", 304 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 305 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 306 | "cpu": [ 307 | "x64" 308 | ], 309 | "optional": true, 310 | "os": [ 311 | "sunos" 312 | ], 313 | "engines": { 314 | "node": ">=12" 315 | } 316 | }, 317 | "node_modules/@esbuild/win32-arm64": { 318 | "version": "0.21.5", 319 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 320 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 321 | "cpu": [ 322 | "arm64" 323 | ], 324 | "optional": true, 325 | "os": [ 326 | "win32" 327 | ], 328 | "engines": { 329 | "node": ">=12" 330 | } 331 | }, 332 | "node_modules/@esbuild/win32-ia32": { 333 | "version": "0.21.5", 334 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 335 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 336 | "cpu": [ 337 | "ia32" 338 | ], 339 | "optional": true, 340 | "os": [ 341 | "win32" 342 | ], 343 | "engines": { 344 | "node": ">=12" 345 | } 346 | }, 347 | "node_modules/@esbuild/win32-x64": { 348 | "version": "0.21.5", 349 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 350 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 351 | "cpu": [ 352 | "x64" 353 | ], 354 | "optional": true, 355 | "os": [ 356 | "win32" 357 | ], 358 | "engines": { 359 | "node": ">=12" 360 | } 361 | }, 362 | "node_modules/d3-color": { 363 | "version": "3.1.0", 364 | "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", 365 | "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", 366 | "engines": { 367 | "node": ">=12" 368 | } 369 | }, 370 | "node_modules/d3-dispatch": { 371 | "version": "3.0.1", 372 | "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", 373 | "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", 374 | "engines": { 375 | "node": ">=12" 376 | } 377 | }, 378 | "node_modules/d3-ease": { 379 | "version": "3.0.1", 380 | "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", 381 | "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", 382 | "engines": { 383 | "node": ">=12" 384 | } 385 | }, 386 | "node_modules/d3-interpolate": { 387 | "version": "3.0.1", 388 | "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", 389 | "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", 390 | "dependencies": { 391 | "d3-color": "1 - 3" 392 | }, 393 | "engines": { 394 | "node": ">=12" 395 | } 396 | }, 397 | "node_modules/d3-selection": { 398 | "version": "3.0.0", 399 | "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", 400 | "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", 401 | "engines": { 402 | "node": ">=12" 403 | } 404 | }, 405 | "node_modules/d3-timer": { 406 | "version": "3.0.1", 407 | "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", 408 | "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", 409 | "engines": { 410 | "node": ">=12" 411 | } 412 | }, 413 | "node_modules/d3-transition": { 414 | "version": "3.0.1", 415 | "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", 416 | "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", 417 | "dependencies": { 418 | "d3-color": "1 - 3", 419 | "d3-dispatch": "1 - 3", 420 | "d3-ease": "1 - 3", 421 | "d3-interpolate": "1 - 3", 422 | "d3-timer": "1 - 3" 423 | }, 424 | "engines": { 425 | "node": ">=12" 426 | }, 427 | "peerDependencies": { 428 | "d3-selection": "2 - 3" 429 | } 430 | }, 431 | "node_modules/esbuild": { 432 | "version": "0.21.5", 433 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 434 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 435 | "hasInstallScript": true, 436 | "bin": { 437 | "esbuild": "bin/esbuild" 438 | }, 439 | "engines": { 440 | "node": ">=12" 441 | }, 442 | "optionalDependencies": { 443 | "@esbuild/aix-ppc64": "0.21.5", 444 | "@esbuild/android-arm": "0.21.5", 445 | "@esbuild/android-arm64": "0.21.5", 446 | "@esbuild/android-x64": "0.21.5", 447 | "@esbuild/darwin-arm64": "0.21.5", 448 | "@esbuild/darwin-x64": "0.21.5", 449 | "@esbuild/freebsd-arm64": "0.21.5", 450 | "@esbuild/freebsd-x64": "0.21.5", 451 | "@esbuild/linux-arm": "0.21.5", 452 | "@esbuild/linux-arm64": "0.21.5", 453 | "@esbuild/linux-ia32": "0.21.5", 454 | "@esbuild/linux-loong64": "0.21.5", 455 | "@esbuild/linux-mips64el": "0.21.5", 456 | "@esbuild/linux-ppc64": "0.21.5", 457 | "@esbuild/linux-riscv64": "0.21.5", 458 | "@esbuild/linux-s390x": "0.21.5", 459 | "@esbuild/linux-x64": "0.21.5", 460 | "@esbuild/netbsd-x64": "0.21.5", 461 | "@esbuild/openbsd-x64": "0.21.5", 462 | "@esbuild/sunos-x64": "0.21.5", 463 | "@esbuild/win32-arm64": "0.21.5", 464 | "@esbuild/win32-ia32": "0.21.5", 465 | "@esbuild/win32-x64": "0.21.5" 466 | } 467 | } 468 | } 469 | } 470 | -------------------------------------------------------------------------------- /posts/2024/sql-vector-search-languages/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sql-vector-search-languages", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "d3-selection": "^3.0.0", 13 | "d3-transition": "^3.0.1", 14 | "esbuild": "^0.21.3" 15 | } 16 | }, 17 | "node_modules/@esbuild/aix-ppc64": { 18 | "version": "0.21.3", 19 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.3.tgz", 20 | "integrity": "sha512-yTgnwQpFVYfvvo4SvRFB0SwrW8YjOxEoT7wfMT7Ol5v7v5LDNvSGo67aExmxOb87nQNeWPVvaGBNfQ7BXcrZ9w==", 21 | "cpu": [ 22 | "ppc64" 23 | ], 24 | "optional": true, 25 | "os": [ 26 | "aix" 27 | ], 28 | "engines": { 29 | "node": ">=12" 30 | } 31 | }, 32 | "node_modules/@esbuild/android-arm": { 33 | "version": "0.21.3", 34 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.3.tgz", 35 | "integrity": "sha512-bviJOLMgurLJtF1/mAoJLxDZDL6oU5/ztMHnJQRejbJrSc9FFu0QoUoFhvi6qSKJEw9y5oGyvr9fuDtzJ30rNQ==", 36 | "cpu": [ 37 | "arm" 38 | ], 39 | "optional": true, 40 | "os": [ 41 | "android" 42 | ], 43 | "engines": { 44 | "node": ">=12" 45 | } 46 | }, 47 | "node_modules/@esbuild/android-arm64": { 48 | "version": "0.21.3", 49 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.3.tgz", 50 | "integrity": "sha512-c+ty9necz3zB1Y+d/N+mC6KVVkGUUOcm4ZmT5i/Fk5arOaY3i6CA3P5wo/7+XzV8cb4GrI/Zjp8NuOQ9Lfsosw==", 51 | "cpu": [ 52 | "arm64" 53 | ], 54 | "optional": true, 55 | "os": [ 56 | "android" 57 | ], 58 | "engines": { 59 | "node": ">=12" 60 | } 61 | }, 62 | "node_modules/@esbuild/android-x64": { 63 | "version": "0.21.3", 64 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.3.tgz", 65 | "integrity": "sha512-JReHfYCRK3FVX4Ra+y5EBH1b9e16TV2OxrPAvzMsGeES0X2Ndm9ImQRI4Ket757vhc5XBOuGperw63upesclRw==", 66 | "cpu": [ 67 | "x64" 68 | ], 69 | "optional": true, 70 | "os": [ 71 | "android" 72 | ], 73 | "engines": { 74 | "node": ">=12" 75 | } 76 | }, 77 | "node_modules/@esbuild/darwin-arm64": { 78 | "version": "0.21.3", 79 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.3.tgz", 80 | "integrity": "sha512-U3fuQ0xNiAkXOmQ6w5dKpEvXQRSpHOnbw7gEfHCRXPeTKW9sBzVck6C5Yneb8LfJm0l6le4NQfkNPnWMSlTFUQ==", 81 | "cpu": [ 82 | "arm64" 83 | ], 84 | "optional": true, 85 | "os": [ 86 | "darwin" 87 | ], 88 | "engines": { 89 | "node": ">=12" 90 | } 91 | }, 92 | "node_modules/@esbuild/darwin-x64": { 93 | "version": "0.21.3", 94 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.3.tgz", 95 | "integrity": "sha512-3m1CEB7F07s19wmaMNI2KANLcnaqryJxO1fXHUV5j1rWn+wMxdUYoPyO2TnAbfRZdi7ADRwJClmOwgT13qlP3Q==", 96 | "cpu": [ 97 | "x64" 98 | ], 99 | "optional": true, 100 | "os": [ 101 | "darwin" 102 | ], 103 | "engines": { 104 | "node": ">=12" 105 | } 106 | }, 107 | "node_modules/@esbuild/freebsd-arm64": { 108 | "version": "0.21.3", 109 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.3.tgz", 110 | "integrity": "sha512-fsNAAl5pU6wmKHq91cHWQT0Fz0vtyE1JauMzKotrwqIKAswwP5cpHUCxZNSTuA/JlqtScq20/5KZ+TxQdovU/g==", 111 | "cpu": [ 112 | "arm64" 113 | ], 114 | "optional": true, 115 | "os": [ 116 | "freebsd" 117 | ], 118 | "engines": { 119 | "node": ">=12" 120 | } 121 | }, 122 | "node_modules/@esbuild/freebsd-x64": { 123 | "version": "0.21.3", 124 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.3.tgz", 125 | "integrity": "sha512-tci+UJ4zP5EGF4rp8XlZIdq1q1a/1h9XuronfxTMCNBslpCtmk97Q/5qqy1Mu4zIc0yswN/yP/BLX+NTUC1bXA==", 126 | "cpu": [ 127 | "x64" 128 | ], 129 | "optional": true, 130 | "os": [ 131 | "freebsd" 132 | ], 133 | "engines": { 134 | "node": ">=12" 135 | } 136 | }, 137 | "node_modules/@esbuild/linux-arm": { 138 | "version": "0.21.3", 139 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.3.tgz", 140 | "integrity": "sha512-f6kz2QpSuyHHg01cDawj0vkyMwuIvN62UAguQfnNVzbge2uWLhA7TCXOn83DT0ZvyJmBI943MItgTovUob36SQ==", 141 | "cpu": [ 142 | "arm" 143 | ], 144 | "optional": true, 145 | "os": [ 146 | "linux" 147 | ], 148 | "engines": { 149 | "node": ">=12" 150 | } 151 | }, 152 | "node_modules/@esbuild/linux-arm64": { 153 | "version": "0.21.3", 154 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.3.tgz", 155 | "integrity": "sha512-vvG6R5g5ieB4eCJBQevyDMb31LMHthLpXTc2IGkFnPWS/GzIFDnaYFp558O+XybTmYrVjxnryru7QRleJvmZ6Q==", 156 | "cpu": [ 157 | "arm64" 158 | ], 159 | "optional": true, 160 | "os": [ 161 | "linux" 162 | ], 163 | "engines": { 164 | "node": ">=12" 165 | } 166 | }, 167 | "node_modules/@esbuild/linux-ia32": { 168 | "version": "0.21.3", 169 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.3.tgz", 170 | "integrity": "sha512-HjCWhH7K96Na+66TacDLJmOI9R8iDWDDiqe17C7znGvvE4sW1ECt9ly0AJ3dJH62jHyVqW9xpxZEU1jKdt+29A==", 171 | "cpu": [ 172 | "ia32" 173 | ], 174 | "optional": true, 175 | "os": [ 176 | "linux" 177 | ], 178 | "engines": { 179 | "node": ">=12" 180 | } 181 | }, 182 | "node_modules/@esbuild/linux-loong64": { 183 | "version": "0.21.3", 184 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.3.tgz", 185 | "integrity": "sha512-BGpimEccmHBZRcAhdlRIxMp7x9PyJxUtj7apL2IuoG9VxvU/l/v1z015nFs7Si7tXUwEsvjc1rOJdZCn4QTU+Q==", 186 | "cpu": [ 187 | "loong64" 188 | ], 189 | "optional": true, 190 | "os": [ 191 | "linux" 192 | ], 193 | "engines": { 194 | "node": ">=12" 195 | } 196 | }, 197 | "node_modules/@esbuild/linux-mips64el": { 198 | "version": "0.21.3", 199 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.3.tgz", 200 | "integrity": "sha512-5rMOWkp7FQGtAH3QJddP4w3s47iT20hwftqdm7b+loe95o8JU8ro3qZbhgMRy0VuFU0DizymF1pBKkn3YHWtsw==", 201 | "cpu": [ 202 | "mips64el" 203 | ], 204 | "optional": true, 205 | "os": [ 206 | "linux" 207 | ], 208 | "engines": { 209 | "node": ">=12" 210 | } 211 | }, 212 | "node_modules/@esbuild/linux-ppc64": { 213 | "version": "0.21.3", 214 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.3.tgz", 215 | "integrity": "sha512-h0zj1ldel89V5sjPLo5H1SyMzp4VrgN1tPkN29TmjvO1/r0MuMRwJxL8QY05SmfsZRs6TF0c/IDH3u7XYYmbAg==", 216 | "cpu": [ 217 | "ppc64" 218 | ], 219 | "optional": true, 220 | "os": [ 221 | "linux" 222 | ], 223 | "engines": { 224 | "node": ">=12" 225 | } 226 | }, 227 | "node_modules/@esbuild/linux-riscv64": { 228 | "version": "0.21.3", 229 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.3.tgz", 230 | "integrity": "sha512-dkAKcTsTJ+CRX6bnO17qDJbLoW37npd5gSNtSzjYQr0svghLJYGYB0NF1SNcU1vDcjXLYS5pO4qOW4YbFama4A==", 231 | "cpu": [ 232 | "riscv64" 233 | ], 234 | "optional": true, 235 | "os": [ 236 | "linux" 237 | ], 238 | "engines": { 239 | "node": ">=12" 240 | } 241 | }, 242 | "node_modules/@esbuild/linux-s390x": { 243 | "version": "0.21.3", 244 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.3.tgz", 245 | "integrity": "sha512-vnD1YUkovEdnZWEuMmy2X2JmzsHQqPpZElXx6dxENcIwTu+Cu5ERax6+Ke1QsE814Zf3c6rxCfwQdCTQ7tPuXA==", 246 | "cpu": [ 247 | "s390x" 248 | ], 249 | "optional": true, 250 | "os": [ 251 | "linux" 252 | ], 253 | "engines": { 254 | "node": ">=12" 255 | } 256 | }, 257 | "node_modules/@esbuild/linux-x64": { 258 | "version": "0.21.3", 259 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.3.tgz", 260 | "integrity": "sha512-IOXOIm9WaK7plL2gMhsWJd+l2bfrhfilv0uPTptoRoSb2p09RghhQQp9YY6ZJhk/kqmeRt6siRdMSLLwzuT0KQ==", 261 | "cpu": [ 262 | "x64" 263 | ], 264 | "optional": true, 265 | "os": [ 266 | "linux" 267 | ], 268 | "engines": { 269 | "node": ">=12" 270 | } 271 | }, 272 | "node_modules/@esbuild/netbsd-x64": { 273 | "version": "0.21.3", 274 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.3.tgz", 275 | "integrity": "sha512-uTgCwsvQ5+vCQnqM//EfDSuomo2LhdWhFPS8VL8xKf+PKTCrcT/2kPPoWMTs22aB63MLdGMJiE3f1PHvCDmUOw==", 276 | "cpu": [ 277 | "x64" 278 | ], 279 | "optional": true, 280 | "os": [ 281 | "netbsd" 282 | ], 283 | "engines": { 284 | "node": ">=12" 285 | } 286 | }, 287 | "node_modules/@esbuild/openbsd-x64": { 288 | "version": "0.21.3", 289 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.3.tgz", 290 | "integrity": "sha512-vNAkR17Ub2MgEud2Wag/OE4HTSI6zlb291UYzHez/psiKarp0J8PKGDnAhMBcHFoOHMXHfExzmjMojJNbAStrQ==", 291 | "cpu": [ 292 | "x64" 293 | ], 294 | "optional": true, 295 | "os": [ 296 | "openbsd" 297 | ], 298 | "engines": { 299 | "node": ">=12" 300 | } 301 | }, 302 | "node_modules/@esbuild/sunos-x64": { 303 | "version": "0.21.3", 304 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.3.tgz", 305 | "integrity": "sha512-W8H9jlGiSBomkgmouaRoTXo49j4w4Kfbl6I1bIdO/vT0+0u4f20ko3ELzV3hPI6XV6JNBVX+8BC+ajHkvffIJA==", 306 | "cpu": [ 307 | "x64" 308 | ], 309 | "optional": true, 310 | "os": [ 311 | "sunos" 312 | ], 313 | "engines": { 314 | "node": ">=12" 315 | } 316 | }, 317 | "node_modules/@esbuild/win32-arm64": { 318 | "version": "0.21.3", 319 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.3.tgz", 320 | "integrity": "sha512-EjEomwyLSCg8Ag3LDILIqYCZAq/y3diJ04PnqGRgq8/4O3VNlXyMd54j/saShaN4h5o5mivOjAzmU6C3X4v0xw==", 321 | "cpu": [ 322 | "arm64" 323 | ], 324 | "optional": true, 325 | "os": [ 326 | "win32" 327 | ], 328 | "engines": { 329 | "node": ">=12" 330 | } 331 | }, 332 | "node_modules/@esbuild/win32-ia32": { 333 | "version": "0.21.3", 334 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.3.tgz", 335 | "integrity": "sha512-WGiE/GgbsEwR33++5rzjiYsKyHywE8QSZPF7Rfx9EBfK3Qn3xyR6IjyCr5Uk38Kg8fG4/2phN7sXp4NPWd3fcw==", 336 | "cpu": [ 337 | "ia32" 338 | ], 339 | "optional": true, 340 | "os": [ 341 | "win32" 342 | ], 343 | "engines": { 344 | "node": ">=12" 345 | } 346 | }, 347 | "node_modules/@esbuild/win32-x64": { 348 | "version": "0.21.3", 349 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.3.tgz", 350 | "integrity": "sha512-xRxC0jaJWDLYvcUvjQmHCJSfMrgmUuvsoXgDeU/wTorQ1ngDdUBuFtgY3W1Pc5sprGAvZBtWdJX7RPg/iZZUqA==", 351 | "cpu": [ 352 | "x64" 353 | ], 354 | "optional": true, 355 | "os": [ 356 | "win32" 357 | ], 358 | "engines": { 359 | "node": ">=12" 360 | } 361 | }, 362 | "node_modules/d3-color": { 363 | "version": "3.1.0", 364 | "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", 365 | "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", 366 | "engines": { 367 | "node": ">=12" 368 | } 369 | }, 370 | "node_modules/d3-dispatch": { 371 | "version": "3.0.1", 372 | "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", 373 | "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", 374 | "engines": { 375 | "node": ">=12" 376 | } 377 | }, 378 | "node_modules/d3-ease": { 379 | "version": "3.0.1", 380 | "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", 381 | "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", 382 | "engines": { 383 | "node": ">=12" 384 | } 385 | }, 386 | "node_modules/d3-interpolate": { 387 | "version": "3.0.1", 388 | "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", 389 | "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", 390 | "dependencies": { 391 | "d3-color": "1 - 3" 392 | }, 393 | "engines": { 394 | "node": ">=12" 395 | } 396 | }, 397 | "node_modules/d3-selection": { 398 | "version": "3.0.0", 399 | "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", 400 | "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", 401 | "engines": { 402 | "node": ">=12" 403 | } 404 | }, 405 | "node_modules/d3-timer": { 406 | "version": "3.0.1", 407 | "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", 408 | "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", 409 | "engines": { 410 | "node": ">=12" 411 | } 412 | }, 413 | "node_modules/d3-transition": { 414 | "version": "3.0.1", 415 | "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", 416 | "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", 417 | "dependencies": { 418 | "d3-color": "1 - 3", 419 | "d3-dispatch": "1 - 3", 420 | "d3-ease": "1 - 3", 421 | "d3-interpolate": "1 - 3", 422 | "d3-timer": "1 - 3" 423 | }, 424 | "engines": { 425 | "node": ">=12" 426 | }, 427 | "peerDependencies": { 428 | "d3-selection": "2 - 3" 429 | } 430 | }, 431 | "node_modules/esbuild": { 432 | "version": "0.21.3", 433 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.3.tgz", 434 | "integrity": "sha512-Kgq0/ZsAPzKrbOjCQcjoSmPoWhlcVnGAUo7jvaLHoxW1Drto0KGkR1xBNg2Cp43b9ImvxmPEJZ9xkfcnqPsfBw==", 435 | "hasInstallScript": true, 436 | "bin": { 437 | "esbuild": "bin/esbuild" 438 | }, 439 | "engines": { 440 | "node": ">=12" 441 | }, 442 | "optionalDependencies": { 443 | "@esbuild/aix-ppc64": "0.21.3", 444 | "@esbuild/android-arm": "0.21.3", 445 | "@esbuild/android-arm64": "0.21.3", 446 | "@esbuild/android-x64": "0.21.3", 447 | "@esbuild/darwin-arm64": "0.21.3", 448 | "@esbuild/darwin-x64": "0.21.3", 449 | "@esbuild/freebsd-arm64": "0.21.3", 450 | "@esbuild/freebsd-x64": "0.21.3", 451 | "@esbuild/linux-arm": "0.21.3", 452 | "@esbuild/linux-arm64": "0.21.3", 453 | "@esbuild/linux-ia32": "0.21.3", 454 | "@esbuild/linux-loong64": "0.21.3", 455 | "@esbuild/linux-mips64el": "0.21.3", 456 | "@esbuild/linux-ppc64": "0.21.3", 457 | "@esbuild/linux-riscv64": "0.21.3", 458 | "@esbuild/linux-s390x": "0.21.3", 459 | "@esbuild/linux-x64": "0.21.3", 460 | "@esbuild/netbsd-x64": "0.21.3", 461 | "@esbuild/openbsd-x64": "0.21.3", 462 | "@esbuild/sunos-x64": "0.21.3", 463 | "@esbuild/win32-arm64": "0.21.3", 464 | "@esbuild/win32-ia32": "0.21.3", 465 | "@esbuild/win32-x64": "0.21.3" 466 | } 467 | } 468 | } 469 | } 470 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-metadata-release/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sql-vector-search-languages", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "d3-selection": "^3.0.0", 13 | "d3-transition": "^3.0.1", 14 | "esbuild": "^0.21.3" 15 | } 16 | }, 17 | "node_modules/@esbuild/aix-ppc64": { 18 | "version": "0.21.5", 19 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 20 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 21 | "cpu": [ 22 | "ppc64" 23 | ], 24 | "optional": true, 25 | "os": [ 26 | "aix" 27 | ], 28 | "engines": { 29 | "node": ">=12" 30 | } 31 | }, 32 | "node_modules/@esbuild/android-arm": { 33 | "version": "0.21.5", 34 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 35 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 36 | "cpu": [ 37 | "arm" 38 | ], 39 | "optional": true, 40 | "os": [ 41 | "android" 42 | ], 43 | "engines": { 44 | "node": ">=12" 45 | } 46 | }, 47 | "node_modules/@esbuild/android-arm64": { 48 | "version": "0.21.5", 49 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 50 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 51 | "cpu": [ 52 | "arm64" 53 | ], 54 | "optional": true, 55 | "os": [ 56 | "android" 57 | ], 58 | "engines": { 59 | "node": ">=12" 60 | } 61 | }, 62 | "node_modules/@esbuild/android-x64": { 63 | "version": "0.21.5", 64 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 65 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 66 | "cpu": [ 67 | "x64" 68 | ], 69 | "optional": true, 70 | "os": [ 71 | "android" 72 | ], 73 | "engines": { 74 | "node": ">=12" 75 | } 76 | }, 77 | "node_modules/@esbuild/darwin-arm64": { 78 | "version": "0.21.5", 79 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 80 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 81 | "cpu": [ 82 | "arm64" 83 | ], 84 | "optional": true, 85 | "os": [ 86 | "darwin" 87 | ], 88 | "engines": { 89 | "node": ">=12" 90 | } 91 | }, 92 | "node_modules/@esbuild/darwin-x64": { 93 | "version": "0.21.5", 94 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 95 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 96 | "cpu": [ 97 | "x64" 98 | ], 99 | "optional": true, 100 | "os": [ 101 | "darwin" 102 | ], 103 | "engines": { 104 | "node": ">=12" 105 | } 106 | }, 107 | "node_modules/@esbuild/freebsd-arm64": { 108 | "version": "0.21.5", 109 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 110 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 111 | "cpu": [ 112 | "arm64" 113 | ], 114 | "optional": true, 115 | "os": [ 116 | "freebsd" 117 | ], 118 | "engines": { 119 | "node": ">=12" 120 | } 121 | }, 122 | "node_modules/@esbuild/freebsd-x64": { 123 | "version": "0.21.5", 124 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 125 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 126 | "cpu": [ 127 | "x64" 128 | ], 129 | "optional": true, 130 | "os": [ 131 | "freebsd" 132 | ], 133 | "engines": { 134 | "node": ">=12" 135 | } 136 | }, 137 | "node_modules/@esbuild/linux-arm": { 138 | "version": "0.21.5", 139 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 140 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 141 | "cpu": [ 142 | "arm" 143 | ], 144 | "optional": true, 145 | "os": [ 146 | "linux" 147 | ], 148 | "engines": { 149 | "node": ">=12" 150 | } 151 | }, 152 | "node_modules/@esbuild/linux-arm64": { 153 | "version": "0.21.5", 154 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 155 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 156 | "cpu": [ 157 | "arm64" 158 | ], 159 | "optional": true, 160 | "os": [ 161 | "linux" 162 | ], 163 | "engines": { 164 | "node": ">=12" 165 | } 166 | }, 167 | "node_modules/@esbuild/linux-ia32": { 168 | "version": "0.21.5", 169 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 170 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 171 | "cpu": [ 172 | "ia32" 173 | ], 174 | "optional": true, 175 | "os": [ 176 | "linux" 177 | ], 178 | "engines": { 179 | "node": ">=12" 180 | } 181 | }, 182 | "node_modules/@esbuild/linux-loong64": { 183 | "version": "0.21.5", 184 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 185 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 186 | "cpu": [ 187 | "loong64" 188 | ], 189 | "optional": true, 190 | "os": [ 191 | "linux" 192 | ], 193 | "engines": { 194 | "node": ">=12" 195 | } 196 | }, 197 | "node_modules/@esbuild/linux-mips64el": { 198 | "version": "0.21.5", 199 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 200 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 201 | "cpu": [ 202 | "mips64el" 203 | ], 204 | "optional": true, 205 | "os": [ 206 | "linux" 207 | ], 208 | "engines": { 209 | "node": ">=12" 210 | } 211 | }, 212 | "node_modules/@esbuild/linux-ppc64": { 213 | "version": "0.21.5", 214 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 215 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 216 | "cpu": [ 217 | "ppc64" 218 | ], 219 | "optional": true, 220 | "os": [ 221 | "linux" 222 | ], 223 | "engines": { 224 | "node": ">=12" 225 | } 226 | }, 227 | "node_modules/@esbuild/linux-riscv64": { 228 | "version": "0.21.5", 229 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 230 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 231 | "cpu": [ 232 | "riscv64" 233 | ], 234 | "optional": true, 235 | "os": [ 236 | "linux" 237 | ], 238 | "engines": { 239 | "node": ">=12" 240 | } 241 | }, 242 | "node_modules/@esbuild/linux-s390x": { 243 | "version": "0.21.5", 244 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 245 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 246 | "cpu": [ 247 | "s390x" 248 | ], 249 | "optional": true, 250 | "os": [ 251 | "linux" 252 | ], 253 | "engines": { 254 | "node": ">=12" 255 | } 256 | }, 257 | "node_modules/@esbuild/linux-x64": { 258 | "version": "0.21.5", 259 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 260 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 261 | "cpu": [ 262 | "x64" 263 | ], 264 | "optional": true, 265 | "os": [ 266 | "linux" 267 | ], 268 | "engines": { 269 | "node": ">=12" 270 | } 271 | }, 272 | "node_modules/@esbuild/netbsd-x64": { 273 | "version": "0.21.5", 274 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 275 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 276 | "cpu": [ 277 | "x64" 278 | ], 279 | "optional": true, 280 | "os": [ 281 | "netbsd" 282 | ], 283 | "engines": { 284 | "node": ">=12" 285 | } 286 | }, 287 | "node_modules/@esbuild/openbsd-x64": { 288 | "version": "0.21.5", 289 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 290 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 291 | "cpu": [ 292 | "x64" 293 | ], 294 | "optional": true, 295 | "os": [ 296 | "openbsd" 297 | ], 298 | "engines": { 299 | "node": ">=12" 300 | } 301 | }, 302 | "node_modules/@esbuild/sunos-x64": { 303 | "version": "0.21.5", 304 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 305 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 306 | "cpu": [ 307 | "x64" 308 | ], 309 | "optional": true, 310 | "os": [ 311 | "sunos" 312 | ], 313 | "engines": { 314 | "node": ">=12" 315 | } 316 | }, 317 | "node_modules/@esbuild/win32-arm64": { 318 | "version": "0.21.5", 319 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 320 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 321 | "cpu": [ 322 | "arm64" 323 | ], 324 | "optional": true, 325 | "os": [ 326 | "win32" 327 | ], 328 | "engines": { 329 | "node": ">=12" 330 | } 331 | }, 332 | "node_modules/@esbuild/win32-ia32": { 333 | "version": "0.21.5", 334 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 335 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 336 | "cpu": [ 337 | "ia32" 338 | ], 339 | "optional": true, 340 | "os": [ 341 | "win32" 342 | ], 343 | "engines": { 344 | "node": ">=12" 345 | } 346 | }, 347 | "node_modules/@esbuild/win32-x64": { 348 | "version": "0.21.5", 349 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 350 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 351 | "cpu": [ 352 | "x64" 353 | ], 354 | "optional": true, 355 | "os": [ 356 | "win32" 357 | ], 358 | "engines": { 359 | "node": ">=12" 360 | } 361 | }, 362 | "node_modules/d3-color": { 363 | "version": "3.1.0", 364 | "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", 365 | "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", 366 | "engines": { 367 | "node": ">=12" 368 | } 369 | }, 370 | "node_modules/d3-dispatch": { 371 | "version": "3.0.1", 372 | "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", 373 | "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", 374 | "engines": { 375 | "node": ">=12" 376 | } 377 | }, 378 | "node_modules/d3-ease": { 379 | "version": "3.0.1", 380 | "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", 381 | "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", 382 | "engines": { 383 | "node": ">=12" 384 | } 385 | }, 386 | "node_modules/d3-interpolate": { 387 | "version": "3.0.1", 388 | "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", 389 | "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", 390 | "dependencies": { 391 | "d3-color": "1 - 3" 392 | }, 393 | "engines": { 394 | "node": ">=12" 395 | } 396 | }, 397 | "node_modules/d3-selection": { 398 | "version": "3.0.0", 399 | "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", 400 | "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", 401 | "engines": { 402 | "node": ">=12" 403 | } 404 | }, 405 | "node_modules/d3-timer": { 406 | "version": "3.0.1", 407 | "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", 408 | "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", 409 | "engines": { 410 | "node": ">=12" 411 | } 412 | }, 413 | "node_modules/d3-transition": { 414 | "version": "3.0.1", 415 | "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", 416 | "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", 417 | "dependencies": { 418 | "d3-color": "1 - 3", 419 | "d3-dispatch": "1 - 3", 420 | "d3-ease": "1 - 3", 421 | "d3-interpolate": "1 - 3", 422 | "d3-timer": "1 - 3" 423 | }, 424 | "engines": { 425 | "node": ">=12" 426 | }, 427 | "peerDependencies": { 428 | "d3-selection": "2 - 3" 429 | } 430 | }, 431 | "node_modules/esbuild": { 432 | "version": "0.21.5", 433 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 434 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 435 | "hasInstallScript": true, 436 | "bin": { 437 | "esbuild": "bin/esbuild" 438 | }, 439 | "engines": { 440 | "node": ">=12" 441 | }, 442 | "optionalDependencies": { 443 | "@esbuild/aix-ppc64": "0.21.5", 444 | "@esbuild/android-arm": "0.21.5", 445 | "@esbuild/android-arm64": "0.21.5", 446 | "@esbuild/android-x64": "0.21.5", 447 | "@esbuild/darwin-arm64": "0.21.5", 448 | "@esbuild/darwin-x64": "0.21.5", 449 | "@esbuild/freebsd-arm64": "0.21.5", 450 | "@esbuild/freebsd-x64": "0.21.5", 451 | "@esbuild/linux-arm": "0.21.5", 452 | "@esbuild/linux-arm64": "0.21.5", 453 | "@esbuild/linux-ia32": "0.21.5", 454 | "@esbuild/linux-loong64": "0.21.5", 455 | "@esbuild/linux-mips64el": "0.21.5", 456 | "@esbuild/linux-ppc64": "0.21.5", 457 | "@esbuild/linux-riscv64": "0.21.5", 458 | "@esbuild/linux-s390x": "0.21.5", 459 | "@esbuild/linux-x64": "0.21.5", 460 | "@esbuild/netbsd-x64": "0.21.5", 461 | "@esbuild/openbsd-x64": "0.21.5", 462 | "@esbuild/sunos-x64": "0.21.5", 463 | "@esbuild/win32-arm64": "0.21.5", 464 | "@esbuild/win32-ia32": "0.21.5", 465 | "@esbuild/win32-x64": "0.21.5" 466 | } 467 | } 468 | } 469 | } 470 | -------------------------------------------------------------------------------- /posts/2024/sqlite-lembed-init/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sql-vector-search-languages", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "d3-selection": "^3.0.0", 13 | "d3-transition": "^3.0.1", 14 | "esbuild": "^0.21.3" 15 | } 16 | }, 17 | "node_modules/@esbuild/aix-ppc64": { 18 | "version": "0.21.5", 19 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 20 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 21 | "cpu": [ 22 | "ppc64" 23 | ], 24 | "license": "MIT", 25 | "optional": true, 26 | "os": [ 27 | "aix" 28 | ], 29 | "engines": { 30 | "node": ">=12" 31 | } 32 | }, 33 | "node_modules/@esbuild/android-arm": { 34 | "version": "0.21.5", 35 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 36 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 37 | "cpu": [ 38 | "arm" 39 | ], 40 | "license": "MIT", 41 | "optional": true, 42 | "os": [ 43 | "android" 44 | ], 45 | "engines": { 46 | "node": ">=12" 47 | } 48 | }, 49 | "node_modules/@esbuild/android-arm64": { 50 | "version": "0.21.5", 51 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 52 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 53 | "cpu": [ 54 | "arm64" 55 | ], 56 | "license": "MIT", 57 | "optional": true, 58 | "os": [ 59 | "android" 60 | ], 61 | "engines": { 62 | "node": ">=12" 63 | } 64 | }, 65 | "node_modules/@esbuild/android-x64": { 66 | "version": "0.21.5", 67 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 68 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 69 | "cpu": [ 70 | "x64" 71 | ], 72 | "license": "MIT", 73 | "optional": true, 74 | "os": [ 75 | "android" 76 | ], 77 | "engines": { 78 | "node": ">=12" 79 | } 80 | }, 81 | "node_modules/@esbuild/darwin-arm64": { 82 | "version": "0.21.5", 83 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 84 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 85 | "cpu": [ 86 | "arm64" 87 | ], 88 | "license": "MIT", 89 | "optional": true, 90 | "os": [ 91 | "darwin" 92 | ], 93 | "engines": { 94 | "node": ">=12" 95 | } 96 | }, 97 | "node_modules/@esbuild/darwin-x64": { 98 | "version": "0.21.5", 99 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 100 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 101 | "cpu": [ 102 | "x64" 103 | ], 104 | "license": "MIT", 105 | "optional": true, 106 | "os": [ 107 | "darwin" 108 | ], 109 | "engines": { 110 | "node": ">=12" 111 | } 112 | }, 113 | "node_modules/@esbuild/freebsd-arm64": { 114 | "version": "0.21.5", 115 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 116 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 117 | "cpu": [ 118 | "arm64" 119 | ], 120 | "license": "MIT", 121 | "optional": true, 122 | "os": [ 123 | "freebsd" 124 | ], 125 | "engines": { 126 | "node": ">=12" 127 | } 128 | }, 129 | "node_modules/@esbuild/freebsd-x64": { 130 | "version": "0.21.5", 131 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 132 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 133 | "cpu": [ 134 | "x64" 135 | ], 136 | "license": "MIT", 137 | "optional": true, 138 | "os": [ 139 | "freebsd" 140 | ], 141 | "engines": { 142 | "node": ">=12" 143 | } 144 | }, 145 | "node_modules/@esbuild/linux-arm": { 146 | "version": "0.21.5", 147 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 148 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 149 | "cpu": [ 150 | "arm" 151 | ], 152 | "license": "MIT", 153 | "optional": true, 154 | "os": [ 155 | "linux" 156 | ], 157 | "engines": { 158 | "node": ">=12" 159 | } 160 | }, 161 | "node_modules/@esbuild/linux-arm64": { 162 | "version": "0.21.5", 163 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 164 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 165 | "cpu": [ 166 | "arm64" 167 | ], 168 | "license": "MIT", 169 | "optional": true, 170 | "os": [ 171 | "linux" 172 | ], 173 | "engines": { 174 | "node": ">=12" 175 | } 176 | }, 177 | "node_modules/@esbuild/linux-ia32": { 178 | "version": "0.21.5", 179 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 180 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 181 | "cpu": [ 182 | "ia32" 183 | ], 184 | "license": "MIT", 185 | "optional": true, 186 | "os": [ 187 | "linux" 188 | ], 189 | "engines": { 190 | "node": ">=12" 191 | } 192 | }, 193 | "node_modules/@esbuild/linux-loong64": { 194 | "version": "0.21.5", 195 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 196 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 197 | "cpu": [ 198 | "loong64" 199 | ], 200 | "license": "MIT", 201 | "optional": true, 202 | "os": [ 203 | "linux" 204 | ], 205 | "engines": { 206 | "node": ">=12" 207 | } 208 | }, 209 | "node_modules/@esbuild/linux-mips64el": { 210 | "version": "0.21.5", 211 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 212 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 213 | "cpu": [ 214 | "mips64el" 215 | ], 216 | "license": "MIT", 217 | "optional": true, 218 | "os": [ 219 | "linux" 220 | ], 221 | "engines": { 222 | "node": ">=12" 223 | } 224 | }, 225 | "node_modules/@esbuild/linux-ppc64": { 226 | "version": "0.21.5", 227 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 228 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 229 | "cpu": [ 230 | "ppc64" 231 | ], 232 | "license": "MIT", 233 | "optional": true, 234 | "os": [ 235 | "linux" 236 | ], 237 | "engines": { 238 | "node": ">=12" 239 | } 240 | }, 241 | "node_modules/@esbuild/linux-riscv64": { 242 | "version": "0.21.5", 243 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 244 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 245 | "cpu": [ 246 | "riscv64" 247 | ], 248 | "license": "MIT", 249 | "optional": true, 250 | "os": [ 251 | "linux" 252 | ], 253 | "engines": { 254 | "node": ">=12" 255 | } 256 | }, 257 | "node_modules/@esbuild/linux-s390x": { 258 | "version": "0.21.5", 259 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 260 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 261 | "cpu": [ 262 | "s390x" 263 | ], 264 | "license": "MIT", 265 | "optional": true, 266 | "os": [ 267 | "linux" 268 | ], 269 | "engines": { 270 | "node": ">=12" 271 | } 272 | }, 273 | "node_modules/@esbuild/linux-x64": { 274 | "version": "0.21.5", 275 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 276 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 277 | "cpu": [ 278 | "x64" 279 | ], 280 | "license": "MIT", 281 | "optional": true, 282 | "os": [ 283 | "linux" 284 | ], 285 | "engines": { 286 | "node": ">=12" 287 | } 288 | }, 289 | "node_modules/@esbuild/netbsd-x64": { 290 | "version": "0.21.5", 291 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 292 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 293 | "cpu": [ 294 | "x64" 295 | ], 296 | "license": "MIT", 297 | "optional": true, 298 | "os": [ 299 | "netbsd" 300 | ], 301 | "engines": { 302 | "node": ">=12" 303 | } 304 | }, 305 | "node_modules/@esbuild/openbsd-x64": { 306 | "version": "0.21.5", 307 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 308 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 309 | "cpu": [ 310 | "x64" 311 | ], 312 | "license": "MIT", 313 | "optional": true, 314 | "os": [ 315 | "openbsd" 316 | ], 317 | "engines": { 318 | "node": ">=12" 319 | } 320 | }, 321 | "node_modules/@esbuild/sunos-x64": { 322 | "version": "0.21.5", 323 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 324 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 325 | "cpu": [ 326 | "x64" 327 | ], 328 | "license": "MIT", 329 | "optional": true, 330 | "os": [ 331 | "sunos" 332 | ], 333 | "engines": { 334 | "node": ">=12" 335 | } 336 | }, 337 | "node_modules/@esbuild/win32-arm64": { 338 | "version": "0.21.5", 339 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 340 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 341 | "cpu": [ 342 | "arm64" 343 | ], 344 | "license": "MIT", 345 | "optional": true, 346 | "os": [ 347 | "win32" 348 | ], 349 | "engines": { 350 | "node": ">=12" 351 | } 352 | }, 353 | "node_modules/@esbuild/win32-ia32": { 354 | "version": "0.21.5", 355 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 356 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 357 | "cpu": [ 358 | "ia32" 359 | ], 360 | "license": "MIT", 361 | "optional": true, 362 | "os": [ 363 | "win32" 364 | ], 365 | "engines": { 366 | "node": ">=12" 367 | } 368 | }, 369 | "node_modules/@esbuild/win32-x64": { 370 | "version": "0.21.5", 371 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 372 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 373 | "cpu": [ 374 | "x64" 375 | ], 376 | "license": "MIT", 377 | "optional": true, 378 | "os": [ 379 | "win32" 380 | ], 381 | "engines": { 382 | "node": ">=12" 383 | } 384 | }, 385 | "node_modules/d3-color": { 386 | "version": "3.1.0", 387 | "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", 388 | "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", 389 | "license": "ISC", 390 | "engines": { 391 | "node": ">=12" 392 | } 393 | }, 394 | "node_modules/d3-dispatch": { 395 | "version": "3.0.1", 396 | "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", 397 | "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", 398 | "license": "ISC", 399 | "engines": { 400 | "node": ">=12" 401 | } 402 | }, 403 | "node_modules/d3-ease": { 404 | "version": "3.0.1", 405 | "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", 406 | "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", 407 | "license": "BSD-3-Clause", 408 | "engines": { 409 | "node": ">=12" 410 | } 411 | }, 412 | "node_modules/d3-interpolate": { 413 | "version": "3.0.1", 414 | "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", 415 | "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", 416 | "license": "ISC", 417 | "dependencies": { 418 | "d3-color": "1 - 3" 419 | }, 420 | "engines": { 421 | "node": ">=12" 422 | } 423 | }, 424 | "node_modules/d3-selection": { 425 | "version": "3.0.0", 426 | "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", 427 | "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", 428 | "license": "ISC", 429 | "engines": { 430 | "node": ">=12" 431 | } 432 | }, 433 | "node_modules/d3-timer": { 434 | "version": "3.0.1", 435 | "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", 436 | "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", 437 | "license": "ISC", 438 | "engines": { 439 | "node": ">=12" 440 | } 441 | }, 442 | "node_modules/d3-transition": { 443 | "version": "3.0.1", 444 | "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", 445 | "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", 446 | "license": "ISC", 447 | "dependencies": { 448 | "d3-color": "1 - 3", 449 | "d3-dispatch": "1 - 3", 450 | "d3-ease": "1 - 3", 451 | "d3-interpolate": "1 - 3", 452 | "d3-timer": "1 - 3" 453 | }, 454 | "engines": { 455 | "node": ">=12" 456 | }, 457 | "peerDependencies": { 458 | "d3-selection": "2 - 3" 459 | } 460 | }, 461 | "node_modules/esbuild": { 462 | "version": "0.21.5", 463 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 464 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 465 | "hasInstallScript": true, 466 | "license": "MIT", 467 | "bin": { 468 | "esbuild": "bin/esbuild" 469 | }, 470 | "engines": { 471 | "node": ">=12" 472 | }, 473 | "optionalDependencies": { 474 | "@esbuild/aix-ppc64": "0.21.5", 475 | "@esbuild/android-arm": "0.21.5", 476 | "@esbuild/android-arm64": "0.21.5", 477 | "@esbuild/android-x64": "0.21.5", 478 | "@esbuild/darwin-arm64": "0.21.5", 479 | "@esbuild/darwin-x64": "0.21.5", 480 | "@esbuild/freebsd-arm64": "0.21.5", 481 | "@esbuild/freebsd-x64": "0.21.5", 482 | "@esbuild/linux-arm": "0.21.5", 483 | "@esbuild/linux-arm64": "0.21.5", 484 | "@esbuild/linux-ia32": "0.21.5", 485 | "@esbuild/linux-loong64": "0.21.5", 486 | "@esbuild/linux-mips64el": "0.21.5", 487 | "@esbuild/linux-ppc64": "0.21.5", 488 | "@esbuild/linux-riscv64": "0.21.5", 489 | "@esbuild/linux-s390x": "0.21.5", 490 | "@esbuild/linux-x64": "0.21.5", 491 | "@esbuild/netbsd-x64": "0.21.5", 492 | "@esbuild/openbsd-x64": "0.21.5", 493 | "@esbuild/sunos-x64": "0.21.5", 494 | "@esbuild/win32-arm64": "0.21.5", 495 | "@esbuild/win32-ia32": "0.21.5", 496 | "@esbuild/win32-x64": "0.21.5" 497 | } 498 | } 499 | } 500 | } 501 | -------------------------------------------------------------------------------- /posts/2024/sqlite-rembed-init/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sql-vector-search-languages", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "d3-selection": "^3.0.0", 13 | "d3-transition": "^3.0.1", 14 | "esbuild": "^0.21.3" 15 | } 16 | }, 17 | "node_modules/@esbuild/aix-ppc64": { 18 | "version": "0.21.5", 19 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 20 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 21 | "cpu": [ 22 | "ppc64" 23 | ], 24 | "license": "MIT", 25 | "optional": true, 26 | "os": [ 27 | "aix" 28 | ], 29 | "engines": { 30 | "node": ">=12" 31 | } 32 | }, 33 | "node_modules/@esbuild/android-arm": { 34 | "version": "0.21.5", 35 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 36 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 37 | "cpu": [ 38 | "arm" 39 | ], 40 | "license": "MIT", 41 | "optional": true, 42 | "os": [ 43 | "android" 44 | ], 45 | "engines": { 46 | "node": ">=12" 47 | } 48 | }, 49 | "node_modules/@esbuild/android-arm64": { 50 | "version": "0.21.5", 51 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 52 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 53 | "cpu": [ 54 | "arm64" 55 | ], 56 | "license": "MIT", 57 | "optional": true, 58 | "os": [ 59 | "android" 60 | ], 61 | "engines": { 62 | "node": ">=12" 63 | } 64 | }, 65 | "node_modules/@esbuild/android-x64": { 66 | "version": "0.21.5", 67 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 68 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 69 | "cpu": [ 70 | "x64" 71 | ], 72 | "license": "MIT", 73 | "optional": true, 74 | "os": [ 75 | "android" 76 | ], 77 | "engines": { 78 | "node": ">=12" 79 | } 80 | }, 81 | "node_modules/@esbuild/darwin-arm64": { 82 | "version": "0.21.5", 83 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 84 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 85 | "cpu": [ 86 | "arm64" 87 | ], 88 | "license": "MIT", 89 | "optional": true, 90 | "os": [ 91 | "darwin" 92 | ], 93 | "engines": { 94 | "node": ">=12" 95 | } 96 | }, 97 | "node_modules/@esbuild/darwin-x64": { 98 | "version": "0.21.5", 99 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 100 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 101 | "cpu": [ 102 | "x64" 103 | ], 104 | "license": "MIT", 105 | "optional": true, 106 | "os": [ 107 | "darwin" 108 | ], 109 | "engines": { 110 | "node": ">=12" 111 | } 112 | }, 113 | "node_modules/@esbuild/freebsd-arm64": { 114 | "version": "0.21.5", 115 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 116 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 117 | "cpu": [ 118 | "arm64" 119 | ], 120 | "license": "MIT", 121 | "optional": true, 122 | "os": [ 123 | "freebsd" 124 | ], 125 | "engines": { 126 | "node": ">=12" 127 | } 128 | }, 129 | "node_modules/@esbuild/freebsd-x64": { 130 | "version": "0.21.5", 131 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 132 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 133 | "cpu": [ 134 | "x64" 135 | ], 136 | "license": "MIT", 137 | "optional": true, 138 | "os": [ 139 | "freebsd" 140 | ], 141 | "engines": { 142 | "node": ">=12" 143 | } 144 | }, 145 | "node_modules/@esbuild/linux-arm": { 146 | "version": "0.21.5", 147 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 148 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 149 | "cpu": [ 150 | "arm" 151 | ], 152 | "license": "MIT", 153 | "optional": true, 154 | "os": [ 155 | "linux" 156 | ], 157 | "engines": { 158 | "node": ">=12" 159 | } 160 | }, 161 | "node_modules/@esbuild/linux-arm64": { 162 | "version": "0.21.5", 163 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 164 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 165 | "cpu": [ 166 | "arm64" 167 | ], 168 | "license": "MIT", 169 | "optional": true, 170 | "os": [ 171 | "linux" 172 | ], 173 | "engines": { 174 | "node": ">=12" 175 | } 176 | }, 177 | "node_modules/@esbuild/linux-ia32": { 178 | "version": "0.21.5", 179 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 180 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 181 | "cpu": [ 182 | "ia32" 183 | ], 184 | "license": "MIT", 185 | "optional": true, 186 | "os": [ 187 | "linux" 188 | ], 189 | "engines": { 190 | "node": ">=12" 191 | } 192 | }, 193 | "node_modules/@esbuild/linux-loong64": { 194 | "version": "0.21.5", 195 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 196 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 197 | "cpu": [ 198 | "loong64" 199 | ], 200 | "license": "MIT", 201 | "optional": true, 202 | "os": [ 203 | "linux" 204 | ], 205 | "engines": { 206 | "node": ">=12" 207 | } 208 | }, 209 | "node_modules/@esbuild/linux-mips64el": { 210 | "version": "0.21.5", 211 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 212 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 213 | "cpu": [ 214 | "mips64el" 215 | ], 216 | "license": "MIT", 217 | "optional": true, 218 | "os": [ 219 | "linux" 220 | ], 221 | "engines": { 222 | "node": ">=12" 223 | } 224 | }, 225 | "node_modules/@esbuild/linux-ppc64": { 226 | "version": "0.21.5", 227 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 228 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 229 | "cpu": [ 230 | "ppc64" 231 | ], 232 | "license": "MIT", 233 | "optional": true, 234 | "os": [ 235 | "linux" 236 | ], 237 | "engines": { 238 | "node": ">=12" 239 | } 240 | }, 241 | "node_modules/@esbuild/linux-riscv64": { 242 | "version": "0.21.5", 243 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 244 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 245 | "cpu": [ 246 | "riscv64" 247 | ], 248 | "license": "MIT", 249 | "optional": true, 250 | "os": [ 251 | "linux" 252 | ], 253 | "engines": { 254 | "node": ">=12" 255 | } 256 | }, 257 | "node_modules/@esbuild/linux-s390x": { 258 | "version": "0.21.5", 259 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 260 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 261 | "cpu": [ 262 | "s390x" 263 | ], 264 | "license": "MIT", 265 | "optional": true, 266 | "os": [ 267 | "linux" 268 | ], 269 | "engines": { 270 | "node": ">=12" 271 | } 272 | }, 273 | "node_modules/@esbuild/linux-x64": { 274 | "version": "0.21.5", 275 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 276 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 277 | "cpu": [ 278 | "x64" 279 | ], 280 | "license": "MIT", 281 | "optional": true, 282 | "os": [ 283 | "linux" 284 | ], 285 | "engines": { 286 | "node": ">=12" 287 | } 288 | }, 289 | "node_modules/@esbuild/netbsd-x64": { 290 | "version": "0.21.5", 291 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 292 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 293 | "cpu": [ 294 | "x64" 295 | ], 296 | "license": "MIT", 297 | "optional": true, 298 | "os": [ 299 | "netbsd" 300 | ], 301 | "engines": { 302 | "node": ">=12" 303 | } 304 | }, 305 | "node_modules/@esbuild/openbsd-x64": { 306 | "version": "0.21.5", 307 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 308 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 309 | "cpu": [ 310 | "x64" 311 | ], 312 | "license": "MIT", 313 | "optional": true, 314 | "os": [ 315 | "openbsd" 316 | ], 317 | "engines": { 318 | "node": ">=12" 319 | } 320 | }, 321 | "node_modules/@esbuild/sunos-x64": { 322 | "version": "0.21.5", 323 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 324 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 325 | "cpu": [ 326 | "x64" 327 | ], 328 | "license": "MIT", 329 | "optional": true, 330 | "os": [ 331 | "sunos" 332 | ], 333 | "engines": { 334 | "node": ">=12" 335 | } 336 | }, 337 | "node_modules/@esbuild/win32-arm64": { 338 | "version": "0.21.5", 339 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 340 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 341 | "cpu": [ 342 | "arm64" 343 | ], 344 | "license": "MIT", 345 | "optional": true, 346 | "os": [ 347 | "win32" 348 | ], 349 | "engines": { 350 | "node": ">=12" 351 | } 352 | }, 353 | "node_modules/@esbuild/win32-ia32": { 354 | "version": "0.21.5", 355 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 356 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 357 | "cpu": [ 358 | "ia32" 359 | ], 360 | "license": "MIT", 361 | "optional": true, 362 | "os": [ 363 | "win32" 364 | ], 365 | "engines": { 366 | "node": ">=12" 367 | } 368 | }, 369 | "node_modules/@esbuild/win32-x64": { 370 | "version": "0.21.5", 371 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 372 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 373 | "cpu": [ 374 | "x64" 375 | ], 376 | "license": "MIT", 377 | "optional": true, 378 | "os": [ 379 | "win32" 380 | ], 381 | "engines": { 382 | "node": ">=12" 383 | } 384 | }, 385 | "node_modules/d3-color": { 386 | "version": "3.1.0", 387 | "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", 388 | "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", 389 | "license": "ISC", 390 | "engines": { 391 | "node": ">=12" 392 | } 393 | }, 394 | "node_modules/d3-dispatch": { 395 | "version": "3.0.1", 396 | "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", 397 | "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", 398 | "license": "ISC", 399 | "engines": { 400 | "node": ">=12" 401 | } 402 | }, 403 | "node_modules/d3-ease": { 404 | "version": "3.0.1", 405 | "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", 406 | "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", 407 | "license": "BSD-3-Clause", 408 | "engines": { 409 | "node": ">=12" 410 | } 411 | }, 412 | "node_modules/d3-interpolate": { 413 | "version": "3.0.1", 414 | "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", 415 | "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", 416 | "license": "ISC", 417 | "dependencies": { 418 | "d3-color": "1 - 3" 419 | }, 420 | "engines": { 421 | "node": ">=12" 422 | } 423 | }, 424 | "node_modules/d3-selection": { 425 | "version": "3.0.0", 426 | "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", 427 | "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", 428 | "license": "ISC", 429 | "engines": { 430 | "node": ">=12" 431 | } 432 | }, 433 | "node_modules/d3-timer": { 434 | "version": "3.0.1", 435 | "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", 436 | "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", 437 | "license": "ISC", 438 | "engines": { 439 | "node": ">=12" 440 | } 441 | }, 442 | "node_modules/d3-transition": { 443 | "version": "3.0.1", 444 | "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", 445 | "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", 446 | "license": "ISC", 447 | "dependencies": { 448 | "d3-color": "1 - 3", 449 | "d3-dispatch": "1 - 3", 450 | "d3-ease": "1 - 3", 451 | "d3-interpolate": "1 - 3", 452 | "d3-timer": "1 - 3" 453 | }, 454 | "engines": { 455 | "node": ">=12" 456 | }, 457 | "peerDependencies": { 458 | "d3-selection": "2 - 3" 459 | } 460 | }, 461 | "node_modules/esbuild": { 462 | "version": "0.21.5", 463 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 464 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 465 | "hasInstallScript": true, 466 | "license": "MIT", 467 | "bin": { 468 | "esbuild": "bin/esbuild" 469 | }, 470 | "engines": { 471 | "node": ">=12" 472 | }, 473 | "optionalDependencies": { 474 | "@esbuild/aix-ppc64": "0.21.5", 475 | "@esbuild/android-arm": "0.21.5", 476 | "@esbuild/android-arm64": "0.21.5", 477 | "@esbuild/android-x64": "0.21.5", 478 | "@esbuild/darwin-arm64": "0.21.5", 479 | "@esbuild/darwin-x64": "0.21.5", 480 | "@esbuild/freebsd-arm64": "0.21.5", 481 | "@esbuild/freebsd-x64": "0.21.5", 482 | "@esbuild/linux-arm": "0.21.5", 483 | "@esbuild/linux-arm64": "0.21.5", 484 | "@esbuild/linux-ia32": "0.21.5", 485 | "@esbuild/linux-loong64": "0.21.5", 486 | "@esbuild/linux-mips64el": "0.21.5", 487 | "@esbuild/linux-ppc64": "0.21.5", 488 | "@esbuild/linux-riscv64": "0.21.5", 489 | "@esbuild/linux-s390x": "0.21.5", 490 | "@esbuild/linux-x64": "0.21.5", 491 | "@esbuild/netbsd-x64": "0.21.5", 492 | "@esbuild/openbsd-x64": "0.21.5", 493 | "@esbuild/sunos-x64": "0.21.5", 494 | "@esbuild/win32-arm64": "0.21.5", 495 | "@esbuild/win32-ia32": "0.21.5", 496 | "@esbuild/win32-x64": "0.21.5" 497 | } 498 | } 499 | } 500 | } 501 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-metadata-release/index.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: "sqlite-vec now supports metadata columns and filtering" 3 | description: Metadata, partition key, and auxiliary column support in sqlite-vec 4 | created_at: 2024-11-20 5 | build: make dist 6 | share_photo_url: https://blog-static.alxg.xyz/Screenshot%202024-11-20%20at%208.26.35%E2%80%AFAM.png 7 | --- 8 | 9 | 10 | 11 | 12 | 13 | 14 |
    15 | 16 | > _tl;dr — [`sqlite-vec`](https://github.com/asg017/sqlite-vec), a SQLite 17 | > extension for vector search, now supports 18 | > [metadata columns](https://alexgarcia.xyz/sqlite-vec/features/vec0.html#metadata), 19 | > [auxiliary columns](https://alexgarcia.xyz/sqlite-vec/features/vec0.html#aux), 20 | > and 21 | > [partitioning](https://alexgarcia.xyz/sqlite-vec/features/vec0.html#partition-keys) 22 | > in vec0 virtual tables! You can use these to store metadata like `user_id` or 23 | > `created_at` fields, add additional `WHERE` clauses in KNN queries, and make 24 | > certain selective queries much faster. Try it out!_ 25 | 26 | 35 |
    36 | 37 | --- 38 | 39 | As of the latest 40 | [v0.1.6](https://github.com/asg017/sqlite-vec/releases/tag/v0.1.6) release of 41 | `sqlite-vec`, you can now store non-vector data in `vec0` virtual tables! For 42 | example: 43 | 44 | ```sql 45 | create virtual table vec_articles using vec0( 46 | 47 | article_id integer primary key, 48 | 49 | -- Vector text embedding of the `headline` column, with 384 dimensions 50 | headline_embedding float[384], 51 | 52 | -- Partition key, internally shard vector index on article published year 53 | year integer partition key, 54 | 55 | -- Metadata columns, can appear in `WHERE` clause of KNN queries 56 | news_desk text, 57 | word_count integer, 58 | pub_date text, 59 | 60 | -- Auxiliary columns, unindexed but fast lookups 61 | +headline text, 62 | +url text 63 | ); 64 | ``` 65 | 66 | Here we are storing a 67 | [New York Time article headlines dataset](https://www.kaggle.com/datasets/johnbandy/new-york-times-headlines) 68 | from the past 30 years, where we embed the headlines with 69 | [`mixedbread-ai/mxbai-embed-xsmall-v1`](https://huggingface.co/mixedbread-ai/mxbai-embed-xsmall-v1). 70 | 71 | If we wanted to see the closest related headlines to `'pandemic'` on article 72 | published in 2020 by the `'Sports'` or `'Business'` new desk with more than 500 73 | but less than 1000 words, we can perform a KNN query like so: 74 | 75 | ```sql 76 | select 77 | article_id, 78 | headline, 79 | news_desk, 80 | word_count, 81 | url, 82 | pub_date, 83 | distance 84 | from vec_articles 85 | where headline_embedding match lembed('pandemic') 86 | and k = 8 87 | and year = 2020 88 | and news_desk in ('Sports', 'Business') 89 | and word_count between 500 and 1000; 90 | ``` 91 | 92 |
    93 | 94 | ``` 95 | ┌────────────┬──────────────────────────────────────────────────────────────────────┬───────────┬────────────┬─────────────────────────────┬──────────────────────────┬───────────┐ 96 | │ article_id │ headline │ news_desk │ word_count │ url │ pub_date │ distance │ 97 | ├────────────┼──────────────────────────────────────────────────────────────────────┼───────────┼────────────┼─────────────────────────────┼──────────────────────────┼───────────┤ 98 | │ 2911716 │ The Pandemic’s Economic Damage Is Growing │ Business │ 910 │ https://www.nytimes.com/... │ 2020-07-07T18:12:40+0000 │ 0.8928120 │ 99 | │ 2892929 │ As Coronavirus Spreads, Olympics Face Ticking Clock and a Tough Call │ Sports │ 987 │ https://www.nytimes.com/... │ 2020-03-06T01:34:36+0000 │ 0.9608180 │ 100 | │ 2932041 │ The Pandemic Is Already Affecting Next Year’s Sports Schedule │ Sports │ 620 │ https://www.nytimes.com/... │ 2020-11-11T13:56:25+0000 │ 0.9802038 │ 101 | │ 2915381 │ The Week in Business: Getting Rich Off the Pandemic │ Business │ 814 │ https://www.nytimes.com/... │ 2020-08-02T11:00:03+0000 │ 1.0064692 │ 102 | │ 2896043 │ The Coronavirus and the Postponement of the Olympics, Explained │ Sports │ 798 │ https://www.nytimes.com/... │ 2020-03-25T17:45:58+0000 │ 1.0115833 │ 103 | │ 2898566 │ Robots Welcome to Take Over, as Pandemic Accelerates Automation │ Business │ 871 │ https://www.nytimes.com/... │ 2020-04-10T09:00:27+0000 │ 1.019637 │ 104 | │ 2898239 │ The Pandemic Feeds Tech Companies’ Power │ Business │ 784 │ https://www.nytimes.com/... │ 2020-04-08T16:43:13+0000 │ 1.0200014 │ 105 | │ 2929224 │ In M.L.S., the Pandemic Changes the Playoff Math │ Sports │ 859 │ https://www.nytimes.com/... │ 2020-10-29T17:09:10+0000 │ 1.0238885 │ 106 | └────────────┴──────────────────────────────────────────────────────────────────────┴───────────┴────────────┴─────────────────────────────┴──────────────────────────┴───────────┘ 107 | ``` 108 | 109 |
    110 | 111 | Here we used 112 | [`sqlite-lembed`](https://github.com/asg017/sqlite-lembed) to embed our query, 113 | but any other embeddings provider could be used! 114 | 115 | We can reference those metadata columns and parition key columns in the `WHERE` 116 | clause of the KNN query, and get the exact results we want! 117 | 118 | Now, what's the difference between metadata, partition key, and auxiliary 119 | columns? 120 | 121 | ## Metadata columns for `WHERE` clause filtering 122 | 123 | Metadata columns are declared with normal column declartions in the `vec0` 124 | constructor. Metadata columns are stored and indexed _alongside_ vectors, and 125 | can appear in the `WHERE` clause of KNN queries. 126 | 127 | ```sql 128 | create virtual table vec_articles using vec0( 129 | article_id integer primary key, 130 | headline_embedding float[384], 131 | news_desk text, 132 | word_count integer, 133 | pub_date text 134 | ); 135 | 136 | select 137 | article_id, 138 | headline, 139 | news_desk, 140 | word_count, 141 | pub_date, 142 | distance 143 | from vec_articles 144 | where headline_embedding match lembed('new york city housing') 145 | and k = 20 146 | and news_desk = 'Metro' 147 | and word_count < 1000 148 | and pub_date between '2004-01-20' and '2009-01-20'; 149 | ``` 150 | 151 |
    152 | 153 | ``` 154 | ┌────────────┬──────────────────────────────────────────────────────────────────────┬───────────┬────────────┬──────────────────────────┬────────────────────┐ 155 | │ article_id │ headline │ news_desk │ word_count │ pub_date │ distance │ 156 | ├────────────┼──────────────────────────────────────────────────────────────────────┼───────────┼────────────┼──────────────────────────┼────────────────────┤ 157 | │ 1717598 │ Manhattan: City to Expand Housing Program │ Metro │ 83 │ 2007-02-28T05:00:00+0000 │ 0.7736235857009888 │ 158 | │ 1607183 │ Manhattan: More Money for Housing │ Metro │ 96 │ 2006-06-16T04:00:00+0000 │ 0.7818768620491028 │ 159 | │ ... │ 160 | │ 1772158 │ Ask About New York Architecture, On Screen and Off │ Metro │ 241 │ 2007-09-17T18:25:57+0000 │ 0.930429220199585 │ 161 | │ 1673007 │ Manhattan: City Balances Budget for 26th Year │ Metro │ 87 │ 2006-11-01T05:00:00+0000 │ 0.9327330589294434 │ 162 | │ 1616702 │ Little Shift in Prices of Manhattan Apartments │ Metro │ 615 │ 2006-07-06T04:00:00+0000 │ 0.9354249238967896 │ 163 | └────────────┴──────────────────────────────────────────────────────────────────────┴───────────┴────────────┴──────────────────────────┴────────────────────┘ 164 | ``` 165 | 166 |
    167 | 168 | There we retrieved the 20 most related article headlines to 169 | `'new york city housing'`, published by the `'Metro'` news desk, with less than 170 | 1000 words, published during the George W Bush administration. 171 | 172 | Metadata columns can be boolean, integer, floats, or text values. More types 173 | like [BLOBs](https://github.com/asg017/sqlite-vec/issues/138), 174 | [dates](https://github.com/asg017/sqlite-vec/issues/139), and 175 | [UUID/ULIDs](https://github.com/asg017/sqlite-vec/issues/140) are coming soon! 176 | 177 | Only a subset of operators are supported during metadata filtering, including: 178 | 179 | - Equality constraints, ie `=` and `!=` 180 | - Comparison constraints, ie `>`, `>=`, `<`, `<=` 181 | - `column in (...)` constraints, only on `INTEGER` and `TEXT` columns on SQLite 182 | 3.38 or above 183 | 184 | Notably absent: `REGEXP`, `LIKE`, `GLOB`, and other custom scalar functions. 185 | Also 186 | [`NULL` values are not supported yet](https://github.com/asg017/sqlite-vec/issues/141), 187 | 188 | ## Partition keys for faster `WHERE` clause filtering 189 | 190 | Now the above query was actually a bit slow! There are 3 million rows in the 191 | table, and metadata filters need to visit every single row to do a comparison. 192 | Metadata comparison are quite fast and built for fast filtering, but they have 193 | their limits. 194 | 195 | But notice how we only wanted a small subset of values – 196 | `between '2004-01-20' and '2009-01-20'` is only 5 years out of 30 years of data. 197 | We can tell the `vec0` virtual table to internally shard the vector index on a 198 | given key, using partition keys! 199 | 200 | ```sql 201 | create virtual table vec_articles using vec0( 202 | article_id integer primary key, 203 | headline_embedding float[384], 204 | 205 | -- shard the vector index based on published year 206 | year integer partition key, 207 | 208 | news_desk text, 209 | word_count integer, 210 | pub_date text 211 | ); 212 | 213 | select 214 | article_id, 215 | headline, 216 | news_desk, 217 | word_count, 218 | pub_date, 219 | distance 220 | from vec_articles 221 | where headline_embedding match lembed('new york city housing') 222 | and k = 20 223 | -- narrow search to these years only 224 | and year between 2004 and 2009 225 | and news_desk = 'Metro' 226 | and word_count < 1000 227 | -- finer filtering for exact dates we care about 228 | and pub_date between '2004-01-20' and '2009-01-20'; 229 | ``` 230 | 231 | This KNN query returns the same exact results as the one above - but is 3x 232 | faster! This is because internally, vectors are stored based on the `year` value 233 | of its row. In that KNN query, `sqlite-vec` will recognize constraints on 234 | partition keys, and quickly pre-filter rows before any vectors are compared. 235 | 236 | But beware! It's easy to accidentally over-shard a vector index on the wrong 237 | values and cause performance issues. Partition keys are great for date-based 238 | items like `year` or `month`, particulary when each unique partition key value 239 | has 100's or 1000's of vectors. They are also great for user IDs or document 240 | IDs, for "per-user" or "per-document" vector indexes. 241 | 242 | Partition key columns can only be `TEXT` or `INTEGER` values, file an issue if 243 | you want to see some other type support. Currently `column in (...)` constraints 244 | are not supported for partition key columns, 245 | [but will be soon](https://github.com/asg017/sqlite-vec/issues/142)! 246 | 247 | ## Auxiliary columns 248 | 249 | Some columns never need to be indexed! You can always store addtionally 250 | `SELECT`-only metadata in separate tables and do a `JOIN` yourself, or you can 251 | use auxiliary columns: 252 | 253 | ```sql 254 | create virtual table vec_articles using vec0( 255 | article_id integer primary key, 256 | headline_embedding float[384], 257 | +headline text, 258 | +url text 259 | ); 260 | 261 | select 262 | article_id, 263 | headline, 264 | url, 265 | distance 266 | from vec_articles 267 | where headline_embedding match lembed('dodgers game') 268 | and k = 20; 269 | ``` 270 | 271 |
    272 | 273 | ``` 274 | ┌────────────┬─────────────────────────────────────────────────────────────────────────────────────┬───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┬────────────────────┐ 275 | │ article_id │ headline │ url │ distance │ 276 | ├────────────┼─────────────────────────────────────────────────────────────────────────────────────┼───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┼────────────────────┤ 277 | │ 1896278 │ Attention Dodgers Fans: There’s a Game Tonight │ https://bats.blogs.nytimes.com/2008/10/15/attention-dodgers-fans-theres-a-game-tonight/ │ 0.6733786463737488 │ 278 | │ 2556896 │ Dodgers, in Flurry of Activity, Move to Revamp Their Infield │ https://www.nytimes.com/2014/12/11/sports/baseball/mlb-jimmy-rollins.html │ 0.7796685099601746 │ 279 | │ 2382487 │ Keeping Up With the Dodgers │ https://www.nytimes.com/2012/12/15/sports/angels-keeping-up-with-the-dodgers-leading-off.html │ 0.7849781513214111 │ 280 | │ 2585169 │ New Life for the Dodgers’ Old Digs │ https://www.nytimes.com/slideshow/2015/04/19/sports/baseball/20150419DODGERTOWN.html │ 0.7894293665885925 │ 281 | │ 1032111 │ Not Dodgers II, but It's Baseball; The Game Is Back in Brooklyn, on a Smaller Scale │ https://www.nytimes.com/2001/06/23/nyregion/not-dodgers-ii-but-it-s-baseball-the-game-is-back-in-brooklyn-on-a-smaller-scale.html │ 0.7978747487068176 │ 282 | └────────────┴─────────────────────────────────────────────────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┴────────────────────┘ 283 | ``` 284 | 285 |
    286 | 287 | Auxiliary columns are denoted by a `+` prefix in the column definition, modeled 288 | after 289 | [the same feature in the SQLite R*Tree extension](https://www.sqlite.org/rtree.html#auxiliary_columns). 290 | These columns are unindex, stored in a separate internal table and `JOIN`'ed at 291 | `SELECT` time. They _cannot_ appear in a KNN `WHERE` query, as performance would 292 | worsen dramatically. 293 | 294 | But it saves you from dealing with additional `JOIN`s yourself! They are 295 | especially great for longer `TEXT` or `BLOB` values. 296 | 297 | ## Roadmap and the future of `sqlite-vec` 298 | 299 | Metadata column support is the biggest update to `sqlite-vec` since the initial 300 | [`v0.1.0` launch 3 months ago](https://alexgarcia.xyz/blog/2024/sqlite-vec-stable-release/index.html), 301 | but I have a lot planned for the project! 302 | 303 | First off: **ANN indexes.** The `vec0` virtual table is brute-force only, which 304 | really slows down KNN queries on larger datasets. There are strategies like 305 | [binary quantization](https://alexgarcia.xyz/sqlite-vec/guides/binary-quant.html) 306 | or 307 | [Matryoshka embeddings](https://alexgarcia.xyz/sqlite-vec/guides/matryoshka.html) 308 | that can help, but `sqlite-vec` won't be fast until ANN indexes are supported. 309 | 310 | I delayed working on ANN indexes until metadata columns were supported, because 311 | its much easier to build an ANN index with metaddata filtering on day 1 than it 312 | is to retroactively try to support them. I think this was the right call — 313 | metadata columns are hard! Follow 314 | [issue #25](https://github.com/asg017/sqlite-vec/issues/25) for future update on 315 | this! 316 | 317 | Next: **Quantizers.** Currently `sqlite-vec` only supported simple binary 318 | quantization and scalar quantization with `int8` vectors. But I want to support 319 | `float16`, `float8`, "smarter" binary quantization (ie custom thresholds instead 320 | of just `> 0`), and other techniques that have come about the last few months. 321 | This will also help support ANN indexes, as many of them rely on vector 322 | compression for fast queries. 323 | 324 | There's also a ton of **performance work** that `sqlite-vec` needs, especially 325 | with these new metadata column features. This initial release was more of a 326 | "make it work" and not "make it fast", so expect much faster metadata filtering 327 | in upcoming releases! 328 | 329 | Sister projects [`sqlite-lembed`](https://github.com/asg017/sqlite-lembed) and 330 | [`sqlite-rembed`](https://github.com/asg017/sqlite-rembed) also need a ton of 331 | love, they both have some older PRs that need merging. Expect releases of both 332 | of these projects very soon! 333 | 334 | And finally, **a ton of smaller integrations**! For example, Rody Davis 335 | [submitted Dart and Flutter bindings](https://github.com/asg017/sqlite-vec/pull/119) 336 | that I have not yet merged, Oscar Franco contributed 337 | [Android and iOS bindings](https://github.com/asg017/sqlite-vec/pull/91) that 338 | needs love, and 339 | [Pyodide support is on the horizon](https://github.com/asg017/sqlite-vec/issues/135). 340 | -------------------------------------------------------------------------------- /posts/2024/sqlite-vec-stable-release/package-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "sql-vector-search-languages", 3 | "version": "1.0.0", 4 | "lockfileVersion": 3, 5 | "requires": true, 6 | "packages": { 7 | "": { 8 | "name": "sql-vector-search-languages", 9 | "version": "1.0.0", 10 | "license": "ISC", 11 | "dependencies": { 12 | "d3-selection": "^3.0.0", 13 | "d3-transition": "^3.0.1", 14 | "esbuild": "^0.21.3", 15 | "lite-youtube-embed": "^0.3.2" 16 | } 17 | }, 18 | "node_modules/@esbuild/aix-ppc64": { 19 | "version": "0.21.5", 20 | "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", 21 | "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", 22 | "cpu": [ 23 | "ppc64" 24 | ], 25 | "license": "MIT", 26 | "optional": true, 27 | "os": [ 28 | "aix" 29 | ], 30 | "engines": { 31 | "node": ">=12" 32 | } 33 | }, 34 | "node_modules/@esbuild/android-arm": { 35 | "version": "0.21.5", 36 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", 37 | "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", 38 | "cpu": [ 39 | "arm" 40 | ], 41 | "license": "MIT", 42 | "optional": true, 43 | "os": [ 44 | "android" 45 | ], 46 | "engines": { 47 | "node": ">=12" 48 | } 49 | }, 50 | "node_modules/@esbuild/android-arm64": { 51 | "version": "0.21.5", 52 | "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", 53 | "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", 54 | "cpu": [ 55 | "arm64" 56 | ], 57 | "license": "MIT", 58 | "optional": true, 59 | "os": [ 60 | "android" 61 | ], 62 | "engines": { 63 | "node": ">=12" 64 | } 65 | }, 66 | "node_modules/@esbuild/android-x64": { 67 | "version": "0.21.5", 68 | "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", 69 | "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", 70 | "cpu": [ 71 | "x64" 72 | ], 73 | "license": "MIT", 74 | "optional": true, 75 | "os": [ 76 | "android" 77 | ], 78 | "engines": { 79 | "node": ">=12" 80 | } 81 | }, 82 | "node_modules/@esbuild/darwin-arm64": { 83 | "version": "0.21.5", 84 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", 85 | "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", 86 | "cpu": [ 87 | "arm64" 88 | ], 89 | "license": "MIT", 90 | "optional": true, 91 | "os": [ 92 | "darwin" 93 | ], 94 | "engines": { 95 | "node": ">=12" 96 | } 97 | }, 98 | "node_modules/@esbuild/darwin-x64": { 99 | "version": "0.21.5", 100 | "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", 101 | "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", 102 | "cpu": [ 103 | "x64" 104 | ], 105 | "license": "MIT", 106 | "optional": true, 107 | "os": [ 108 | "darwin" 109 | ], 110 | "engines": { 111 | "node": ">=12" 112 | } 113 | }, 114 | "node_modules/@esbuild/freebsd-arm64": { 115 | "version": "0.21.5", 116 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", 117 | "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", 118 | "cpu": [ 119 | "arm64" 120 | ], 121 | "license": "MIT", 122 | "optional": true, 123 | "os": [ 124 | "freebsd" 125 | ], 126 | "engines": { 127 | "node": ">=12" 128 | } 129 | }, 130 | "node_modules/@esbuild/freebsd-x64": { 131 | "version": "0.21.5", 132 | "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", 133 | "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", 134 | "cpu": [ 135 | "x64" 136 | ], 137 | "license": "MIT", 138 | "optional": true, 139 | "os": [ 140 | "freebsd" 141 | ], 142 | "engines": { 143 | "node": ">=12" 144 | } 145 | }, 146 | "node_modules/@esbuild/linux-arm": { 147 | "version": "0.21.5", 148 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", 149 | "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", 150 | "cpu": [ 151 | "arm" 152 | ], 153 | "license": "MIT", 154 | "optional": true, 155 | "os": [ 156 | "linux" 157 | ], 158 | "engines": { 159 | "node": ">=12" 160 | } 161 | }, 162 | "node_modules/@esbuild/linux-arm64": { 163 | "version": "0.21.5", 164 | "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", 165 | "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", 166 | "cpu": [ 167 | "arm64" 168 | ], 169 | "license": "MIT", 170 | "optional": true, 171 | "os": [ 172 | "linux" 173 | ], 174 | "engines": { 175 | "node": ">=12" 176 | } 177 | }, 178 | "node_modules/@esbuild/linux-ia32": { 179 | "version": "0.21.5", 180 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", 181 | "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", 182 | "cpu": [ 183 | "ia32" 184 | ], 185 | "license": "MIT", 186 | "optional": true, 187 | "os": [ 188 | "linux" 189 | ], 190 | "engines": { 191 | "node": ">=12" 192 | } 193 | }, 194 | "node_modules/@esbuild/linux-loong64": { 195 | "version": "0.21.5", 196 | "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", 197 | "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", 198 | "cpu": [ 199 | "loong64" 200 | ], 201 | "license": "MIT", 202 | "optional": true, 203 | "os": [ 204 | "linux" 205 | ], 206 | "engines": { 207 | "node": ">=12" 208 | } 209 | }, 210 | "node_modules/@esbuild/linux-mips64el": { 211 | "version": "0.21.5", 212 | "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", 213 | "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", 214 | "cpu": [ 215 | "mips64el" 216 | ], 217 | "license": "MIT", 218 | "optional": true, 219 | "os": [ 220 | "linux" 221 | ], 222 | "engines": { 223 | "node": ">=12" 224 | } 225 | }, 226 | "node_modules/@esbuild/linux-ppc64": { 227 | "version": "0.21.5", 228 | "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", 229 | "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", 230 | "cpu": [ 231 | "ppc64" 232 | ], 233 | "license": "MIT", 234 | "optional": true, 235 | "os": [ 236 | "linux" 237 | ], 238 | "engines": { 239 | "node": ">=12" 240 | } 241 | }, 242 | "node_modules/@esbuild/linux-riscv64": { 243 | "version": "0.21.5", 244 | "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", 245 | "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", 246 | "cpu": [ 247 | "riscv64" 248 | ], 249 | "license": "MIT", 250 | "optional": true, 251 | "os": [ 252 | "linux" 253 | ], 254 | "engines": { 255 | "node": ">=12" 256 | } 257 | }, 258 | "node_modules/@esbuild/linux-s390x": { 259 | "version": "0.21.5", 260 | "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", 261 | "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", 262 | "cpu": [ 263 | "s390x" 264 | ], 265 | "license": "MIT", 266 | "optional": true, 267 | "os": [ 268 | "linux" 269 | ], 270 | "engines": { 271 | "node": ">=12" 272 | } 273 | }, 274 | "node_modules/@esbuild/linux-x64": { 275 | "version": "0.21.5", 276 | "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", 277 | "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", 278 | "cpu": [ 279 | "x64" 280 | ], 281 | "license": "MIT", 282 | "optional": true, 283 | "os": [ 284 | "linux" 285 | ], 286 | "engines": { 287 | "node": ">=12" 288 | } 289 | }, 290 | "node_modules/@esbuild/netbsd-x64": { 291 | "version": "0.21.5", 292 | "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", 293 | "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", 294 | "cpu": [ 295 | "x64" 296 | ], 297 | "license": "MIT", 298 | "optional": true, 299 | "os": [ 300 | "netbsd" 301 | ], 302 | "engines": { 303 | "node": ">=12" 304 | } 305 | }, 306 | "node_modules/@esbuild/openbsd-x64": { 307 | "version": "0.21.5", 308 | "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", 309 | "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", 310 | "cpu": [ 311 | "x64" 312 | ], 313 | "license": "MIT", 314 | "optional": true, 315 | "os": [ 316 | "openbsd" 317 | ], 318 | "engines": { 319 | "node": ">=12" 320 | } 321 | }, 322 | "node_modules/@esbuild/sunos-x64": { 323 | "version": "0.21.5", 324 | "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", 325 | "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", 326 | "cpu": [ 327 | "x64" 328 | ], 329 | "license": "MIT", 330 | "optional": true, 331 | "os": [ 332 | "sunos" 333 | ], 334 | "engines": { 335 | "node": ">=12" 336 | } 337 | }, 338 | "node_modules/@esbuild/win32-arm64": { 339 | "version": "0.21.5", 340 | "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", 341 | "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", 342 | "cpu": [ 343 | "arm64" 344 | ], 345 | "license": "MIT", 346 | "optional": true, 347 | "os": [ 348 | "win32" 349 | ], 350 | "engines": { 351 | "node": ">=12" 352 | } 353 | }, 354 | "node_modules/@esbuild/win32-ia32": { 355 | "version": "0.21.5", 356 | "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", 357 | "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", 358 | "cpu": [ 359 | "ia32" 360 | ], 361 | "license": "MIT", 362 | "optional": true, 363 | "os": [ 364 | "win32" 365 | ], 366 | "engines": { 367 | "node": ">=12" 368 | } 369 | }, 370 | "node_modules/@esbuild/win32-x64": { 371 | "version": "0.21.5", 372 | "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", 373 | "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", 374 | "cpu": [ 375 | "x64" 376 | ], 377 | "license": "MIT", 378 | "optional": true, 379 | "os": [ 380 | "win32" 381 | ], 382 | "engines": { 383 | "node": ">=12" 384 | } 385 | }, 386 | "node_modules/d3-color": { 387 | "version": "3.1.0", 388 | "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz", 389 | "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==", 390 | "license": "ISC", 391 | "engines": { 392 | "node": ">=12" 393 | } 394 | }, 395 | "node_modules/d3-dispatch": { 396 | "version": "3.0.1", 397 | "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz", 398 | "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==", 399 | "license": "ISC", 400 | "engines": { 401 | "node": ">=12" 402 | } 403 | }, 404 | "node_modules/d3-ease": { 405 | "version": "3.0.1", 406 | "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz", 407 | "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==", 408 | "license": "BSD-3-Clause", 409 | "engines": { 410 | "node": ">=12" 411 | } 412 | }, 413 | "node_modules/d3-interpolate": { 414 | "version": "3.0.1", 415 | "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz", 416 | "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==", 417 | "license": "ISC", 418 | "dependencies": { 419 | "d3-color": "1 - 3" 420 | }, 421 | "engines": { 422 | "node": ">=12" 423 | } 424 | }, 425 | "node_modules/d3-selection": { 426 | "version": "3.0.0", 427 | "resolved": "https://registry.npmjs.org/d3-selection/-/d3-selection-3.0.0.tgz", 428 | "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", 429 | "license": "ISC", 430 | "engines": { 431 | "node": ">=12" 432 | } 433 | }, 434 | "node_modules/d3-timer": { 435 | "version": "3.0.1", 436 | "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz", 437 | "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==", 438 | "license": "ISC", 439 | "engines": { 440 | "node": ">=12" 441 | } 442 | }, 443 | "node_modules/d3-transition": { 444 | "version": "3.0.1", 445 | "resolved": "https://registry.npmjs.org/d3-transition/-/d3-transition-3.0.1.tgz", 446 | "integrity": "sha512-ApKvfjsSR6tg06xrL434C0WydLr7JewBB3V+/39RMHsaXTOG0zmt/OAXeng5M5LBm0ojmxJrpomQVZ1aPvBL4w==", 447 | "license": "ISC", 448 | "dependencies": { 449 | "d3-color": "1 - 3", 450 | "d3-dispatch": "1 - 3", 451 | "d3-ease": "1 - 3", 452 | "d3-interpolate": "1 - 3", 453 | "d3-timer": "1 - 3" 454 | }, 455 | "engines": { 456 | "node": ">=12" 457 | }, 458 | "peerDependencies": { 459 | "d3-selection": "2 - 3" 460 | } 461 | }, 462 | "node_modules/esbuild": { 463 | "version": "0.21.5", 464 | "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", 465 | "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", 466 | "hasInstallScript": true, 467 | "license": "MIT", 468 | "bin": { 469 | "esbuild": "bin/esbuild" 470 | }, 471 | "engines": { 472 | "node": ">=12" 473 | }, 474 | "optionalDependencies": { 475 | "@esbuild/aix-ppc64": "0.21.5", 476 | "@esbuild/android-arm": "0.21.5", 477 | "@esbuild/android-arm64": "0.21.5", 478 | "@esbuild/android-x64": "0.21.5", 479 | "@esbuild/darwin-arm64": "0.21.5", 480 | "@esbuild/darwin-x64": "0.21.5", 481 | "@esbuild/freebsd-arm64": "0.21.5", 482 | "@esbuild/freebsd-x64": "0.21.5", 483 | "@esbuild/linux-arm": "0.21.5", 484 | "@esbuild/linux-arm64": "0.21.5", 485 | "@esbuild/linux-ia32": "0.21.5", 486 | "@esbuild/linux-loong64": "0.21.5", 487 | "@esbuild/linux-mips64el": "0.21.5", 488 | "@esbuild/linux-ppc64": "0.21.5", 489 | "@esbuild/linux-riscv64": "0.21.5", 490 | "@esbuild/linux-s390x": "0.21.5", 491 | "@esbuild/linux-x64": "0.21.5", 492 | "@esbuild/netbsd-x64": "0.21.5", 493 | "@esbuild/openbsd-x64": "0.21.5", 494 | "@esbuild/sunos-x64": "0.21.5", 495 | "@esbuild/win32-arm64": "0.21.5", 496 | "@esbuild/win32-ia32": "0.21.5", 497 | "@esbuild/win32-x64": "0.21.5" 498 | } 499 | }, 500 | "node_modules/lite-youtube-embed": { 501 | "version": "0.3.2", 502 | "resolved": "https://registry.npmjs.org/lite-youtube-embed/-/lite-youtube-embed-0.3.2.tgz", 503 | "integrity": "sha512-b1dgKyF4PHhinonmr3PB172Nj0qQgA/7DE9EmeIXHR1ksnFEC2olWjNJyJGdsN2cleKHRjjsmrziKlwXtPlmLQ==", 504 | "license": "Apache-2.0" 505 | } 506 | } 507 | } 508 | --------------------------------------------------------------------------------