oxigdal_node/lib.rs
1//! Node.js bindings for OxiGDAL
2//!
3//! This crate provides comprehensive Node.js bindings for the OxiGDAL ecosystem,
4//! enabling pure Rust geospatial processing from JavaScript/TypeScript with
5//! zero-copy Buffer integration and full async/await support.
6//!
7//! # Features
8//!
9//! - **Raster I/O**: Read and write GeoTIFF, COG, and other raster formats
10//! - **Vector I/O**: GeoJSON support with full geometry operations
11//! - **Algorithms**: Resampling, terrain analysis, calculator, statistics
12//! - **Async/Await**: Promise-based async operations for I/O and processing
13//! - **Buffer Integration**: Zero-copy data transfer with Node.js Buffers
14//! - **TypeScript**: Comprehensive TypeScript definitions included
15//!
16//! # Example Usage
17//!
18//! ```javascript
19//! const oxigdal = require('@oxigdal/node');
20//!
21//! // Open a raster file
22//! const dataset = oxigdal.openRaster('input.tif');
23//! console.log(`Size: ${dataset.width}x${dataset.height}`);
24//!
25//! // Read a band
26//! const band = dataset.readBand(0);
27//! const stats = band.statistics();
28//! console.log(`Mean: ${stats.mean}, StdDev: ${stats.stddev}`);
29//!
30//! // Compute hillshade
31//! const hillshade = oxigdal.hillshade(band, 315, 45, 1.0);
32//!
33//! // Save result
34//! const output = oxigdal.createRaster(dataset.width, dataset.height, 1, 'uint8');
35//! output.writeBand(0, hillshade);
36//! output.save('hillshade.tif');
37//! ```
38//!
39//! # Async Example
40//!
41//! ```javascript
42//! const oxigdal = require('@oxigdal/node');
43//!
44//! async function processRaster() {
45//! const dataset = await oxigdal.openRasterAsync('input.tif');
46//! const band = dataset.readBand(0);
47//! const slope = await oxigdal.slopeAsync(band, 1.0, false);
48//!
49//! const output = oxigdal.createRaster(dataset.width, dataset.height, 1, 'float32');
50//! output.writeBand(0, slope);
51//! await oxigdal.saveRasterAsync(output, 'slope.tif');
52//! }
53//!
54//! processRaster().catch(console.error);
55//! ```
56
57#![warn(missing_docs)]
58#![warn(clippy::all)]
59#![deny(clippy::unwrap_used)]
60#![allow(clippy::module_name_repetitions)]
61
62mod algorithms;
63mod async_ops;
64mod buffer;
65mod error;
66mod raster;
67mod vector;
68
69use napi_derive::napi;
70
71/// Returns the version of OxiGDAL
72#[napi]
73pub fn version() -> String {
74 oxigdal_core::VERSION.to_string()
75}
76
77/// Returns the OxiGDAL name
78#[napi]
79pub fn name() -> String {
80 "OxiGDAL Node.js Bindings".to_string()
81}
82
83/// Module information
84#[napi(object)]
85pub struct ModuleInfo {
86 /// Version string
87 pub version: String,
88 /// Module name
89 pub name: String,
90 /// Build information
91 pub build_info: String,
92 /// Supported formats
93 pub formats: Vec<String>,
94}
95
96/// Returns module information
97#[napi]
98pub fn get_info() -> ModuleInfo {
99 ModuleInfo {
100 version: oxigdal_core::VERSION.to_string(),
101 name: "OxiGDAL Node.js Bindings".to_string(),
102 build_info: format!(
103 "Built with Rust {} on {}",
104 env!("CARGO_PKG_RUST_VERSION"),
105 std::env::consts::OS
106 ),
107 formats: vec![
108 "GeoTIFF".to_string(),
109 "COG".to_string(),
110 "GeoJSON".to_string(),
111 ],
112 }
113}
114
115/// Data type constants
116#[napi(object)]
117pub struct DataTypes {
118 /// Unsigned 8-bit integer
119 pub uint8: String,
120 /// Signed 16-bit integer
121 pub int16: String,
122 /// Unsigned 16-bit integer
123 pub uint16: String,
124 /// Signed 32-bit integer
125 pub int32: String,
126 /// Unsigned 32-bit integer
127 pub uint32: String,
128 /// 32-bit floating point
129 pub float32: String,
130 /// 64-bit floating point
131 pub float64: String,
132}
133
134/// Returns available data types
135#[napi]
136pub fn get_data_types() -> DataTypes {
137 DataTypes {
138 uint8: "uint8".to_string(),
139 int16: "int16".to_string(),
140 uint16: "uint16".to_string(),
141 int32: "int32".to_string(),
142 uint32: "uint32".to_string(),
143 float32: "float32".to_string(),
144 float64: "float64".to_string(),
145 }
146}
147
148/// Resampling method constants
149#[napi(object)]
150pub struct ResamplingMethods {
151 /// Nearest neighbor (fast, preserves exact values)
152 pub nearest_neighbor: String,
153 /// Bilinear interpolation (smooth, good for continuous data)
154 pub bilinear: String,
155 /// Bicubic interpolation (high quality, slower)
156 pub bicubic: String,
157 /// Lanczos resampling (highest quality, expensive)
158 pub lanczos: String,
159}
160
161/// Returns available resampling methods
162#[napi]
163pub fn get_resampling_methods() -> ResamplingMethods {
164 ResamplingMethods {
165 nearest_neighbor: "NearestNeighbor".to_string(),
166 bilinear: "Bilinear".to_string(),
167 bicubic: "Bicubic".to_string(),
168 lanczos: "Lanczos".to_string(),
169 }
170}
171
172#[cfg(test)]
173mod tests {
174 use super::*;
175
176 #[test]
177 fn test_version() {
178 let ver = version();
179 assert!(!ver.is_empty());
180 }
181
182 #[test]
183 fn test_info() {
184 let info = get_info();
185 assert!(!info.version.is_empty());
186 assert!(!info.formats.is_empty());
187 }
188
189 #[test]
190 fn test_data_types() {
191 let types = get_data_types();
192 assert_eq!(types.uint8, "uint8");
193 assert_eq!(types.float32, "float32");
194 }
195}