# Description of Changes
Update pgwire to 0.37
Make `DataRowEncoder` reusable as enabled in this release, make
introduce 3x performance on encoding.
# API and ABI breaking changes
N/A
# Expected complexity level and risk
N/A
# 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. -->
---------
Signed-off-by: Ning Sun <sunning@greptime.com>
Signed-off-by: joshua-spacetime <josh@clockworklabs.io>
Co-authored-by: joshua-spacetime <josh@clockworklabs.io>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
When creating sql queries, we were using the column accessor name,
rather than the name used in the database. This should fix that.
# Expected complexity level and risk
1.
# Testing
This has some unit tests.
# Description of Changes
- Fix issue with back to top button displays incorrectly
- Move the button to bottom left not to overlap with Ask AI
# Demo and screenshots
- After
<img width="1459" height="894" alt="image"
src="https://github.com/user-attachments/assets/75b4edda-dc54-493f-9274-0ca78f10fac7"
/>
https://github.com/user-attachments/assets/4cf7c3f4-51cc-4987-87db-b065ce4f7746
- Before
<img width="173" height="78" alt="image"
src="https://github.com/user-attachments/assets/052be945-fd2b-4276-a129-89c34a6a818b"
/>
<!-- Please describe your change, mention any related tickets, and so on
here. -->
# 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
<!--
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] Back to top button displays correctly and works
Closes#4635
In `crates/client-api/src/routes/database.rs` line 1111,
`lookup_database_identity` returns a `Result` but the error was handled
with `.unwrap()`, which panics instead of returning an HTTP 500.
Replaced it with `.map_err(log_and_500)?` to match the rest of the file.
---------
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Summary
When an HTTP request fails inside a procedure, the error message only
shows something like "error sending request for url (https://...)" with
no details about what actually went wrong.
This change walks the full error chain so the message includes the root
cause — things like DNS failures, connection refused, timeouts, etc.
- Before: error sending request for url (https://httpbin.org/get)
- After: error sending request for url (https://httpbin.org/get): error
trying to connect: dns error: failed to lookup address information:
Fixes#4608
Test plan
- Trigger an HTTP failure in a procedure and check that the error
message now shows the actual reason for the failure
- Existing tests should still pass since this only changes error
formatting
Co-authored-by: Phoebe Goldman <phoebe@clockworklabs.io>
# Description of Changes
- Updated the Unreal SDK and generated Unreal bindings for the websocket
2.0 protocol/model
- Reworked DbConnectionBase to handle the updated message shapes
- Switched subscription handling over to new message types and
QuerySetId
- Updated reducer to ReducerResult, removal of callbacks, and set
reducer flags
- Added event table support
- Baked in multi-module support replacing [the old
PR](<https://github.com/clockworklabs/SpacetimeDB/pull/3417>)
- Added functionality to generate module support for multiple folders in
the Unreal project (add <module>.Build.cs, <module>.h, <module>.cpp)
using the --module-name
- Add new configuration option for spacetime generate to handle module
prefix
- Regenerated Unreal Blackholio/TestClient/QuickstartChat bindings
- Rebuilt Unreal Blackholio's consume entity to use event tables
- Updated migration documentation
- Updated the version bump tool to impact C++
# API and ABI breaking changes
- Unreal websocket/message handling updated to the new protocol
- Unreal generation now expects a real .uproject target and will stop
immediately if project
metadata is invalid instead of continuing past setup issues.
# Expected complexity level and risk
3 - A large set of changes to update the websocket/message handling
along with heavy codegen changes to handle multi-module support
# Testing
Test coverage of the Unreal SDK will need expansion in a future ticket
once our issues with flakiness on CI is resolved.
- [x] Updated Unreal Blackholio
- [x] Ran full Unreal SDK test suite
- [x] Built new test project using the new `--module-prefix`
- [x] Run through Unreal Blackholio (C++ and Blueprint)
- [x] Rebuilt Unreal Blackholio with multi-module, and duplicate
generated module testing side-by-side modules that would overlap
# Review Question(s)
- [x] Updates to `spacetime init` have made the tutorial a little
confusing with pathing for the Unreal Blackholio tutorial. To fix though
we'd have to update all the commands to be more explicit, or update the
tutorial `spacetime init` to use `--project-path .` to keep pathing
simpler, thoughts?
---------
Signed-off-by: Jason Larabie <jason@clockworklabs.io>
Co-authored-by: Ryan <r.ekhoff@clockworklabs.io>
# Description of Changes
Cpp-related tutorial stale links correction in Readme.
# API and ABI breaking changes
None
# Expected complexity level and risk
0
# Testing
N/A (?)
Signed-off-by: Leonid Satanovsky (home profile) <539045+leosat@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
Fixes a bug during view cleanup where we would drop anonymous views that
had live subscribers.
The reason for this bug is that the `st_view_sub` does not have a single
entry for an anonymous view. Rather it has multiple entries - one per
identity subscribed. However the code was assuming only a single entry
per anonymous view, and so when view cleanup ran, we would only look at
the first entry in `st_view_sub` for an anonymous view, and if there
were no subscribers, we would drop the view's backing table and read
set. But there could still have been other clients subscribed to that
view, at which point they would stop receiving updates.
This change fixes the bug by making sure there aren't any rows in
`st_view_sub` with live subscribers before dropping the anonymous view's
backing table and read set.
The better fix would be to update `st_view_sub` so that there's only
ever at most one row per anonymous view. Unfortunately `st_view_sub`
mixes both anonymous and sender-scoped views, and the `sender` column is
of type `Identity`, not `Option<Identity>`. Instead of adding a new
system table to correct this, I chose to keep using `st_view_sub` and
delay this refactor until we add support for view parameters.
# API and ABI breaking changes
None
# Expected complexity level and risk
1.5
# Testing
Added regression tests that assert on the underlying system table rows.
A smoketest was **not** added because cleanup runs periodically and
currently there's no way to force a clean up.
# Description of Changes
This bug was introduced when we added the v2 subscription protocol.
Before this change, when a v2 client disconnected or unsubscribed, other
clients could stop receiving updates for sender-scoped views they were
subscribed to.
This happened because `SubscriptionManager::remove_all_subscriptions()`
was cleaning up v2 subscription state correctly, but we would also run
the legacy v1 cleanup loop which mixed v1 and v2 queries. This meant the
same query hash could be processed again in the v1 cleanup loop after
the v2 removal had already happened. In the sender-view case, that
second pass could remove metadata (`indexes` / `search_args`) for active
subscribers.
Specifically, we could have the following sequence:
1. Client B disconnects.
2. The v2 loop removes B’s v2 subscription for `query_hash`.
3. `query_hash` now has no subscribers, so
`remove_query_from_tables(query_hash)` runs once.
4. That compatibility loop then visits `query_hash` again via
`subscription_ref_count.keys()`.
5. `query_hash` still has no subscribers, so
`remove_query_from_tables(query_hash)` runs a second time.
and when `remove_query_from_tables(query_hash)` runs a 2nd time, it
calls `index_ids.delete_index_ids_for_query()` which is refcounted, not
idempotent. So calling it twice for the same query decrements the shared
index count twice, and the 2nd decrement drops an index that client A’s
query still needs.
The fix was to:
1. Collect the disconnected client’s v1 query hashes from
`client_info.v1_subscriptions`
2. Run the v2 cleanup loop over `client_info.v2_subscriptions` (as we
did before this change)
3. Run the old compatibility cleanup loop only over the deduplicated v1
hashes
# API and ABI breaking changes
None
# Expected complexity level and risk
2
Small fix to a rather intricate bug. Most of the code in this patch is
testing code.
# Testing
This bug was not reproducible with the current smoketest harness,
because `spacetime subscribe` still uses the `v1` subscription protocol.
I added a Rust SDK test, which did reproduce the bug before the fix,
because the Rust SDK uses the `v2` subscription protocol.
The commitlog so far assumed that the latest segment is never compressed
and can be opened for writing (if it is intact).
However, restoring the entire commitlog from cold storage results in all
segments being compressed. Make it so the resumption logic reads the
metadata from the potentially compressed last segment, and starts a new
segment for writing if the latest one was indeed compressed.
# Expected complexity level and risk
1.5
# Testing
Added a test.
# Description of Changes
Fixes a bug where clients subscribed through views could miss delete
updates when a one-shot scheduled reducer or procedure completed and the
scheduler automatically deleted the corresponding schedule row. This
patch ensures that scheduled-row cleanup refreshes any stale views
before commit/broadcast.
Note, this only affected one-shot schedules. Interval schedules do not
delete their schedule row after each run, so they were not going through
this path.
# API and ABI breaking changes
None
# Expected complexity level and risk
1.5
# Testing
Added regression coverage for:
- one-shot scheduled reducer: table + view subscription sees insert then
delete
- one-shot scheduled procedure: table + view subscription sees insert
then delete
- failing scheduled reducer: cleanup still refreshes the dependent view
delete
- observe transitive scheduled table updates through join
The one-shot tests now assert on the scheduled table and dependent view
in the same subscription updates, which proves the delete comes from the
automatic cleanup transaction itself rather than a later manual write.
# Description of Changes
Adds `count` to rust's procedural view API.
This API already existed in C# and typescript. This patch just adds
tests for those module languages.
We were already tracking reads for `count`, and so all this patch does
is add the new rust module bindings.
# API and ABI breaking changes
None
# Expected complexity level and risk
1
# Testing
Smoketests for rust, C#, and typescript.
# Description of Changes
Adds a new reference documentation page for `spacetime.json` and fixes
several bugs where the CLI behavior diverged from the proposal.
**Docs:**
- New page at `/cli-reference/spacetime-json` covering config structure,
field reference, generate configuration, children/inheritance,
`spacetime dev` config, database selection, flag overrides,
`--no-config`, `--env`/environments, config file discovery, and editor
support
**Bug fixes:**
- `generate` was incorrectly inherited by child databases. A child with
a different `module-path` would silently inherit the parent's generate
entries, causing bindings to be written to the wrong output directory.
Generate is now never inherited, matching the proposal.
- The source conflict rule for `module-path`/`bin-path`/`js-path` was
not implemented during inheritance. A child specifying `module-path`
could still inherit `bin-path` from the parent. Now, if a child
specifies any module source, the others are not inherited.
- `--num-replicas` was not marked as a per-database override, so it
could be used with multiple databases selected without error.
# API and ABI breaking changes
None. These are bug fixes aligning the implementation with the intended
behavior from the proposal:
- `generate` inheritance was never documented or intended
- The source conflict rule was specified in the proposal but not
implemented
- `--num-replicas` as per-database is consistent with the other
module-source flags
# Expected complexity level and risk
2 - The changes are small and well-scoped. The generate inheritance fix
simplifies the code (removes a parameter). The source conflict rule adds
a straightforward check during field inheritance. Tests have been
updated to match.
# Testing
- [x] All 136 existing CLI tests pass
- [x] Updated tests for generate non-inheritance behavior
- [x] Docs site builds successfully, page renders in sidebar
- [ ] Manual test: verify a child with a different `module-path` no
longer inherits parent's `generate`
- [ ] Manual test: verify `--num-replicas` errors when multiple
databases are selected
---------
Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Phoebe Goldman <phoebe@clockworklabs.io>
Co-authored-by: John Detter <4099508+jdetter@users.noreply.github.com>
Fixes#4559.
## Bug
The `subscribe` callback passed to `useSyncExternalStore` captures
`computeSnapshot` in its closure but did not list it as a dependency.
When `subscribeApplied` flips to `true`:
1. `computeSnapshot` is recreated with `subscribeApplied = true`
2. But `subscribe` still holds the **stale** closure that captured
`subscribeApplied = false`
3. On the next row event, the stale `computeSnapshot` writes `[rows,
false]` into `lastSnapshotRef`
4. `isReady` drops to `false` permanently
## Fix
Add `computeSnapshot` to the `subscribe` dependency array so event
handlers always use the current snapshot function.
Note: PR #4499 previously fixed a related issue where the cached
snapshot was stale after `subscribeApplied` changed. This fix addresses
the remaining case where the `subscribe` closure itself was stale.
---------
Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
Updates the reference docs with the implications of primary key
inference for query builder views, implemented in #4572, #4573, #4614.
# API and ABI breaking changes
None
# Expected complexity level and risk
1. Docs only change
# Testing
N/A
# Description of Changes
Fixes the `reducers.onTransfer is not a function` error - that was old
code left from the 1.x sdk. Also, regenerate the module_bindings and
make sure the rust and typescript modules are identical in that respect.
# Expected complexity level and risk
1
# Testing
- [x] Verified that `spacetime generate --lang typescript --module-path
spacetimedb --out-dir module_bindings` and `spacetime generate --lang
typescript --module-path rust_module --out-dir module_bindings` give the
same output.
- [x] Setting `USE_SPACETIME_METRICS_ENDPOINT` to `0` no longer causes
the error.
Relates to #4608
## Timeout bump
The previous defaults for HTTP requests in procedures were far too
restrictive:
| | Before | After |
|---|---|---|
| Default (no timeout set) | 500ms | **30s** |
| Maximum (clamp ceiling) | 10s | **180s** |
Users are hitting the 10s ceiling when calling LLM APIs (OpenAI, Gemini,
etc.) from procedures. These APIs routinely take 30-120 seconds,
especially for image/vision models. The 500ms default also caused silent
failures for users who did not explicitly set a timeout.
### Comparable platforms
- **Supabase Edge Functions**: 150s (free) / 400s (pro) total execution
- **Vercel Functions**: 10s (hobby) / 60s (pro) / 300s (enterprise)
total
- **Convex actions**: 120s limit
- **AWS Lambda**: up to 15 min total
- **Firebase/GCF**: 60s default, configurable up to 540s
Most platforms do not separately clamp outbound HTTP timeouts at all.
## Docs fix
The procedures docs page had a note inside the C++ tab only that said
`All timeouts are clamped to a maximum of 500ms by the host`. This was
wrong (the max was 10s, not 500ms) and buried in the wrong place
(applies to all languages, not just C++).
Moved the note outside the language tabs and updated the values to match
the new code.
### Changes
- `crates/core/src/host/instance_env.rs`: `HTTP_DEFAULT_TIMEOUT` 500ms →
30s, `HTTP_MAX_TIMEOUT` 10s → 180s
- `docs/.../procedures.md`: Fix and relocate timeout note
---------
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
# Description of Changes
Same change set as
https://github.com/clockworklabs/SpacetimeDB/pull/4614, just targeting
master.
The return type of a query builder view is now a special SATS product
type `{ __query__: T }`. A view with this return type now has a primary
key if `T` has a primary key. This means that client codegen will
generate an `OnUpdate` callback for such views. It will also generate
query builder index bindings for the primary key column.
# API and ABI breaking changes
None. Old modules with query builder views still work, they just don't
have primary keys.
# Expected complexity level and risk
2
# Testing
Added equivalent tests to the ones that were added in #4573 and #4572.
# Description of Changes
<!-- Please describe your change, mention any related tickets, and so on
here. -->
- Bumps version to 2.0.5
# API and ABI breaking changes
None - this is just a version bump
<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->
# Expected complexity level and risk
1 - 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 properly updated, including the date change
- [x] CI is passing other than the internal check
Prior to #4549 the host type in `st_module` was always set to wasm. We
now correctly use the host type from the database, but the module may in
fact be a JS module. So if launching it as a wasm module fails, try JS
instead. If this succeeds, the module is definitely a JS module, so
attempt to repair `st_module` in this case.
# Expected complexity level and risk
2
# Testing
- [x] Added smoketest
# Description of Changes
Upgrades the rust SDK's prometheus dependency from 0.13 to 0.14.
Fixes https://github.com/clockworklabs/SpacetimeDB/issues/4597
# API and ABI breaking changes
[The prometheus
changelog](https://github.com/tikv/rust-prometheus/blob/master/CHANGELOG.md#0140)
claims that the MSRV for the new version is 1.82, but this project
doesn't seem to have an official MSRV, so I don't think that's an ABI
change.
I don't think depending on a different prometheus version is itself a
breaking change. Prometheus is exposed through the rust SDK, but in an
explicitly [unstable
module](https://github.com/clockworklabs/SpacetimeDB/blob/3f58b5951bf3c49971c51aecb526439597b9c044/sdks/rust/src/lib.rs#L69-L76)
which "may change incompatibly without a major version bump". Prometheus
structs are also exposed from several crates, but with the same
disclaimers about unstable interfaces.
# Expected complexity level and risk
1. This is a module bump with simple-looking changes.
# Testing
- [x] Just confirmed everything still compiles and the tests still pass
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
This fixes an Issue in the Rust [Chat App
Tutorial](https://spacetimedb.com/docs/tutorials/chat-app#creating-the-client),
that is caused by the [Event Type
Changes](https://spacetimedb.com/docs/upgrade/?client-language=rust&server-language=rust#event-type-changes)
in 2.0
This resulted in other clients not receiving new messages, since they
are now Event::Transaction and no longer included within the
Event::Reducer
# API and ABI breaking changes
<!-- If this is an API or ABI breaking change, please apply the
corresponding GitHub label. -->
I don't think any? I only changed a tutorial, the real change was in 2.0
# Expected complexity level and risk
1
# Testing
- [x] I ran the Tutorial app with these changes and messages started to
appear as expected on the second client when writing something on the
first.
There might be more places where this is an Issue, I just noticed this
one while following the Tutorial.
---------
Signed-off-by: Frederik <39029799+OMGeeky@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: Phoebe Goldman <phoebe@clockworklabs.io>
# Description of Changes
This change exports the Range (and Bound) types so that ranged filtering
can be done from Typescript modules. I chose to do export * so that both
Range and Bounds are included and I chose to not export as types since
the user will need to instantiate a Range for use in a query
# API and ABI breaking changes
None
# Expected complexity level and risk
1
It seems like this export was just missed as the [documentation for
range
queries](https://spacetimedb.com/docs/tables/indexes/#range-queries)
makes reference to them, but I was unable to import them as it
recommends (or at all)
# Testing
At the time of writing, I haven't tested the fix yet, I'll see if I can
get a local copy of spacetime built and validate I can now imports
Ranges.
---------
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
In the Rust client SDK, with this PR, doing
`.with_debug_to_file("path.txt")` on the connection builder will result
in the SDK logging additional verbose info to `path.txt`.
# API and ABI breaking changes
Adds a new user-facing-ish API to the Rust client SDK.
# Expected complexity level and risk
2? Some possibility of deadlock due to adding a new mutex, but this is
explicitly not for production use.
# Testing
- [x] Ran `chat-console-rs` locally with this enabled and got some debug
logs out of it.
The PR approval check workflow uses `pull_request`, which does not grant
the `GITHUB_TOKEN` write permissions for commit statuses on fork PRs.
This causes the check to silently fail on external contributions.
Switches to `pull_request_target`, which runs in the context of the base
branch and has the necessary permissions.
**Security notes** (also documented as comments in the workflow file):
- `pull_request_target` grants write access to the repository. This is
safe here because the workflow **only reads PR metadata via the GitHub
API** and never checks out, builds, or executes code from the PR branch.
- A clear `SECURITY` comment block at the top of the file explains why
`pull_request_target` is used and warns against adding a checkout step.
- An additional inline comment on the job warns against adding checkout
steps.
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
# Description of Changes
Fixes a bug in client disconnect logic that would mark a client's views
as dropped(unsubscribed). However it was marking the identity's views as
dropped, not the connection. So if an identity had multiple connections
open, each subscribing to different views, and one of them disconnected,
the subscriptions for the other connections would break. The observed
behavior would be that they would stop receiving subscription updates.
This could potentially lead to their client cache getting into a
corrupted state.
Now, instead of dropping all of the views for a particular identity on
disconnect, we drop only the views for that particular connection. And
when I say drop, what I really mean is decrement. A view is not dropped
completely unless it no longer had any subscribers.
# API and ABI breaking changes
None
# Expected complexity level and risk
2
# Testing
Regression smoketest was added
# Description of Changes
Query builder views return a subset of rows from a physical table. If
that table has a primary key, then so should the view. What this means
concretely is that the view should expose the same api as the table,
specifically as it relates to the primary key column.
With that in mind, this patch commits the following changes:
1. Annotates `ViewDef` with a `primary_key`
2. Updates the return type of query builder views in the raw module def
to a special product type
3. Adds an index for the primary key on the view's backing table
4. Updates the query planner to use this index
5. Updates rust client codegen to generate `on_update` for such views
# API and ABI breaking changes
None
Old `impl Query` views compiled with an older version of SpacetimeDB
will continue to work as they did before - without a primary key.
# Expected complexity level and risk
3
# Testing
- [x] New rust sdk integration suite exercising `on_update` for PK views
and semijoin scenarios
- [x] Smoketests for PK views and semijoin scenarios
# Description of Changes
It doesn't have permission to run on external PRs, but that's kinda okay
since external PRs are rarely authored by clockwork-labs-bot anyway.
# API and ABI breaking changes
None.
# Expected complexity level and risk
1
# Testing
None
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
# Description of Changes
`and` and `or` are scoped to only a single table. So using them in a
semijoin with two tables will fail to compile. Previously this resulted
in a gnarly error message (see #4586). This patch improves the error
message.
# API and ABI breaking changes
None
# Expected complexity level and risk
2
# Testing
Adds error message assertion tests.
Fixes#4591
## Root Cause
The `isFixedSizeProduct` fast-path deserializer in `algebraic_type.ts`
maps `Bool` to `view.getUint8()`, which returns a **number** (0 or 1)
instead of a JavaScript **boolean**. The slow path (`reader.readBool()`)
correctly converts via `!== 0`.
This means any product type containing only fixed-size primitives
(bools, ints, floats) hits the fast path and returns numbers for boolean
fields. Products containing strings, arrays, or nested objects go
through the slow path and work correctly.
This explains the inconsistency in the issue: a flat `{ foo: bool }`
returns `{ foo: 1 }`, but adding a nested object pushes it to the slow
path where `foo` becomes `true` (though the nested bool still hits the
fast path within its own product).
## Fix
Special-case `Bool` in the fast-path code generation to emit:
```js
result.foo = view.getUint8(reader.offset) !== 0;
```
instead of:
```js
result.foo = view.getUint8(reader.offset);
```
One-line change in the ternary within `makeDeserializer`.
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
<!-- Please describe your change, mention any related tickets, and so on
here. -->
- Bumps version to 2.0.4
# API and ABI breaking changes
None - this is just a version bump
<!-- 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 with correct version + time
---------
Signed-off-by: John Detter <4099508+jdetter@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
This shouldn't actually be required in the long-term, because it runs on
new PRs and any label changes, but the case where it _is_ required? PRs
that are currently already open and merge in `master`. That triggers a
`synchronize` event but not any of the events that this check runs on.
Sigh.
# API and ABI breaking changes
None
# Expected complexity level and risk
1
# Testing
None
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
# Description of Changes
`cargo ci lint` was running `cargo fmt`, but that didn't pick up all
files. As a result, our pre-commit hook (which just runs `rustfmt` on
any changed `.rs` files) would change otherwise-untouched files in merge
commits.
This PR addresses that discrepancy by having `cargo ci lint` run
`rustfmt` on all tracked `.rs` files.
The entire diff is just `rustfmt` changes except for the changes in
`tools/ci/src/main.rs`.
# 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
2
# Testing
- [x] `cargo ci lint` fails
- [x] `cargo ci lint` passes after running `rustfmt` on everything
- [x] `cargo fmt --all` doesn't cause any diff after doing the above
---------
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
# Description of Changes
The CI check for the Do Not Merge label was only running on label-change
events, so if a PR never received a label (any label), the check would
never run. This meant that the check couldn't be marked required because
it was missing on PRs that were never labeled anything.
Additionally, the check was not configured to run properly in the merge
queue, so it would have blocked the merge queue if it were a required
check.
This PR fixes those issues by making the check run on more pull request
events, and by trivially succeeding in the merge queue.
This enables the check to be made required.
# API and ABI breaking changes
None. CI only.
# Expected complexity level and risk
1
# Testing
- [x] The check is now showing as run on this PR
- [x] The check still fails if I add a "do not merge" label
---------
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Fixes two issues that would prevent updating a database while also
changing the host type:
- We never actually updated the `ModuleKind` in `st_module` (hardcoded
to wasm)
- We never actually honored the value from `st_module` when
instantiating a module
To do so, the `Program` type from the datastore crate now carries the
`ModuleKind`, forcing call sites to make a decision.
Small adjustments to the smoketests / guard crate where made when
writing the test for this.
# Expected complexity level and risk
1
# Testing
- [x] Added smoketest
# Description of Changes
These have been running alongside the Rust smoketests for a while, and
we feel fairly confident that the Rust ones are doing a good job.
(However, I leave them in the repo because we still use them elsewhere).
# 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
# Testing
None
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
## Bug
PR #4367 (login/logout UX overhaul) accidentally removed the early
`return Ok(())` after saving a token via `spacetime login --token`. This
caused the command to fall through into the web login flow
(`spacetimedb_login_and_save`), which fails when no browser or server is
available.
## Impact
All tests that use `spacetime login --token` are broken:
- 4 replication tests (`test_enable_disable_replication`,
`test_enable_replication_on_suspended_database`,
`test_enable_replication_fails_if_not_suspended`, `test_prefer_leader`)
- 5 teams tests (`test_permissions_clear_org`,
`test_permissions_delete_org`,
`test_org_permissions_mut_sql_org_members`,
`test_org_permissions_private_tables`,
`test_permissions_publish_org_members`)
## Fix
One line: restore `return Ok(())` after the `--token` branch.
---------
Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
The previous version ended up incurring two different entries on the PR
(one for the `pull_request` event and one for the `pull_request_review`
event). Both versions were marked "required", so PRs could end up in an
unmergeable state if one check had succeeded but the other had failed
(e.g. if you submitted a PR approval, the previous `pull_request`
version of the check would still be failed since it didn't refresh).
See the entries at top and bottom here:
<img width="481" height="225" alt="image"
src="https://github.com/user-attachments/assets/5b7a4302-6bc2-47e9-93c8-812cb9ece60b"
/>
This PR fixes it by only allowing the `pull_request_review` events. I
_think_ this covers all the cases, but I'm not sure.
# API and ABI breaking changes
None.
# Expected complexity level and risk
1
# Testing
I don't know how to test it really 🤷
---------
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Audited all registered routes in `database.rs` and `identity.rs` against
the HTTP API documentation.
## Fixes
**database.md:**
- `/v1/database/:name_or_identity` publish: `POST` → `PUT` (code has
`db_put: put(publish::<S>)`)
- `DELETE` row in summary table: anchor pointed to POST section instead
of DELETE section
- Typo: `Updgrade` → `Upgrade` in WebSocket subscribe headers
**identity.md:**
- Removed `POST /v1/identity/:identity/set-email` — documented but has
no handler registered in `IdentityRoutes` (dead documentation)
## Routes in code but intentionally not documented (internal/unstable)
- `POST /v1/database/:noi/pre_publish`
- `PUT /v1/database/:noi/reset`
- `GET /v1/database/:noi/unstable/timestamp`
These are used internally by the CLI and are not part of the public API.
---------
Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
# Description of Changes
PRs created by `clockwork-labs-bot` require 2 approvals.
After merging, we would need to make this check required.
# API and ABI breaking changes
CI only.
# Expected complexity level and risk
1. This is copy-pasted and simplified from another repo that has the
same workflow.
# Testing
None
---------
Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
## Summary
Improves the `spacetime login` and `spacetime logout` UX to behave more
like standard CLI tools.
### `spacetime login`
**Before:** If already logged in, prints "You are already logged in" and
exits. User must manually run `logout` first.
**After:** If already logged in, automatically logs out the previous
session and proceeds with a fresh login. Prints the old identity being
logged out and the new identity on success.
```
$ spacetime login
Logged out of previous session (identity 0xabc...).
Opening https://spacetimedb.com/login/cli?token=... in your browser.
Waiting to hear response from the server...
Logged in with identity 0xdef...
```
### `spacetime logout`
**Before:** No output on success. Hard failure if offline.
**After:**
- Prints confirmation: `Logged out (identity 0xabc...).`
- Prints `You are not logged in.` if already logged out
- Best-effort server-side session invalidation with 5s timeout (prints
warning if offline instead of failing)
### Changes
- `login.rs`: Remove `spacetimedb_token_cached` early-return; instead
log out previous session and proceed. Show identity on login success.
- `logout.rs`: Add identity display, not-logged-in check, 5s timeout for
server call with warning on failure.
Note: This subsumes the offline fix from #4361.
---------
Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
## Summary
Adds a version update check to the `spacetimedb-update` proxy, so users
are notified when a newer version of SpacetimeDB is available.
## Changes
Adds `crates/update/src/update_notice.rs` — a lightweight update check
that runs in the proxy path before exec'ing the CLI:
- **Cache-based**: Stores the last check result in
`~/.spacetime/.update_check_cache`. Only hits the network once every 24
hours.
- **Non-blocking on cache hit**: If the cache is fresh, it's a single
file read — no network, no delay.
- **Short timeout**: When the cache is stale, makes a single HTTP
request to GitHub releases API with a 5-second timeout. Uses the same
`SPACETIME_UPDATE_RELEASES_URL` env var as `spacetime version upgrade`.
- **Best-effort**: Any failure (network, parse, file I/O) is silently
ignored. The update check never interferes with the user's command.
- **Uses semver**: Proper version comparison via the `semver` crate
(already a dependency).
## Output
When a newer version is available:
```
A new version of SpacetimeDB is available: v2.1.0 (current: v2.0.0)
Run `spacetime version upgrade` to update.
```
# Testing
- [x] I get a warning if my local version is less than 2.0.2
- [x] If I have a cached update check, I get the same error even if I
have no network connection
- [x] if the cache is old, the next command checks again
- [x] if I'm not connected and the cache is stale, I'm still able to use
the CLI
---------
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <bot@clockworklabs.com>
Co-authored-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
The README was significantly out of date. This overhaul brings it in
line with the current docs and product state.
## What changed
**Content updates:**
- "What is SpacetimeDB" now mentions all 4 module languages (Rust, C#,
TypeScript, C++) instead of only Rust
- Removed the smart contracts comparison (outdated framing)
- Updated BitCraft description to match current docs wording
- Shortened the architecture description to be punchier
**New Quick Start section:**
- 5-step flow: install, login, init, dev, publish
- Introduces `spacetime dev` (the primary local development experience)
- Introduces `spacetime publish` to Maincloud
- Much more approachable than the old "Installation" wall of text
**New "How It Works" section:**
- Rust module code example showing tables and reducers
- TypeScript client code example showing `useTable` subscriptions
- Shows the core value prop in < 20 lines of code
**Language support:**
- Added TypeScript and C++ as server module languages
- Added Unreal Engine (C++) as a client SDK
- Listed all supported web frameworks (React, Next.js, Vue, Svelte,
Angular, Node.js, Bun, Deno)
- Fixed all doc links to current URL patterns (`/docs/quickstarts/...`)
**Build from source:**
- Collapsed into expandable `<details>` sections (macOS/Linux and
Windows)
- Removed duplicate Git for Windows instructions
- Still complete, just not the first thing you see
**Badges:**
- Added npm download count badge for the TypeScript SDK
**License:**
- Shortened to essentials with link to full license file
---------
Signed-off-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
Co-authored-by: clockwork-labs-bot <clockwork-labs-bot@users.noreply.github.com>
Co-authored-by: Tyler Cloutier <cloutiertyler@users.noreply.github.com>
# Description of Changes
We apparently have stale usage of `--project-path` in a ton of our
templates. This was renamed to `module-path` a while ago, but it looks
like that was only partially fixed in templates.
# API and ABI breaking changes
None
# Expected complexity level and risk
1
# Testing
I don't think it's _more_ broken 🤷
---------
Signed-off-by: Zeke Foppa <196249+bfops@users.noreply.github.com>
Co-authored-by: Zeke Foppa <bfops@users.noreply.github.com>
# Description of Changes
Adds implicit query builder conversions from `bool` to `BoolExpr` so
that you can write:
```rust
ctx.from.user().r#where(|u| u.online)
```
instead of
```rust
ctx.from.user().r#where(|u| u.online.eq(true))
```
Also removes `NullableCol` and `NullableIxCol` types from C# query
builder.
# API and ABI breaking changes
None
# Expected complexity level and risk
1
# Testing
Unit and smoketests