Skip to content

feat(spacetimedb): typed SpacetimeDB provider - #1044

Open
Cyberistic wants to merge 5 commits into
alchemy-run:mainfrom
Cyberistic:feat/spacetimedb-maincloud
Open

feat(spacetimedb): typed SpacetimeDB provider#1044
Cyberistic wants to merge 5 commits into
alchemy-run:mainfrom
Cyberistic:feat/spacetimedb-maincloud

Conversation

@Cyberistic

@Cyberistic Cyberistic commented Aug 2, 2026

Copy link
Copy Markdown

PR in case it's useful to the devs, close as "not planned" if needed. Code mirror lives in https://github.com/Cyberistic/alchemy-spacetimedb-provider

tested most functionalities in a real app, and fixed regressions found.

here's your ai slop summary:

SpacetimeDB provider — typed modules, bindings, and realtime connections as Alchemy resources.

// packages/alchemy/src/SpacetimeDB/index.ts
export const Database = Resource<Database>("SpacetimeDB.Database", {
  defaultRemovalPolicy: "retain",
});

export const Connect = Binding.Service<Connect>("SpacetimeDB.Connect");

export const DatabaseProvider = () =>
  ProviderLayer.dual(Database, {
    live: () => DatabaseProviderLive(),
    local: () => Layer.unwrap(Effect.promise(() =>
      import("./LocalDatabase.ts").then((m) => m.DatabaseProviderLocal()),
    )),
  });

A new packages/alchemy/src/SpacetimeDB/ package ships four resources, four binding services, and a runtime tag parameterized by name:

  • SpacetimeDB.Database publishes a module to Maincloud (or a configured host). Defaults to retain so data is not deleted on alchemy destroy; opt in via destroy().
  • SpacetimeDB.Generate runs spacetime generate to emit typed client bindings; module-content-hash aware so subsequent deploys detect stale clients.
  • SpacetimeDB.Project writes spacetime.json + spacetime.local.json for multi-database projects.
  • SpacetimeDB.SpacetimeAuthProject tracks an OIDC client config (config-only — the SpacetimeAuth dashboard is the source of truth for client provisioning).
  • SpacetimeDB.Connect is a Binding.Service that hands a Worker env-var bundle (SPACETIMEDB_*_URI, _DATABASE_NAME, _TOKEN, _HOST, _DASHBOARD_URL) — the token makes in-Worker DbConnections authenticated.
  • Connection<C>("name") is a Context.Tag parameterized by name so two connections in one app don't collide.

alchemy dev boots a sidecar that runs spacetime dev --server-only on 127.0.0.1:3000, watching modulePath for hot-reload. SpacetimeDB.viteEnv(db) inlines coordinates into a Vite SPA bundle.

// examples/cloudflare-spacetimedb-todo/alchemy.run.ts
export const Todos = SpacetimeDB.Database("Todos", {
  name: "alchemy-todo",
  modulePath: "./spacetimedb",
});

export const ClientBindings = SpacetimeDB.Generate("ClientBindings", {
  lang: "typescript",
  outDir: "./src/module_bindings",
  modulePath: "./spacetimedb",
});

export const Api = Cloudflare.Worker("Api", {
  main: "./worker/api.ts",
  env: { SPACETIMEDB: Todos },
});

69 unit tests cover CLI helpers, HTTP client, runtime, naming, browser token persistence, and the live provider (mocked HTTP).

Notable design choices

  • Database defaults to retain (same as GitHub.Repository); user-visible breaking change vs. a destroy default — call it out in the release notes.
  • A single envName / fnv1a64 implementation in packages/alchemy/src/Util/EnvName.ts is now shared by SpacetimeDB.Connect and Prisma.Connect/Prisma.Connection (was duplicated).
  • connect/refresh ergonomics flow through a Connect binding so a Worker gets a typed client without env-var gymnastics.
  • Live mode is the same code path the prior Database.ts was shaping (HTTP + CLI); local mode spawns the dev server.

Outstanding:

  • No live-suite tests (planned in plans/014-local-and-live-test-suites.md, deferred — requires a live SpacetimeDB CLI + Maincloud token).
  • Generated API reference pages under website/src/content/docs/providers/SpacetimeDB/ are gitignored per repo convention; CI regenerates them from resource JSDoc via bun docs:gen.
  • SpacetimeAuth is config-as-code only — there is no public create API yet (beta).

Run locally:

spacetime login show --token
export SPACETIMEDB_TOKEN="<token>"
cd examples/cloudflare-spacetimedb-todo
bun install
bun alchemy dev

Cyberistic and others added 4 commits August 3, 2026 00:38
Adds a typed SpacetimeDB provider to Alchemy with Database, Generate, Project, SpacetimeAuthProject resources; Connect binding service; in-Worker DbConnection runtime; browser-side token persistence; per-database Connection tags. Local mode spawns 'spacetime dev --server-only'. 69 unit tests cover CLI helpers, HTTP client, runtime, naming, browsers, and the live provider.
Adds website/src/content/docs/spacetimedb/{index,getting-started}.mdx walking through Database → Generate → Worker → Vite SPA flow, auth setup, removal policy, and browser token persistence. Each step is one concept per heading (per AGENTS.md tutorial standard). Generated provider markdown under website/src/content/docs/providers/SpacetimeDB/ is gitignored and regenerated by 'bun docs:gen' from resource JSDoc.
Adds examples/cloudflare-spacetimedb-todo — an end-to-end todo app that wires SpacetimeDB.Database + Generate + Cloudflare Worker + Vite SPA in a single Alchemy Stack. Includes an activity table, ownership checks on reducers, and on_connect lifecycle. Gitignore keeps node_modules / .alchemy / generated module_bindings / spacetime config out of the working tree.
@Cyberistic
Cyberistic marked this pull request as ready for review August 2, 2026 22:12
Copilot AI review requested due to automatic review settings August 2, 2026 22:12

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a first-class SpacetimeDB provider to Alchemy, including typed resources/bindings, local-dev support, and a Cloudflare + SpacetimeDB todo example plus docs.

Changes:

  • Introduce a new packages/alchemy/src/SpacetimeDB/ surface (resources, bindings, runtime helpers, auth provider, local provider sidecar entry).
  • Add extensive unit tests for the SpacetimeDB provider modules.
  • Add new docs pages under website/src/content/docs/spacetimedb/ and a full example app under examples/cloudflare-spacetimedb-todo/.

Reviewed changes

Copilot reviewed 51 out of 52 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
website/src/content/docs/spacetimedb/index.mdx SpacetimeDB docs landing page introducing resources, local dev, auth, and removal policy.
website/src/content/docs/spacetimedb/getting-started.mdx Step-by-step walkthrough for the Cloudflare + SpacetimeDB todo example.
packages/alchemy/test/SpacetimeDB/SpacetimeAuthProject.test.ts Unit tests for the config-only SpacetimeAuth project resource/provider behavior.
packages/alchemy/test/SpacetimeDB/Runtime.test.ts Tests for scoped connection lifecycle + timeout behavior in the runtime helper layer.
packages/alchemy/test/SpacetimeDB/Providers.test.ts Tests for provider-layer composition and credential resolution helpers.
packages/alchemy/test/SpacetimeDB/Project.test.ts Tests for generating spacetime.json and spacetime.local.json.
packages/alchemy/test/SpacetimeDB/LocalDatabase.test.ts Tests for shell-quoting used by the local dev server runner.
packages/alchemy/test/SpacetimeDB/Host.test.ts Tests for host normalization, websocket URI conversion, and env resolution.
packages/alchemy/test/SpacetimeDB/Database.test.ts Tests covering the live HTTP provider behavior via an in-memory mock backend.
packages/alchemy/test/SpacetimeDB/ConnectBinding.test.ts Tests for Connect binding tag identity and env key naming.
packages/alchemy/test/SpacetimeDB/Connect.test.ts Tests for env key stability/disambiguation and database-name regex behavior.
packages/alchemy/test/SpacetimeDB/Client.test.ts Tests for token decoding and client HTTP envelope/error mapping.
packages/alchemy/test/SpacetimeDB/Client.ops.test.ts Tests for reducer calls, SQL calls, log retrieval, and log parsing behavior.
packages/alchemy/test/SpacetimeDB/Cli.test.ts Tests for CLI argument shaping and CLI output parsing.
packages/alchemy/test/SpacetimeDB/Browser.test.ts Tests for browser token persistence helper behavior.
packages/alchemy/src/Util/EnvName.ts New shared env-key mangling helpers (also reused by Prisma).
packages/alchemy/src/SpacetimeDB/SpacetimeAuth.ts New config-only SpacetimeAuth resource/provider with typed outputs for apps.
packages/alchemy/src/SpacetimeDB/Runtime.ts Connection layer + Connection<C>(name) tag helper for runtime connection lookups.
packages/alchemy/src/SpacetimeDB/Providers.ts Provider collection and layer wiring for SpacetimeDB resources + auth provider.
packages/alchemy/src/SpacetimeDB/Project.ts Project resource/provider to materialize spacetime.json + local overrides.
packages/alchemy/src/SpacetimeDB/LocalDatabase.ts Local (dev-mode) provider implementation that spawns spacetime dev --server-only.
packages/alchemy/src/SpacetimeDB/Local.ts Sidecar entrypoint to host the long-running local dev process via RPC server.
packages/alchemy/src/SpacetimeDB/index.ts SpacetimeDB package barrel exports.
packages/alchemy/src/SpacetimeDB/Host.ts Host normalization + env resolution + websocket/dashboard URL helpers.
packages/alchemy/src/SpacetimeDB/Generate.ts Generate resource/provider and module hashing utilities.
packages/alchemy/src/SpacetimeDB/DatabaseHttp.ts Effect-native HTTP management client layer for a single database.
packages/alchemy/src/SpacetimeDB/Credentials.ts Credential service + helpers to resolve token/host from env/profile/literal token.
packages/alchemy/src/SpacetimeDB/ConnectBinding.ts Binding implementation that wires DB coordinates into Worker/Lambda bindings.
packages/alchemy/src/SpacetimeDB/Connect.ts Connect binding contract + env-key derivation + Vite env helpers.
packages/alchemy/src/SpacetimeDB/Cli.ts CLI runner + helpers for build/publish/generate/delete/lock/unlock + hashing utilities.
packages/alchemy/src/SpacetimeDB/Browser.ts Browser-side helper for persisting identity tokens (no Effect dependency).
packages/alchemy/src/SpacetimeDB/AuthProvider.ts AuthProvider integration for alchemy login and token/host configuration.
packages/alchemy/src/Prisma/Internal/EnvName.ts Refactor Prisma env-name logic to reuse Util/EnvName.ts.
packages/alchemy/package.json Export-map updates to add SpacetimeDB package entrypoints.
examples/cloudflare-spacetimedb-todo/worker/api.ts Worker for upload + file serving (R2-backed) used by the todo example.
examples/cloudflare-spacetimedb-todo/vite.config.ts Vite config for the example SPA.
examples/cloudflare-spacetimedb-todo/tsconfig.json TypeScript config for the example project.
examples/cloudflare-spacetimedb-todo/src/styles.css Styling for the example SPA.
examples/cloudflare-spacetimedb-todo/src/main.tsx SPA bootstrap using SpacetimeDB React provider and generated bindings.
examples/cloudflare-spacetimedb-todo/src/App.tsx Todo SPA UI wired to reducers/tables and optional attachment uploads.
examples/cloudflare-spacetimedb-todo/spacetimedb/tsconfig.json TS config for the SpacetimeDB module sources in the example.
examples/cloudflare-spacetimedb-todo/spacetimedb/src/index.ts SpacetimeDB module schema + reducers used by the todo example.
examples/cloudflare-spacetimedb-todo/spacetimedb/package.json Module package manifest pinning spacetimedb dependency.
examples/cloudflare-spacetimedb-todo/spacetimedb/.gitignore Ignores module build artifacts and deps.
examples/cloudflare-spacetimedb-todo/README.md Example documentation and commands.
examples/cloudflare-spacetimedb-todo/package.json Example app manifest and scripts.
examples/cloudflare-spacetimedb-todo/index.html SPA HTML entrypoint.
examples/cloudflare-spacetimedb-todo/alchemy.run.ts The example stack wiring SpacetimeDB + Cloudflare resources.
examples/cloudflare-spacetimedb-todo/.gitignore Ignores local state, generated configs, and generated bindings.
Suppressed comments (4)

packages/alchemy/src/SpacetimeDB/Cli.ts:304

  • Effect.gen blocks are returning yield* new SpacetimeCliError(...) on non-zero exit. This should fail the effect via Effect.fail(...), otherwise the error isn't propagated through the Effect error channel.
      return yield* new SpacetimeCliError({
        command: args.join(" "),
        ...result,
      });
    }

packages/alchemy/src/SpacetimeDB/Cli.ts:342

  • Effect.gen blocks are returning yield* new SpacetimeCliError(...) on non-zero exit. Return an Effect.fail(...) so this path actually fails with SpacetimeCliError.
      return yield* new SpacetimeCliError({
        command: args.join(" "),
        ...result,
      });
    }

packages/alchemy/src/SpacetimeDB/Cli.ts:379

  • On non-zero exit, this path also does return yield* new SpacetimeCliError(...) which isn't an Effect. This should fail via Effect.fail(...) so downstream code can catch/handle SpacetimeCliError.
      return yield* new SpacetimeCliError({
        command: args.join(" "),
        ...result,
      });
    }

packages/alchemy/src/SpacetimeDB/Cli.ts:449

  • renameViaCli returns yield* new SpacetimeCliError(...) on failure; this should be an Effect.fail(...) so the function's effect fails correctly.
      return yield* new SpacetimeCliError({
        command: args.join(" "),
        ...result,
      });
    }

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/alchemy/src/SpacetimeDB/Cli.ts Outdated
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants