Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions docs/04-get-started/03-how-it-works.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ description: 'Start building with Serverpod. Learn how to add endpoints, call th

# How Serverpod works

With Serverpod, you write type-safe Dart on both your Flutter app and the backend. With hot reload, all the changes immediately take effect. Edit a file, hit save, and your running server, your Flutter app, your database, and the generated code that connects them update together. No manual rebuilds or restarts, no Docker to wire up, and no API code to write by hand.
With Serverpod, you write type-safe Dart on both your Flutter app and the backend. With hot reload, all the changes immediately take effect. Edit a file, hit save, and your running server, your Flutter app, your database, and the generated code that connects them update together. No manual rebuilds or restarts, no Docker to set up, and no API code to write by hand.

Serverpod is a full backend. It manages your database, authentication, file uploads, caching, real-time communication, scheduling, and logging. You can focus on building features instead of wiring together separate services. A project is a single workspace of Dart packages, and a code generator keeps the types shared between your server and app in sync. If you rename a field or use an incorrect type, they will show up as compile-time errors rather than a surprise when you run the app.

Expand Down Expand Up @@ -106,7 +106,7 @@ These run on the same `session` your endpoint method receives. When you change a

That database runs without setup on your part: Serverpod manages an embedded Postgres for you, with no Docker to configure. If you would rather manage Postgres yourself, you can change the configuration in the server's `config` directory.

See [Working with the database](./concepts/data-and-the-database/database/crud) for building queries, relations, and transactions.
See [CRUD](./concepts/data-and-the-database/database/crud) for the generated query methods, [relations](./concepts/data-and-the-database/database/relations) for linking tables, and [transactions](./concepts/data-and-the-database/database/transactions) for atomic operations.

## Build with an AI agent

Expand Down
6 changes: 3 additions & 3 deletions docs/05-build-your-first-app/03-working-with-the-database.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ fields:
Save the file. The regenerated `Recipe` class now exposes database methods through `Recipe.db`.

:::info
See the [database models](../concepts/data-and-the-database/models#keywords-1) reference for all the keywords you can use in a table.
See the [Model reference](../concepts/lookups/model-reference) for all the keywords you can use in a table.
:::

## Create and apply the migration
Expand All @@ -63,7 +63,7 @@ Now that `Recipe` is a table, you can write rows. In `recipe_endpoint.dart`, sav
return Recipe.db.insertRow(session, recipe);
```

`insertRow` returns the saved row with its `id` populated by the database.
The `insertRow` method returns the saved row with its `id` populated by the database.

## List past recipes

Expand All @@ -77,7 +77,7 @@ Add a second method to the endpoint that returns every saved recipe, newest firs
```

:::info
`insertRow` and `find` are Serverpod's typed database methods. See [CRUD](../concepts/data-and-the-database/database/crud) for the full set of operations.
Both `insertRow` and `find` are Serverpod's typed database methods. See [CRUD](../concepts/data-and-the-database/database/crud) for the full set of operations.
:::

## Show the saved recipes in your app
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,9 +103,9 @@ For how users sign in and how scopes work, see [Authentication](./authentication

## Pass and return data

Parameters and return values can be of type `bool`, `int`, `double`, `String`, `UuidValue`, `Duration`, `DateTime`, `ByteData`, `Uri`, `BigInt`, `dynamic`, [vector and geography types](./data-and-the-database/models/vector-and-geography-fields), or generated serializable objects ([data models](./data-and-the-database/models)). You can also use `List`, `Map`, `Record`, and `Set`, strictly typed with the types above. Null safety is supported, and return types follow the same rules as parameters. A `DateTime` is always converted to UTC when passed.
Parameters and return values can be of type `bool`, `int`, `double`, `String`, `UuidValue`, `Duration`, `DateTime`, `ByteData`, `Uri`, `BigInt`, `dynamic`, [vector and geography types](./data-and-the-database/database/vector-and-geography-fields), or generated serializable objects ([data models](./data-and-the-database/models)). You can also use `List`, `Map`, `Record`, and `Set`, strictly typed with the types above. Null safety is supported, and return types follow the same rules as parameters. A `DateTime` is always converted to UTC when passed.

Parameters are sent by name in the request between app and server, so renaming an endpoint method's parameters breaks older app builds. See [backward compatibility](./data-and-the-database/models/backward-compatibility) before changing a published API.
Parameters are sent by name in the request between app and server, so renaming an endpoint method's parameters breaks older app builds. See [backward compatibility](./endpoints-and-apis/backward-compatibility) before changing a published API.

Binary data over a method call is capped by the request size limit, 512 KiB by default (an oversized call fails with an HTTP 413 error). The limit is the `maxRequestSize` key in the [Configuration reference](./lookups/configuration-reference). For transferring files, use the [file upload](./endpoints-and-apis/file-uploads) interface instead.

Expand Down Expand Up @@ -154,7 +154,7 @@ The generated test tools call your endpoints the same way production code does,
## Related

- [Sessions](./endpoints-and-apis/sessions): the object every endpoint method receives.
- [Error handling and exceptions](./endpoints-and-apis/error-handling-and-exceptions): typed errors across the wire.
- [Error handling and exceptions](./endpoints-and-apis/error-handling-and-exceptions): typed errors between server and app.
- [Streaming](./endpoints-and-apis/streaming): push live data to your app.
- [File uploads](./endpoints-and-apis/file-uploads): direct-to-storage uploads.
- [Endpoint inheritance](./endpoints-and-apis/endpoint-inheritance): share behavior across endpoints and reshape module endpoints.
Expand Down
2 changes: 1 addition & 1 deletion docs/06-concepts/02-endpoints-and-apis/02-sessions.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ class ExampleEndpoint extends Endpoint {

| Member | What it is |
| --------------------------- | ----------------------------------------------------------------------------------------------- |
| `db` | Database access. See the [database docs](../data-and-the-database/database/connection). |
| `db` | Database access. See the [CRUD docs](../data-and-the-database/database/crud). |
| `caches` | Local and distributed caching. See [caching](../operations/caching). |
| `storage` | File storage. See [file uploads](./file-uploads). |
| `messages` | Server events for real-time communication. See [server events](./server-events). |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
---
description: Errors in Serverpod cross the wire as serializable exceptions defined in model files, caught by type in the app alongside typed HTTP failures.
description: Errors in Serverpod reach the app as serializable exceptions defined in model files, caught by type alongside typed HTTP failures.
---

# Error handling and exceptions
Expand Down Expand Up @@ -117,7 +117,7 @@ fields:

A call from the client can fail in three ways, and you usually handle each one differently:

- A **serializable exception you defined** (`MyException` above): a known, app-level failure. Catch it by its type and show the user what happened. (On the wire, it travels as an HTTP 400 with a typed payload.)
- A **serializable exception you defined** (`MyException` above): a known, app-level failure. Catch it by its type and show the user what happened. (It is sent as an HTTP 400 response with a typed payload.)
- A **`ServerpodClientException`**: something went wrong in the communication or on the server. Its typed subclasses map to HTTP status codes: `ServerpodClientBadRequest` (400), `ServerpodClientUnauthorized` (401), `ServerpodClientForbidden` (403), `ServerpodClientNotFound` (404), and `ServerpodClientInternalServerError` (500).
- A **connection failure**: when the app cannot reach the server (offline, wrong URL, or a timeout), it throws a `ServerpodClientException` with a `statusCode` of `-1`. A call that exceeds the [request size limit](../endpoints-and-apis#pass-and-return-data) fails with a generic `ServerpodClientException` with status code 413.

Expand Down Expand Up @@ -152,3 +152,7 @@ Only the serializable exceptions you define reach the client, and every field on
- Don't put stack traces, secrets, database IDs, or internal messages into serializable exception fields. Send only what the user should see.
- Write user-facing messages, and keep the diagnostic detail in your server logs where you can look it up later.
- Validate and sanitize input before acting on it, so a bad request fails cleanly instead of surfacing an internal error.

## Related

- [Database exceptions](../data-and-the-database/database/exceptions): the typed exceptions that database operations throw on the server.
Original file line number Diff line number Diff line change
@@ -1,24 +1,24 @@
---
description: Backward compatibility keeps your Serverpod server working with older client versions through rules for endpoint signatures, serialized model fields, and future call methods.
description: Backward compatibility keeps your Serverpod server working with older client versions through rules for endpoint signatures, model fields, and future calls.
---

# Backward compatibility

As your app evolves, features will be added or changed. However, your users may still use older versions of the app as not everyone will update to the latest version and automatic updates through the app stores take time. Therefore it may be essential to make updates to your server compatible with older app versions.
As your app evolves, features will be added or changed. Your users may still run older versions of the app, since not everyone updates and app store updates take time. Therefore it may be essential to make updates to your server compatible with older app versions.

Following a simple set of rules, your server will stay compatible with older app versions:

1. __Avoid changing parameter names in endpoint methods.__ In the REST API Serverpod generates, the parameters are passed by name. This means that changing the parameter names of the endpoint methods will break backward compatibility.
1. __Avoid changing parameter names in endpoint methods.__ In the API Serverpod generates, the parameters are passed by name. This means that changing the parameter names of the endpoint methods will break backward compatibility.
2. __Do not delete endpoint methods or change their signature.__ Instead, add new methods if you must pass another set of parameters. Technically, you can add new named parameters if they are not required, but creating a new method may still feel cleaner.
3. __Avoid changing or removing fields and types in the serialized classes.__ However, you are free to add new fields as long as they are nullable or have a default value.
4. __Avoid changing parameter names in future call methods.__ Changing the parameter names of the future call methods will break backward compatibility since parameters are passed by name.
5. __Do not delete future call methods or change their signature.__ Instead, add new methods if you must pass another set of parameters.
4. __Do not rename registered future calls.__ Queued invocations are stored in the database under the future call's registered name, so a rename breaks calls that were scheduled before the update.
5. __Keep future call payload models compatible.__ A future call receives a single serializable object, and queued invocations were serialized with the old model version, so the model rules above apply to it too.

For polymorphic models, Serverpod can also deserialize an unknown subtype as its known base class, which lets you add subtypes without breaking older clients. See [Handling unknown class names](./inheritance-and-polymorphism#handling-unknown-class-names).
For polymorphic models, Serverpod can also deserialize an unknown subtype as its known base class, which lets you add subtypes without breaking older clients. See [Handling unknown class names](../data-and-the-database/models/inheritance-and-polymorphism#handling-unknown-class-names).

## Managing breaking changes with endpoint inheritance

An [endpoint sub-class](../../endpoints-and-apis) can be useful when you have to make a breaking change to an entire endpoint but need to keep supporting existing clients. Doing so allows you to share most of its implementation with the old endpoint.
An endpoint sub-class can be useful when you have to make a breaking change to an entire endpoint but need to keep supporting existing clients. Doing so allows you to share most of its implementation with the old endpoint. For the mechanics of endpoint inheritance and the `@doNotGenerate` annotation, see [Endpoint inheritance](./endpoint-inheritance).

Imagine you had a "team" management endpoint where before a user could join if they had an e-mail address ending in the expected domain, but now it should be opened up for anyone to join if they can provide an "invite code". Additionally, the return type (serialized classes) should be updated across the entire endpoint, which would not be allowed on the existing one.

Expand Down Expand Up @@ -53,6 +53,4 @@ While we may have liked to re-use the `join` method name, Dart inheritance rules

In your client, you could then move all usages from `client.team` to `client.teamV2` and eventually (after all clients have upgraded) remove the old endpoint on the server. That means either marking the old endpoint with `@doNotGenerate` on the class or deleting it and moving the re-used method implementations you want to keep to the new V2 endpoint class.

An alternative pattern to consider would be to move all the business logic for an endpoint into a helper class and then call into that from the endpoint. In case you want to create a V2 version later, you might be able to reuse most of the underlying business logic through that helper class, and don't have to subclass the old endpoint. This has the added benefit of the endpoint class clearly listing all exposed methods, and you don't have to wonder what you inherit from the base class.

Either approach has pros and cons, and it depends on the concrete circumstances to pick the most useful one. Both give you all the tools you need to extend and update your API while gracefully moving clients along and giving them time to update.
An alternative pattern to consider would be to move all the business logic for an endpoint into a helper class and then call into that from the endpoint. A V2 endpoint can then reuse the business logic through the helper class without subclassing the old endpoint. This has the added benefit of the endpoint class clearly listing all exposed methods, and you don't have to wonder what you inherit from the base class.
Loading
Loading