V0.38.4 full composition (#237)
Co-authored-by: gobha <jasafpro@gmail.com> Co-committed-by: gobha <jasafpro@gmail.com>
This commit is contained in:
103
server/handlers/connection_types.go
Normal file
103
server/handlers/connection_types.go
Normal file
@@ -0,0 +1,103 @@
|
||||
package handlers
|
||||
|
||||
// v0.38.4: Connection type discovery endpoint.
|
||||
// Returns merged connection types from all active packages.
|
||||
// Library declarations take precedence over non-library declarations.
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"chat-switchboard/store"
|
||||
)
|
||||
|
||||
// ConnectionTypeEntry is a single connection type in the API response.
|
||||
type ConnectionTypeEntry struct {
|
||||
Type string `json:"type"`
|
||||
Label string `json:"label"`
|
||||
PackageID string `json:"package_id"`
|
||||
PackageTitle string `json:"package_title"`
|
||||
Fields map[string]map[string]string `json:"fields"`
|
||||
Scopes []string `json:"scopes,omitempty"`
|
||||
}
|
||||
|
||||
// ConnectionTypeHandler serves GET /api/v1/connection-types.
|
||||
type ConnectionTypeHandler struct {
|
||||
stores store.Stores
|
||||
}
|
||||
|
||||
func NewConnectionTypeHandler(s store.Stores) *ConnectionTypeHandler {
|
||||
return &ConnectionTypeHandler{stores: s}
|
||||
}
|
||||
|
||||
// ListConnectionTypes returns all connection types declared by active packages.
|
||||
// Library packages take precedence when multiple packages declare the same type.
|
||||
func (h *ConnectionTypeHandler) ListConnectionTypes(c *gin.Context) {
|
||||
ctx := c.Request.Context()
|
||||
pkgs, err := h.stores.Packages.List(ctx)
|
||||
if err != nil {
|
||||
c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to list packages"})
|
||||
return
|
||||
}
|
||||
|
||||
type entry struct {
|
||||
ct ConnectionTypeEntry
|
||||
isLibrary bool
|
||||
}
|
||||
seen := map[string]*entry{}
|
||||
|
||||
for _, pkg := range pkgs {
|
||||
if pkg.Status != "active" || !pkg.Enabled {
|
||||
continue
|
||||
}
|
||||
connsRaw, ok := pkg.Manifest["connections"]
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
connsJSON, _ := json.Marshal(connsRaw)
|
||||
var conns []struct {
|
||||
Type string `json:"type"`
|
||||
Label string `json:"label"`
|
||||
Fields map[string]map[string]string `json:"fields"`
|
||||
Scopes []string `json:"scopes"`
|
||||
}
|
||||
if err := json.Unmarshal(connsJSON, &conns); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
isLib := pkg.Type == "library"
|
||||
for _, cd := range conns {
|
||||
if cd.Type == "" {
|
||||
continue
|
||||
}
|
||||
existing, exists := seen[cd.Type]
|
||||
// Library declarations take precedence
|
||||
if exists && !isLib && existing.isLibrary {
|
||||
continue
|
||||
}
|
||||
label := cd.Label
|
||||
if label == "" {
|
||||
label = cd.Type
|
||||
}
|
||||
seen[cd.Type] = &entry{
|
||||
ct: ConnectionTypeEntry{
|
||||
Type: cd.Type,
|
||||
Label: label,
|
||||
PackageID: pkg.ID,
|
||||
PackageTitle: pkg.Title,
|
||||
Fields: cd.Fields,
|
||||
Scopes: cd.Scopes,
|
||||
},
|
||||
isLibrary: isLib,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result := make([]ConnectionTypeEntry, 0, len(seen))
|
||||
for _, e := range seen {
|
||||
result = append(result, e.ct)
|
||||
}
|
||||
c.JSON(http.StatusOK, gin.H{"data": result})
|
||||
}
|
||||
@@ -814,6 +814,10 @@ func main() {
|
||||
protected.GET("/api-configs/:id/models", provCfg.ListModels)
|
||||
protected.POST("/api-configs/:id/models/fetch", provCfg.FetchModels)
|
||||
|
||||
// Connection Type Discovery (v0.38.4)
|
||||
connTypeH := handlers.NewConnectionTypeHandler(stores)
|
||||
protected.GET("/connection-types", connTypeH.ListConnectionTypes)
|
||||
|
||||
// Extension Connections (personal scope — v0.38.1)
|
||||
connH := handlers.NewConnectionHandler(stores, keyResolver)
|
||||
protected.GET("/connections", connH.ListConnections)
|
||||
|
||||
@@ -8888,6 +8888,31 @@ paths:
|
||||
$ref: '#/components/schemas/ExtDependency'
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
# ── Connection Type Discovery (v0.38.4) ─────────────────────────────
|
||||
/api/v1/connection-types:
|
||||
get:
|
||||
tags: [Extensions]
|
||||
summary: List available connection types
|
||||
description: |
|
||||
Returns merged connection types from all active packages.
|
||||
Library declarations take precedence over non-library declarations.
|
||||
Any authenticated user can call this endpoint.
|
||||
security:
|
||||
- bearerAuth: []
|
||||
responses:
|
||||
'200':
|
||||
description: Connection type list
|
||||
content:
|
||||
application/json:
|
||||
schema:
|
||||
type: object
|
||||
properties:
|
||||
data:
|
||||
type: array
|
||||
items:
|
||||
$ref: '#/components/schemas/ConnectionType'
|
||||
'401':
|
||||
$ref: '#/components/responses/Unauthorized'
|
||||
# ── Extension Connections (v0.38.1) ─────────────────────────────────
|
||||
/api/v1/connections:
|
||||
get:
|
||||
@@ -12334,6 +12359,39 @@ components:
|
||||
updated_at:
|
||||
type: string
|
||||
format: date-time
|
||||
ConnectionType:
|
||||
type: object
|
||||
description: "v0.38.4: Available connection type from an installed package"
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
description: Connection type identifier (e.g. gitea, slack)
|
||||
label:
|
||||
type: string
|
||||
description: Human-readable label
|
||||
package_id:
|
||||
type: string
|
||||
description: Package that declares this connection type
|
||||
package_title:
|
||||
type: string
|
||||
description: Title of the declaring package
|
||||
fields:
|
||||
type: object
|
||||
description: Field definitions (name → {type, required, label})
|
||||
additionalProperties:
|
||||
type: object
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
required:
|
||||
type: string
|
||||
label:
|
||||
type: string
|
||||
scopes:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: Allowed scopes (global, team, personal)
|
||||
ExtDependency:
|
||||
type: object
|
||||
description: "v0.38.2: Package dependency record (consumer → library)"
|
||||
|
||||
Reference in New Issue
Block a user