Native Workflow Support

This commit is contained in:
2026-04-09 11:01:39 +02:00
parent dc93feb176
commit 4f8bfc133a
9 changed files with 912 additions and 17 deletions
+111 -4
View File
@@ -12,6 +12,7 @@ import (
"strconv"
"strings"
"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/erf"
"gitea.westgate.pw/ShadowsOverWestgate/sow-tools/internal/project"
)
@@ -72,6 +73,18 @@ type BuildResult struct {
FilesTLK int
}
type PackageResult struct {
Mode string
Output2DADir string
OutputTLKDir string
OutputHAKPath string
OutputTLKPath string
Files2DA int
FilesTLK int
HAKResources int
AssetFiles int
}
type CompareResult struct {
Mode string
Compared2DA int
@@ -192,6 +205,7 @@ func ValidateProject(p *project.Project) ValidationReport {
report.DataFiles++
_ = validateJSONFile(path, "data", &report)
})
validateTopPackageAssets(sourceDir, dataDir, &report)
validateNativeOutputCatalog(dataDir, &report)
validateItempropsRegistryGraph(dataDir, &report)
if _, err := os.Stat(statePath); err == nil {
@@ -635,20 +649,26 @@ func validateBaseDialogObject(path string, obj map[string]any, report *Validatio
func validateLegacyDialogEntries(path string, obj map[string]any, report *ValidationReport, label string) {
entries, ok := obj["entries"]
if ok {
if _, ok := entries.(map[string]any); !ok {
switch entries.(type) {
case map[string]any, []any:
// accepted compatibility shapes
default:
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: fmt.Sprintf("%s entries must be a JSON object", label),
Message: fmt.Sprintf("%s entries must be a JSON object or array", label),
})
}
}
if language, ok := obj["language"]; ok {
if _, ok := language.(string); !ok {
switch language.(type) {
case string, float64:
// accepted compatibility shapes
default:
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: fmt.Sprintf("%s language must be a string when present", label),
Message: fmt.Sprintf("%s language must be a string or numeric language id when present", label),
})
}
}
@@ -866,6 +886,93 @@ func validateNativeOutputCatalog(dataDir string, report *ValidationReport) {
}
}
func validateTopPackageAssets(sourceDir, dataDir string, report *ValidationReport) {
assetsDir := filepath.Join(sourceDir, "assets")
info, err := os.Stat(assetsDir)
if err != nil {
if errors.Is(err, os.ErrNotExist) {
return
}
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: assetsDir,
Message: err.Error(),
})
return
}
if !info.IsDir() {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: assetsDir,
Message: "must be a directory",
})
return
}
projectOutputs, err := discoverNativeOutputCatalog(dataDir)
if err != nil {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: assetsDir,
Message: err.Error(),
})
return
}
seen := map[string]string{}
err = filepath.WalkDir(assetsDir, func(path string, d fs.DirEntry, walkErr error) error {
if walkErr != nil {
return walkErr
}
if d.IsDir() {
return nil
}
report.Files++
rel, err := filepath.Rel(assetsDir, path)
if err != nil {
return err
}
if strings.HasPrefix(filepath.Base(path), ".") {
return nil
}
base := strings.ToLower(strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)))
ext := strings.TrimPrefix(strings.ToLower(filepath.Ext(path)), ".")
if _, ok := erf.ResourceTypeForExtension(ext); !ok {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: fmt.Sprintf("unsupported topdata asset resource extension %q", filepath.Ext(path)),
})
return nil
}
key := base + "." + ext
if previous, ok := seen[key]; ok {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: fmt.Sprintf("duplicate topdata asset resource %q also defined by %s", key, previous),
})
return nil
}
seen[key] = rel
if owner, ok := projectOutputs[key]; ok {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: path,
Message: fmt.Sprintf("topdata asset resource %q collides with compiled topdata output from %s", key, owner),
})
}
return nil
})
if err != nil {
report.Diagnostics = append(report.Diagnostics, Diagnostic{
Severity: SeverityError,
Path: assetsDir,
Message: err.Error(),
})
}
}
func recordNativeOutputOwner(outputName, owner string, outputOwners map[string]string, report *ValidationReport) {
if existing, ok := outputOwners[outputName]; ok {
report.Diagnostics = append(report.Diagnostics, Diagnostic{