docs and fuzz

This commit is contained in:
Alex Garcia 2024-07-16 22:28:15 -07:00
parent ff30ed3df3
commit f4fe53e584
8 changed files with 1312 additions and 103 deletions

View file

@ -4,7 +4,6 @@ import (
"bytes"
_ "embed"
"encoding/binary"
"fmt"
"log"
_ "github.com/asg017/sqlite-vec-ncruces-bindings"
@ -35,7 +34,7 @@ func main() {
stmt.Step()
fmt.Printf("sqlite_version=%s, vec_version=%s\n", stmt.ColumnText(0), stmt.ColumnText(1))
log.Printf("sqlite_version=%s, vec_version=%s\n", stmt.ColumnText(0), stmt.ColumnText(1))
err = db.Exec("CREATE VIRTUAL TABLE vec_items USING vec0(embedding float[4])")
@ -96,7 +95,7 @@ func main() {
for stmt.Step() {
rowid := stmt.ColumnInt64(0)
distance := stmt.ColumnFloat(1)
fmt.Printf("rowid=%d, distance=%f\n", rowid, distance)
log.Printf("rowid=%d, distance=%f\n", rowid, distance)
}
if err := stmt.Err(); err != nil {
log.Fatal(err)

View file

@ -1,9 +1,19 @@
sections:
meta: Meta functions
constructor: Vector constructor functions
op: Vector operation functions
distance: Vector distance functions
quantize: Vector quantization functions
meta:
title: Meta
desc: TODO
constructors:
title: Constructors
desc: TODO
op:
title: Operations
desc: TODO
distance:
title: Distance functions
desc: TODO
quantization:
title: Quantization
desc: TODO
functions:
vec_version:
params: []
@ -15,34 +25,32 @@ functions:
section: meta
desc: Returns debugging information of the current `sqlite-vec` installation.
example: select vec_debug();
vec_bit:
params: [vector]
section: constructor
desc: Creates a binary vector from a BLOB.
example:
- select vec_bit(X'F0');
- select subtype(vec_bit(X'F0'));
- select vec_to_json(vec_bit(X'F0'));
vec_f32:
params: [vector]
section: constructor
section: constructors
desc: |
Creates a float vector from a BLOB or JSON text. If a BLOB is provided,
the length must be divisible by 4, as a float takes up 4 bytes of space each.
The returned value is a BLOB with 4 bytes per element, with a special [subtype](https://www.sqlite.org/c3ref/result_subtype.html)
of `223`.
example:
- select vec_float32('[.1, .2, .3, 4]');
- select subtype(vec_float32('[.1, .2, .3, 4]'));
- select vec_float32(X'AABBCCDD');
- select vec_to_json(vec_float32(X'AABBCCDD'));
- select vec_float32(X'AA');
- select vec_f32('[.1, .2, .3, 4]');
- select subtype(vec_f32('[.1, .2, .3, 4]'));
- select vec_f32(X'AABBCCDD');
- select vec_to_json(vec_f32(X'AABBCCDD'));
- select vec_f32(X'AA');
vec_int8:
params: [vector]
section: constructor
desc: |
section: constructors
desc: |
Creates a 8-bit integer vector from a BLOB or JSON text. If a BLOB is provided,
the length must be divisible by 4, as a float takes up 4 bytes of space each.
If JSON text is provided, each element must be an integer between -128 and 127 inclusive.
The returned value is a BLOB with 1 byte per element, with a special [subtype](https://www.sqlite.org/c3ref/result_subtype.html)
of `225`.
example:
- select vec_int8('[1, 2, 3, 4]');
- select subtype(vec_int8('[1, 2, 3, 4]'));
@ -50,14 +58,44 @@ functions:
- select vec_to_json(vec_int8(X'AABBCCDD'));
- select vec_int8('[999]');
vec_bit:
params: [vector]
section: constructors
desc: |
Creates a binary vector from a BLOB.
The returned value is a BLOB with 4 bytes per element, with a special [subtype](https://www.sqlite.org/c3ref/result_subtype.html)
of `224`.
example:
- select vec_bit(X'F0');
- select subtype(vec_bit(X'F0'));
- select vec_to_json(vec_bit(X'F0'));
vec_length:
params: [vector]
section: op
desc: |
Returns the number of elements in the given vector.
The vector can be `JSON`, `BLOB`, or the result of a [constructor function](#constructors).
This function will return an error if `vector` is invalid.
example:
- select vec_length('[.1, .2]');
- select vec_length(X'AABBCCDD');
- select vec_length(vec_int8(X'AABBCCDD'));
- select vec_length(vec_bit(X'AABBCCDD'));
- select vec_length(X'CCDD');
vec_add:
params: [a, b]
section: op
desc: |
Adds each element in vector `a` with vector `b`, returning a new vector `c`. Both vectors
must be of the same type, and can only be a `float32` or `int8` vector.
example: |
- select vec_add(
Adds every element in vector `a` with vector `b`, returning a new vector `c`. Both vectors
must be of the same type and same length. Only `float32` and `int8` vectors are supported.
An error is raised if either `a` or `b` are invalid, or if they are not the same type or same length.
example:
- |
select vec_add(
'[.1, .2, .3]',
'[.4, .5, .6]'
);
@ -70,89 +108,101 @@ functions:
);
- |
select vec_to_json(
vec_int8('[1, 2, 3]'),
vec_int8('[4, 5, 6]')
)
vec_length:
params: []
section: op
desc: x
example: x
vec_normalize:
params: []
section: op
desc: x
example: x
vec_slice:
params: []
section: op
desc: x
example: x
vec_add(
vec_int8('[1, 2, 3]'),
vec_int8('[4, 5, 6]')
)
);
- select vec_add('[.1]', vec_int8('[1]'));
- select vec_add(vec_bit(X'AA'), vec_bit(X'BB'));
vec_sub:
params: []
params: [a, b]
section: op
desc: x
example: x
example:
- |
select vec_sub(
'[.1, .2, .3]',
'[.4, .5, .6]'
);
- |
select vec_to_json(
vec_sub(
'[.1, .2, .3]',
'[.4, .5, .6]'
)
);
- |
select vec_to_json(
vec_sub(
vec_int8('[1, 2, 3]'),
vec_int8('[4, 5, 6]')
)
);
- select vec_sub('[.1]', vec_int8('[1]'));
- select vec_sub(vec_bit(X'AA'), vec_bit(X'BB'));
vec_normalize:
params: [vector]
section: op
desc: x
example: select 'todo';
vec_slice:
params: [vector, start, end]
section: op
desc: x
example: select 'todo';
vec_to_json:
params: []
params: [vector]
section: op
desc: x
example: x
example: select 'todo';
vec_distance_cosine:
params: []
params: [a, b]
section: distance
desc: x
example: x
example: select 'todo';
vec_distance_hamming:
params: []
params: [a, b]
section: distance
desc: x
example: x
example: select 'todo';
vec_distance_l2:
params: []
params: [a, b]
section: distance
desc: x
example: x
example: select 'todo';
vec_quantize_binary:
params: []
params: [vector]
section: quantization
desc: x
example: x
example: select 'todo';
vec_quantize_i8:
params: []
params: [vector, "[start]", "[end]"]
section: quantization
desc: x
example: x
vec_quantize_i8:
params: []
section: quantization
desc: x
example: x
table_functions:
vec_each:
columns: [rowid, value]
inputs: ["vector"]
desc:
example:
vec_npy_each:
columns: [rowid, vector]
inputs: ["input"]
desc:
example:
virtual_tables:
vec0:
desc:
example:
entrypoints:
sqlite3_vec_init: {}
sqlite3_vec_fs_read_init: {}
compile_options:
- SQLITE_VEC_ENABLE_AVX
- SQLITE_VEC_ENABLE_NEON
- SQLITE_VEC_OMIT_FS
example: select 'todo';
#table_functions:
# vec_each:
# columns: [rowid, value]
# inputs: ["vector"]
# desc:
# example:
# vec_npy_each:
# columns: [rowid, vector]
# inputs: ["input"]
# desc:
# example:
#virtual_tables:
# vec0:
# desc:
# example:
#entrypoints:
# sqlite3_vec_init: {}
# sqlite3_vec_fs_read_init: {}
#compile_options:
# - SQLITE_VEC_ENABLE_AVX
# - SQLITE_VEC_ENABLE_NEON
# - SQLITE_VEC_OMIT_FS
#

View file

@ -0,0 +1,324 @@
# API Reference
::: warning
sqlite-vec is pre-v1, so expect breaking changes.
:::
[[toc]]
## Meta {#meta}
TODO
### `vec_version()` {#vec_version}
Returns a version string of the current `sqlite-vec` installation.
```sql
select vec_version();
-- 'v0.0.1-alpha.33'
```
### `vec_debug()` {#vec_debug}
Returns debugging information of the current `sqlite-vec` installation.
```sql
select vec_debug();
/*
'Version: v0.0.1-alpha.33
Date: 2024-07-14T14:24:27Z-0700
Commit: 18e33edf143cafd881643965a559cd0259ab0666
Build flags: avx '
*/
```
## Constructors {#constructors}
TODO
### `vec_f32(vector)` {#vec_f32}
Creates a float vector from a BLOB or JSON text. If a BLOB is provided,
the length must be divisible by 4, as a float takes up 4 bytes of space each.
The returned value is a BLOB with 4 bytes per element, with a special [subtype](https://www.sqlite.org/c3ref/result_subtype.html)
of `223`.
```sql
select vec_f32('[.1, .2, .3, 4]');
-- X'CDCCCC3DCDCC4C3E9A99993E008040'
select subtype(vec_f32('[.1, .2, .3, 4]'));
-- 223
select vec_f32(X'AABBCCDD');
-- X'AABBCCDD'
select vec_to_json(vec_f32(X'AABBCCDD'));
-- '[-1844071490169864000.000000]'
select vec_f32(X'AA');
-- ❌ invalid float32 vector BLOB length. Must be divisible by 4, found 1
```
### `vec_int8(vector)` {#vec_int8}
Creates a 8-bit integer vector from a BLOB or JSON text. If a BLOB is provided,
the length must be divisible by 4, as a float takes up 4 bytes of space each.
If JSON text is provided, each element must be an integer between -128 and 127 inclusive.
The returned value is a BLOB with 1 byte per element, with a special [subtype](https://www.sqlite.org/c3ref/result_subtype.html)
of `225`.
```sql
select vec_int8('[1, 2, 3, 4]');
-- X'1234'
select subtype(vec_int8('[1, 2, 3, 4]'));
-- 225
select vec_int8(X'AABBCCDD');
-- X'AABBCCDD'
select vec_to_json(vec_int8(X'AABBCCDD'));
-- '[-86,-69,-52,-35]'
select vec_int8('[999]');
-- ❌ JSON parsing error: value out of range for int8
```
### `vec_bit(vector)` {#vec_bit}
Creates a binary vector from a BLOB.
The returned value is a BLOB with 4 bytes per element, with a special [subtype](https://www.sqlite.org/c3ref/result_subtype.html)
of `224`.
```sql
select vec_bit(X'F0');
-- X'F0'
select subtype(vec_bit(X'F0'));
-- 224
select vec_to_json(vec_bit(X'F0'));
-- '[0,0,0,0,1,1,1,1]'
```
## Operations {#op}
TODO
### `vec_length(vector)` {#vec_length}
Returns the number of elements in the given vector.
The vector can be `JSON`, `BLOB`, or the result of a [constructor function](#constructors).
This function will return an error if `vector` is invalid.
```sql
select vec_length('[.1, .2]');
-- 2
select vec_length(X'AABBCCDD');
-- 1
select vec_length(vec_int8(X'AABBCCDD'));
-- 4
select vec_length(vec_bit(X'AABBCCDD'));
-- 32
select vec_length(X'CCDD');
-- ❌ invalid float32 vector BLOB length. Must be divisible by 4, found 2
```
### `vec_add(a, b)` {#vec_add}
Adds every element in vector `a` with vector `b`, returning a new vector `c`. Both vectors
must be of the same type and same length. Only `float32` and `int8` vectors are supported.
An error is raised if either `a` or `b` are invalid, or if they are not the same type or same length.
```sql
select vec_add(
'[.1, .2, .3]',
'[.4, .5, .6]'
);
-- X'0003F3333333F6766663F'
select vec_to_json(
vec_add(
'[.1, .2, .3]',
'[.4, .5, .6]'
)
);
-- '[0.500000,0.700000,0.900000]'
select vec_to_json(
vec_add(
vec_int8('[1, 2, 3]'),
vec_int8('[4, 5, 6]')
)
);
-- '[5,7,9]'
select vec_add('[.1]', vec_int8('[1]'));
-- ❌ Vector type mistmatch. First vector has type float32, while the second has type int8.
select vec_add(vec_bit(X'AA'), vec_bit(X'BB'));
-- ❌ Cannot add two bitvectors together.
```
### `vec_sub(a, b)` {#vec_sub}
x
```sql
select vec_sub(
'[.1, .2, .3]',
'[.4, .5, .6]'
);
-- X'9A9999BE9A9999BE9A9999BE'
select vec_to_json(
vec_sub(
'[.1, .2, .3]',
'[.4, .5, .6]'
)
);
-- '[-0.300000,-0.300000,-0.300000]'
select vec_to_json(
vec_sub(
vec_int8('[1, 2, 3]'),
vec_int8('[4, 5, 6]')
)
);
-- '[-3,-3,-3]'
select vec_sub('[.1]', vec_int8('[1]'));
-- ❌ Vector type mistmatch. First vector has type float32, while the second has type int8.
select vec_sub(vec_bit(X'AA'), vec_bit(X'BB'));
-- ❌ Cannot subtract two bitvectors together.
```
### `vec_normalize(vector)` {#vec_normalize}
x
```sql
select 'todo';
-- 'todo'
```
### `vec_slice(vector, start, end)` {#vec_slice}
x
```sql
select 'todo';
-- 'todo'
```
### `vec_to_json(vector)` {#vec_to_json}
x
```sql
select 'todo';
-- 'todo'
```
## Distance functions {#distance}
TODO
### `vec_distance_cosine(a, b)` {#vec_distance_cosine}
x
```sql
select 'todo';
-- 'todo'
```
### `vec_distance_hamming(a, b)` {#vec_distance_hamming}
x
```sql
select 'todo';
-- 'todo'
```
### `vec_distance_l2(a, b)` {#vec_distance_l2}
x
```sql
select 'todo';
-- 'todo'
```
## Quantization {#quantization}
TODO
### `vec_quantize_binary(vector)` {#vec_quantize_binary}
x
```sql
select 'todo';
-- 'todo'
```
### `vec_quantize_i8(vector, [start], [end])` {#vec_quantize_i8}
x
```sql
select 'todo';
-- 'todo'
```

194
site/build-ref.mjs Normal file
View file

@ -0,0 +1,194 @@
import Database from "better-sqlite3";
import { load } from "js-yaml";
import { fileURLToPath } from "node:url";
import { resolve, dirname } from "node:path";
import { readFileSync, writeFileSync } from "node:fs";
import * as v from "valibot";
import { table } from "table";
const REF_PATH = resolve(
dirname(fileURLToPath(import.meta.url)),
"../reference.yaml"
);
const EXT_PATH = resolve(
dirname(fileURLToPath(import.meta.url)),
"../dist/vec0"
);
const DocSchema = v.object({
sections: v.record(
v.string(),
v.object({
title: v.string(),
desc: v.string(),
})
),
functions: v.record(
v.string(),
v.object({
params: v.array(v.string()),
desc: v.string(),
section: v.string(),
example: v.union([v.string(), v.array(v.string())]),
})
),
/*table_functions: v.record(
v.string(),
v.object({
params: v.array(v.string()),
desc: v.string(),
example: v.union([v.string(), v.array(v.string())]),
})
),*/
});
const tableConfig = {
border: {
topBody: ``,
topJoin: ``,
topLeft: ``,
topRight: ``,
bottomBody: ``,
bottomJoin: ``,
bottomLeft: ``,
bottomRight: ``,
bodyLeft: ``,
bodyRight: ``,
bodyJoin: ``,
joinBody: ``,
joinLeft: ``,
joinRight: ``,
joinJoin: ``,
},
};
function formatSingleValue(value) {
if (typeof value === "string") {
const s = `'${value.replace(/'/g, "''")}'`;
if (s.split("\n").length > 1) {
return `/*\n${s}\n*/`;
}
return `-- ${s}`;
}
if (typeof value === "number") return `-- ${value.toString()}`;
if (value === null) return "-- NULL";
if (value instanceof Uint8Array) {
let s = "X'";
for (const v of value) {
s += v.toString(16).toUpperCase();
}
s += "'";
return `-- ${s}`;
}
if (typeof value === "object" || Array.isArray(value))
return "-- " + JSON.stringify(value, null, 2);
}
function formatValue(value) {
if (typeof value === "string" || typeof value === "number") return value;
if (value === null) return "NULL";
if (value instanceof Uint8Array) {
let s = "X'";
for (const v of value) {
s += v.toString(16);
}
s += "'";
return s;
}
if (typeof value === "object" || Array.isArray(value))
return JSON.stringify(value, null, 2);
}
function tableize(stmt, results) {
const columnNames = stmt.columns().map((c) => c.name);
const rows = results.map((row) =>
row.map((value) => {
return formatValue(value);
})
);
return table([columnNames, ...rows], tableConfig);
}
function renderExamples(db, name, example) {
let md = "```sql\n";
const examples = Array.isArray(example) ? example : [example];
for (const example of examples) {
const sql = example
/* Strip any '```sql' markdown at the beginning */
.replace(/^\w*```sql/, "")
/* Strip any '```' markdown at the end */
.replace(/```\w*$/m, "")
.trim();
let stmt, results, error;
results = null;
try {
stmt = db.prepare(sql);
stmt.raw(true);
} catch (error) {
console.error(`Error preparing statement for ${name}:`);
console.error(error);
throw Error();
}
try {
results = stmt.all();
} catch (e) {
error = e.message;
}
md += sql + "\n";
if (!results) {
md += `-- ❌ ${error}\n\n`;
continue;
}
const result =
results.length > 1 || stmt.columns().length > 1
? `/*\n${tableize(stmt, results)}\n*/\n`
: formatSingleValue(results[0][0]);
md += result + "\n\n";
}
md += "\n```\n\n";
return md;
}
let md = `# API Reference
::: warning
sqlite-vec is pre-v1, so expect breaking changes.
:::
[[toc]]
`;
const doc = v.parse(DocSchema, load(readFileSync(REF_PATH, "utf8")));
const db = new Database();
db.loadExtension(EXT_PATH);
let lastSection = null;
for (const [name, { params, desc, example, section }] of Object.entries(
doc.functions
)) {
const headerText = `\`${name}(${(params ?? []).join(", ")})\` {#${name}}`;
if (lastSection != section) {
md += `## ${doc.sections[section].title} {#${section}} \n\n`;
md += doc.sections[section].desc;
md += "\n\n";
lastSection = section;
}
md += "### " + headerText + "\n\n";
md += desc + "\n\n";
md += renderExamples(db, name, example);
}
writeFileSync("api-reference.md", md, "utf8");
console.log("done");

592
site/package-lock.json generated
View file

@ -6,6 +6,10 @@
"": {
"dependencies": {
"@types/node": "^20.12.8",
"better-sqlite3": "^11.1.2",
"js-yaml": "^4.1.0",
"table": "^6.8.2",
"valibot": "^0.36.0",
"vitepress": "^1.1.4"
},
"devDependencies": {
@ -1140,6 +1144,21 @@
}
}
},
"node_modules/ajv": {
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
"integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
"dependencies": {
"fast-deep-equal": "^3.1.3",
"fast-uri": "^3.0.1",
"json-schema-traverse": "^1.0.0",
"require-from-string": "^2.0.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/algoliasearch": {
"version": "4.23.3",
"resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.23.3.tgz",
@ -1162,11 +1181,180 @@
"@algolia/transporter": "4.23.3"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
},
"node_modules/astral-regex": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
"integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/better-sqlite3": {
"version": "11.1.2",
"resolved": "https://registry.npmjs.org/better-sqlite3/-/better-sqlite3-11.1.2.tgz",
"integrity": "sha512-gujtFwavWU4MSPT+h9B+4pkvZdyOUkH54zgLdIrMmmmd4ZqiBIrRNBzNzYVFO417xo882uP5HBu4GjOfaSrIQw==",
"hasInstallScript": true,
"dependencies": {
"bindings": "^1.5.0",
"prebuild-install": "^7.1.1"
}
},
"node_modules/bindings": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
"integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
"dependencies": {
"file-uri-to-path": "1.0.0"
}
},
"node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/chownr": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg=="
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/csstype": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
},
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"dependencies": {
"mimic-response": "^3.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/detect-libc": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
"integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
"engines": {
"node": ">=8"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/end-of-stream": {
"version": "1.4.4",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
@ -1220,6 +1408,29 @@
"resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
},
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
"engines": {
"node": ">=6"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-uri": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.1.tgz",
"integrity": "sha512-MWipKbbYiYI0UC7cl8m/i/IWTqfC8YXsqjzybjddLsFjStroQzsHXkc73JutMvBiXmOvapk+axIl79ig5t55Bw=="
},
"node_modules/file-uri-to-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
"integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw=="
},
"node_modules/focus-trap": {
"version": "7.5.4",
"resolved": "https://registry.npmjs.org/focus-trap/-/focus-trap-7.5.4.tgz",
@ -1228,6 +1439,11 @@
"tabbable": "^6.2.0"
}
},
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
@ -1241,11 +1457,74 @@
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw=="
},
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"engines": {
"node": ">=8"
}
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/json-schema-traverse": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
"integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
},
"node_modules/lodash.truncate": {
"version": "4.4.2",
"resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
"integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw=="
},
"node_modules/magic-string": {
"version": "0.30.10",
"resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.10.tgz",
@ -1259,6 +1538,25 @@
"resolved": "https://registry.npmjs.org/mark.js/-/mark.js-8.11.1.tgz",
"integrity": "sha512-1I+1qpDt4idfgLQG+BNWmrqku+7/2bi5nLf4YwF8y8zXvmfiTBY3PV3ZibfrjBueCByROpuBjLLFCajqkgYoLQ=="
},
"node_modules/mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/minisearch": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/minisearch/-/minisearch-6.3.0.tgz",
@ -1269,6 +1567,11 @@
"resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
"integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw=="
},
"node_modules/mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A=="
},
"node_modules/nanoid": {
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
@ -1286,6 +1589,30 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/napi-build-utils": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz",
"integrity": "sha512-ONmRUqK7zj7DWX0D9ADe03wbwOBZxNAfF20PlGfCWQcD3+/MakShIHrMqx9YwPTfxDdF1zLeL+RGZiR9kGMLdg=="
},
"node_modules/node-abi": {
"version": "3.65.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.65.0.tgz",
"integrity": "sha512-ThjYBfoDNr08AWx6hGaRbfPwxKV9kVzAzOzlLKbk2CuqXE2xnCh+cbAGnwM3t8Lq4v9rUB7VfondlkBckcJrVA==",
"dependencies": {
"semver": "^7.3.5"
},
"engines": {
"node": ">=10"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/perfect-debounce": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz",
@ -1332,6 +1659,75 @@
"url": "https://opencollective.com/preact"
}
},
"node_modules/prebuild-install": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz",
"integrity": "sha512-UnNke3IQb6sgarcZIDU3gbMeTp/9SSU1DAIkil7PrqG1vZlBtY5msYccSKSHDqa3hNg436IXK+SNImReuA1wEQ==",
"dependencies": {
"detect-libc": "^2.0.0",
"expand-template": "^2.0.3",
"github-from-package": "0.0.0",
"minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3",
"napi-build-utils": "^1.0.1",
"node-abi": "^3.3.0",
"pump": "^3.0.0",
"rc": "^1.2.7",
"simple-get": "^4.0.0",
"tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0"
},
"bin": {
"prebuild-install": "bin.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/pump": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"dependencies": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
},
"bin": {
"rc": "cli.js"
}
},
"node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/require-from-string": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/rfdc": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz",
@ -1371,12 +1767,42 @@
"fsevents": "~2.3.2"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/search-insights": {
"version": "2.13.0",
"resolved": "https://registry.npmjs.org/search-insights/-/search-insights-2.13.0.tgz",
"integrity": "sha512-Orrsjf9trHHxFRuo9/rzm0KIWmgzE8RMlZMzuhZOJ01Rnz3D0YBAe+V6473t6/H6c7irs6Lt48brULAiRWb3Vw==",
"peer": true
},
"node_modules/semver": {
"version": "7.6.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz",
"integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/shiki": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/shiki/-/shiki-1.4.0.tgz",
@ -1385,6 +1811,65 @@
"@shikijs/core": "1.4.0"
}
},
"node_modules/simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/simple-get": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"decompress-response": "^6.0.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"node_modules/slice-ansi": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
"integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
"dependencies": {
"ansi-styles": "^4.0.0",
"astral-regex": "^2.0.0",
"is-fullwidth-code-point": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/slice-ansi?sponsor=1"
}
},
"node_modules/source-map-js": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz",
@ -1401,16 +1886,118 @@
"node": ">=0.10.0"
}
},
"node_modules/string_decoder": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
"integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
"dependencies": {
"safe-buffer": "~5.2.0"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/tabbable": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
"integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
},
"node_modules/table": {
"version": "6.8.2",
"resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz",
"integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==",
"dependencies": {
"ajv": "^8.0.1",
"lodash.truncate": "^4.4.2",
"slice-ansi": "^4.0.0",
"string-width": "^4.2.3",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/tar-fs": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.1.tgz",
"integrity": "sha512-V0r2Y9scmbDRLCNex/+hYzvp/zyYjvFbHPNgVTKfQvVrb6guiE/fxP+XblDNR011utopbkex2nM4dHNV6GDsng==",
"dependencies": {
"chownr": "^1.1.1",
"mkdirp-classic": "^0.5.2",
"pump": "^3.0.0",
"tar-stream": "^2.1.4"
}
},
"node_modules/tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"dependencies": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"dependencies": {
"safe-buffer": "^5.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/valibot": {
"version": "0.36.0",
"resolved": "https://registry.npmjs.org/valibot/-/valibot-0.36.0.tgz",
"integrity": "sha512-CjF1XN4sUce8sBK9TixrDqFM7RwNkuXdJu174/AwmQUB62QbCQADg5lLe8ldBalFgtj1uKj+pKwDJiNo4Mn+eQ=="
},
"node_modules/vite": {
"version": "5.2.11",
"resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz",
@ -1521,6 +2108,11 @@
"optional": true
}
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
}
}
}

View file

@ -1,7 +1,8 @@
{
"scripts": {
"ref": "node build-ref.mjs",
"dev": "vitepress dev",
"build": "vitepress build",
"build": "npm run ref && vitepress build",
"preview": "vitepress preview"
},
"devDependencies": {
@ -9,6 +10,10 @@
},
"dependencies": {
"@types/node": "^20.12.8",
"better-sqlite3": "^11.1.2",
"js-yaml": "^4.1.0",
"table": "^6.8.2",
"valibot": "^0.36.0",
"vitepress": "^1.1.4"
}
}

View file

@ -523,6 +523,10 @@ static int fvec_from_value(sqlite3_value *value, f32 **vector,
if (value_type == SQLITE_TEXT) {
const char *source = (const char *)sqlite3_value_text(value);
int source_len = sqlite3_value_bytes(value);
if(source_len == 0) {
*pzErr = sqlite3_mprintf("zero-length vectors are not supported.");
return SQLITE_ERROR;
}
int i = 0;
struct Array x;
@ -658,6 +662,11 @@ static int int8_vec_from_value(sqlite3_value *value, i8 **vector,
int source_len = sqlite3_value_bytes(value);
int i = 0;
if(source_len == 0) {
*pzErr = sqlite3_mprintf("zero-length vectors are not supported.");
return SQLITE_ERROR;
}
struct Array x;
int rc = array_init(&x, sizeof(i8), ceil(source_len / 2.0));
if (rc != SQLITE_OK) {
@ -805,7 +814,7 @@ int ensure_vector_match(sqlite3_value *aValue, sqlite3_value *bValue, void **a,
int rc;
enum VectorElementType aType, bType;
size_t aDims, bDims;
char *error;
char *error = NULL;
vector_cleanup aCleanup, bCleanup;
rc = vector_from_value(aValue, a, &aDims, &aType, &aCleanup, &error);
@ -828,8 +837,8 @@ int ensure_vector_match(sqlite3_value *aValue, sqlite3_value *bValue, void **a,
sqlite3_mprintf("Vector type mistmatch. First vector has type %s, "
"while the second has type %s.",
vector_subtype_name(aType), vector_subtype_name(bType));
aCleanup(a);
bCleanup(b);
aCleanup(*a);
bCleanup(*b);
return SQLITE_ERROR;
}
if (aDims != bDims) {
@ -837,8 +846,8 @@ int ensure_vector_match(sqlite3_value *aValue, sqlite3_value *bValue, void **a,
"Vector dimension mistmatch. First vector has %ld dimensions, "
"while the second has %ld dimensions.",
aDims, bDims);
aCleanup(a);
bCleanup(b);
aCleanup(*a);
bCleanup(*b);
return SQLITE_ERROR;
}
*element_type = aType;
@ -879,7 +888,7 @@ static void vec_npy_file(sqlite3_context *context, int argc,
static void vec_f32(sqlite3_context *context, int argc, sqlite3_value **argv) {
assert(argc == 1);
int rc;
f32 *vector;
f32 *vector = NULL;
size_t dimensions;
fvec_cleanup cleanup;
char *errmsg;
@ -953,7 +962,7 @@ static void vec_distance_cosine(sqlite3_context *context, int argc,
sqlite3_value **argv) {
assert(argc == 2);
int rc;
void *a, *b;
void *a = NULL, *b = NULL;
size_t dimensions;
vector_cleanup aCleanup, bCleanup;
char *error;
@ -995,7 +1004,7 @@ static void vec_distance_l2(sqlite3_context *context, int argc,
sqlite3_value **argv) {
assert(argc == 2);
int rc;
void *a, *b;
void *a = NULL, *b = NULL;
size_t dimensions;
vector_cleanup aCleanup, bCleanup;
char *error;
@ -1035,7 +1044,7 @@ static void vec_distance_hamming(sqlite3_context *context, int argc,
sqlite3_value **argv) {
assert(argc == 2);
int rc;
void *a, *b;
void *a = NULL, *b = NULL;
size_t dimensions;
vector_cleanup aCleanup, bCleanup;
char *error;
@ -1187,7 +1196,7 @@ static void vec_quantize_binary(sqlite3_context *context, int argc,
static void vec_add(sqlite3_context *context, int argc, sqlite3_value **argv) {
assert(argc == 2);
int rc;
void *a, *b;
void *a = NULL, *b = NULL;
size_t dimensions;
vector_cleanup aCleanup, bCleanup;
char *error;
@ -1244,7 +1253,7 @@ finish:
static void vec_sub(sqlite3_context *context, int argc, sqlite3_value **argv) {
assert(argc == 2);
int rc;
void *a, *b;
void *a = NULL, *b = NULL;
size_t dimensions;
vector_cleanup aCleanup, bCleanup;
char *error;

36
tests/fuzz.py Normal file
View file

@ -0,0 +1,36 @@
import sqlite3
EXT_PATH = "dist/vec0"
db = sqlite3.connect(":memory:")
db.execute(
"create temp table base_functions as select name from pragma_function_list"
)
db.execute("create temp table base_modules as select name from pragma_module_list")
db.enable_load_extension(True)
db.load_extension(EXT_PATH)
db.row_factory = sqlite3.Row
loaded_functions = db.execute(
"select name, narg from pragma_function_list where name not in (select name from base_functions) order by name"
).fetchall()
db.execute(
"create temp table loaded_modules as select name from pragma_module_list where name not in (select name from base_modules) order by name"
)
db.row_factory = sqlite3.Row
def trace(sql):
print(sql)
db.set_trace_callback(trace)
def spread_args(n):
return ",".join(["?"] * n)
for f in loaded_functions:
v = [None, 1, 1.2, b"", '', "asdf", b"\xff", b"\x00", "\0\0\0\0"]
for x in v:
try:
db.execute("select {}({}); ".format(f['name'],spread_args(f['narg'])), [x] * f['narg'])
except sqlite3.OperationalError:
pass