Protocol Buffer схемы для сервисов SEP
npm install @pksep/contracts
contracts/
├── SEP/ # Исходные .proto файлы
│ ├── common/v1/ # Общие типы данных
│ └── kafka/ # Kafka-сообщения
│ ├── v1/ # Общие Kafka-сообщения
│ │ └── topics.proto # Константы для топиков Kafka
│ └── citadel/v1/ # Kafka-сообщения сервиса citadel
│ └── participant_created.proto
├── generated/ # Сгенерированный TypeScript код
├── docs/ # Документация
└── scripts/ # Скрипты для генерации кода
`
Установка
`bash
Для использования в проекте
npm install @pksep/proto-models
Для разработки
git clone https://github.com/pksep/contracts.git
cd contracts
npm install
`
Разработка
$3
В проекте используются два инструмента для линтинга:
1. buf - для проверки .proto файлов
`bash
npm run lint
`
2. Biome - для проверки и форматирования TypeScript/JavaScript кода
`bash
# Проверка кода
npm run lint:biome
# Форматирование кода
npm run format
`
При коммите изменений автоматически запускаются pre-commit хуки, которые проверяют код на соответствие правилам.
Использование в NestJS
$3
`typescript
import { ClientKafka } from '@nestjs/microservices';
import { ParticipantCreated, KAFKA_TOPICS } from '@SEP-is/proto-models';
@Injectable()
export class UserService {
constructor(
@Inject('KAFKA_SERVICE') private readonly kafkaClient: ClientKafka,
) {}
async createUser(userData: Record) {
// Создание участника
const participant = await this.participantRepository.save(userData);
// Отправка события в Kafka
const participantCreatedEvent: ParticipantCreated = {
id: participant.id,
createdAt: {
milliseconds: Date.now(),
},
metadata: {
eventId: 'event-123',
source: 'user-service',
},
source: {
telegram: {
username: participant.username,
userId: 12345678,
}
}
};
// Используем константы для топиков вместо строковых литералов
this.kafkaClient.emit(KAFKA_TOPICS.CITADEL.PARTICIPANT.CREATED, participantCreatedEvent);
return participant;
}
}
`
$3
Вместо использования строковых литералов для топиков Kafka, используйте константы из пакета:
`typescript
import { KAFKA_TOPICS } from '@pksep/proto-models';
// Продюсер
kafkaClient.emit(KAFKA_TOPICS.CITADEL.PARTICIPANT.CREATED, participantCreatedEvent);
// Консьюмер
@MessagePattern(KAFKA_TOPICS.CITADEL.PARTICIPANT.CREATED)
async handleParticipantCreated(data: ParticipantCreated) {
// Обработка события
}
`
Подробные рекомендации по именованию топиков Kafka можно найти в документации по именованию топиков.
Разработка
$3
`bash
npm run generate
`
$3
Для генерации документации из .proto файлов используется инструмент protoc-gen-doc. Документация генерируется в форматах HTML и Markdown.
`bash
npm run generate:docs
`
Сгенерированная документация доступна:
- В директории docs/ локально
- На GitHub Pages после релиза
$3
1. Создайте новый .proto файл в соответствующей директории
2. Добавьте необходимые импорты и определения сообщений
3. Запустите npm run generate для генерации TypeScript кода
$3
1. Обновите файл sep/kafka/v1/topics.proto, добавив новый топик в enum KafkaTopic с префиксом KAFKA_TOPIC_
2. Добавьте комментарий со строковым представлением топика в формате
3. Запустите npm run generate для обновления констант
Пример добавления нового топика:
`proto
// В sep/kafka/v1/topics.proto
enum KafkaTopic {
// ... existing code ...
// Топики сервиса billing
// Событие создания счета
// Строковое представление: billing.invoice.created.v1
KAFKA_TOPIC_BILLING_INVOICE_CREATED = 3;
}
`
После запуска npm run generate константы будут автоматически сгенерированы:
`typescript
// В сгенерированном файле kafka-topics.ts
export const KAFKA_TOPICS = {
// ... existing code ...
BILLING: {
INVOICE: {
CREATED: 'billing.invoice.created.v1',
},
},
};
`
Подробные рекомендации по именованию топиков можно найти в документации по именованию топиков.
Правила совместимости
При изменении существующих схем необходимо соблюдать обратную совместимость:
- Не удаляйте существующие поля, помечайте их как deprecated
- Не меняйте типы существующих полей
- Добавляйте новые поля с атрибутом optional
- Не меняйте порядковые номера полей
Соглашения об именовании
- Имена пакетов: snake_case (например, sep.kafka.citadel.v1)
- Имена сообщений: PascalCase (например, ParticipantCreated)
- Имена полей: snake_case (например, created_at)
- Имена файлов: snake_case (например, participant_created.proto)
- Имена топиков Kafka: lowercase.dot.separated (например, citadel.participant.created.v1)
- Имена констант в enum KafkaTopic: UPPERCASE_SNAKE_CASE с префиксом KAFKA_TOPIC_ (например, KAFKA_TOPIC_CITADEL_PARTICIPANT_CREATED`)