Add endpoint
Рецепт: создать новый Serverpod endpoint с нуля.
Шаг 1: Создать YAML модель (если нужна новая таблица)¶
# onewallet_base_server/lib/src/models/my_model.spy.yaml
class: MyModel
table: my_model
fields:
userId: int
value: String
createdAt: DateTime
indexes:
my_model_user_idx:
fields: userId
Правила YAML:
- Тип поля — Dart-синтаксис: int, String, DateTime, bool, double
- Для nullable: String?
- id генерируется автоматически, не объявлять
- Имена полей — camelCase; в SQL Serverpod процитирует как "userId", "createdAt" (всегда цитировать в raw SQL)
Шаг 2: Запустить codegen¶
После этого в lib/src/generated/ появится Dart-класс модели. Если модель с таблицей — в migrations/ появится SQL-миграция.
Шаг 3: Создать endpoint файл¶
// onewallet_base_server/lib/src/endpoints/my_endpoint.dart
import 'package:serverpod/serverpod.dart';
import '../util/endpoint_guard.dart';
import '../generated/my_model.dart';
class MyEndpoint extends Endpoint {
@override
bool get requireLogin => true;
Future<String> doSomething(Session session, String param) async {
// requireAccountType выбросит NotAuthorizedException если тип не совпадает
final user = await requireAccountType(session, ['consumer', 'wallet']);
// Бизнес-логика
final row = await MyModel.db.findFirstRow(
session,
where: (t) => t.userId.equals(user.id!),
);
return row?.value ?? 'default';
}
Future<void> createSomething(Session session, String value) async {
final user = await requireAccountType(session, ['consumer']);
await MyModel.db.insertRow(
session,
MyModel(
userId: user.id!,
value: value,
createdAt: DateTime.now().toUtc(),
),
);
}
}
Типы account для requireAccountType:
- 'consumer' — пользователи wallet и closeloop
- 'wallet' — только основной кошелёк
- 'merchant' — мерчант
- 'agent' — агент
Шаг 4: Регистрация в endpoints¶
Не редактировать lib/src/generated/endpoints.dart вручную. Serverpod находит эндпоинты автоматически по наследованию от Endpoint. Повторно запустите codegen:
Имя эндпоинта на клиенте = имя класса в camelCase без суффикса Endpoint:
MyEndpoint → endpoints.my (или endpoints.myEndpoint в зависимости от версии Serverpod).
Шаг 5: Применить миграцию (если создана новая модель с таблицей)¶
Шаг 6: Написать тест¶
// test/integration/my_endpoint_test.dart
import 'package:test/test.dart';
import 'package:serverpod/serverpod.dart';
import 'package:uuid/uuid.dart';
import '../test_tools/serverpod_test_tools.dart';
import 'package:onewallet_base_server/src/generated/user.dart';
void main() {
withServerpod('MyEndpoint',
rollbackDatabase: RollbackDatabase.afterEach,
(sessionBuilder, endpoints) {
// Создать тестового пользователя с authUserId для аутентификации
Future<String> seedUser(Session session) async {
final authUuidStr = const Uuid().v4();
await User.db.insertRow(session, User(
email: 'test-${authUuidStr}@test.local',
passwordHash: '',
status: 'active',
accountType: 'consumer',
authUserId: UuidValue.fromString(authUuidStr),
createdAt: DateTime.now(),
isArchived: false,
));
return authUuidStr;
}
test('doSomething returns default when no row', () async {
final session = sessionBuilder.build();
final authUuid = await seedUser(session);
final authedSession = sessionBuilder.copyWith(
authentication: AuthenticationOverride.authenticationInfo(authUuid, const {}),
).build();
final result = await endpoints.my.doSomething(authedSession, 'param');
expect(result, equals('default'));
});
});
}