Skip to content

Commit 51145a3

Browse files
Merge branch 'feat-nearest-filters-e2f8d' into feat-nearest-filters-via-indexed-filter-ranges
2 parents 1c765e8 + 8bfaa6d commit 51145a3

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+3304
-16473
lines changed

.github/workflows/test.yml

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: Test and lint
2+
concurrency:
3+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
4+
cancel-in-progress: true
5+
6+
on:
7+
push:
8+
branches: [main]
9+
pull_request:
10+
branches: ["**"]
11+
12+
jobs:
13+
check:
14+
name: Test and lint
15+
runs-on: ubuntu-latest
16+
timeout-minutes: 30
17+
18+
steps:
19+
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5
20+
21+
- name: Node setup
22+
uses: actions/setup-node@a0853c24544627f65ddf259abe73b1d18a591444 # v5
23+
with:
24+
cache-dependency-path: package.json
25+
node-version: "20.x"
26+
cache: "npm"
27+
28+
- name: Install and build
29+
run: |
30+
npm i
31+
npm run build
32+
- name: Publish package for testing branch
33+
run: npx pkg-pr-new publish || echo "Have you set up pkg-pr-new for this repo?"
34+
- name: Test
35+
run: |
36+
npm run test
37+
npm run typecheck
38+
npm run lint

.gitignore

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ dist-ssr
99
explorations
1010
node_modules
1111
.eslintcache
12-
# components are libraries!
1312
.package-lock.json
1413

1514
# this is a package-json-redirect stub dir, see https://github.com/andrewbranch/example-subpath-exports-ts-compat?tab=readme-ov-file
1615
frontend/package.json
1716
# npm pack output
1817
*.tgz
18+
*.tsbuildinfo

.prettierrc

Lines changed: 0 additions & 7 deletions
This file was deleted.

.prettierrc.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,4 @@
1-
{}
1+
{
2+
"trailingComma": "all",
3+
"proseWrap": "always"
4+
}

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# Changelog
2+
3+
## 0.2.0
4+
5+
- Adds /test and /\_generated/component.js entrypoints
6+
- Drops commonjs support
7+
- Improves source mapping for generated files
8+
- Changes to a statically generated component API

CONTRIBUTING.md

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Developing guide
2+
3+
## Running locally
4+
5+
```sh
6+
npm i
7+
npm run dev
8+
```
9+
10+
## Testing
11+
12+
```sh
13+
npm run clean
14+
npm run build
15+
npm run typecheck
16+
npm run lint
17+
npm run test
18+
```
19+
20+
## Deploying
21+
22+
### Building a one-off package
23+
24+
```sh
25+
npm run clean
26+
npm ci
27+
npm pack
28+
```
29+
30+
### Deploying a new version
31+
32+
```sh
33+
npm run release
34+
```
35+
36+
or for alpha release:
37+
38+
```sh
39+
npm run alpha
40+
```

README.md

Lines changed: 63 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -6,25 +6,31 @@
66

77
<!-- START: Include on https://convex.dev/components -->
88

9-
This component adds a geospatial index to Convex, allowing you to efficiently store and query points on the Earth's surface.
9+
This component adds a geospatial index to Convex, allowing you to efficiently
10+
store and query points on the Earth's surface.
1011

11-
- Insert points into the geospatial key value store along with their geographic coordinates.
12+
- Insert points into the geospatial key value store along with their geographic
13+
coordinates.
1214
- Efficiently query for all points within a given rectangle on the sphere.
1315
- Control the sort order for the results with a custom sorting key.
1416
- Filter query results with equality and `IN` clauses.
15-
- And since it's built on Convex, everything is automatically consistent, reactive, and cached!
17+
- And since it's built on Convex, everything is automatically consistent,
18+
reactive, and cached!
1619

17-
This component is currently in beta. It's missing some functionality, but what's there should work. We've tested the example
18-
app up to about 1,000,000 points, so reach out if you're using a much larger dataset.
19-
If you find a bug or have a feature request, you can [file it here](https://github.com/get-convex/geospatial/issues).
20+
This component is currently in beta. It's missing some functionality, but what's
21+
there should work. We've tested the example app up to about 1,000,000 points, so
22+
reach out if you're using a much larger dataset. If you find a bug or have a
23+
feature request, you can
24+
[file it here](https://github.com/get-convex/geospatial/issues).
2025

2126
## Pre-requisite: Convex
2227

23-
You'll need an existing Convex project to use the component.
24-
Convex is a hosted backend platform, including a database, serverless functions,
25-
and a ton more you can learn about [here](https://docs.convex.dev/get-started).
28+
You'll need an existing Convex project to use the component. Convex is a hosted
29+
backend platform, including a database, serverless functions, and a ton more you
30+
can learn about [here](https://docs.convex.dev/get-started).
2631

27-
Run `npm create convex` or follow any of the [quickstarts](https://docs.convex.dev/home) to set one up.
32+
Run `npm create convex` or follow any of the
33+
[quickstarts](https://docs.convex.dev/home) to set one up.
2834

2935
## Installation
3036

@@ -34,11 +40,12 @@ First, add `@convex-dev/geospatial` to your Convex project:
3440
npm install @convex-dev/geospatial
3541
```
3642

37-
Then, install the component into your Convex project within the `convex/convex.config.ts` file:
43+
Then, install the component into your Convex project within the
44+
`convex/convex.config.ts` file:
3845

3946
```ts
4047
// convex/convex.config.ts
41-
import geospatial from "@convex-dev/geospatial/convex.config";
48+
import geospatial from "@convex-dev/geospatial/convex.config.js";
4249
import { defineApp } from "convex/server";
4350

4451
const app = defineApp();
@@ -47,7 +54,8 @@ app.use(geospatial);
4754
export default app;
4855
```
4956

50-
Finally, create a new `GeospatialIndex` within your `convex/` folder, and point it to the installed component:
57+
Finally, create a new `GeospatialIndex` within your `convex/` folder, and point
58+
it to the installed component:
5159

5260
```ts
5361
// convex/index.ts
@@ -59,9 +67,10 @@ const geospatial = new GeospatialIndex(components.geospatial);
5967

6068
## Inserting points
6169

62-
After installing the component, you can `insert`, `get`, and `remove` points from the index. You can specify
63-
a `filterKeys` record for filtering at query time and optionally a `sortKey` for the query result order. We
64-
currently only support ascending order on the `sortKey`.
70+
After installing the component, you can `insert`, `get`, and `remove` points
71+
from the index. You can specify a `filterKeys` record for filtering at query
72+
time and optionally a `sortKey` for the query result order. We currently only
73+
support ascending order on the `sortKey`.
6574

6675
```ts
6776
// convex/index.ts
@@ -85,9 +94,11 @@ const example = mutation({
8594
});
8695
```
8796

88-
If you would like some more typesafety, you can specify a type argument for the `GeospatialIndex` class. This
89-
will also provide you with auto-complete for the `filterKeys` and `sortKey` parameters.
90-
Above the key was "American Museum of Natural History" but most commonly the `key` will be an ID in another table of yours.
97+
If you would like some more typesafety, you can specify a type argument for the
98+
`GeospatialIndex` class. This will also provide you with auto-complete for the
99+
`filterKeys` and `sortKey` parameters. Above the key was "American Museum of
100+
Natural History" but most commonly the `key` will be an ID in another table of
101+
yours.
91102

92103
```ts
93104
// convex/index.ts
@@ -125,13 +136,13 @@ const example = query({
125136
});
126137
```
127138

128-
This query will find all points that lie within the query rectangle, sort them in ascending
129-
`sortKey` order, and return at most 16 results.
139+
This query will find all points that lie within the query rectangle, sort them
140+
in ascending `sortKey` order, and return at most 16 results.
130141

131142
You can optionally add filter conditions to queries.
132143

133-
The first type of filter condition is an `in()` filter, which requires that a matching
134-
document have a filter field with a value in a specified set.
144+
The first type of filter condition is an `in()` filter, which requires that a
145+
matching document have a filter field with a value in a specified set.
135146

136147
```ts
137148
// convex/index.ts
@@ -153,8 +164,8 @@ const example = query({
153164
});
154165
```
155166

156-
The second type of filter condition is an `eq()` filter, which requires that a matching
157-
document have a filter field with a value equal to a specified value.
167+
The second type of filter condition is an `eq()` filter, which requires that a
168+
matching document have a filter field with a value equal to a specified value.
158169

159170
```ts
160171
// convex/index.ts
@@ -170,7 +181,9 @@ const example = query({
170181
});
171182
```
172183

173-
The final type of filter condition allows you to specify ranges over the `sortKey`. We currently only support (optional) inclusive lower bounds and exclusive upper bounds.
184+
The final type of filter condition allows you to specify ranges over the
185+
`sortKey`. We currently only support (optional) inclusive lower bounds and
186+
exclusive upper bounds.
174187

175188
```ts
176189
// convex/index.ts
@@ -192,10 +205,13 @@ const example = query({
192205
});
193206
```
194207

195-
Queries take in a `limit`, which bounds the maximum number of rows returned. If this limit is hit,
196-
the query will return a `nextCursor` for continuation. The query may also return a `nextCursor` with fewer than `limit` results if it runs out of its IO budget while executing.
208+
Queries take in a `limit`, which bounds the maximum number of rows returned. If
209+
this limit is hit, the query will return a `nextCursor` for continuation. The
210+
query may also return a `nextCursor` with fewer than `limit` results if it runs
211+
out of its IO budget while executing.
197212

198-
In either case, you can continue the stream by passing `nextCursor` to the next call's `cursor` parameter.
213+
In either case, you can continue the stream by passing `nextCursor` to the next
214+
call's `cursor` parameter.
199215

200216
```ts
201217
// convex/index.ts
@@ -234,11 +250,13 @@ const example = query({
234250
});
235251
```
236252

237-
**Note: you typically pass the `nextCursor` in from a client that is paginating through results, to avoid loading too much data in a single query.**
253+
**Note: you typically pass the `nextCursor` in from a client that is paginating
254+
through results, to avoid loading too much data in a single query.**
238255

239256
## Querying the points nearest a query point
240257

241-
You can also query for the points closest to a given point, optionally limiting to a maximum distance (in meters).
258+
You can also query for the points closest to a given point, optionally limiting
259+
to a maximum distance (in meters).
242260

243261
```ts
244262
// convex/index.ts
@@ -252,7 +270,7 @@ const example = query({
252270
{ latitude: 40.7813, longitude: -73.9737 },
253271
maxResults,
254272
{
255-
maxDistance,
273+
maxDistance,
256274
filter: (q) => q.eq("category", "coffee"),
257275
},
258276
);
@@ -261,11 +279,19 @@ const example = query({
261279
});
262280
```
263281

264-
The fourth argument can either be a numeric `maxDistance` (for backwards compatibility) or an options object. When you pass an options object you can combine `maxDistance` with the same filter builder used by `query`, including `eq`, `in`, `gte`, and `lt` conditions. These filters are enforced through the indexed `pointsByFilterKey` range before documents are loaded, so the database does the heavy lifting and the query avoids reading unrelated points. Pairing that with a sensible `maxDistance` further constrains the search space and can speed up lookups.
282+
The fourth argument can either be a numeric `maxDistance` (for backwards
283+
compatibility) or an options object. When you pass an options object you can
284+
combine `maxDistance` with the same filter builder used by `query`, including
285+
`eq`, `in`, `gte`, and `lt` conditions. These filters are enforced through the
286+
indexed `pointsByFilterKey` range before documents are loaded, so the database
287+
does the heavy lifting and the query avoids reading unrelated points. Pairing
288+
that with a sensible `maxDistance` further constrains the search space and can
289+
greatly speed up searching the index.
265290

266291
## Example
267292

268-
See [`example/`](./example/) for a full example with a [Leaflet](https://leafletjs.com/)-based frontend.
293+
See [`example/`](./example/) for a full example with a
294+
[Leaflet](https://leafletjs.com/)-based frontend.
269295

270296
## Development
271297

@@ -278,7 +304,8 @@ npm install
278304
npm run dev
279305
```
280306

281-
The component definition is in `src/` and reflects what users of the component will install. The example app,
282-
which is entirely independent, lives in `example/`.
307+
The component definition is in `src/` and reflects what users of the component
308+
will install. The example app, which is entirely independent, lives in
309+
`example/`.
283310

284311
<!-- END: Include on https://convex.dev/components -->

commonjs.json

Lines changed: 0 additions & 8 deletions
This file was deleted.

convex.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"$schema": "./node_modules/convex/schemas/convex.schema.json",
3+
"functions": "example/convex",
4+
"codegen": {
5+
"legacyComponentApi": false
6+
}
7+
}

0 commit comments

Comments
 (0)