/ duper-js-node / src / lib.rs
lib.rs
 1  use duper::{
 2      DuperIdentifierTryFromError, DuperObjectTryFromError, DuperParser, DuperTemporalTryFromError,
 3      DuperValue, PrettyPrinter, Serializer,
 4  };
 5  use napi::{Env, bindgen_prelude::Object};
 6  use napi_derive::napi;
 7  
 8  use crate::{
 9      de::DuperMetaDeserializer,
10      ser::{DuperMetaSerializer, SerdeError},
11  };
12  
13  mod de;
14  mod ser;
15  
16  #[derive(Debug, thiserror::Error)]
17  pub enum DuperError {
18      #[error("Parse error: {0}")]
19      Parse(String),
20      #[error("serde_json error: {0}")]
21      SerdeJson(#[from] serde_json::Error),
22      #[error("Serde error: {0}")]
23      Serde(#[from] SerdeError),
24      #[error("Invalid serialization options: {0}")]
25      SerializeOptions(&'static str),
26      #[error("Identifier error: {0}")]
27      InvalidIdentifier(#[from] DuperIdentifierTryFromError<'static>),
28      #[error("Object error: {0}")]
29      InvalidObject(#[from] DuperObjectTryFromError<'static>),
30      #[error("Temporal error: {0}")]
31      InvalidTemporal(#[from] DuperTemporalTryFromError<'static>),
32  }
33  
34  #[napi]
35  pub fn parse(env: &Env, input: String, parse_any: bool) -> anyhow::Result<Object<'_>> {
36      let value = match parse_any {
37          true => DuperParser::parse_duper_value(&input),
38          false => DuperParser::parse_duper_trunk(&input),
39      }
40      .map_err(|err| {
41          DuperError::Parse(
42              DuperParser::prettify_error(&input, &err, None).unwrap_or_else(|_| format!("{err:?}")),
43          )
44      })?;
45      Ok(value.serialize_meta(&DuperMetaSerializer::new(env))?)
46  }
47  
48  #[napi(object)]
49  pub struct SerializeOptions {
50      pub indent: Option<String>,
51      pub strip_identifiers: bool,
52      pub minify: bool,
53  }
54  
55  #[napi]
56  pub fn serialize(
57      env: &Env,
58      value: Object,
59      options: Option<SerializeOptions>,
60  ) -> anyhow::Result<String> {
61      let SerializeOptions {
62          indent,
63          strip_identifiers,
64          minify,
65      } = options.unwrap_or(SerializeOptions {
66          indent: None,
67          strip_identifiers: false,
68          minify: false,
69      });
70      if let Some(indent) = indent {
71          if minify {
72              Err(DuperError::SerializeOptions(
73                  "Cannot serialize Duper value with both indent and minify options",
74              )
75              .into())
76          } else {
77              Ok(PrettyPrinter::new(strip_identifiers, indent.as_ref())
78                  .map_err(DuperError::SerializeOptions)?
79                  .pretty_print(&DuperValue::deserialize_meta(DuperMetaDeserializer {
80                      env,
81                      object: value,
82                  })?))
83          }
84      } else {
85          Ok(
86              Serializer::new(strip_identifiers, minify).serialize(&DuperValue::deserialize_meta(
87                  DuperMetaDeserializer { env, object: value },
88              )?),
89          )
90      }
91  }