├── .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 |
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 |
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 |
--------------------------------------------------------------------------------