Closed14

Serverpod(+Flutter)挑戦メモ

村松龍之介村松龍之介

ServerpodをDartコマンドでインストール

dart pub global activate serverpod_cli

以下のコマンド使用できるようになったかを確認。

serverpod
村松龍之介村松龍之介

DockerをHomebrewでインストール

brew install --cask docker

Docker Desktopもインストールされる。

インストール完了後、初回起動を済ませてHelperのインストールやチュートリアルを終わらせておく。

村松龍之介村松龍之介

Serverpodの新規プロジェクトを作成

Docker Desktopが起動している状態で、 create コマンドを使用することで新規プロジェクトが作成できる。

プロジェクトを作成したいディレクトリに移動して以下のコマンドを実行。

serverpod create {project_name}

Serverpodのドキュメントでは mypod という名前プロジェクト作成を説明しています。

プロジェクト作成完了すると以下のような出力があった

プロジェクト名は、Serverpodのドキュメントと同じ mypod にした場合の例です。

SERVERPOD CREATED 🥳

All setup. You are ready to rock!

Start your Serverpod by running:

  $ cd mypod/mypod_server
  $ docker compose up --build --detach
  $ dart bin/main.dart

作成されたプロジェクトディレクトリには以下の3つのディレクトリが作成されている。

  • {project_name}_server: サーバーサイドのコード
  • {project_name}_client: サーバーと通信するためのコード(自動生成のため直接編集はしない)
  • {project_name}_flutter: Flutterアプリ
村松龍之介村松龍之介

サーバーを起動させる

cd {project_name}/mypod_server
docker-compose up -d --build
serverpod run
成功ログ
Starting mypod_server_postgres_1 ... done
Starting mypod_server_redis_1    ... done

Starting Serverpod.

• Automatic generate and reload are enabled.

Spinning up serverpod generate (this can take a few seconds).
Waiting for Postgres on localhost:8090.
Waiting for Redis on localhost:8091.
Setup complete. Starting the server.

SERVERPOD version: 0.9.8 mode: development
Insights listening on port 8081
Server id 0 listening on port 8080

コンテナの停止

docker-compose stop
村松龍之介村松龍之介

Redisとは

リモートディクショナリサーバーの略。
オープンソースのインメモリデータストア。

NoSQLでKey-Value Storeとして動作する。

村松龍之介村松龍之介

Serverpod Insights

Serverpodのコンパニオンアプリ。
これを使えば、サーバーのログやヘルスメトリクスにアクセスすることができる。

Serverpodと同じバージョンのものをインストールして使用する。
https://docs.serverpod.dev/insights

村松龍之介村松龍之介

Model / Entityの定義(Serialization)

yaml で定義することもできるし、 freezed 当を使用して dart で定義することもできる。

yamlファイルで定義してprotocolに置く独自の方法

### Information about a company.
class: Company

### DBの行を表す場合にTable Keyを定義する。lower_snake_caseを使用する。
table: company

fields:
  ### The name of the company.
  name: String

  ### The date the company was founded, if known.
  foundedDate: DateTime?

  ### A list of people currently employed at the company.
  employees: List<Employee>

freezed 等を使用して定義する、慣れ親しんだ方法

import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:serverpod_serialization/serverpod_serialization.dart';

part 'freezed_custom_class.freezed.dart';
part 'freezed_custom_class.g.dart';


class FreezedCustomClass with _$FreezedCustomClass {
  const factory FreezedCustomClass({
    required String firstName,
    required String lastName,
    required int age,
  }) = _FreezedCustomClass;

  factory FreezedCustomClass.fromJson(
    Map<String, Object?> json,
    SerializationManager serializationManager,
  ) =>
      _$FreezedCustomClassFromJson(json);
}

config/generator.yaml ファイルで、宣言する必要がある。

extraClasses:
  - package:my_shared_package/my_shared_package.dart:FreezedCustomClass

fromJsonへのSerializationManagerパラメータ追加でエラーになる問題について

https://docs.serverpod.dev/concepts/serialization

村松龍之介村松龍之介

例外の定義とエラーハンドリング

シリアライズ可能なEntityを定義するのと同じようにyamlファイルで適宜可能。

exception: MyException
fields:
  message: String
  errorType: MyEnum

サーバー側では例外をスローする。

throw MyException(
        message: 'Failed to do thingy',
        errorType: MyEnum.thingyError,
      );

アプリ側で例外をキャッチする。

try {
  client.example.doThingy();
}
on MyException catch(e) {
  print(e.message);
}
村松龍之介村松龍之介

Database

モデルや例外と同様、protocol ディレクトリにyamlファイルを作成する。

class: Company
table: company
fields:
  name: String
  foundedDate: DateTime?

serverpod generategenerated/tables.pgsql が生成される。

特定のフィールドをデータベースに保存したいが、クライアント側に提供したくない機密情報などは database スコープを追加する。

class: UserData
fields:
  name: String
  password: String?, database

逆に(?)アクセスできるだけでサーバーに保存しないようにするには、 api スコープを追加する。

インデックス

fieldsキーには、カラム名をカンマで区切ったリストを格納します。さらに、タイプキー(デフォルトはbtree)、ユニークキー(デフォルトはfalse)を追加することが可能です。

class: Company
table: company
fields:
  name: String
  foundedDate: DateTime?
  employees: List<Employee>?, api
indexes:
  company_name_idx:
    fields: name

Parent/child リレーションシップ

class: Employee
table: employee
fields:
  companyId: int, parent=company
  name: String
  birthday: DateTime
村松龍之介村松龍之介

Session

エンドポイントのメソッドコール時の、コンテキスト情報。
セッションを使用して、サーバー内のDB、キャッシュ、認証、データストレージやメッセージングへアクセスできます。
また、HTTPリクエストオブジェクトの情報やIPアドレスにもアクセス可能。

以下のサブクラスにキャストすると、それぞれ追加情報が入手できる。

  • session as MethodCallSession: エンドポイントやメソッドの名前、HttpRequestオブジェクトなどの追加プロパティを提供する。
  • session as StreamingSession

稀なユースケースとして、 Serverpod.instance?.createSession() を使って手動でセッションを作ることも可能だが、 session.close() メソッドでセッションを手動で閉じる必要がある。

https://docs.serverpod.dev/concepts/sessions

村松龍之介村松龍之介

Authentication

session.auth.authenticatedUserId でユーザーID ( Future<int?> ) が取得できる。

村松龍之介村松龍之介

Starting the server の一連のコマンドをVS Codeでタスク化👍

{
	"version": "2.0.0",
	"tasks": [
		{
			"type": "shell",
			"command": "docker-compose",
			"args": [
				"up",
				"--build",
				"--detach"
			],
			"group": "none",
			"problemMatcher": [],
			"options": {
				"cwd": "mypod_server" // <- `xxx_server` ディレクトリのパスを指定する
			},
			"label": "docker-compose up"
		},
		{
			"type": "shell",
			"command": "dart",
			"args": [
				"bin/main.dart"
			],
			"group": "build",
			"problemMatcher": [],
			"options": {
				"cwd": "mypod_server" // <- `xxx_server` ディレクトリのパスを指定する
			},
			"dependsOrder": "sequence",
			"dependsOn": [
				"docker-compose up",
			],
			"label": "run main.dart"
		}
	]
}

https://docs.serverpod.dev/#starting-the-server

このスクラップは2023/06/30にクローズされました