diff --git a/docs/docs/00200-core-concepts/00100-databases/00300-spacetime-publish.md b/docs/docs/00200-core-concepts/00100-databases/00300-spacetime-publish.md index f8aaf847553..dd0402479a4 100644 --- a/docs/docs/00200-core-concepts/00100-databases/00300-spacetime-publish.md +++ b/docs/docs/00200-core-concepts/00100-databases/00300-spacetime-publish.md @@ -94,6 +94,10 @@ If this publish is a major upgrade from 1.x to 2.0, read [1.x to 2.0 Upgrade Not To completely reset your database and delete all data: + + ```bash spacetime publish --delete-data ``` diff --git a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00300-reducers.md b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00300-reducers.md index 4180d28ba6d..6238cf8eab4 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00300-reducers.md +++ b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00300-reducers.md @@ -546,7 +546,7 @@ import { ScheduleAt } from 'spacetimedb'; import { schema, t, table } from 'spacetimedb/server'; // Define a schedule table for the procedure -const fetchSchedule = table( +const fetch_schedule = table( { name: 'fetch_schedule', scheduled: (): any => fetch_external_data }, { scheduled_id: t.u64().primaryKey().autoInc(), @@ -555,12 +555,12 @@ const fetchSchedule = table( } ); -const spacetimedb = schema({ fetchSchedule }); +const spacetimedb = schema({ fetch_schedule }); export default spacetimedb; // The procedure to be scheduled export const fetch_external_data = spacetimedb.procedure( - { arg: fetchSchedule.rowType }, + { arg: fetch_schedule.rowType }, t.unit(), (ctx, { arg }) => { const response = ctx.http.fetch(arg.url); @@ -571,7 +571,7 @@ export const fetch_external_data = spacetimedb.procedure( // From a reducer, schedule the procedure by inserting into the schedule table export const queueFetch = spacetimedb.reducer({ url: t.string() }, (ctx, { url }) => { - ctx.db.fetchSchedule.insert({ + ctx.db.fetch_schedule.insert({ scheduled_id: 0n, scheduled_at: ScheduleAt.interval(0n), // Run immediately url, diff --git a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md index 06e30fb7b2a..e45f9174561 100644 --- a/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md +++ b/docs/docs/00200-core-concepts/00200-functions/00300-reducers/00400-reducer-context.md @@ -324,7 +324,7 @@ Scheduled reducers and procedures are private by default in SpacetimeDB 2.x, so ```typescript import { schema, table, t } from 'spacetimedb/server'; -const scheduledTask = table( +const scheduled_task = table( { name: 'scheduled_task', scheduled: (): any => send_reminder }, { taskId: t.u64().primaryKey().autoInc(), @@ -333,10 +333,10 @@ const scheduledTask = table( } ); -const spacetimedb = schema({ scheduledTask }); +const spacetimedb = schema({ scheduled_task }); export default spacetimedb; -export const send_reminder = spacetimedb.reducer({ arg: scheduledTask.rowType }, (_ctx, { arg }) => { +export const send_reminder = spacetimedb.reducer({ arg: scheduled_task.rowType }, (_ctx, { arg }) => { console.log(`Reminder: ${arg.message}`); }); ``` diff --git a/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md b/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md index 86c1589ea46..9b88b2de7d8 100644 --- a/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md +++ b/docs/docs/00200-core-concepts/00300-tables/00210-file-storage.md @@ -20,7 +20,7 @@ Store binary data using `Vec` (Rust), `List` (C#), `std::vector { // Delete existing avatar if present - ctx.db.userAvatar.userId.delete(userId); + ctx.db.user_avatar.userId.delete(userId); // Insert new avatar - ctx.db.userAvatar.insert({ + ctx.db.user_avatar.insert({ userId, mimeType, data, diff --git a/docs/docs/00200-core-concepts/00300-tables/00550-event-tables.md b/docs/docs/00200-core-concepts/00300-tables/00550-event-tables.md index 3f2936ca7ea..9bcdc1e5b52 100644 --- a/docs/docs/00200-core-concepts/00300-tables/00550-event-tables.md +++ b/docs/docs/00200-core-concepts/00300-tables/00550-event-tables.md @@ -21,7 +21,8 @@ To declare a table as an event table, add the `event` attribute to the table def ```typescript -const damageEvent = table({ +const damage_event = table({ + name: 'damage_event', public: true, event: true, }, { @@ -31,7 +32,7 @@ const damageEvent = table({ }); const spacetimedb = schema({ - damageEvent, + damage_event, }); export default spacetimedb; ``` @@ -97,7 +98,7 @@ export const attack = spacetimedb.reducer( // Game logic... // Publish the event - ctx.db.damageEvent.insert({ + ctx.db.damage_event.insert({ entity_id: target_id, damage, source: "melee_attack", diff --git a/docs/docs/00200-core-concepts/00600-clients/00600-csharp-reference.md b/docs/docs/00200-core-concepts/00600-clients/00600-csharp-reference.md index 0db7e730c91..264ce97c797 100644 --- a/docs/docs/00200-core-concepts/00600-clients/00600-csharp-reference.md +++ b/docs/docs/00200-core-concepts/00600-clients/00600-csharp-reference.md @@ -306,14 +306,14 @@ interface IRemoteDbContext ``` `Reducers` will have methods to invoke each reducer defined by the module, -plus methods for adding and removing callbacks on each of those reducers. +plus events for observing the result of reducer calls made by this connection. ##### Example ```csharp var conn = ConnectToDB(); -// Register a callback to be run every time the SendMessage reducer is invoked +// Register a callback to observe the result of SendMessage calls made by this connection. conn.Reducers.OnSendMessage += Reducer_OnSendMessageEvent; ``` @@ -711,9 +711,9 @@ record Event } ``` -Event when we are notified that a reducer ran in the remote database. The [`ReducerEvent`](#record-reducerevent) contains metadata about the reducer run, including its arguments and termination [`Status`](#record-status). +Event when we are notified of the result of a reducer call made by this connection. The [`ReducerEvent`](#record-reducerevent) contains metadata about the reducer run, including its arguments and termination [`Status`](#record-status). -This event is passed to row callbacks resulting from modifications by the reducer. +For changes caused by other clients' reducer calls, use table row callbacks or event tables rather than reducer callbacks. The server does not broadcast reducer arguments globally. #### Variant `SubscribeApplied` @@ -1084,13 +1084,14 @@ int CountPlayersAtLevel(RemoteTables tables, uint level) => tables.Player.Level. ## Observe and invoke reducers -All [`IDbContext`](#interface-idbcontext) implementors, including [`DbConnection`](#type-dbconnection) and [`EventContext`](#type-eventcontext), have a `.Reducers` property, which in turn has methods for invoking reducers defined by the module and registering callbacks on it. +All [`IDbContext`](#interface-idbcontext) implementors, including [`DbConnection`](#type-dbconnection) and [`EventContext`](#type-eventcontext), have a `.Reducers` property. Generated module bindings expose one invoke method and one result event for each reducer. -Each reducer defined by the module has three methods on the `.Reducers`: +For a reducer named `send_message`, generated C# bindings use PascalCase names: -- An invoke method, whose name is the reducer's name converted to snake case, like `set_name`. This requests that the module run the reducer. -- A callback registation method, whose name is prefixed with `on_`, like `on_set_name`. This registers a callback to run whenever we are notified that the reducer ran, including successfully committed runs and runs we requested which failed. This method returns a callback id, which can be passed to the callback remove method. -- A callback remove method, whose name is prefixed with `remove_on_`, like `remove_on_set_name`. This cancels a callback previously registered via the callback registration method. +- An invoke method, like `SendMessage(...)`. This requests that the module run the reducer. +- A result event, like `OnSendMessage`. This event fires on the calling connection when SpacetimeDB reports that reducer call's result, including committed, failed, and out-of-energy statuses. + +Reducer result events are not global notifications. They are for reducer calls made by this connection. To notify other clients that something happened, write to a public table or event table and subscribe to it. ## Identify a client diff --git a/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md b/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md index 8f70388d274..aef29ff65f9 100644 --- a/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md +++ b/docs/docs/00300-resources/00100-how-to/00600-migrating-to-2.0.md @@ -190,15 +190,15 @@ spacetimedb.reducer('deal_damage', { target: t.identity(), amount: t.u32() }, (c **Server (module) -- after:** ```typescript // 2.0 server -- explicitly publish events via an event table -const damageEvent = table({ event: true }, { +const damage_event = table({ name: 'damage_event', event: true }, { target: t.identity(), amount: t.u32(), }) -// schema() takes an object: schema({ damageEvent }), never schema(damageEvent) -const spacetimedb = schema({ damageEvent }); +// schema() takes an object: schema({ damage_event }), never schema(damage_event) +const spacetimedb = schema({ damage_event }); export const dealDamage = spacetimedb.reducer({ target: t.identity(), amount: t.u32() }, (ctx, { target, amount }) => { - ctx.db.damageEvent.insert({ target, amount }); + ctx.db.damage_event.insert({ target, amount }); }); ``` diff --git a/docs/docs/00300-resources/00200-reference/00100-cli-reference/00300-spacetime-json.md b/docs/docs/00300-resources/00200-reference/00100-cli-reference/00300-spacetime-json.md index f14340c3337..0e90d315c80 100644 --- a/docs/docs/00300-resources/00200-reference/00100-cli-reference/00300-spacetime-json.md +++ b/docs/docs/00300-resources/00200-reference/00100-cli-reference/00300-spacetime-json.md @@ -211,7 +211,7 @@ These apply to all selected databases: - `--server`: target server - `--break-clients`: allow breaking changes -- `--delete-data`: clear database data +- `--delete-data=`: clear database data (`always`, `on-conflict`, or `never`) - `--yes` / `--force`: skip confirmation prompts ### Per-database overrides diff --git a/skills/cli/SKILL.md b/skills/cli/SKILL.md index 534ad7ee4ec..f5cd3479128 100644 --- a/skills/cli/SKILL.md +++ b/skills/cli/SKILL.md @@ -63,6 +63,10 @@ spacetime publish my-database --server local --yes spacetime publish my-database --delete-data=always --yes ``` +Bare `--delete-data` defaults to `always`. Keep simple interactive docs examples +bare, and use `--delete-data=always` for scripted/non-interactive examples that +also pass `--yes`. + ### Database Interaction ```bash diff --git a/skills/typescript-server/SKILL.md b/skills/typescript-server/SKILL.md index 2e4db3ba262..0ab41b1b10d 100644 --- a/skills/typescript-server/SKILL.md +++ b/skills/typescript-server/SKILL.md @@ -52,7 +52,8 @@ import { ScheduleAt } from 'spacetimedb'; // for scheduled tables only ## Tables -`table(OPTIONS, COLUMNS)` takes two arguments. The `name` field MUST be snake_case: +`table(OPTIONS, COLUMNS)` takes two arguments. The `name` field is optional; +when present, it overrides the canonical SQL name and should be snake_case: ```typescript const entity = table( @@ -65,9 +66,13 @@ const entity = table( ); ``` -Options: `name` (snake_case, recommended), `public: true`, `event: true`, `scheduled: (): any => reducerRef`, `indexes: [...]` +Options: `name` (optional canonical SQL name override), `public: true`, `event: true`, `scheduled: (): any => reducerRef`, `indexes: [...]` -`ctx.db` accessors are the keys passed to `schema({...})`, verbatim: `schema({ score_record })` → `ctx.db.score_record`. Use snake_case keys matching the table `name`. Client codegen converts case; server `ctx.db` does not. +`ctx.db` accessors are the keys passed to `schema({ ... })`, verbatim: +`schema({ score_record })` -> `ctx.db.score_record`. The optional `name` +field overrides the canonical SQL name; it does not change the server +`ctx.db` accessor. Use snake_case keys matching the table `name`. Client +codegen converts case; server `ctx.db` does not. ## Column Types