package main
import "C"
import (
"encoding/json"
"fmt"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"sync"
"unsafe"
"cuelang.org/go/cue"
"cuelang.org/go/cue/ast"
"cuelang.org/go/cue/build"
"cuelang.org/go/cue/cuecontext"
"cuelang.org/go/cue/load"
"cuelang.org/go/mod/modconfig"
)
const BridgeVersion = "bridge/1"
const (
ErrorCodeInvalidInput = "INVALID_INPUT"
ErrorCodeLoadInstance = "LOAD_INSTANCE"
ErrorCodeBuildValue = "BUILD_VALUE"
ErrorCodeOrderedJSON = "ORDERED_JSON"
ErrorCodePanicRecover = "PANIC_RECOVER"
ErrorCodeJSONMarshal = "JSON_MARSHAL_ERROR"
ErrorCodeRegistryInit = "REGISTRY_INIT"
ErrorCodeDependencyRes = "DEPENDENCY_RESOLUTION"
)
type BridgeError struct {
Code string `json:"code"`
Message string `json:"message"`
Hint *string `json:"hint,omitempty"`
}
type BridgeResponse struct {
Version string `json:"version"`
Ok *json.RawMessage `json:"ok,omitempty"`
Error *BridgeError `json:"error,omitempty"`
}
func cue_free_string(s *C.char) {
C.free(unsafe.Pointer(s))
}
func cue_bridge_version() *C.char {
versionInfo := fmt.Sprintf("%s (Go %s)", BridgeVersion, runtime.Version())
return C.CString(versionInfo)
}
func createErrorResponse(code, message string, hint *string) *C.char {
error := &BridgeError{
Code: code,
Message: message,
Hint: hint,
}
response := &BridgeResponse{
Version: BridgeVersion,
Error: error,
}
responseBytes, err := json.Marshal(response)
if err != nil {
fallbackResponse := fmt.Sprintf(`{"version":"%s","error":{"code":"%s","message":"Failed to marshal error response: %s"}}`, BridgeVersion, ErrorCodeJSONMarshal, err.Error())
return C.CString(fallbackResponse)
}
return C.CString(string(responseBytes))
}
func createSuccessResponse(data string) *C.char {
rawData := json.RawMessage(data)
response := &BridgeResponse{
Version: BridgeVersion,
Ok: &rawData,
}
responseBytes, err := json.Marshal(response)
if err != nil {
msg := fmt.Sprintf("Failed to marshal success response: %s", err.Error())
return createErrorResponse(ErrorCodeJSONMarshal, msg, nil)
}
return C.CString(string(responseBytes))
}
type TaskSourcePos struct {
File string
Line int
Column int
}
type ValueMeta struct {
Directory string `json:"directory"`
Filename string `json:"filename"`
Line int `json:"line"`
}
type MetaValue struct {
Value interface{} `json:"_value"`
Meta ValueMeta `json:"_meta"`
}
func extractTaskPositions(inst *build.Instance, moduleRoot string) map[string]TaskSourcePos {
positions := make(map[string]TaskSourcePos)
for _, f := range inst.Files {
for _, decl := range f.Decls {
field, ok := decl.(*ast.Field)
if !ok {
continue
}
label, _, _ := ast.LabelName(field.Label)
if label != "tasks" {
continue
}
st, ok := field.Value.(*ast.StructLit)
if !ok {
continue
}
extractTaskPositionsFromStruct(st, "", f.Filename, moduleRoot, positions)
}
}
return positions
}
func extractTaskPositionsFromStruct(st *ast.StructLit, prefix, filename, moduleRoot string, positions map[string]TaskSourcePos) {
for _, elem := range st.Elts {
taskField, ok := elem.(*ast.Field)
if !ok {
continue
}
taskLabel, _, _ := ast.LabelName(taskField.Label)
fullName := taskLabel
if prefix != "" {
fullName = prefix + "." + taskLabel
}
relPath := filename
if moduleRoot != "" && strings.HasPrefix(filename, moduleRoot) {
relPath = strings.TrimPrefix(filename, moduleRoot)
relPath = strings.TrimPrefix(relPath, string(filepath.Separator))
}
if relPath == "" {
relPath = "env.cue"
}
pos := taskField.Pos()
positions[fullName] = TaskSourcePos{
File: relPath,
Line: pos.Line(),
Column: pos.Column(),
}
if nestedSt, ok := taskField.Value.(*ast.StructLit); ok {
for _, nestedElem := range nestedSt.Elts {
if nestedField, ok := nestedElem.(*ast.Field); ok {
nestedLabel, _, _ := ast.LabelName(nestedField.Label)
if nestedLabel == "tasks" {
if nestedTasksSt, ok := nestedField.Value.(*ast.StructLit); ok {
extractTaskPositionsFromStruct(nestedTasksSt, fullName, filename, moduleRoot, positions)
}
}
}
}
}
}
}
func extractAllFieldPositions(inst *build.Instance, moduleRoot, instanceDir string) map[string]ValueMeta {
positions := make(map[string]ValueMeta)
for _, f := range inst.Files {
relPath := f.Filename
if moduleRoot != "" && strings.HasPrefix(f.Filename, moduleRoot) {
relPath = strings.TrimPrefix(f.Filename, moduleRoot)
relPath = strings.TrimPrefix(relPath, string(filepath.Separator))
}
if relPath == "" {
relPath = "env.cue"
}
dir := instanceDir
if dir == "" || dir == "." {
dir = "."
}
for _, decl := range f.Decls {
field, ok := decl.(*ast.Field)
if !ok {
continue
}
label, _, _ := ast.LabelName(field.Label)
extractFieldPositionsRecursive(field, label, relPath, dir, positions)
}
}
return positions
}
func extractFieldPositionsRecursive(field *ast.Field, path, filename, directory string, positions map[string]ValueMeta) {
pos := field.Pos()
positions[path] = ValueMeta{
Directory: directory,
Filename: filename,
Line: pos.Line(),
}
if st, ok := field.Value.(*ast.StructLit); ok {
for _, elem := range st.Elts {
if childField, ok := elem.(*ast.Field); ok {
childLabel, _, _ := ast.LabelName(childField.Label)
childPath := path + "." + childLabel
extractFieldPositionsRecursive(childField, childPath, filename, directory, positions)
}
}
}
if list, ok := field.Value.(*ast.ListLit); ok {
for i, elem := range list.Elts {
if st, ok := elem.(*ast.StructLit); ok {
indexPath := fmt.Sprintf("%s[%d]", path, i)
for _, structElem := range st.Elts {
if childField, ok := structElem.(*ast.Field); ok {
childLabel, _, _ := ast.LabelName(childField.Label)
childPath := indexPath + "." + childLabel
extractFieldPositionsRecursive(childField, childPath, filename, directory, positions)
}
}
}
}
}
}
func makeMetaKey(instancePath, fieldPath string) string {
if instancePath == "." {
return "./" + fieldPath
}
return instancePath + "/" + fieldPath
}
func extractFieldMetaSeparate(inst *build.Instance, moduleRoot, instancePath string) map[string]ValueMeta {
positions := make(map[string]ValueMeta)
for _, f := range inst.Files {
relPath := f.Filename
if moduleRoot != "" && strings.HasPrefix(f.Filename, moduleRoot) {
relPath = strings.TrimPrefix(f.Filename, moduleRoot)
relPath = strings.TrimPrefix(relPath, string(filepath.Separator))
}
if relPath == "" {
relPath = filepath.Base(f.Filename)
}
dir := instancePath
if dir == "" {
dir = "."
}
for _, decl := range f.Decls {
field, ok := decl.(*ast.Field)
if !ok {
continue
}
label, _, _ := ast.LabelName(field.Label)
extractFieldMetaRecursive(field, label, relPath, dir, instancePath, positions)
}
}
return positions
}
func extractFieldMetaRecursive(field *ast.Field, fieldPath, filename, directory, instancePath string, positions map[string]ValueMeta) {
pos := field.Pos()
metaKey := makeMetaKey(instancePath, fieldPath)
positions[metaKey] = ValueMeta{
Directory: directory,
Filename: filename,
Line: pos.Line(),
}
if st, ok := field.Value.(*ast.StructLit); ok {
for _, elem := range st.Elts {
if childField, ok := elem.(*ast.Field); ok {
childLabel, _, _ := ast.LabelName(childField.Label)
childPath := fieldPath + "." + childLabel
extractFieldMetaRecursive(childField, childPath, filename, directory, instancePath, positions)
}
}
}
if list, ok := field.Value.(*ast.ListLit); ok {
for i, elem := range list.Elts {
if st, ok := elem.(*ast.StructLit); ok {
indexPath := fmt.Sprintf("%s[%d]", fieldPath, i)
for _, structElem := range st.Elts {
if childField, ok := structElem.(*ast.Field); ok {
childLabel, _, _ := ast.LabelName(childField.Label)
childPath := indexPath + "." + childLabel
extractFieldMetaRecursive(childField, childPath, filename, directory, instancePath, positions)
}
}
}
}
}
}
func buildJSONClean(v cue.Value) ([]byte, error) {
result := buildValueClean(v)
return json.Marshal(result)
}
func unquoteSelector(s string) string {
if len(s) >= 2 && s[0] == '"' && s[len(s)-1] == '"' {
return s[1 : len(s)-1]
}
return s
}
func buildValueClean(v cue.Value) interface{} {
switch v.Kind() {
case cue.StructKind:
result := make(map[string]interface{})
iter, _ := v.Fields(cue.Definitions(false))
for iter.Next() {
sel := iter.Selector()
fieldName := unquoteSelector(sel.String())
result[fieldName] = buildValueClean(iter.Value())
}
return result
case cue.ListKind:
var items []interface{}
iter, _ := v.List()
for iter.Next() {
items = append(items, buildValueClean(iter.Value()))
}
return items
default:
var val interface{}
v.Decode(&val)
return val
}
}
func buildJSONWithMeta(v cue.Value, positions map[string]ValueMeta) ([]byte, error) {
result := buildValueWithMeta(v, "", positions)
return json.Marshal(result)
}
func buildValueWithMeta(v cue.Value, path string, positions map[string]ValueMeta) interface{} {
switch v.Kind() {
case cue.StructKind:
result := make(map[string]interface{})
iter, _ := v.Fields(cue.Definitions(false))
for iter.Next() {
sel := iter.Selector()
fieldName := unquoteSelector(sel.String())
childPath := fieldName
if path != "" {
childPath = path + "." + fieldName
}
result[fieldName] = buildValueWithMeta(iter.Value(), childPath, positions)
}
return result
case cue.ListKind:
var items []interface{}
iter, _ := v.List()
i := 0
for iter.Next() {
indexPath := fmt.Sprintf("%s[%d]", path, i)
items = append(items, buildValueWithMeta(iter.Value(), indexPath, positions))
i++
}
if meta, ok := positions[path]; ok {
return MetaValue{Value: items, Meta: meta}
}
return items
default:
var val interface{}
v.Decode(&val)
if meta, ok := positions[path]; ok {
return MetaValue{Value: val, Meta: meta}
}
return val
}
}
func buildJSON(v cue.Value, moduleRoot string, taskPositions map[string]TaskSourcePos) ([]byte, error) {
result := make(map[string]interface{})
iter, err := v.Fields(cue.Definitions(false))
if err != nil {
return nil, err
}
for iter.Next() {
sel := iter.Selector()
fieldName := unquoteSelector(sel.String())
fieldValue := iter.Value()
val := buildValueClean(fieldValue)
if fieldName == "tasks" {
val = enrichTasksWithSource(val, "", taskPositions)
}
result[fieldName] = val
}
return json.Marshal(result)
}
func enrichTasksWithSource(decoded interface{}, prefix string, positions map[string]TaskSourcePos) interface{} {
tasksMap, ok := decoded.(map[string]interface{})
if !ok {
return decoded
}
for taskName, taskDef := range tasksMap {
fullName := taskName
if prefix != "" {
fullName = prefix + "." + taskName
}
enrichTaskWithSource(taskDef, fullName, positions)
}
return tasksMap
}
func enrichTaskWithSource(taskDef interface{}, fullName string, positions map[string]TaskSourcePos) {
taskObj, ok := taskDef.(map[string]interface{})
if !ok {
return
}
if nested, ok := taskObj["tasks"].(map[string]interface{}); ok {
for childName, childDef := range nested {
childFullName := fullName + "." + childName
enrichTaskWithSource(childDef, childFullName, positions)
}
return
}
if _, isArray := taskDef.([]interface{}); isArray {
return
}
_, hasCommand := taskObj["command"]
_, hasScript := taskObj["script"]
_, hasTaskRef := taskObj["task_ref"]
if !hasCommand && !hasScript && !hasTaskRef {
return
}
if pos, ok := positions[fullName]; ok {
taskObj["_source"] = map[string]interface{}{
"file": pos.File,
"line": pos.Line,
"column": pos.Column,
}
}
}
func cue_eval_package(dirPath *C.char, packageName *C.char) *C.char {
var result *C.char
defer func() {
if r := recover(); r != nil {
panic_msg := fmt.Sprintf("Internal panic: %v", r)
result = createErrorResponse(ErrorCodePanicRecover, panic_msg, nil)
}
}()
goDir := C.GoString(dirPath)
goPackageName := C.GoString(packageName)
if goDir == "" {
result = createErrorResponse(ErrorCodeInvalidInput, "Directory path cannot be empty", nil)
return result
}
if goPackageName == "" {
result = createErrorResponse(ErrorCodeInvalidInput, "Package name cannot be empty", nil)
return result
}
ctx := cuecontext.New()
registry, err := modconfig.NewRegistry(&modconfig.Config{
Transport: http.DefaultTransport,
ClientType: "cuenv",
})
if err != nil {
hint := "Check CUE registry configuration (CUE_REGISTRY env var) and network access"
result = createErrorResponse(ErrorCodeRegistryInit,
fmt.Sprintf("Failed to initialize CUE registry: %v", err), &hint)
return result
}
moduleRoot := resolveCueModuleRoot(goDir)
cfg := &load.Config{
Dir: goDir,
Registry: registry,
}
if moduleRoot != "" {
cfg.ModuleRoot = moduleRoot
}
var instances []*build.Instance
packagePath := ".:" + goPackageName
instances = load.Instances([]string{packagePath}, cfg)
if len(instances) == 0 {
hint := "Check that the package name exists and CUE files are present"
result = createErrorResponse(ErrorCodeLoadInstance, "No CUE instances found", &hint)
return result
}
inst := instances[0]
if inst.Err != nil {
msg := fmt.Sprintf("Failed to load CUE instance: %v", inst.Err)
hint := "Check CUE syntax and import statements"
result = createErrorResponse(ErrorCodeLoadInstance, msg, &hint)
return result
}
v := ctx.BuildInstance(inst)
if v.Err() != nil {
msg := fmt.Sprintf("Failed to build CUE value: %v", v.Err())
hint := "Check CUE constraints and value definitions"
result = createErrorResponse(ErrorCodeBuildValue, msg, &hint)
return result
}
taskPositions := extractTaskPositions(inst, moduleRoot)
jsonBytes, err := buildJSON(v, moduleRoot, taskPositions)
if err != nil {
msg := fmt.Sprintf("Failed to marshal JSON: %v", err)
result = createErrorResponse(ErrorCodeOrderedJSON, msg, nil)
return result
}
result = createSuccessResponse(string(jsonBytes))
return result
}
type ModuleInstance struct {
Path string `json:"path"`
Value json.RawMessage `json:"value"`
}
type ModuleResult struct {
Instances map[string]json.RawMessage `json:"instances"`
Projects []string `json:"projects"` Meta map[string]ValueMeta `json:"meta,omitempty"` }
type ModuleEvalOptions struct {
WithMeta bool `json:"withMeta"` Recursive bool `json:"recursive"` PackageName *string `json:"packageName"` TargetDir *string `json:"targetDir"` }
type instanceResult struct {
relPath string
jsonBytes []byte
isProject bool
meta map[string]ValueMeta
err error
}
func cue_eval_module(moduleRootPath *C.char, packageName *C.char, optionsJSON *C.char) *C.char {
var result *C.char
defer func() {
if r := recover(); r != nil {
panic_msg := fmt.Sprintf("Internal panic: %v", r)
result = createErrorResponse(ErrorCodePanicRecover, panic_msg, nil)
}
}()
goModuleRoot := C.GoString(moduleRootPath)
goPackageName := C.GoString(packageName) goOptionsJSON := C.GoString(optionsJSON)
options := ModuleEvalOptions{
WithMeta: false,
Recursive: false,
}
if goOptionsJSON != "" {
if err := json.Unmarshal([]byte(goOptionsJSON), &options); err != nil {
hint := "Options must be valid JSON: {\"withMeta\": true, \"recursive\": true, \"packageName\": \"pkg\"}"
result = createErrorResponse(ErrorCodeInvalidInput, fmt.Sprintf("Failed to parse options: %v", err), &hint)
return result
}
}
effectivePackageName := goPackageName
if options.PackageName != nil {
effectivePackageName = *options.PackageName
}
if goModuleRoot == "" {
result = createErrorResponse(ErrorCodeInvalidInput, "Module root path cannot be empty", nil)
return result
}
moduleFile := filepath.Join(goModuleRoot, "cue.mod", "module.cue")
if _, err := os.Stat(moduleFile); os.IsNotExist(err) {
hint := "Ensure path contains a cue.mod/module.cue file"
result = createErrorResponse(ErrorCodeInvalidInput, "Not a valid CUE module root", &hint)
return result
}
registry, err := modconfig.NewRegistry(&modconfig.Config{
Transport: http.DefaultTransport,
ClientType: "cuenv",
})
if err != nil {
hint := "Check CUE registry configuration (CUE_REGISTRY env var) and network access"
result = createErrorResponse(ErrorCodeRegistryInit,
fmt.Sprintf("Failed to initialize CUE registry: %v", err), &hint)
return result
}
evalDir := goModuleRoot
if options.TargetDir != nil && *options.TargetDir != "" {
evalDir = *options.TargetDir
}
cfg := &load.Config{
Dir: evalDir,
ModuleRoot: goModuleRoot,
Registry: registry,
}
var loadPattern string
if options.Recursive {
loadPattern = "./..."
} else {
loadPattern = "."
}
loadedInstances := load.Instances([]string{loadPattern}, cfg)
if len(loadedInstances) == 0 {
hint := "No CUE files found matching the load pattern"
result = createErrorResponse(ErrorCodeLoadInstance, "No CUE instances found", &hint)
return result
}
var validInstances []*build.Instance
for _, inst := range loadedInstances {
if inst.Err != nil {
continue
}
if effectivePackageName != "" && inst.PkgName != effectivePackageName {
continue
}
validInstances = append(validInstances, inst)
}
instances := make(map[string]json.RawMessage)
projects := []string{} allMeta := make(map[string]ValueMeta)
type builtInstance struct {
relPath string
value cue.Value
isProject bool
inst *build.Instance }
var builtInstances []builtInstance
ctx := cuecontext.New()
for _, inst := range validInstances {
relPath, err := filepath.Rel(goModuleRoot, inst.Dir)
if err != nil {
relPath = inst.Dir
}
if relPath == "" {
relPath = "."
}
v := ctx.BuildInstance(inst)
if v.Err() != nil {
continue
}
isProject := false
nameField := v.LookupPath(cue.ParsePath("name"))
if nameField.Exists() && nameField.Err() == nil {
isProject = true
}
builtInstances = append(builtInstances, builtInstance{
relPath: relPath,
value: v,
isProject: isProject,
inst: inst,
})
}
results := make(chan instanceResult, len(builtInstances))
var wg sync.WaitGroup
semaphore := make(chan struct{}, runtime.NumCPU())
moduleRoot := goModuleRoot
withMeta := options.WithMeta
for _, built := range builtInstances {
wg.Add(1)
go func(b builtInstance) {
defer wg.Done()
semaphore <- struct{}{} defer func() { <-semaphore }()
jsonBytes, err := buildJSONClean(b.value)
if err != nil {
results <- instanceResult{err: err}
return
}
var meta map[string]ValueMeta
if withMeta {
meta = extractFieldMetaSeparate(b.inst, moduleRoot, b.relPath)
}
results <- instanceResult{
relPath: b.relPath,
jsonBytes: jsonBytes,
isProject: b.isProject,
meta: meta,
}
}(built)
}
go func() {
wg.Wait()
close(results)
}()
var buildErrors []string
for r := range results {
if r.err != nil {
buildErrors = append(buildErrors, r.err.Error())
continue }
instances[r.relPath] = json.RawMessage(r.jsonBytes)
if r.isProject {
projects = append(projects, r.relPath)
}
for k, v := range r.meta {
allMeta[k] = v
}
}
if len(instances) == 0 {
hint := fmt.Sprintf("evalDir=%s, moduleRoot=%s, loadPattern=%s, loadedInstances=%d, validInstances=%d, builtInstances=%d, errors=%v",
evalDir, goModuleRoot, loadPattern, len(loadedInstances), len(validInstances), len(builtInstances), buildErrors)
result = createErrorResponse(ErrorCodeBuildValue, "No instances could be evaluated", &hint)
return result
}
moduleResult := ModuleResult{
Instances: instances,
Projects: projects,
}
if options.WithMeta && len(allMeta) > 0 {
moduleResult.Meta = allMeta
}
resultBytes, err := json.Marshal(moduleResult)
if err != nil {
result = createErrorResponse(ErrorCodeJSONMarshal, fmt.Sprintf("Failed to marshal module result: %v", err), nil)
return result
}
result = createSuccessResponse(string(resultBytes))
return result
}
func findEnvCueDirectories(moduleRoot, packageName string) ([]string, error) {
var dirs []string
err := filepath.Walk(moduleRoot, func(path string, info os.FileInfo, err error) error {
if err != nil {
return nil }
if info.IsDir() {
name := info.Name()
if strings.HasPrefix(name, ".") || name == "cue.mod" || name == "node_modules" {
return filepath.SkipDir
}
return nil
}
if info.Name() == "env.cue" {
content, err := os.ReadFile(path)
if err != nil {
return nil
}
if containsPackageDecl(string(content), packageName) {
dirs = append(dirs, filepath.Dir(path))
}
}
return nil
})
return dirs, err
}
func containsPackageDecl(content, packageName string) bool {
lines := strings.Split(content, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)
if strings.HasPrefix(line, "//") {
continue
}
if strings.HasPrefix(line, "package ") {
parts := strings.Fields(line)
if len(parts) >= 2 && parts[1] == packageName {
return true
}
}
if strings.HasPrefix(line, "import") || strings.Contains(line, "{") {
break
}
}
return false
}
func resolveCueModuleRoot(startDir string) string {
if envRoot := os.Getenv("CUENV_CUE_MODULE_ROOT"); envRoot != "" {
if info, err := os.Stat(filepath.Join(envRoot, "cue.mod", "module.cue")); err == nil && !info.IsDir() {
return envRoot
}
}
dir, err := filepath.Abs(startDir)
if err != nil {
dir = startDir
}
for {
moduleFile := filepath.Join(dir, "cue.mod", "module.cue")
if info, err := os.Stat(moduleFile); err == nil && !info.IsDir() {
return dir
}
parent := filepath.Dir(dir)
if parent == dir {
break
}
dir = parent
}
return ""
}
func main() {}