Files
Piotr Sarnacki 4c962b9170 spacetime.json config implementation (#4199)
# Description of Changes

This PR implements support for the `spacetime.json` configuration file
that can be used to set up common `generate` and `publish` targets. An
example of `spacetime.json` could look like this:

```
{
  "dev_run": "pnpm dev",
  "generate": [
    { "out-dir": "./foobar", "module-path": "region-module", "language": "c-sharp" },
    { "out-dir": "./global", "module-path": "global-module", "language": "c-sharp" },
  ],
  "publish": {
    "database": "bitcraft",
    "module-path": "spacetimedb",
    "server": "local",
    "children": [
      { "database": "region-1", "module-path": "region-module", server: "local" },
      { "database": "region-2", "module-path": "region-module", server: "local" }
    ]
  }
}
```

With this config, running `spacetime generate` without any arguments
would generate bindings for two targets: `region-module` and
`global-module`. `spacetime publish` without any arguments would publish
three modules, starting from the parent: `bitcraft`, `region-1`, and
`region-2`. On top of that, the command `pnpm dev` would be executed
when using `spacetime dev`.

It is also possible to pass additional command line arguments when
calling the `publish` and `generate` commands, but there are certain
limitations. There is a special case when passing either a module path
to generate or a module name to publish. Doing that will filter out
entries in the config file that do not match. For example, running:

```
spacetime generate --project-path global-module
```

would only generate bindings for the second entry in the `generate`
list.

In a similar fashion, running:

```
spacetime publish region-1
```

would only publish the child database with the name `region-1`

Passing other existing arguments is also possible, but not all of the
arguments are available for multiple configs. For example, when running
`spacetime publish --server maincloud`, the publish command would be
applied to all of the modules listed in the config file, but the
`server` value from the command line arguments would take precedence.
Running with arguments like `--bin-path` would, however, would throw an
error as `--bin-path` makes sense only in a context of a specific
module, thus this wouldn't work: `spacetime publish --bin-path
spacetimedb/target/debug/bitcraft.wasm`. I will throw an error unless
there is only one entry to process, thus `spacetime publish --bin-path
spacetimedb/target/debug/bitcraft.wasm bitcraft` would work, as it
filters the publish targets to one entry.

# API and ABI breaking changes

None

# Expected complexity level and risk

3

The config file in itself is not overly complex, but when coupled with
the CLI it is somewhat tricky to get right. There are also some changes
that I had to make to how clap arguments are validated - because the
values can now come from both the config file and the clap config, we
can't use some of the built-in validations like `required`, or at least
I haven't found a clean way to do so.

# Testing

I've added some automated tests, but more tests and manual testing is
coming.

---------

Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: bradleyshep <148254416+bradleyshep@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: = <cloutiertyler@gmail.com>
Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
2026-02-15 23:22:44 +00:00

93 lines
3.1 KiB
Bash

#!/bin/bash
# Script to regenerate Rust SDK client from latest sdk-test module
# This ensures we're always comparing against the most current Rust module
set -e # Exit on any error
RUST_DIR="rust-sdk-test"
SDK_TEST_DIR=$(realpath "../../../../modules/sdk-test")
CLI_PATH=$(realpath "../../../../target/release/spacetimedb-cli")
# Check if rebuild is needed
check_needs_rebuild() {
local source_dir="$1"
local target_dir="$2"
# If target directory doesn't exist or is empty, we need to build
if [ ! -d "$target_dir" ] || [ -z "$(ls -A "$target_dir" 2>/dev/null)" ]; then
return 0 # true - needs rebuild
fi
# Find the newest source file in sdk-test
local newest_src=$(find "$source_dir/src" -type f \( -name "*.rs" -o -name "*.toml" \) -printf '%T@\n' 2>/dev/null | sort -n | tail -1)
# Find the oldest generated file in rust-sdk-test
local oldest_gen=$(find "$target_dir" -type f -name "*.rs" -printf '%T@\n' 2>/dev/null | sort -n | head -1)
# Check if any source is newer than generated files
if [ -n "$newest_src" ] && [ -n "$oldest_gen" ] && [ $(echo "$newest_src" | cut -d. -f1) -gt $(echo "$oldest_gen" | cut -d. -f1) ]; then
return 0 # true - needs rebuild
fi
return 1 # false - no rebuild needed
}
echo "Regenerating Rust SDK client from latest sdk-test module..."
echo "=========================================================="
# Check if sdk-test needs rebuilding
if check_needs_rebuild "$SDK_TEST_DIR" "$RUST_DIR"; then
echo "Source files changed - regenerating Rust client..."
echo "--------------------------------------------------"
else
echo "✅ No source changes detected - using existing Rust client"
if [ -d "$RUST_DIR" ]; then
echo "Files present: $(find "$RUST_DIR" -name "*.rs" | wc -l)"
fi
echo ""
exit 0
fi
if [ ! -f "$CLI_PATH" ]; then
echo "ERROR: SpacetimeDB CLI not found at $CLI_PATH"
echo "Please build the CLI first, from the project root:"
echo " cargo build --release -p spacetimedb-cli"
exit 1
fi
if [ ! -d "$SDK_TEST_DIR" ]; then
echo "ERROR: SDK test module not found at $SDK_TEST_DIR"
echo "Please ensure the sdk-test module exists."
exit 1
fi
# Clear existing Rust client directory
echo "Clearing existing Rust client directory..."
if [ -d "$RUST_DIR" ]; then
rm -rf "$RUST_DIR"/*
echo "Cleared $RUST_DIR/"
else
mkdir -p "$RUST_DIR"
echo "Created $RUST_DIR/"
fi
# Generate new Rust client
echo "Generating new Rust client from sdk-test module..."
cd "$RUST_DIR"
"$CLI_PATH" generate --lang rust --out-dir . --module-path "$SDK_TEST_DIR" >/dev/null 2>&1
if [ $? -eq 0 ]; then
echo ""
echo "✅ Rust SDK client regenerated successfully!"
echo "Files generated: $(find . -name "*.rs" | wc -l)"
echo ""
echo "Next steps:"
echo " 1. Run ./compare_clients.sh to generate new comparison"
echo " 2. Review client_diff_analysis.txt for updated differences"
else
echo ""
echo "❌ Client generation failed!"
echo "Check the error messages above for details."
exit 1
fi