Files
schemas/graph/cosmo.go
T

107 lines
2.8 KiB
Go
Raw Normal View History

package graph
import (
"fmt"
"os"
"os/exec"
"path/filepath"
"gopkg.in/yaml.v3"
"gitlab.com/unboundsoftware/schemas/graph/model"
)
// GenerateCosmoRouterConfig generates a Cosmo Router execution config from subgraphs
// using the official wgc CLI tool via npx
func GenerateCosmoRouterConfig(subGraphs []*model.SubGraph) (string, error) {
if len(subGraphs) == 0 {
return "", fmt.Errorf("no subgraphs provided")
}
// Create a temporary directory for composition
tmpDir, err := os.MkdirTemp("", "cosmo-compose-*")
if err != nil {
return "", fmt.Errorf("create temp dir: %w", err)
}
defer os.RemoveAll(tmpDir)
// Write each subgraph SDL to a file
type SubgraphConfig struct {
Name string `yaml:"name"`
RoutingURL string `yaml:"routing_url,omitempty"`
Schema map[string]string `yaml:"schema"`
Subscription map[string]interface{} `yaml:"subscription,omitempty"`
}
type InputConfig struct {
Version int `yaml:"version"`
Subgraphs []SubgraphConfig `yaml:"subgraphs"`
}
inputConfig := InputConfig{
Version: 1,
Subgraphs: make([]SubgraphConfig, 0, len(subGraphs)),
}
for _, sg := range subGraphs {
// Write SDL to a temp file
schemaFile := filepath.Join(tmpDir, fmt.Sprintf("%s.graphql", sg.Service))
if err := os.WriteFile(schemaFile, []byte(sg.Sdl), 0o644); err != nil {
return "", fmt.Errorf("write schema file for %s: %w", sg.Service, err)
}
subgraphCfg := SubgraphConfig{
Name: sg.Service,
Schema: map[string]string{
"file": schemaFile,
},
}
if sg.URL != nil {
subgraphCfg.RoutingURL = *sg.URL
}
if sg.WsURL != nil {
subgraphCfg.Subscription = map[string]interface{}{
"url": *sg.WsURL,
"protocol": "ws",
"websocket_subprotocol": "graphql-ws",
}
}
inputConfig.Subgraphs = append(inputConfig.Subgraphs, subgraphCfg)
}
// Write input config YAML
inputFile := filepath.Join(tmpDir, "input.yaml")
inputYAML, err := yaml.Marshal(inputConfig)
if err != nil {
return "", fmt.Errorf("marshal input config: %w", err)
}
if err := os.WriteFile(inputFile, inputYAML, 0o644); err != nil {
return "", fmt.Errorf("write input config: %w", err)
}
// Execute wgc router compose
// wgc is installed globally in the Docker image
outputFile := filepath.Join(tmpDir, "config.json")
cmd := exec.Command("wgc", "router", "compose",
"--input", inputFile,
"--out", outputFile,
"--suppress-warnings",
)
output, err := cmd.CombinedOutput()
if err != nil {
return "", fmt.Errorf("wgc router compose failed: %w\nOutput: %s", err, string(output))
}
// Read the generated config
configJSON, err := os.ReadFile(outputFile)
if err != nil {
return "", fmt.Errorf("read output config: %w", err)
}
return string(configJSON), nil
}