Commit Graph

2996 Commits

Author SHA1 Message Date
Noa ee3eb85377 Fix ArrayBuilder.{name,default} 2026-02-17 13:34:33 -06:00
Shubham Mishra de2b65fb8d SQL alias (#4304)
# Description of Changes


- [x] : Store "accessor"s names in ModuleDef (for tables, columns, and
indexes for now) and pass them to TableSchema as aliases.

- [x] Create accessor system tables for each of them:
`st_table_accessor`,`st_column_accessor`, `st_index_accessor`

- [x] Update the SQL parsing logic to also consider alias names.



Alias name stored will be same as actual names until we merge
https://github.com/clockworklabs/SpacetimeDB/pull/4263
# API and ABI breaking changes
NA

# Expected complexity level and risk

3

This patch updates SQL name resolution which isn't a very complex change
since table and column name resolution are each handled by their own
helper method.

It also adds new system tables which need to be handle correctly during
restore/replay. We do have regression tests for this that should catch
any incorrect handling or missing steps.

I would say the main risk is that we don't populate cached table and
column schemas with the alias/accessor name. Regression tests have been
added to catch this, but there are edge cases around migrations and
replay that currently aren't covered.

# Testing
 
Added SQL smoketests that use canonical/accessor table/column names.
They currently fail because we're currently using the accessor name for
both. They should pass once this is updated.

---------

Co-authored-by: rekhoff <r.ekhoff@clockworklabs.io>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2026-02-17 10:15:15 +00:00
clockwork-labs-bot 3e71f4decf Docs: Expand FAQ for 2.0 launch (#4314)
Rewrites the FAQ from 5 basic questions to a comprehensive guide
covering:

- **General** — What is SpacetimeDB, is it only for games, is it
blockchain, licensing, self-hosting
- **Comparisons** — vs Mirror/Photon/networking libs, vs
Firebase/Supabase, vs PostgreSQL
- **Architecture** — Data persistence, real-time sync, reducers vs REST,
module languages, views, procedures
- **Development** — Getting started, `spacetime dev`, SQL usage,
Unity/Unreal/React/framework support, auth
- **Deployment** — Production publishing, hot-swapping modules, schema
migrations, size limits, pricing
- **Troubleshooting** — Global database names (401/403), confusing
generate errors, resetting databases

Content drawn from README, architecture docs, Zen of SpacetimeDB, and
common user questions from GitHub issues and Discord.

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-17 05:56:47 +00:00
clockwork-labs-bot 8a2208bbcf docs: expand Maincloud deployment page (#4316)
Rewrites the Maincloud deployment guide from a bare-bones stub into a
comprehensive page. Addresses all three points from #3108 plus a
community request for the connection URI.

**New content:**

1. **Finding your module on the dashboard** - Direct URL
(`spacetimedb.com/my-module`) and profile page navigation
2. **Database lifecycle** - Running vs suspended states, automatic
suspension after inactivity, automatic resumption on first request
3. **Next steps section** - Links to dashboard, SpacetimeAuth setup,
quickstart guides, and usage monitoring

**Also added:**
- Prerequisites section (CLI install + `spacetime login` to link web
account)
- Publishing workflow (initial publish, hot-swap updates,
`--delete-data`)
- Client connection code examples for TypeScript, C#, Rust, and C++ with
the Maincloud host URL (`https://maincloud.spacetimedb.com`) - per
community request in #3108
- Database deletion instructions
- Link to pricing page

Closes #3108

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-17 05:14:35 +00:00
Ryan e03b7d7516 Updated C# Name attribute to Accessor (#4306)
# Description of Changes

Implementation of #4295

Convert existing `Name` attribute to `Accessor` to support new Canonical
Case conversation of 2.0

# API and ABI breaking changes

Yes, in C# modules, we no longer use the attribute name `Name`, it
should now be `Accessor`

# Expected complexity level and risk

1

# Testing

- [X] Build and tested locally
- [X] Ran regression tests locally
2026-02-17 01:16:16 +00:00
Zeke Foppa 5696089096 Fix metadata version check for 2.0 (#4313)
# Description of Changes

The server upgrade path yells when we upgrade from 1.* to 2.0, but this
upgrade path is confirmed to be good.

# API and ABI breaking changes

None.

# Expected complexity level and risk

2

# Testing

"I" added some unit tests to cover the new cases

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-02-17 01:02:28 +00:00
Noa fcd9f294e7 Don't call init reducer in spacetime generate (#4312)
# Description of Changes

Fixes #3492.

# Expected complexity level and risk

1

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
2026-02-16 23:34:19 +00:00
joshua-spacetime 919908fb70 Trigger view refresh when a WASM procedure commits a transaction (#4301)
# Description of Changes

This PR fixes the bug where WASM procedures could commit a transaction
without refreshing affected materialized views, which caused view-backed
subscriptions to miss updates from procedure writes.

The equivalent changes for V8 will be made in a separate patch.

# API and ABI breaking changes

None

# Expected complexity level and risk

3

This was not a simple translation of the reducer code path, because
reducers are run in a single transaction whereas procedures can have
multiple transactions via `with_tx` and views must be refreshed with
each transaction instead of once at the end of the procedure. This
required refresh to be inserted into the syscall itself which required
some extra plumbing. Mainly that we had to attach the validated
`ModuleDef` to the `WasmInstanceEnv`. This should not affect hotswapping
because we instantiate an entirely new `WasmInstanceEnv` in that case.

# Testing

- [x] Added a regression test in the form of a smoketest that subscribes
to a view and calls a procedure
2026-02-16 21:16:35 +00:00
Jeffrey Dallatezza 08ff1e1c11 TS Quickstart: Store different auth tokens for different servers/modules (#3252)
# Description of Changes

In the typescript quickstart example, this includes the server and
module name in the local storage variable name that we use for the auth
token.

This fixes an otherwise annoying issue people run into if they start
running the quickstart locally, then try to run it on maincloud. If they
have already run the app with a local server, their browser will store
the locally signed token, which will get rejected by maincloud.

# Expected complexity level and risk

1.

# Testing

I was able to connect to my local quickstart, then change the variables
to point to a module on maincloud, and I didn't get any errors.

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
v2.0.0-candidate
2026-02-16 16:34:46 +00:00
Shubham Mishra e4098f98d9 Rust: macro change name -> accessor (#4264)
## Description of Changes

This PR primarily affects the `bindings-macro` and `schema` crates to
review:

### Core changes

1. Replaces the `name` macro with `accessor` for **Tables, Views,
Procedures, and Reducers** in Rust modules.
2. Extends `RawModuleDefV10` with a new section for:

   * case conversion policies
   * explicit names
    New sections are not validated in this PR so not functional.
3. Updates index behavior:

* Index names are now always **system-generated** for clients. Which
will be fixed in follow-up PR when we start validating RawModuleDef with
explicit names.
   * The `accessor` name for an index is used only inside the module.


## Breaking changes (API/ABI)

1. **Rust modules**

   * The `name` macro must be replaced with `accessor`.

2. **Client bindings (all languages)**

* Index names are now system-generated instead of using explicitly
provided names.


**Complexity:** 3

A follow-up PR will reintroduce explicit names with support for case
conversion.

---------

Co-authored-by: rekhoff <r.ekhoff@clockworklabs.io>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
2026-02-16 15:23:50 +00:00
Julien Lavocat 83851fe9df Add Angular integration (#4139)
# Description of Changes

- Add Angular integration
- Add Angular quickstart chat template

# API and ABI breaking changes

None.

# Expected complexity level and risk

2

# Testing

Ran the template

---------

Co-authored-by: Tien Pham <tien@clockworklabs.io>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-16 02:21:52 +00:00
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
Tyler Cloutier 3f58b5951b Implement event tables (server, Rust/TS/C# codegen + client SDKs) (#4217)
## Summary

Implements event tables end-to-end: server datastore, module bindings
(Rust/TypeScript/C#), client codegen (Rust/TypeScript/C#), client SDKs
(Rust/TypeScript/C#), and integration tests.

Event tables are tables whose rows are ephemeral — they persist to the
commitlog and are delivered to V2 subscribers, but are NOT merged into
committed state. Rows are only visible within the transaction that
inserted them. This is the mechanism that replaces reducer event
callbacks in 2.0.

## What's included

### Server
- `is_event` flag on `RawTableDefV10`, `TableDef`, `TableSchema`
- Event table rows recorded in TxData but skipped during committed state
merge
- Commitlog replay treats event table inserts as no-ops
- Migration validation rejects changing `is_event` between module
versions
- `SELECT * FROM *` excludes event tables
- V1 WebSocket subscriptions to event tables rejected with upgrade
message
- V2 subscription path delivers event table rows correctly
- `CanBeLookupTable` trait — event tables cannot be lookup tables in
semijoins
- Runtime view validation rejects event tables

### Module bindings
- **Rust**: `#[spacetimedb::table(name = my_events, public, event)]`
- **TypeScript**: `table({ event: true }, ...)`
- **C#**: `[Table(Event = true)]`

### Client codegen (`crates/codegen/`)
- **Rust**: Generates `EventTable` impl (insert-only) for event tables,
`Table` impl for normal tables. `CanBeLookupTable` emitted for non-event
tables.
- **TypeScript**: Emits `event: true` in generated table schemas.
`ClientTableCore` type excludes `onDelete`/`onUpdate` for event tables
via conditional types.
- **C#**: Generates classes inheriting from `RemoteEventTableHandle`
(which hides `OnDelete`/`OnBeforeDelete`/`OnUpdate`) for event tables.

### Client SDKs
- **Rust**: `EventTable` trait with insert-only callbacks, client cache
bypass, `count()` returns 0, `iter()` returns empty
- **TypeScript**: Event table cache bypass in `table_cache.ts` — fires
`onInsert` callbacks but doesn't store rows. Type-level narrowing
excludes delete/update methods.
- **C#**: `RemoteEventTableHandle` base class hides delete/update
events. Parse/Apply/PostApply handle `EventTableRows` wire format, skip
cache storage, fire only `OnInsert`.

### Tests
- 9 datastore unit tests (insert/delete/update semantics, replay,
constraints, indexes, auto-inc, cross-tx reset)
- 3 Rust SDK integration tests (basic events, multiple events per
reducer, no persistence across transactions)
- Codegen snapshot tests (Rust, TypeScript, C#)
- Trybuild compile tests (event tables rejected as semijoin lookup
tables)

## Deferred
- `on_delete` codegen for event tables (server only sends inserts;
client synthesis deferred)
- Event tables in subscription joins / views (well-defined but
restricted for now)
- C++ SDK support
- RLS integration test

## API and ABI breaking changes

- `is_event: bool` added to `RawTableDefV10` (appended, defaults to
`false` — existing modules unaffected)
- `CanBeLookupTable` trait bound on semijoin methods in query builder
(all non-event tables implement it, so existing code compiles unchanged)
- `RemoteEventTableHandle` added to C# SDK (new base class for generated
event table handles)

## Expected complexity level and risk

3 — Changes touch the schema pipeline end-to-end and all three client
SDKs, but each individual change is straightforward. The core risk area
is the committed state merge skip in `committed_state.rs`. Client SDK
changes are additive (new code paths for event tables, existing paths
unchanged).

## Testing

- [x] `cargo clippy --workspace --tests --benches` passes
- [x] `cargo test -p spacetimedb-codegen` (snapshot tests)
- [x] `cargo test -p spacetimedb-datastore --features
spacetimedb-schema/test -- event_table` (9 unit tests)
- [x] `pnpm format` passes
- [x] Rust SDK integration tests pass (`event_table_tests` module)

---------

Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Co-authored-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
2026-02-15 22:56:20 +00:00
Shubham Mishra 124808c2ff Case conversion Raw Def changes (#4294)
# Description of Changes

Case conversion addtion to `RawModuleDefV10`.
Chunk has been taken from -
https://github.com/clockworklabs/SpacetimeDB/pull/4264 to unblock
csharp, and ts modules.

# API and ABI breaking changes
NA
2026-02-13 22:27:29 +00:00
clockwork-labs-bot b79413baf2 Add GREMLINS.md documenting repo bots and agents (#4290)
Documents the automated agents operating on this repo. Starting with
Clawd (clockwork-labs-bot), the CI watchdog.

This is a living document — new bots/gremlins get documented here.

# API and ABI breaking changes
None — documentation only.

# Expected complexity level and risk
0 — documentation only.

# Testing
N/A — documentation only.

---------

Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
2026-02-13 18:09:07 +00:00
Zeke Foppa c85219e0c0 CI - Check smoketests for changes (#4282)
# Description of Changes

`Cargo.lock` was getting stale in our smoketests modules, because we
don't check it anywhere. I added a check.

# API and ABI breaking changes

CI only.

# Expected complexity level and risk

1

# Testing

- [x] new CI step fails without the `Cargo.lock` changes
(<https://github.com/clockworklabs/SpacetimeDB/actions/runs/21960035403/job/63435284426?pr=4282>)
- [x] new CI step passes with the `Cargo.lock` changes

---------

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-02-13 17:57:53 +00:00
Phoebe Goldman 15b748026e Add ws_schema.json to gitignore (#2745)
# Description of Changes

Gitignore a file that's an intermediate artifact of updating the
external client SDKs when the WS protocol gets extended.

# API and ABI breaking changes

N/a

# Expected complexity level and risk

0

# Testing

N/a

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-13 16:59:23 +00:00
clockwork-labs-bot 927d4c4020 [2.0 Breaking] Update C# client SDK for V2 WebSocket format (#4293)
Re-opened from #4289 which was accidentally merged into its base branch
(`rekhoff/csharp-module-defs-v10-no-et`) instead of `master`.

This is the same PR, now correctly targeting `master`.

---

Original description from #4289:

This PR migrates the C# SDK client path to WebSocket v2 semantics and
aligns behavior with the Rust SDK direction for 2.0, including follow-on
fixes in generation/tests.

See #4289 for full description.

---------

Co-authored-by: rekhoff <r.ekhoff@clockworklabs.io>
Co-authored-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-13 16:53:38 +00:00
SteveGibson a344465847 Set name of network thread in C# SDK (#4090)
# Description of Changes

Set name for C# SDK network thread. Helpful when profiling and debugging

# API and ABI breaking changes

No breaking changes

# Expected complexity level and risk

1 - Trivial

# Testing

Tested in Unity Profiler

Co-authored-by: SteveGibsonX <stevegibsonxj@gmail.com>
Co-authored-by: Ryan <r.ekhoff@clockworklabs.io>
2026-02-13 15:11:35 +00:00
Jason Larabie 495064a565 Fix Unreal Blackholio Tutorial for project rename (#4044)
# Description of Changes

Fixes a problem with renaming the project from client_unreal to
blackholio which causes the C++ header code to be incorrect

# API and ABI breaking changes

N/A

# Expected complexity level and risk

1 - Updates a small portion of the Unreal Tutorial documentation

# Testing

Testing the current docs is what found the issue.

- [x] Rebuilt the Unreal Blackholio from the tutorial

---------

Signed-off-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-13 14:43:52 +00:00
clockwork-labs-bot bad5335114 Revert "Append commit instead of individual transactions to commitlog (#4140)" (#4292)
Reverts #4140 per @kim's request — was not ready to merge yet.

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-13 10:23:24 -05:00
Kim Altintop c4c3bf78b3 Append commit instead of individual transactions to commitlog (#4140)
Changes the commitlog (and durability) write API, such that the caller
decides how many transactions are in a single commit, and has to supply
the transaction offsets.

This simplifies commitlog-side buffering logic to essentially a
`BufWriter` (which, of course, we must not forget to flush). This will
help throughput, but offers less opportunity to retry failed writes.
This is probably a good thing, as disks can fail in erratic ways, and we
should rather crash and re-verify the commitlog (suffix) than continue
writing.

To that end, this patch liberally raises panics when there is a chance
that internal state could be "poisoned" by partial writes, which may be
debatable.


# Motivation

The main motivation is to avoid maintaining the transaction offset in
two places in such a way that they could diverge. As ordering commits is
the responsibility of the datastore, we make it authoritative on this
matter -- the commitlog will still check that offsets are contiguous,
and refuse to commit if that's not the case.

A secondary, related motivation is the following:

A "commit" is an atomic unit of storage, meaning that a torn (partial)
write of a commit will render the entire commit corrupt. There hasn't
been a compelling case where we would want this, and have always
configured the server to write exactly one transaction per commit.
The code to handle buffering of transactions is, however, rather
complex, as it tries hard to allow the caller to retry writes at commit
boundaries. An unfortunate consequence of this is that we'd flush to the
OS very often, leaving throughput performance on the table.

So, if there is a compelling case for batching multiple transactions in
a commit, it should be the datastore's responsibility.


# API and ABI breaking changes

Breaks internal APIs only.

# Expected complexity level and risk

5 - Mostly for the risk

# Testing

Existing tests.
2026-02-13 13:10:30 +00:00
Noa c044d96a7a [TS] schema() takes an object (#4273)
# Description of Changes

Implements the rest of the casing proposal.

# Expected complexity level and risk

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
2026-02-13 07:53:42 +00:00
Ryan bba6f89e5f [C#] Adding RawModuleDefV10 to C# Module Bindings without Event Tables (#4288)
# Description of Changes
This is the implementation of #4255
This is a rebuild of #4262 after a rebase throughly messed up that PR's
changelog, this time under `master` branch.
* Refactored `Module` so all V10 builder state and registration helpers
now live on `partial class RawModuleDefV10`. The static `Module` class
simply registers components against that builder and serializes via
`moduleDef.BuildModuleDefinition()`
* Removed the deprecated `__describe_module__` export. Only
`__describe_module_v10__` is emitted now across the runtime, native
shim, generated bindings, and snapshots
* Mirrored the Rust TODO that future V10 sections will cover Event
tables and Case-conversion policy so we don't lose track of those items

Event Tables will be added once they are finished being implemented.

# API and ABI breaking changes
Modules built with these bindings now expose only
`__describe_module_v10__`
The legacy `__describe_module__` symbol is gone from both managed and
native layers. Hosts expecting the old export must switch to the V10
entry point (which is already the canonical ABI for 2.0).

# Expected complexity level and risk
2 - Low. The refactor keeps the previous builder logic but relocates it,
and the export removal matches the already-supported V10 host path.

# Testing
- [X] Successfully built CLI and DLLs without errors.
- [X] Ran `dotnet build crates/bindings-csharp/Runtime/Runtime.csproj`
without errors.
- [X] Ran `dotnet test
crates/bindings-csharp/Codegen.Tests/Codegen.Tests.csproj` without
errors.
- [X] Ran `bash run-regression-tests.sh` without errors.

---------

Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
2026-02-13 07:49:44 +00:00
Tyler Cloutier 2ec07a3f70 Standardize query builder syntax across Rust, TypeScript, and C# (Server/Client) (#4261)
# Description of Changes

Standardizes the query builder API across all three language SDKs (Rust,
TypeScript, C#) for consistency.

**Rust:**
- Rename `Query` struct to `RawQuery`, make `Query` a trait with `fn
into_sql(self) -> String`
- All builder types (`Table`, `FromWhere`, `LeftSemiJoin`,
`RightSemiJoin`) implement `Query<T>` trait
- Views can return `-> impl Query<T>` instead of specifying exact
builder types
- The `#[view]` macro auto-detects `impl Query<T>` and rewrites to
`RawQuery<T>`
- Add `Not` variant to `BoolExpr` with `.not()` method

**TypeScript:**
- Add `ne()` to `ColumnExpression`
- Refactor `BooleanExpr` to `BoolExpr` class with chainable `.and()`,
`.or()`, `.not()` methods
- Make builders valid queries directly (`.build()` deprecated but still
works)
- Deprecate `from()` wrapper — use `tables.person.where(...)` directly
- Merge `query` export into `tables` so table refs are also query
builders
- Add subscription callback form: `subscribe(ctx =>
ctx.from.person.where(...))`
- Unify `useTable` with query builder syntax; deprecate `filter.ts`

**C#:**
- Add `Not()` method to `BoolExpr<TRow>`
- Add `IQuery<TRow>` interface implemented by all builder types
(`Table`, `FromWhere`, `LeftSemiJoin`, `RightSemiJoin`, `Query`)
- Add `ToSql()` to all builder types so `.Build()` is no longer required
- Update `AddQuery` to accept `IQuery<TRow>` instead of `Query<TRow>`

# API and ABI breaking changes

- Rust: `Query<T>` is now a trait (was a struct). The struct is renamed
to `RawQuery<T>`. This is a breaking change for any code that used
`Query<T>` as a type directly.
- TypeScript: `BooleanExpr` is now a `BoolExpr` class (was a
discriminated union type). The `query` export is deprecated in favor of
`tables`.
- C#: `AddQuery` now accepts `Func<QueryBuilder, IQuery<TRow>>` instead
of `Func<QueryBuilder, Query<TRow>>`. Existing `.Build()` calls still
work since `Query<TRow>` implements `IQuery<TRow>`.

# Expected complexity level and risk

3 — Changes touch multiple language SDKs and codegen, but each
individual change is straightforward. The Rust macro rewrite for `impl
Query<T>` detection is the most complex piece. All existing
`.build()`/`.Build()` calls continue to work.

# Testing

- [x] `cargo test -p spacetimedb-query-builder` — 16/16 tests pass
- [x] `cargo check -p spacetimedb` — clean, no warnings
- [x] `cargo check` on views-query, views-sql, views-basic,
views-trapped smoketest modules — all clean
- [x] `cargo test -p spacetimedb-codegen codegen_csharp` — snapshot
updated, passes
- [x] `npm test` (TypeScript) — 101/101 tests pass
- [x] C# QueryBuilder tests — new tests for `Not()`, `IQuery<T>`
interface
- [ ] CI passes
2026-02-13 04:22:49 +00:00
Tyler Cloutier ef9bee058b Event tables: datastore tests, migration validation, and bootstrap fix (#4251)
# Description of Changes

Cherry-picks the core event table implementation (`fa83d6d40`,
`07d57a552`) and adds:

1. **Bootstrap fix**: Register `st_event_table` in
`bootstrap_system_tables()` — it was missing from the cherry-picked
commit, causing event table creation to fail at runtime when inserting
into `ST_EVENT_TABLE_ID`.

2. **4 datastore unit tests** covering event table behaviors:
- Insert+delete in the same tx cancels out (no TxData entry, no
committed state)
- Update yields only the final row in TxData (old row replaced, not
accumulated)
   - Bare insert records in TxData but not in committed state
- `replay_insert` is a no-op for event tables (commitlog replay doesn't
rebuild state)

3. **Migration validation**: `ChangeTableEventFlag` error in
`auto_migrate.rs` prevents changing a table's event flag
(event→non-event or vice versa) via auto-migration. Includes tests for
both directions and a positive test that identical flags are accepted.

4. **Test fixture updates**: Bootstrap test expectations updated for the
new `st_event_table` system table (table row, column, index ID 23,
constraint ID 19). Enabled `spacetimedb-schema/test` feature in
datastore dev-deps to fix pre-existing test compilation issue with
`for_test` methods.

# API and ABI breaking changes

None. The `ChangeTableEventFlag` error variant is added to the internal
`AutoMigrateError` enum but this is not a public API.

# Expected complexity level and risk

1 — Straightforward additions. The bootstrap fix is a one-liner that was
simply missing from the cherry-pick. The tests exercise existing
behavior without changing it. The migration guard follows the exact same
pattern as the existing `ChangeTableType` check.

# Testing

- [x] `cargo test -p spacetimedb-datastore` — 77 tests pass (73 existing
+ 4 new)
- [x] `cargo test -p spacetimedb-schema --features test --lib` — 98
tests pass (96 existing + 2 new)
- [x] `cargo check --workspace --exclude view-client` — compiles clean
(`view-client` has a pre-existing issue with `CanBeLookupTable` from the
cherry-pick)
- [ ] Reviewer: confirm that the 4 event table test names/assertions
match the behaviors described in review feedback

---------

Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: Mazdak Farrokhzad <twingoow@gmail.com>
2026-02-13 04:10:42 +00:00
Noa ce89acafe8 [V8 host] Fix panic when client disconnects (#4286)
# Description of Changes

Spiritual successor to #4162.

# Expected complexity level and risk

1

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
2026-02-13 03:54:46 +00:00
Noa f29d54f633 [TS] Pretty-print objects passed to console.log (#4285)
# Description of Changes

Uses the
[`object-inspect`](https://www.npmjs.com/package/object-inspect) package
to stringify objects passed to console methods, so that you can actually
get useful information without having to `JSON.stringify`. Should've
happened a long time ago.

# Expected complexity level and risk

1

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
2026-02-13 01:37:29 +00:00
Phoebe Goldman 1592dec8af Update Rust client SDK for V2 WebSocket format (#4257)
# Description of Changes

Update the Rust client SDK to use the new V2 WebSocket format, and
present the V2 user-facing API.

## Reducer events

### Remove on-reducer callbacks

It's no longer possible to observe reducers called by other clients by
registering callbacks with `ctx.reducers.on_{my_reducer}`. We no longer
code-generate those methods, or the associated
`ctx.reducers.remove_on_{my_reducer}`. Internal plumbing for storing and
invoking those callbacks is also removed.

### Add specific reducer invocation callbacks

In addition to the previous way to invoke reducers,
`ctx.reducers.{my_reducer}(args...)`, we add a method that registers a
callback to run after the reducer is finished. This method has the
suffix `_then`, as in `ctx.reducers.{my_reducer}_then(args...,
callback)`.

The callback will accept two arguments:
- `ctx: &ReducerEventContext`, the same context as was previously passed
to on-reducer callbacks.
- `status: Result<Result<(), String>, InternalError>`, denoting the
outcome of the reducer.
- `Ok(Ok(())` means the reducer committed. This corresponds to
`ReducerOutcome::Ok` or `ReducerOutcome::Okmpty` in the new WS format.
- `Ok(Err(message))` means the reducer returned an "expected" or "user"
error. This corresponds to `ReducerOutcome::Err` in the new WS format.
- `Err(internal_error)` means something went wrong with host execution.
This corresponds to `ReducerOutcome::InternalError` in the new WS
format.

Internally, the SDK stores the callbacks in its `ReducerCallbacks` map.
This is keyed on `request_id: u32`, a number that is generated for each
reducer call (from an `AtomicU32` that we increment each time), and
included in the `ClientMessage::CallReducer` request. The
`ServerMessage::ReducerResult` includes the same `request_id`, so the
SDK pops out of the `ReducerCallbacks` and invokes the appropriate
callback when processing that message.

These new callbacks are very similar to the existing procedure
callbacks.

### The `Event` exposed to row callbacks

Row callbacks caused by a reducer invoked by this client will see
`Event::Reducer`, the same as they would prior to this PR. These
callbacks will be the result of a `ServerMessage::ReducerResult` with
`ReducerOutcome::Ok`. In order to expose the reducer name and arguments
to this event, the client stores them in its `ReducerCallbacks` map,
alongside the callback for when the reducer is complete.

Row callbacks caused by any other reducer, or any non-reducer
transaction, are now indistinguishable to the client. These will see
`Event::Transaction`, which is renamed from the old
`Event::UnknownTransaction`.

### Less metadata in `ReducerEvent`

Some metadata is removed from `ReducerEvent`, as the V2 WebSocket format
no longer publishes it, even to the caller.

## `CallReducerFlags` are removed

All machinery for setting, storing and applying call reducer flags is
removed from the SDK, as the new WS format does not have any non-default
flags.

## Requesting rows in unsubscribe

When sending a `ClientMessage::Unsubscribe`, we always request that the
server include the matching rows in its response
`ServerMessage::UnsubscribeApplied`. This saves us having to update the
SDK to store query sets separately, at least for now. (We'll do that
later.)

## Handling rows

The new SDK does some additional parsing to wrangle rows in the new
WebSocket format into the same internal data structures as before,
rather than re-writing the client cache. (We'll do that later.)
Specifically, parsing of `DbUpdate` is changed so that:

- We parse raw `TransactionUpdate` into the generated `DbUpdate` type,
which requires an additional loop compared to the previous version, to
cope with the new WS format's dividing updates by query set. We define a
function `transaction_update_iter_table_updates` which encapsulates this
nested loop in an iterator.
- We have two new functions for parsing raw `QueryRows` into the
generated `DbUpdate` type, one for when they come from a
`SubscribeApplied`, and the other when they come from an
`UnsubscribeApplied`. `QueryRows` from `SubscribeApplied` translate to a
`DbUpdate` of all inserts, while one from `UnsubscribeApplied` will be
all deletes.

## Legacy subscriptions

"Legacy subscriptions" are removed. These were only used for
`subscribe_to_all_tables`, which as of now is stubbed. I will follow up
with a change to re-implement `subscribe_to_all_tables` by
code-generating a list of all known tables, and having it subscribe to
`select * from {table}` for every table in that list.

## `subscribe_to_all_tables` via a list

Previously, `subscribe_to_all_tables` worked by sending a legacy
subscription with the query `SELECT * FROM *`, which the host had
special handling to expand to subscribing to all tables. As legacy
subscriptions are no longer usable in V2 clients, this can't work.
Instead, we code-generate `SpacetimeModule::ALL_TABLE_NAMES`, a list of
all the known table names. `subscribe_to_all_tables` then maps across
this list to construct a list of queries in the form `SELECT * FROM
{table_name}`, and subscribes to all of those queries. This has the
upside that defining a new table in the module without regenerating
client bindings will no longer result in the client seeing rows of
tables it does not know about and cannot parse.

## Light mode removed

Light mode is no longer meaningful in the V2 WS format, so all code
related to it is removed.

## Internal changes

### Renamed WS messages

The SDK's internal code is updated to account for various renames:

- `QueryId` -> `QuerySetId`, `query_id` -> `query_set_id`.
- `SubscribeMulti` -> `Subscribe`, `UnsubscribeMulti` -> `Unsubscribe`.

## Incidental changes in this PR, not necessary for other client SDKs

### Don't filter out empty ranges in `RowSizeHint`

The Rust implementation of `RowSizeHint` in `BsatnRowList` got regressed
in the base branch to not work with zero-sized rows. This change fixes
that.

# API and ABI breaking changes

Boy howdy is it!

# Expected complexity level and risk

3? Changes ended up being less complicated than I feared, but we do have
some fiddly code here, and we have internal dependencies on the SDK.

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [x] Updated automated test suite.
  - Known failures:
- [ ] `subscribe_all_select_star`, which is currently broken because
it's trying to subscribe to rows from private tables. #4241 will fix
this.

---------

Co-authored-by: Jeffrey Dallatezza <jeffreydallatezza@gmail.com>
Co-authored-by: = <cloutiertyler@gmail.com>
2026-02-13 01:08:37 +00:00
Tyler Cloutier 57b7ef5e79 Limit update() to only work on primary keys (#4279)
## Summary
- Restricts `update()` across all three server-side SDKs (Rust, C#,
TypeScript) to only work on primary key columns, not all unique columns
- Calling `update()` on a non-PK unique column is semantically a
delete+insert — clients won't see it as a row update unless the primary
key stays the same
- Fresh re-implementation of #1862, extended to cover C# and TypeScript
bindings

### Design principle

Primary key is a constraint on columns, not a property of indexes. An
index is unique or not unique — whether `update()` is available is
derived from the column's attributes at the point of use, not stored on
the index.

This differs from #1862 which introduced a `Uniqueness` enum (`No |
Unique | PrimaryKey`) on the index itself. Instead, we keep `is_unique:
bool` and check the column metadata where needed.

### Rust changes
- Add `PrimaryKey` marker trait and `where Col: PrimaryKey` bound on
`UniqueColumn::update()`
- `marker_type()` receives `primary_key_column` and checks the column
directly — no `is_pk` field on the index
- `sdk-test` unique tables use `update_non_pk_by` (delete+insert)
instead of `update_by`
- Benchmarks that used `update()` on `#[unique]` columns changed to
either `#[primary_key]` or delete+insert

### C# changes
- Only emit `Update()` on `UniqueIndex` when the column has `PrimaryKey`
attrs
- Update `unique_*` test reducers in `sdk-test-cs` to use
`Delete()`+`Insert()` instead

### TypeScript changes
- `UniqueIndex` now has only `find` + `delete` (no `update`)
- `AllColumnsPrimaryKey` type-level helper checks column metadata from
the `TableDef`
- `Index` routing conditionally intersects `{ update() }` when columns
are PK
- Runtime only attaches `update` method for PK unique indexes
- `sdk-test-ts` unique tables use delete+insert instead of update
- Type-level test in `schema.test-d.ts` verifies `id.update()` compiles
(PK) and `name2.update` errors (non-PK unique)

## Test plan
- [x] C# codegen tests pass (`dotnet test
crates/bindings-csharp/Codegen.Tests`)
- [x] Rust SDK test module compiles
- [x] Benchmarks compile
- [x] TypeScript type checks pass (`npx tsc --noEmit`)
- [ ] CI passes

Closes #1862
2026-02-13 00:56:54 +00:00
Jeffrey Dallatezza 626e2090ac Typescript v2 API (#4271)
# Description of Changes

This update the typescript sdk to use the v2 protocol.

The main user-facing API change is removing the existing reducer
callbacks, and instead having reducers return a `Promise`.

# API and ABI breaking changes

The reducer functions `conn.reducers.onX` and `conn.reducers.removeOnX`
no longer exist, and reducers now return `Promise<void>`.

# Expected complexity level and risk

2.5. 

# Testing

This has mostly been tested manually. I'm still updating some of the
unit tests (I commented out the ones that used reducer callbacks).

---------

Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Co-authored-by: = <cloutiertyler@gmail.com>
2026-02-13 00:34:00 +00:00
Noa 59a2824893 [TS] Remove fast-text-encoding polyfill (#4283)
# Description of Changes

Hasn't been needed in months (since #3800), it'd be nice to get it in to
2.0 if possible.

# Expected complexity level and risk

1

# Testing

- [x] Builds successfully
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
2026-02-12 21:01:43 +00:00
Tyler Cloutier 184d4e9d3f Implement server-side support for the v2 websocket protocol (#4213)
# Description of Changes

This adds the v2 websocket protocol and adds support on the server side.
For context on many of the changes/decisions, you can look at the
discussion on https://github.com/clockworklabs/SpacetimeDB/pull/4023.

To restate some of the key changes:
- The reducer event information is no longer sent with transaction
updates (because we don't want to broadcast reducer call information
anymore).
- If a client calls a reducer, they are sent a `ReducerResult` which
includes the outcome of the reducer call and and related row updates for
queries that the client is subscribed to.
- We no longer dedupe queries that appear in multiple query sets for the
same client. This is because we are moving toward per-query storage.
- Related to that, Unsubscribe requests have an option to send the
related rows. We need this for now, since clients don't have per-query
storage implemented yet.
 - We don't have the json format in v2.

Notes for reviewers:
- This moves around the messages in
`crates/client-api-messages/src/websocket` (into `common`, `v1`, and
`v2`), and this renaming of existing messages adds a lot of noise to the
PR.
- In many places, I chose to duplicate a lot of code to have a v1
version and a v2 version. I went with this to make it easier to remove
the v1 version in the future (hopefully we can just fully delete most of
the v1 functions).
- `module_subscription_manager.rs` has probably has the biggest changes,
since we now track queries by query_set_id, and we get to remove some
complexity of v1's FormatSwitch.

<!-- Please describe your change, mention any related tickets, and so on
here. -->

# API and ABI breaking changes

The v1 protocol still works, though we won't send the reducer event info
for v10 modules.

# Expected complexity level and risk

4. This touches a lot of places.

# Testing

Unit testing is pretty minimal for the new code paths. I've done some
manual e2e testing with the typescript quickstart, and this has been
tested with a different branch implementing the v2 rust client.

---------

Co-authored-by: Phoebe Goldman <phoebe@goldman-tribe.org>
Co-authored-by: Jeffrey Dallatezza <jeffreydallatezza@gmail.com>
2026-02-12 20:39:26 +00:00
Alessandro Asoni 12f931e52c Sort version output of spacetime version list (#4250)
# Description of Changes

The output of `spacetime version list` is sorted in alphabetical order,
which is not the correct semver order.
This fixes the order printed, by sorting correctly.

Example before:
```
1.11.0
1.9.0
1.3.0
1.3.1
1.1.2
1.12.0 (current)
1.0.0
```

After:
```
1.12.0 (current)
1.11.0
1.9.0
1.3.1
1.3.0
1.1.2
1.0.0
```

# API and ABI breaking changes

Not an API or ABI breaking change

# Expected complexity level and risk

1

# Testing

Ran `spacetime version list` and `spacetime version list --all` with the
new code and confirmed that the result was correctly sorted.
I additionally tested that if the latest available version was not
installed that it would show with the upgrade hint command.
2026-02-12 20:03:43 +00:00
Phoebe Goldman 8706349047 Expand and correct docs on procedure_http_request ABI function (#3950)
# Description of Changes

Title.

# API and ABI breaking changes

N/a

# Expected complexity level and risk

1

# Testing

- [ ] Get @coolreader18 to confirm what I've written here is correct.
2026-02-12 19:15:28 +00:00
Zeke Foppa 3910b59f08 CI - Fix smoketests using wrong binary path (#4280)
# Description of Changes

The smoketests try to infer whether to use the built `debug` or
`release` binaries.. but the common invocation via `cargo ci smoketests`
always pre-builds the release binaries. This was causing people to test
the wrong binary locally.

# API and ABI breaking changes

None.

# Expected complexity level and risk

1.

# Testing

- [x] CI passes

Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
2026-02-12 19:07:02 +00:00
Mazdak Farrokhzad cd071610af websocket format: use RawIdentifier (#4181)
# Description of Changes

Adjusts the websocket format to use `RawIdentifier` instead of
`Box<str>`, avoiding some allocations in the process.
This seems to be a net gain of 1.5k TPS on phoenix nap.

Based on https://github.com/clockworklabs/SpacetimeDB/pull/4177.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

Covered by existing tests.
2026-02-12 17:28:38 +00:00
John Detter 50295ac865 Version upgrade to 2.0 (#4252)
# Description of Changes

<!-- Please describe your change, mention any related tickets, and so on
here. -->

- Version upgrade to 2.0.

# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

1 - this is just a version bump

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [x] License file has been updated
- [x] CI passing

---------

Signed-off-by: John Detter <4099508+jdetter@users.noreply.github.com>
2026-02-12 16:25:49 +00:00
clockwork-tien 99edb2954c feat: Quickstart and client for TanStack Start (#4107)
# Description of Changes
- Quickstart template `tanstack-ts` and client for TanStack Start
- Add Vue Quickstart Docs

<!-- Please describe your change, mention any related tickets, and so on
here. -->

# Screenshots
- `tanstack-ts` template
<img width="1461" height="898" alt="image"
src="https://github.com/user-attachments/assets/6b7e5473-33c4-4f76-92a7-18607c74422c"
/>

- TanStack Start Quickstart Docs
<img width="1459" height="896" alt="image"
src="https://github.com/user-attachments/assets/b7557498-ff5a-4ce5-9c85-68db943e1b9a"
/>

# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [x] Tested the templates locally (e.g. able to add people), works well
for me
2026-02-12 15:14:32 +00:00
Kim Altintop 914338457e client-api: Resolve organization names via the tld, not the dns table (#4266)
As specified in the proposal.
2026-02-12 12:00:22 +00:00
Noa 253095aab5 Bump rolldown to 1.0.0-rc.3 (#4259)
# Description of Changes

Rolldown likely [won't release 1.0 until after vite
8.0](https://voidzero.dev/posts/announcing-rolldown-rc), but I figure we
should keep up to date somewhat and switch from the beta to the rc.

# Expected complexity level and risk

1

# Testing

- [x] `spacetime build` with typescript modules still works.

---------

Signed-off-by: Noa <coolreader18@gmail.com>
2026-02-12 09:01:39 +00:00
Noa 00560f025e [TS] Throw error objects from syscalls (#4260)
# Description of Changes

This lets us avoid the try/catch around every syscall in javascript.

# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
2026-02-12 08:48:53 +00:00
joshua-spacetime eb2f7a3535 Add missing query builder docs (#4196)
# Description of Changes

Document the client query builder api for rust, csharp, and typescript.
Also add/fix some documentation for the module-side query builder.

# API and ABI breaking changes

N/A

# Expected complexity level and risk

0

# Testing

N/A. Just documentation.

---------

Signed-off-by: joshua-spacetime <josh@clockworklabs.io>
Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
2026-02-12 07:31:15 +00:00
John Detter 2ffe174388 Download from Digital Ocean if Github download fails (#4265)
# Description of Changes

<!-- Please describe your change, mention any related tickets, and so on
here. -->

Since Github has been going down *a lot* recently, we would like to add
support for downloading from our mirror instead. This PR updates:
- The install script for both windows and linux to try the mirror if
Github is down
- The `spacetime version install ...` to install a specific version
- The `spacetime upgrade` which grabs the latest version from Github.

# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

None

# Expected complexity level and risk

3 - This is touching both the windows and linux/macos install scripts
which are quite sensitive. Proper manual testing is needed on this (see
Testing below)

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

For these tests I executed the respective install script locally. To
simulate github being down I set the github download to http instead of
https and then I spun up a local server which returns 500. I also added
a `127.0.0.1 github.com` entry to my hosts file (this works on both
Windows, linux and macOS).

Linux
- [x] Tested that the Github download works normally
- [x] Tested that if Github returns a 500 the digital ocean download
works normally

The download failed here and then it correctly retried with the mirror -
I wasn't able to capture the retry part because it's part of the
progress spinner so it just updates dynamically but this was the final
output:
```
boppy@geralt:~/clockwork/SpacetimeDB$ spacetime-install
The SpacetimeDB command line tool will now be installed:
        CLI configuration directory: /home/boppy/.config/spacetime/
        `spacetime` binary: /home/boppy/.local/bin/spacetime
        directory for installed SpacetimeDB versions: /home/boppy/.local/share/spacetime/bin
        database directory: /home/boppy/.local/share/spacetime/data
Would you like to continue? yes
Downloading latest version...
  Installing v1.12.0: done!                                                                                                                                                                                                                                 The `spacetime` command has been installed as /home/boppy/.local/bin/spacetime

The install process is complete; check out our quickstart guide to get started!
        <https://spacetimedb.com/docs/getting-started>
```

Windows
- [x] Tested that the Github download works normally
- [x] Tested that if Github returns a 500 the digital ocean download
works normally

This worked as well:
```
PS C:\Users\boppy\clockwork\SpacetimeDB\crates\update> .\spacetime-install.ps1
vcruntime140.dll is already installed at C:\WINDOWS\System32\vcruntime140.dll
Downloading installer...
Download failed, trying mirror...
We have added spacetimedb to your Path. You may have to logout and log back in to reload your environment.
```

macOS
- [x] Tested that the Github download works normally
- [x] Tested that if Github returns a 500 the digital ocean download
works normally

```
boppy@Johns-Laptop update % bash ./spacetime-install.sh
Downloading installer...
curl: (22) The requested URL returned error: 500
Download failed, trying mirror...
The SpacetimeDB command line tool will now be installed:
        CLI configuration directory: /Users/boppy/.config/spacetime/
        `spacetime` binary: /Users/boppy/.local/bin/spacetime
        directory for installed SpacetimeDB versions: /Users/boppy/.local/share/spacetime/bin
        database directory: /Users/boppy/.local/share/spacetime/data
Would you like to continue? yes
Downloading latest version...
  Installing v1.12.0: done!
The `spacetime` command has been installed as /Users/boppy/.local/bin/spacetime

The install process is complete; check out our quickstart guide to get started!
        <https://spacetimedb.com/docs/getting-started>
```
2026-02-12 03:48:05 +00:00
Phoebe Goldman 98585e858d Rename with_module_name -> with_database_name (#4267)
# Description of Changes

Modules are like programs, databases are like processes. Your client
connects to a remote database, not a remote module.

<!-- Please describe your change, mention any related tickets, and so on
here. -->

# API and ABI breaking changes

Yep!

# Expected complexity level and risk

2? I made this change with find + replace, and it's possible that I
borked the edit, or missed some reference somehow. It seems unlikely,
however, that this change will have deeper implications we haven't
considered.

# Testing

N/a
2026-02-12 02:11:33 +00:00
bradleyshep 798d17bef6 Keynote Spacetime simulation comparisons (#4072)
# Description of Changes

Adds a comprehensive benchmarking suite for comparing SpacetimeDB
performance against other databases and backends.

**Key features:**
- Load testing framework that runs repeatable benchmarks across multiple
connectors
- Supports SpacetimeDB, PostgreSQL, CockroachDB, SQLite, Supabase,
Convex, and Bun
- Configurable test parameters: duration, concurrency, Zipf distribution
(α) for hot/cold account skew
- Outputs JSON reports with TPS and latency statistics to `./runs/`
- Docker Compose support for containerized benchmarking
- Includes a test SpacetimeDB Rust module (`modules/test-1/server`)

**Connectors included:**
- Direct SQL connectors (Postgres, CockroachDB, SQLite)
- Drizzle ORM wrappers
- RPC-based connectors for network-isolated benchmarking
- SpacetimeDB WebSocket connector
- Supabase and Convex cloud connectors

# API and ABI breaking changes

None. This is a new standalone template with no changes to existing
code.

# Expected complexity level and risk

**1** - This is an additive change that introduces a new isolated
template folder. It has no interactions with existing SpacetimeDB crates
or modules.

# Testing

- [ ] Run `pnpm install` in `templates/keynote-2/`
- [ ] Verify SpacetimeDB module compiles: `cd
templates/keynote-2/modules/test-1/server && cargo build`
- [ ] Run a basic benchmark against SpacetimeDB (requires local
SpacetimeDB instance)

---------

Signed-off-by: bradleyshep <148254416+bradleyshep@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <62310815+github-advanced-security[bot]@users.noreply.github.com>
Co-authored-by: = <cloutiertyler@gmail.com>
2026-02-11 23:43:10 +00:00
Mazdak Farrokhzad c5b2d780f7 TypeScript modules: Expose hash indices (#4233)
# Description of Changes

This allows `.index('hash')`.

# API and ABI breaking changes

None

# Expected complexity level and risk

1

# Testing

Verified that it works using the keynote 2 benchmark.
2026-02-11 22:54:30 +00:00
Noa 7677b5478f [TS] Export reducers, etc from a module (#4220)
# Description of Changes

Haven't changed `schema()` to accept an object yet, maybe that's for a
followup?

Now everything exported from the module must be exported from the
typescript module.

# Expected complexity level and risk

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->
2026-02-11 22:45:36 +00:00
bradleyshep 41d793f904 Deno quickstart (#4191)
# Description of Changes

Adds a Deno quickstart template and documentation.

**Template (`templates/deno-ts/`):**
- `deno.json` with tasks and import map for spacetimedb
- `src/main.ts` using Deno-native APIs (`Deno.stdin`,
`Deno.readTextFile`, `Deno.writeTextFile`, `Deno.env`)
- `spacetimedb/` server module (TypeScript)
- Pre-generated `module_bindings/`

**Documentation
(`docs/docs/00100-intro/00200-quickstarts/00275-deno.md`):**
- Step-by-step quickstart following existing pattern
- Covers project structure, tables/reducers, running the client, CLI
usage
- Documents Deno-specific features: permissions, built-in TypeScript,
import maps, no node_modules
- Explains `--unstable-sloppy-imports` flag (required because generated
bindings use extensionless imports)

# API and ABI breaking changes

None. This is a new template and documentation addition.

# Expected complexity level and risk

**1** - Trivial addition. New template files and documentation only, no
changes to existing code or generator.

# Testing

- [x] Server module publishes successfully
- [x] Bindings generate correctly
- [x] Run `deno task start` and verify connection to SpacetimeDB
- [x] Test interactive CLI commands: add names, `list`, `hello`
2026-02-11 22:04:44 +00:00
clockwork-tien 132112b435 feat: Quickstart and client for Nuxt (#4176)
# Description of Changes

The PR implements the following updates:
- Create `nuxt-ts` template
- Add Nuxt Quickstart Docs

<!-- Please describe your change, mention any related tickets, and so on
here. -->

# Screenshots
- `nuxt-ts` template
<img width="1446" height="894" alt="image"
src="https://github.com/user-attachments/assets/743a946a-3570-4c0b-823a-c919be722d0a"
/>

- Nuxt Quickstart Docs
<img width="1460" height="898" alt="image"
src="https://github.com/user-attachments/assets/a7014d04-6dc1-4e1d-ac39-051c9ef7c09e"
/>


# API and ABI breaking changes

<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->

# Expected complexity level and risk

<!--
How complicated do you think these changes are? Grade on a scale from 1
to 5,
where 1 is a trivial change, and 5 is a deep-reaching and complex
change.

This complexity rating applies not only to the complexity apparent in
the diff,
but also to its interactions with existing and future code.

If you answered more than a 2, explain what is complex about the PR,
and what other components it interacts with in potentially concerning
ways. -->

# Testing

<!-- Describe any testing you've done, and any testing you'd like your
reviewers to do,
so that you're confident that all the changes work as expected! -->

- [ ] <!-- maybe a test you want to do -->
- [ ] <!-- maybe a test you want a reviewer to do, so they can check it
off when they're satisfied. -->

---------

Co-authored-by: = <cloutiertyler@gmail.com>
2026-02-11 20:04:48 +00:00