Service Sequences as Code — генерация сервисного кода из DSL Go-комментариев.

Сервисная логика — это серия решений: какую модель запросить, от чего защититься, когда отклонить, что вернуть. Эти решения принадлежат тому, кто понимает бизнес — но они тонут в шаблонном коде, разбросаны по слоям и теряются при переписывании.

SSaC сохраняет эти решения как декларативную спецификацию. Вы объявляете что происходит и в каком порядке. Инструмент генерирует реализацию.

specs/service/*.go  →  ssac validate  →  ssac gen  →  artifacts/service/*.go

GitHub

Ключевая идея

Каждая сервисная функция — последовательность шагов. Каждый шаг следует бинарному контракту: успех → следующая строка, неудача → return. Это не абстракция, которую мы изобрели — так сервисная логика уже работает. SSaC делает это явным.

10 фиксированных типов последовательностей покрывают все операции сервисного уровня, следующие этому контракту. Что не подходит — делегируется в call. Множество закрыто по дизайну.

Без LLM, без вывода — чистая символьная кодогенерация из шаблонов. Спецификация — единственный источник истины.

Пример

// @sequence get
// @model Project.FindByID
// @param ProjectID request
// @result project Project

// @sequence guard nil project
// @message "project not found"

// @sequence post
// @model Session.Create
// @param ProjectID request
// @param Command request
// @result session Session

// @sequence response json
// @var session
func CreateSession(w http.ResponseWriter, r *http.Request) {}

Эта 10-строчная декларация генерирует следующий код:

func CreateSession(w http.ResponseWriter, r *http.Request) {
    projectID := r.FormValue("ProjectID")
    command := r.FormValue("Command")

    project, err := projectModel.FindByID(projectID)
    if err != nil {
        http.Error(w, "Project lookup failed", http.StatusInternalServerError)
        return
    }

    if project == nil {
        http.Error(w, "project not found", http.StatusNotFound)
        return
    }

    session, err := sessionModel.Create(projectID, command)
    if err != nil {
        http.Error(w, "Session creation failed", http.StatusInternalServerError)
        return
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(map[string]interface{}{
        "session": session,
    })
}

Типы последовательностей (10)

ТипРоль
authorizeПроверка прав (OPA и т.д.)
getПоиск ресурса
guard nilВыход при null
guard existsВыход при наличии
postСоздание ресурса
putОбновление ресурса
deleteУдаление ресурса
passwordСравнение паролей
callВнешний вызов (@component / @func)
responseВозврат ответа (json)

Возможности кодогенерации

/api/reservations:
  get:
    operationId: ListReservations
    x-pagination:
      style: offset
      defaultLimit: 20
      maxLimit: 100
    x-sort:
      allowed: [start_at, created_at]
      default: start_at
      direction: desc
    x-filter:
      allowed: [status, room_id]
    x-include:
      allowed: [room, user]

Лицензия

MIT — GitHub