Skip to content

Commit db5cd21

Browse files
authored
feat: wasm (#744)
## Closes - #218 It's by no means complete, but it's a start. We'll want to add CI and such later.
1 parent 8a33be4 commit db5cd21

File tree

13 files changed

+5482
-0
lines changed

13 files changed

+5482
-0
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ members = [
1010
"crates/io",
1111
"crates/pgstac",
1212
"crates/server",
13+
"crates/wasm",
1314
]
1415
default-members = [
1516
"crates/api",

crates/wasm/Cargo.toml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
[package]
2+
name = "stac-wasm"
3+
version = "0.0.2"
4+
description = "Converts Arrow arrays to STAC items, via WASM"
5+
authors.workspace = true
6+
edition.workspace = true
7+
homepage.workspace = true
8+
repository.workspace = true
9+
license.workspace = true
10+
categories.workspace = true
11+
rust-version.workspace = true
12+
publish = false
13+
14+
[lib]
15+
crate-type = ["cdylib", "rlib"]
16+
17+
[dependencies]
18+
arrow-array.workspace = true
19+
arrow-schema.workspace = true
20+
arrow-wasm = { git = "https://github.com/kylebarron/arrow-wasm", version = "0.1.0" }
21+
serde.workspace = true
22+
serde-wasm-bindgen = "0.6.5"
23+
stac = { workspace = true, features = ["geoarrow"] }
24+
thiserror.workspace = true
25+
wasm-bindgen = "0.2.84"
26+
27+
[dev-dependencies]
28+
wasm-bindgen-test = "0.3.34"

crates/wasm/LICENSE-APACHE

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../LICENSE-APACHE

crates/wasm/LICENSE-MIT

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
../../LICENSE-MIT

crates/wasm/README.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# stac-wasm
2+
3+
Converts [Arrow](https://arrow.apache.org/) arrays to [SpatioTemporal Asset Catalog (STAC)](https://stacspec.org/) items, via [WebAssembly (WASM)](https://webassembly.org/).
4+
5+
> [!WARNING]
6+
> This package is in an "alpha" state and will likely break and change a lot.
7+
8+
## Usage
9+
10+
```shell
11+
npm i stac-wasm
12+
```
13+
14+
We give you one function:
15+
16+
```javascript
17+
import * as stac_wasm from "stac-wasm";
18+
19+
const table = loadArrowTable(); // e.g. from DuckDB
20+
const items = stac_wasm.arrowToStacJson(table);
21+
```
22+
23+
## Tests
24+
25+
We don't have automated tests.
26+
If you want to play with the function, modify `www/index.js` and then:
27+
28+
```shell
29+
cd www
30+
npm run start
31+
```
32+
33+
This should open a page at <http://localhost:8080/> that you can use to test out the WASM library.
34+
35+
## Contributing
36+
37+
**stac-wasm** is part of [rustac](https://github.com/stac-utils/rustac), a monorepo that includes the Rust code used to build the WASM module.
38+
See [CONTRIBUTING.md](https://github.com/stac-utils/rustac/blob/main/CONTRIBUTING.md) for instructions on contributing to the monorepo.

crates/wasm/src/lib.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
use arrow_array::RecordBatchIterator;
2+
use arrow_schema::ArrowError;
3+
use arrow_wasm::{Table, arrow_js::table::JSTable, error::WasmResult};
4+
use serde::Serialize;
5+
use serde_wasm_bindgen::Serializer;
6+
use thiserror::Error;
7+
use wasm_bindgen::prelude::*;
8+
9+
#[derive(Debug, Error)]
10+
pub enum Error {
11+
#[error(transparent)]
12+
Arrow(#[from] ArrowError),
13+
}
14+
15+
#[wasm_bindgen(js_name = arrowToStacJson)]
16+
pub fn arrow_to_stac_json(table: JSTable) -> WasmResult<JsValue> {
17+
let table = Table::from_js(&table)?;
18+
let reader = RecordBatchIterator::new(
19+
table.record_batches().into_iter().map(From::from).map(Ok),
20+
table.schema().into(),
21+
);
22+
let items = stac::geoarrow::json::from_record_batch_reader(reader)?;
23+
let serializer = Serializer::json_compatible();
24+
let items = items.serialize(&serializer)?;
25+
Ok(items)
26+
}

crates/wasm/www/.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules
2+
dist

crates/wasm/www/bootstrap.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// A dependency graph that contains any wasm must all be imported
2+
// asynchronously. This `bootstrap.js` file does the single async import, so
3+
// that no one else needs to worry about it again.
4+
import("./index.js")
5+
.catch(e => console.error("Error importing `index.js`:", e));

crates/wasm/www/index.html

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!DOCTYPE html>
2+
<html>
3+
<head>
4+
<meta charset="utf-8" />
5+
<title>stac-wasm</title>
6+
</head>
7+
<body>
8+
<noscript
9+
>This page contains webassembly and javascript content, please enable
10+
javascript in your browser.</noscript
11+
>
12+
<script src="./bootstrap.js"></script>
13+
</body>
14+
</html>

crates/wasm/www/index.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import * as duckdb from "@duckdb/duckdb-wasm";
2+
import * as stac_wasm from "stac-wasm";
3+
4+
const JSDELIVR_BUNDLES = duckdb.getJsDelivrBundles();
5+
6+
// Select a bundle based on browser checks
7+
const bundle = await duckdb.selectBundle(JSDELIVR_BUNDLES);
8+
9+
const worker_url = URL.createObjectURL(
10+
new Blob([`importScripts("${bundle.mainWorker}");`], {
11+
type: "text/javascript",
12+
})
13+
);
14+
15+
// Instantiate the asynchronous version of DuckDB-wasm
16+
const worker = new Worker(worker_url);
17+
const logger = new duckdb.ConsoleLogger();
18+
const db = new duckdb.AsyncDuckDB(logger, worker);
19+
await db.instantiate(bundle.mainModule, bundle.pthreadWorker);
20+
URL.revokeObjectURL(worker_url);
21+
22+
const connection = await db.connect();
23+
const table = await connection.query("select 'an-id' as id");
24+
console.log(stac_wasm.arrowToStacJson(table));

0 commit comments

Comments
 (0)