This directory contains executable Node.js scripts that demonstrate and verify cross-platform synchronization between JavaScript and R using Automerge.
The easiest way to verify interoperability:
# From package root directory
Rscript inst/js/run-examples.R
# Or from this directory (inst/js/)
Rscript run-examples.R
This automated script will: 1. Check for Node.js availability 2. Install required npm packages 3. Run all examples 4. Verify results 5. Display colored output showing success/failure
# Install Node.js from https://nodejs.org/
The automated test runner (run-examples.R) handles npm package installation automatically using R's user cache directory. This means:
~/.cache/R/automerge/js/ (Unix) or similar OS-specific locationIf you want to install npm packages manually:
# Navigate to this directory
cd inst/js
# Install npm packages
npm install
This installs the @automerge/automerge package and dependencies locally.
node create-shared-doc.js [output-path]
Creates an Automerge document in JavaScript and saves it to a binary file that can be loaded in R.
Example:
node create-shared-doc.js shared_doc.automerge
Default output: shared_doc.automerge
node verify-r-changes.js [input-path]
Loads a document modified by R, verifies the changes, and adds JavaScript changes.
Example:
node verify-r-changes.js shared_doc.automerge
node concurrent-edit.js <base-doc-path> <output-path>
Loads a base document and makes concurrent edits (simulating what would happen if a JavaScript user edited the document at the same time as an R user).
Example:
node concurrent-edit.js base.automerge js_edited.automerge
node verify-merge.js <merged-doc-path>
Verifies that a merged document contains changes from both R and JavaScript, demonstrating CRDT conflict-free merge.
Example:
node verify-merge.js merged.automerge
inst/js/ # Installed JavaScript examples
├── README.md # This file
├── run-examples.R # Automated test runner
├── package.json # npm dependencies
├── create-shared-doc.js # Example 1: JS creates doc
├── verify-r-changes.js # Example 2: JS verifies R changes
├── concurrent-edit.js # Example 3: JS concurrent edit
└── verify-merge.js # Example 4: Verify CRDT merge
vignettes/
└── cross-platform.Rmd # Main vignette with examples
From R, you can execute these scripts:
# Check if Node.js is available
node_available <- system2("node", "--version", stdout = FALSE, stderr = FALSE) == 0
if (node_available) {
# Get JavaScript directory (works with installed package or source)
js_dir <- system.file("js", package = "automerge")
# Run example 1
temp_file <- tempfile(fileext = ".automerge")
system2("node", c(file.path(js_dir, "create-shared-doc.js"), temp_file),
stdout = TRUE, stderr = TRUE)
# Load the result
doc <- automerge::am_load(readBin(temp_file, "raw", 1e7))
print(doc)
}
When the package is installed:
# Get directory path
js_dir <- system.file("js", package = "automerge")
# List available scripts
list.files(js_dir, pattern = "\\.js$")
# From installed package
JS_DIR=$(Rscript -e "cat(system.file('js', package='automerge'))")
node $JS_DIR/create-shared-doc.js test.automerge
# Or from source
node inst/js/create-shared-doc.js test.automerge
# Load in R
library(automerge)
doc <- am_load(readBin("test.automerge", "raw", 1e7))
print(doc)
# Modify in R
library(automerge)
doc <- am_load(readBin("test.automerge", "raw", 1e7))
doc[["r_data"]] <- list(value = 42, timestamp = Sys.time())
am_commit(doc, "Add R data")
writeBin(am_save(doc), "test.automerge")
# Verify in JavaScript
node inst/js/verify-r-changes.js test.automerge
# Create base document
library(automerge)
base <- am_create() |>
am_put(AM_ROOT, "document", "Shared") |>
am_put(AM_ROOT, "sections", am_list())
writeBin(am_save(base), "base.automerge")
# R makes concurrent edit
r_doc <- am_load(readBin("base.automerge", "raw", 1e7))
sections <- r_doc[["sections"]]
am_insert(r_doc, sections, 1, list(title = "R Section", author = "R Team"))
writeBin(am_save(r_doc), "r_edit.automerge")
# JavaScript makes concurrent edit (from same base)
node inst/js/concurrent-edit.js base.automerge js_edit.automerge
# Merge in R
js_doc <- am_load(readBin("js_edit.automerge", "raw", 1e7))
am_merge(r_doc, js_doc)
# Verify both changes present
sections_merged <- r_doc[["sections"]]
am_length(r_doc, sections_merged) # Should be 2
# Save merged document
writeBin(am_save(r_doc), "merged.automerge")
# Verify merge contains both changes
node inst/js/verify-merge.js merged.automerge
These scripts can be used to create test fixtures:
# tests/testthat/helper-js-fixtures.R
create_js_fixtures <- function() {
if (system2("node", "--version", stdout = FALSE, stderr = FALSE) != 0) {
skip("Node.js not available")
}
js_dir <- system.file("js", package = "automerge")
if (js_dir == "") {
js_dir <- file.path(getwd(), "..", "..", "inst", "js")
}
fixture_dir <- test_path("fixtures")
dir.create(fixture_dir, showWarnings = FALSE, recursive = TRUE)
system2("node", c(file.path(js_dir, "create-shared-doc.js"),
file.path(fixture_dir, "js_document.automerge")))
}
Example test:
# tests/testthat/test-js-interop.R
test_that("JavaScript interoperability works", {
skip_if_not(system2("node", "--version", stdout = FALSE, stderr = FALSE) == 0,
"Node.js not available")
# Get JavaScript directory (works with installed package or source)
js_dir <- system.file("js", package = "automerge")
if (js_dir == "") {
js_dir <- file.path(getwd(), "..", "..", "inst", "js")
}
# Run JavaScript to create fixture
js_script <- file.path(js_dir, "create-shared-doc.js")
temp_file <- tempfile(fileext = ".automerge")
system2("node", c(js_script, temp_file))
# Load in R
doc <- am_load(readBin(temp_file, "raw", 1e7))
# Verify
expect_equal(doc[["title"]], "Collaborative Analysis")
expect_equal(doc[["metadata"]][["created_by"]], "javascript")
})
For automated testing in CI/CD:
# .github/workflows/test.yml
steps:
- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: '18'
- name: Install npm packages
run: |
cd inst/js
npm install
- name: Run interoperability tests
run: Rscript inst/js/run-examples.R
Install Node.js from https://nodejs.org/
The automated test runner should install packages to the cache automatically. If you see this error:
Check cache location:
r
tools::R_user_dir("automerge", which = "cache")
Clear cache and retry:
r
unlink(tools::R_user_dir("automerge", which = "cache"), recursive = TRUE)
Or install manually:
bash
cd inst/js
npm install
To remove cached npm packages:
# Clean automerge cache
cache_dir <- tools::R_user_dir("automerge", which = "cache")
unlink(cache_dir, recursive = TRUE)
This will force reinstallation on next run.
Each session generates a random actor ID. This is expected behavior.
JavaScript uses milliseconds since epoch, R uses seconds. Small differences (< 1ms) are expected.
The test suite verifies:
vignette("cross-platform", package = "automerge")Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.