Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,22 @@ on:
- main

jobs:
coverage:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4

- name: Setup Rust
uses: dtolnay/rust-toolchain@stable
with:
components: llvm-tools-preview

- name: Install cargo-llvm-cov
uses: taiki-e/install-action@cargo-llvm-cov

- name: Coverage check
run: cargo llvm-cov --lib --fail-under-lines 20

lint:
runs-on: ubuntu-latest
steps:
Expand Down Expand Up @@ -79,4 +95,3 @@ jobs:

- name: Test
run: pnpm test

10 changes: 5 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,16 @@ publish = false
crate-type = ["cdylib"]

[dependencies]
toml_edit = { version = "0.23.7" }
wasm-bindgen = { version = "0.2.105" }
toml_edit = { version = "0.23.9" }
wasm-bindgen = { version = "0.2.108" }
console_error_panic_hook = "0.1.7"
web-sys = { version = "0.3.82", features = ["console"] }
web-sys = { version = "0.3.85", features = ["console"] }
once_cell = "1.21.3"
thiserror = "2.0.17"
thiserror = "2.0.18"

[dev-dependencies]
indoc = "2.0.7"
wasm-bindgen-test = "0.3.55"
wasm-bindgen-test = "0.3.58"

[profile.release]
lto = true
Expand Down
2 changes: 1 addition & 1 deletion eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ export default defineConfig({
toml: true,
typescript: true,
}, {
ignores: ["bench/fixture/5mb-mixed.toml"],
ignores: ["bench/fixture/5mb-mixed.toml", ".alma-snapshots"],
})
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
"release": "pnpm bump && pnpm build && pnpm -r publish",
"test": "vitest",
"test:wasm": "wasm-pack test --chrome",
"test:rust": "cargo test --lib",
"coverage:rust": "cargo llvm-cov --lib --fail-under-lines 20",
"bench": "vitest bench",
"typecheck": "tsc --noEmit"
},
Expand Down
9 changes: 9 additions & 0 deletions src/core/error.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,29 @@
//! Error types and helpers shared by parse/stringify/edit flows.

use thiserror::Error;
use wasm_bindgen::JsValue;

/// Domain errors returned by core editing routines.
#[derive(Error, Debug)]
pub enum TomlEditJsError<'a> {
/// Failed to parse input TOML text.
#[error("Parse Error: {0}")]
ParseError(#[from] toml_edit::TomlError),
/// Invalid key token in a path expression.
#[error("Key Error: invalid key '{0}'")]
KeyError(&'a str),
/// Array index is outside the current bounds.
#[error("Key Error: index out of boundary '{0}' for '{1}'")]
IndexOutOfBounds(usize, String),
/// Empty path key sequence was provided.
#[error("Key Error: path key is empty")]
EmptyKey,
/// Type mismatch for operation or option value.
#[error("Type error: {0}")]
TypeError(String),
}

/// Converts domain errors to JS-friendly string exceptions.
impl From<TomlEditJsError<'_>> for JsValue {
fn from(value: TomlEditJsError) -> Self {
JsValue::from(value.to_string())
Expand Down
19 changes: 12 additions & 7 deletions src/core/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
//! High-level wasm-exposed APIs.
//!
//! This module bridges JavaScript values and `toml_edit` document structures.
pub(crate) mod error;

use toml_edit::{Document, DocumentMut, Item, Value};
Expand All @@ -15,11 +18,13 @@ use crate::{
};

#[wasm_bindgen(start)]
/// Installs panic hooks for better browser console error output.
pub fn init_panic_hook() {
console_error_panic_hook::set_once();
}

#[wasm_bindgen]
/// Parses a TOML string into a JavaScript value tree.
pub fn parse(input: &str) -> Result<JsValue, JsValue> {
match Document::parse(input) {
Ok(doc) => Ok(from_item(doc.as_item())),
Expand All @@ -28,6 +33,9 @@ pub fn parse(input: &str) -> Result<JsValue, JsValue> {
}

#[wasm_bindgen]
/// Serializes a JavaScript value into TOML text.
///
/// The conversion strategy depends on value shape and stringify options.
pub fn stringify(input: JsValue, opts: Option<IStringifyOptions>) -> Result<String, JsValue> {
let opts = StringifyOptions::new(opts)?;

Expand All @@ -47,6 +55,9 @@ pub fn stringify(input: JsValue, opts: Option<IStringifyOptions>) -> Result<Stri
}

#[wasm_bindgen]
/// Edits a TOML document by path and returns the updated text.
///
/// Path segments support dotted keys and array index notation like `foo.bar.[0]`.
pub fn edit(
input: &str,
path: &str,
Expand All @@ -58,13 +69,7 @@ pub fn edit(

let edit_opts = EditOptions::new(opts)?;
let (path_keys, value_key) = parse_edit_path(path);
set_value(
doc.as_item_mut(),
path_keys.iter().map(|x| &**x).collect(),
value_key,
value,
&edit_opts,
)?;
set_value(doc.as_item_mut(), &path_keys, value_key, value, &edit_opts)?;

let mut result_str = doc.to_string();
if !edit_opts.final_newline {
Expand Down
8 changes: 8 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
//! Public crate surface for TOML parse/stringify/edit operations.
//!
//! The crate is organized by concern:
//! - `core`: wasm bindings and high-level APIs
//! - `ops`: low-level document mutation routines
//! - `options`: JS option parsing and validation
//! - `util`: conversion and formatting helpers
pub mod core;
pub mod ops;
pub mod options;
pub mod util;

/// Re-export high-level APIs for JavaScript consumers.
pub use core::{edit, parse, stringify};
1 change: 1 addition & 0 deletions src/ops/mod.rs
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
//! Low-level mutation operations over `toml_edit::Item`.
pub(crate) mod set;
Loading