1use std::fmt::Display;
2use std::fmt::Formatter;
3use std::iter::{once, Once};
4use std::ops::Deref;
5use std::result::Result as StdResult;
6
7use js_sys::Array;
8use js_sys::ArrayBuffer;
9use js_sys::JsString;
10use js_sys::Uint8Array;
11use serde::Deserialize;
12use wasm_bindgen::{JsCast, JsValue};
13use wasm_bindgen_futures::JsFuture;
14use worker_sys::types::D1Database as D1DatabaseSys;
15use worker_sys::types::D1ExecResult;
16use worker_sys::types::D1PreparedStatement as D1PreparedStatementSys;
17use worker_sys::types::D1Result as D1ResultSys;
18
19use crate::env::EnvBinding;
20use crate::Error;
21use crate::Result;
22
23pub use serde_wasm_bindgen;
24
25pub mod macros;
26
27#[derive(Debug)]
29pub struct D1Database(D1DatabaseSys);
30
31unsafe impl Sync for D1Database {}
32unsafe impl Send for D1Database {}
33
34impl D1Database {
35 pub fn prepare<T: Into<String>>(&self, query: T) -> D1PreparedStatement {
37 self.0.prepare(&query.into()).unwrap().into()
38 }
39
40 pub async fn dump(&self) -> Result<Vec<u8>> {
42 let result = JsFuture::from(self.0.dump()?).await;
43 let array_buffer = cast_to_d1_error(result)?;
44 let array_buffer = array_buffer.dyn_into::<ArrayBuffer>()?;
45 let array = Uint8Array::new(&array_buffer);
46 Ok(array.to_vec())
47 }
48
49 pub async fn batch(&self, statements: Vec<D1PreparedStatement>) -> Result<Vec<D1Result>> {
53 let statements = statements.into_iter().map(|s| s.0).collect::<Array>();
54 let results = JsFuture::from(self.0.batch(statements)?).await;
55 let results = cast_to_d1_error(results)?;
56 let results = results.dyn_into::<Array>()?;
57 let mut vec = Vec::with_capacity(results.length() as usize);
58 for result in results.iter() {
59 let result = result.unchecked_into::<D1ResultSys>();
60 vec.push(D1Result(result));
61 }
62 Ok(vec)
63 }
64
65 pub async fn exec(&self, query: &str) -> Result<D1ExecResult> {
78 let result = JsFuture::from(self.0.exec(query)?).await;
79 let result = cast_to_d1_error(result)?;
80 Ok(result.into())
81 }
82}
83
84impl EnvBinding for D1Database {
85 const TYPE_NAME: &'static str = "D1Database";
86
87 fn get(val: JsValue) -> Result<Self> {
89 let obj = js_sys::Object::from(val);
90 if obj.constructor().name() == Self::TYPE_NAME || obj.constructor().name() == "BetaDatabase"
91 {
92 Ok(obj.unchecked_into())
93 } else {
94 Err(format!(
95 "Binding cannot be cast to the type {} from {}",
96 Self::TYPE_NAME,
97 obj.constructor().name()
98 )
99 .into())
100 }
101 }
102}
103
104impl JsCast for D1Database {
105 fn instanceof(val: &JsValue) -> bool {
106 val.is_instance_of::<D1DatabaseSys>()
107 }
108
109 fn unchecked_from_js(val: JsValue) -> Self {
110 Self(val.into())
111 }
112
113 fn unchecked_from_js_ref(val: &JsValue) -> &Self {
114 unsafe { &*(val as *const JsValue as *const Self) }
115 }
116}
117
118impl From<D1Database> for JsValue {
119 fn from(database: D1Database) -> Self {
120 JsValue::from(database.0)
121 }
122}
123
124impl AsRef<JsValue> for D1Database {
125 fn as_ref(&self) -> &JsValue {
126 &self.0
127 }
128}
129
130impl From<D1DatabaseSys> for D1Database {
131 fn from(inner: D1DatabaseSys) -> Self {
132 Self(inner)
133 }
134}
135
136#[derive(Debug)]
139pub enum D1Type<'a> {
140 Null,
141 Real(f64),
142 Integer(i32),
146 Text(&'a str),
147 Boolean(bool),
148 Blob(&'a [u8]),
149}
150
151#[derive(Debug)]
157pub struct D1PreparedArgument<'a> {
158 value: &'a D1Type<'a>,
159 js_value: JsValue,
160}
161
162impl<'a> D1PreparedArgument<'a> {
163 pub fn new(value: &'a D1Type) -> D1PreparedArgument<'a> {
164 Self {
165 value,
166 js_value: value.into(),
167 }
168 }
169}
170
171impl<'a> From<&'a D1Type<'a>> for JsValue {
172 fn from(value: &'a D1Type<'a>) -> Self {
173 match *value {
174 D1Type::Null => JsValue::null(),
175 D1Type::Real(f) => JsValue::from_f64(f),
176 D1Type::Integer(i) => JsValue::from_f64(i as f64),
177 D1Type::Text(s) => JsValue::from_str(s),
178 D1Type::Boolean(b) => JsValue::from_bool(b),
179 D1Type::Blob(a) => serde_wasm_bindgen::to_value(a).unwrap(),
180 }
181 }
182}
183
184impl<'a> Deref for D1PreparedArgument<'a> {
185 type Target = D1Type<'a>;
186 fn deref(&self) -> &Self::Target {
187 self.value
188 }
189}
190
191impl<'a> IntoIterator for &'a D1Type<'a> {
192 type Item = &'a D1Type<'a>;
193 type IntoIter = Once<&'a D1Type<'a>>;
194 fn into_iter(self) -> Self::IntoIter {
196 once(self)
197 }
198}
199
200impl<'a> IntoIterator for &'a D1PreparedArgument<'a> {
201 type Item = &'a D1PreparedArgument<'a>;
202 type IntoIter = Once<&'a D1PreparedArgument<'a>>;
203 fn into_iter(self) -> Self::IntoIter {
205 once(self)
206 }
207}
208
209pub trait D1Argument {
210 fn js_value(&self) -> impl AsRef<JsValue>;
211}
212
213impl D1Argument for D1Type<'_> {
214 fn js_value(&self) -> impl AsRef<JsValue> {
215 Into::<JsValue>::into(self)
216 }
217}
218
219impl D1Argument for D1PreparedArgument<'_> {
220 fn js_value(&self) -> impl AsRef<JsValue> {
221 &self.js_value
222 }
223}
224
225#[derive(Debug, Clone)]
227pub struct D1PreparedStatement(D1PreparedStatementSys);
228
229impl D1PreparedStatement {
230 pub fn bind(self, values: &[JsValue]) -> Result<Self> {
240 let array: Array = values.iter().collect::<Array>();
241
242 match self.0.bind(array) {
243 Ok(stmt) => Ok(D1PreparedStatement(stmt)),
244 Err(err) => Err(Error::from(err)),
245 }
246 }
247
248 pub fn bind_refs<'a, T: IntoIterator<Item = &'a U>, U: D1Argument + 'a>(
251 &self,
252 values: T,
253 ) -> Result<Self> {
254 let array: Array = values.into_iter().map(|t| t.js_value()).collect::<Array>();
255
256 match self.0.bind(array) {
257 Ok(stmt) => Ok(D1PreparedStatement(stmt)),
258 Err(err) => Err(Error::from(err)),
259 }
260 }
261
262 pub fn batch_bind<
265 'a,
266 U: IntoIterator<Item = &'a V> + 'a,
267 T: IntoIterator<Item = U> + 'a,
268 V: D1Argument + 'a,
269 >(
270 &self,
271 values: T,
272 ) -> Result<Vec<Self>> {
273 values
274 .into_iter()
275 .map(|batch| self.bind_refs(batch))
276 .collect()
277 }
278
279 pub async fn first<T>(&self, col_name: Option<&str>) -> Result<Option<T>>
287 where
288 T: for<'a> Deserialize<'a>,
289 {
290 let result = JsFuture::from(self.0.first(col_name)?).await;
291 let js_value = cast_to_d1_error(result)?;
292 let value = serde_wasm_bindgen::from_value(js_value)?;
293 Ok(value)
294 }
295
296 pub async fn run(&self) -> Result<D1Result> {
298 let result = JsFuture::from(self.0.run()?).await;
299 let result = cast_to_d1_error(result)?;
300 Ok(D1Result(result.into()))
301 }
302
303 pub async fn all(&self) -> Result<D1Result> {
305 let result = JsFuture::from(self.0.all()?).await?;
306 Ok(D1Result(result.into()))
307 }
308
309 pub async fn raw<T>(&self) -> Result<Vec<Vec<T>>>
311 where
312 T: for<'a> Deserialize<'a>,
313 {
314 let result = JsFuture::from(self.0.raw()?).await;
315 let result = cast_to_d1_error(result)?;
316 let result = result.dyn_into::<Array>()?;
317 let mut vec = Vec::with_capacity(result.length() as usize);
318 for value in result.iter() {
319 let value = serde_wasm_bindgen::from_value(value)?;
320 vec.push(value);
321 }
322 Ok(vec)
323 }
324
325 pub async fn raw_js_value(&self) -> Result<Vec<JsValue>> {
327 let result = JsFuture::from(self.0.raw()?).await;
328 let result = cast_to_d1_error(result)?;
329 let array = result.dyn_into::<Array>()?;
330
331 Ok(array.to_vec())
332 }
333
334 pub fn inner(&self) -> &D1PreparedStatementSys {
336 &self.0
337 }
338}
339
340impl From<D1PreparedStatementSys> for D1PreparedStatement {
341 fn from(inner: D1PreparedStatementSys) -> Self {
342 Self(inner)
343 }
344}
345
346#[derive(Debug)]
348pub struct D1Result(D1ResultSys);
349
350#[derive(Debug, Clone, Deserialize)]
352pub struct D1ResultMeta {
353 pub changed_db: Option<bool>,
354 pub changes: Option<usize>,
355 pub duration: Option<f64>,
356 pub last_row_id: Option<i64>,
357 pub rows_read: Option<usize>,
358 pub rows_written: Option<usize>,
359 pub size_after: Option<usize>,
360}
361
362impl D1Result {
363 pub fn success(&self) -> bool {
365 self.0.success().unwrap()
366 }
367
368 pub fn error(&self) -> Option<String> {
372 self.0.error().unwrap()
373 }
374
375 pub fn results<T>(&self) -> Result<Vec<T>>
377 where
378 T: for<'a> Deserialize<'a>,
379 {
380 if let Some(results) = self.0.results()? {
381 let mut vec = Vec::with_capacity(results.length() as usize);
382 for result in results.iter() {
383 let result = serde_wasm_bindgen::from_value(result).unwrap();
384 vec.push(result);
385 }
386 Ok(vec)
387 } else {
388 Ok(Vec::new())
389 }
390 }
391
392 pub fn meta(&self) -> Result<Option<D1ResultMeta>> {
396 if let Ok(meta) = self.0.meta() {
397 let meta: D1ResultMeta = serde_wasm_bindgen::from_value(meta.into())?;
398 Ok(Some(meta))
399 } else {
400 Ok(None)
401 }
402 }
403}
404
405#[derive(Clone)]
406pub struct D1Error {
407 inner: js_sys::Error,
408}
409
410impl D1Error {
411 pub fn cause(&self) -> String {
413 if let Ok(cause) = self.inner.cause().dyn_into::<js_sys::Error>() {
414 cause.message().into()
415 } else {
416 "unknown error".into()
417 }
418 }
419}
420
421impl std::fmt::Debug for D1Error {
422 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
423 let cause = self.inner.cause();
424
425 f.debug_struct("D1Error").field("cause", &cause).finish()
426 }
427}
428
429impl Display for D1Error {
430 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
431 let cause = self.inner.cause();
432 let cause = JsString::from(cause);
433 write!(f, "{cause}")
434 }
435}
436
437impl AsRef<js_sys::Error> for D1Error {
438 fn as_ref(&self) -> &js_sys::Error {
439 &self.inner
440 }
441}
442
443impl AsRef<JsValue> for D1Error {
444 fn as_ref(&self) -> &JsValue {
445 &self.inner
446 }
447}
448
449fn cast_to_d1_error<T>(result: StdResult<T, JsValue>) -> StdResult<T, crate::Error> {
450 let err = match result {
451 Ok(value) => return Ok(value),
452 Err(err) => err,
453 };
454
455 let err: JsValue = match err.dyn_into::<js_sys::Error>() {
456 Ok(err) => {
457 let message: String = err.message().into();
458
459 if message.starts_with("D1") {
460 return Err(D1Error { inner: err }.into());
461 };
462 err.into()
463 }
464 Err(err) => err,
465 };
466
467 Err(err.into())
468}