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
84 changes: 42 additions & 42 deletions docs/06-concepts/02-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ fields:

indexes:
created_at_index:
fields: createdAt # Index on inherited field
fields: createdAt # Index on inherited field
```

**ServerOnly Inheritance**: If a parent class is marked as `serverOnly`, all child classes must also be marked as `serverOnly`. A non-serverOnly class cannot extend a serverOnly class, but a serverOnly child can extend a non-serverOnly parent.
Expand Down Expand Up @@ -338,9 +338,9 @@ It is easy to add custom enums with serialization support by using the `enum` ke
```yaml
enum: Animal
values:
- dog
- cat
- bird
- dog
- cat
- bird
```

By default the serialization will convert the enum to an int representing the index of the value. Changing the order may therefore have unforeseen consequences when reusing old data (such as from a database). Changing the serialization to be based on the name instead of index is easy.
Expand All @@ -349,9 +349,9 @@ By default the serialization will convert the enum to an int representing the in
enum: Animal
serialized: byName
values:
- dog
- cat
- bird
- dog
- cat
- bird
```

`serialized` has two valid values `byName` and `byIndex`. When using `byName` the string literal of the enum is used, when using `byIndex` the index value (0, 1, 2, etc) is used.
Expand All @@ -373,10 +373,10 @@ enum: Animal
serialized: byName
default: unknown
values:
- unknown
- dog
- cat
- bird
- unknown
- dog
- cat
- bird
```

In the example above, if the Enum `Animal` receives an unknown option such as `"fish"` it will be deserialized to `Animal.unknown`. This is useful for maintaining backward compatibility when changing the enum values.
Expand Down Expand Up @@ -689,34 +689,34 @@ fields:

## Keywords

| **Keyword** | Note | [class](#class) | [exception](#exception) | [enum](#enum) |
| ------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------- | :-------------: | :---------------------: | :-----------: |
| [**values**](#enum) | A special key for enums with a list of all enum values. | | | ✅ |
| [**serialized**](#enum) | Sets the mode enums are serialized in | | | ✅ |
| [**immutable**](#immutable-classes) | Boolean flag to generate an immutable class with final fields, equals operator, and hashCode. | ✅ | ✅ | |
| [**serverOnly**](#limiting-visibility-of-a-generated-class) | Boolean flag if code generator only should create the code for the server. | ✅ | ✅ | ✅ |
| [**table**](database/models) | A name for the database table, enables generation of database code. | ✅ | | |
| [**managedMigration**](database/migrations#opt-out-of-migrations) | A boolean flag to opt out of the database migration system. | ✅ | | |
| [**fields**](#class) | All fields in the generated class should be listed here. | ✅ | ✅ | |
| [**type (fields)**](#class) | Denotes the data type for a field. | ✅ | ✅ | |
| [**required**](#required-fields) | Makes the field as required. This keyword can only be used for **nullable** fields. | ✅ | ✅ | |
| [**scope**](#limiting-visibility-of-a-generated-class) | Denotes the scope for a field. | ✅ | | |
| [**persist**](database/models) | A boolean flag if the data should be stored in the database or not can be negated with `!persist` | ✅ | | |
| [**relation**](database/relations/one-to-one) | Sets a relation between model files, requires a table name to be set. | ✅ | | |
| [**name**](database/relations/one-to-one#bidirectional-relations) | Give a name to a relation to pair them. | ✅ | | |
| [**parent**](database/relations/one-to-one#with-an-id-field) | Sets the parent table on a relation. | ✅ | | |
| [**field**](database/relations/one-to-one#custom-foreign-key-field) | A manual specified foreign key field. | ✅ | | |
| [**onUpdate**](database/relations/referential-actions) | Set the referential actions when updating data in the database. | ✅ | | |
| [**onDelete**](database/relations/referential-actions) | Set the referential actions when deleting data in the database. | ✅ | | |
| [**optional**](database/relations/one-to-one#optional-relation) | A boolean flag to make a relation optional. | ✅ | | |
| [**indexes**](database/indexing) | Create indexes on your fields / columns. | ✅ | | |
| [**fields (index)**](database/indexing) | List the fields to create the indexes on. | ✅ | | |
| [**type (index)**](database/indexing) | The type of index to create. | ✅ | | |
| [**parameters (index)**](database/indexing#vector-indexes) | Parameters for specialized index types like HNSW and IVFFLAT vector indexes. | ✅ | | |
| [**distanceFunction (index)**](database/indexing#vector-indexes) | Distance function for vector indexes (l2, innerProduct, cosine, l1). | ✅ | | |
| [**unique**](database/indexing) | Boolean flag to make the entries unique in the database. | ✅ | | |
| [**default**](#default-values) | Sets the default value for both the model and the database. This keyword cannot be used with **relation**. | ✅ | | |
| [**defaultModel**](#default-values) | Sets the default value for the model side. This keyword cannot be used with **relation**. | ✅ | | |
| [**defaultPersist**](#default-values) | Sets the default value for the database side. This keyword cannot be used with **relation** and **!persist**. | ✅ | | |
| [**extends**](#inheritance) | Specifies a parent class to inherit from. | ✅ | ✅ | |
| [**sealed**](#inheritance) | Boolean flag to create a sealed class hierarchy, enabling exhaustive type checking. | ✅ | | |
| **Keyword** | Note | [class](#class) | [exception](#exception) | [enum](#enum) |
| ------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------- | :-------------: | :---------------------: | :-----------: |
| [**values**](#enum) | A special key for enums with a list of all enum values. | | | ✅ |
| [**serialized**](#enum) | Sets the mode enums are serialized in | | | ✅ |
| [**immutable**](#immutable-classes) | Boolean flag to generate an immutable class with final fields, equals operator, and hashCode. | ✅ | ✅ | |
| [**serverOnly**](#limiting-visibility-of-a-generated-class) | Boolean flag if code generator only should create the code for the server. | ✅ | ✅ | ✅ |
| [**table**](database/models) | A name for the database table, enables generation of database code. | ✅ | | |
| [**managedMigration**](database/migrations#opt-out-of-migrations) | A boolean flag to opt out of the database migration system. | ✅ | | |
| [**fields**](#class) | All fields in the generated class should be listed here. | ✅ | ✅ | |
| [**type (fields)**](#class) | Denotes the data type for a field. | ✅ | ✅ | |
| [**required**](#required-fields) | Makes the field as required. This keyword can only be used for **nullable** fields. | ✅ | ✅ | |
| [**scope**](#limiting-visibility-of-a-generated-class) | Denotes the scope for a field. | ✅ | | |
| [**persist**](database/models) | A boolean flag if the data should be stored in the database or not can be negated with `!persist` | ✅ | | |
| [**relation**](database/relations/one-to-one) | Sets a relation between model files, requires a table name to be set. | ✅ | | |
| [**name**](database/relations/one-to-one#bidirectional-relations) | Give a name to a relation to pair them. | ✅ | | |
| [**parent**](database/relations/one-to-one#with-an-id-field) | Sets the parent table on a relation. | ✅ | | |
| [**field**](database/relations/one-to-one#custom-foreign-key-field) | A manual specified foreign key field. | ✅ | | |
| [**onUpdate**](database/relations/referential-actions) | Set the referential actions when updating data in the database. | ✅ | | |
| [**onDelete**](database/relations/referential-actions) | Set the referential actions when deleting data in the database. | ✅ | | |
| [**optional**](database/relations/one-to-one#optional-relation) | A boolean flag to make a relation optional. | ✅ | | |
| [**indexes**](database/indexing) | Create indexes on your fields / columns. | ✅ | | |
| [**fields (index)**](database/indexing) | List the fields to create the indexes on. | ✅ | | |
| [**type (index)**](database/indexing) | The type of index to create. | ✅ | | |
| [**parameters (index)**](database/indexing#vector-indexes) | Parameters for specialized index types like HNSW and IVFFLAT vector indexes. | ✅ | | |
| [**distanceFunction (index)**](database/indexing#vector-indexes) | Distance function for vector indexes (l2, innerProduct, cosine, l1). | ✅ | | |
| [**unique**](database/indexing) | Boolean flag to make the entries unique in the database. | ✅ | | |
| [**default**](#default-values) | Sets the default value for both the model and the database. This keyword cannot be used with **relation**. | ✅ | | |
| [**defaultModel**](#default-values) | Sets the default value for the model side. This keyword cannot be used with **relation**. | ✅ | | |
| [**defaultPersist**](#default-values) | Sets the default value for the database side. This keyword cannot be used with **relation** and **!persist**. | ✅ | | |
| [**extends**](#inheritance) | Specifies a parent class to inherit from. | ✅ | ✅ | |
| [**sealed**](#inheritance) | Boolean flag to create a sealed class hierarchy, enabling exhaustive type checking. | ✅ | | |
40 changes: 35 additions & 5 deletions docs/06-concepts/18-webserver/08-single-page-apps.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,13 @@ pod.webServer.addRoute(
webDir,
fallback: File('web/app/index.html'),
),
'/**',
);
```

:::info
The route path defaults to `'/'` (root). See [Serving from a sub-path](#serving-from-a-sub-path) to mount the SPA at a different location.
:::

This configuration:

- Serves static files from `web/app` when they exist
Expand Down Expand Up @@ -49,7 +52,6 @@ pod.webServer.addRoute(
maxAge: const Duration(minutes: 5),
),
),
'/**',
);
```

Expand All @@ -76,7 +78,6 @@ pod.webServer.addRoute(
maxAge: const Duration(minutes: 5),
),
),
'/**',
);
```

Expand All @@ -95,10 +96,9 @@ pod.webServer.addMiddleware(
fallback: StaticRoute.file(indexFile),
on: (response) => response.statusCode == 404,
),
'/**',
);

pod.webServer.addRoute(StaticRoute.directory(webDir), '/**');
pod.webServer.addRoute(StaticRoute.directory(webDir), '/');
```

This gives you flexibility to customize the fallback condition. For example, you could fall back on any 4xx error:
Expand All @@ -110,6 +110,36 @@ FallbackMiddleware(
)
```

## Serving from a sub-path

To serve your SPA from a sub-path instead of the root, pass the path as the second argument to `addRoute`:

```dart
final webDir = Directory('web/app');

pod.webServer.addRoute(
SpaRoute(
webDir,
fallback: File('web/app/index.html'),
),
'/app',
);
```

This serves the SPA at `/app`, so users would access it at `http://localhost:8082/app`.

:::note
When using cache busting with a sub-path, update the `mountPrefix` to match:

```dart
final cacheBustingConfig = CacheBustingConfig(
mountPrefix: '/app',
fileSystemRoot: webDir,
);
```

:::

## Serving Flutter web applications

For serving Flutter web applications specifically, see [Flutter web apps](flutter-web).
13 changes: 7 additions & 6 deletions docs/06-concepts/18-webserver/09-flutter-web.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ Use `FlutterRoute` to serve your Flutter web build:
```dart
pod.webServer.addRoute(
FlutterRoute(Directory('web/app')),
'/**',
);
```

:::info
The route path defaults to `'/'` (root). See [Serving from a sub-path](single-page-apps#serving-from-a-sub-path) to mount the app at a different location.
:::

This configuration:

- Serves all static files from the Flutter build
Expand Down Expand Up @@ -69,14 +72,14 @@ Flutter WASM builds can use multi-threaded rendering for improved performance. T
If you're using `SpaRoute` or custom routes instead of `FlutterRoute`, add the headers manually with `WasmHeadersMiddleware`:

```dart
pod.webServer.addMiddleware(const WasmHeadersMiddleware(), '/**');
pod.webServer.addMiddleware(const WasmHeadersMiddleware());

pod.webServer.addRoute(
SpaRoute(
Directory('web/app'),
fallback: File('web/app/index.html'),
),
'/**',
'/',
);
```

Expand All @@ -92,7 +95,6 @@ pod.webServer.addRoute(
maxAge: const Duration(minutes: 5),
),
),
'/**',
);
```

Expand All @@ -118,7 +120,6 @@ pod.webServer.addRoute(
maxAge: const Duration(minutes: 5),
),
),
'/**',
);
```

Expand All @@ -145,7 +146,7 @@ void run(List<String> args) async {
print('Warning: Flutter web app not found at ${flutterAppDir.path}');
print('Build your Flutter app and copy it to web/app/');
} else {
pod.webServer.addRoute(FlutterRoute(flutterAppDir), '/**');
pod.webServer.addRoute(FlutterRoute(flutterAppDir));
}

await pod.start();
Expand Down
Loading