Add Notarius reference configuration vocabulary
This commit is contained in:
43
internal/notariusref/selector.go
Normal file
43
internal/notariusref/selector.go
Normal file
@@ -0,0 +1,43 @@
|
||||
// Package notariusref owns Narratio's Notarius CLI reference-selector
|
||||
// vocabulary without depending on Notarius implementation packages.
|
||||
package notariusref
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// NormalizeSelector validates and normalizes a Notarius v0.6 reference
|
||||
// selector. It intentionally validates selector structure only; Notarius owns
|
||||
// target, slot, and media compatibility.
|
||||
func NormalizeSelector(value string) (string, error) {
|
||||
selector := strings.TrimSpace(value)
|
||||
if selector == "" {
|
||||
return "", fmt.Errorf("reference selector is required")
|
||||
}
|
||||
if strings.Contains(selector, "=") {
|
||||
return "", fmt.Errorf("reference selector must not contain '='")
|
||||
}
|
||||
|
||||
parts := strings.Split(selector, ".")
|
||||
for index := range parts {
|
||||
parts[index] = strings.TrimSpace(parts[index])
|
||||
if parts[index] == "" {
|
||||
return "", fmt.Errorf("reference selector components must not be empty")
|
||||
}
|
||||
}
|
||||
|
||||
switch len(parts) {
|
||||
case 1, 2:
|
||||
return strings.Join(parts, "."), nil
|
||||
case 3:
|
||||
switch parts[1] {
|
||||
case "extract", "merge", "normalize":
|
||||
return strings.Join(parts, "."), nil
|
||||
default:
|
||||
return "", fmt.Errorf("three-component reference selector must use extract, merge, or normalize as its middle component")
|
||||
}
|
||||
default:
|
||||
return "", fmt.Errorf("reference selector must use slot, chunk.slot, lane.slot, or lane.stage.slot")
|
||||
}
|
||||
}
|
||||
58
internal/notariusref/selector_test.go
Normal file
58
internal/notariusref/selector_test.go
Normal file
@@ -0,0 +1,58 @@
|
||||
package notariusref
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestNormalizeSelectorAcceptsDocumentedForms(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value string
|
||||
want string
|
||||
}{
|
||||
{name: "pipeline", value: "party", want: "party"},
|
||||
{name: "chunk", value: "chunk.party", want: "chunk.party"},
|
||||
{name: "lane", value: "npc-registry.party", want: "npc-registry.party"},
|
||||
{name: "extract", value: "npc-registry.extract.party", want: "npc-registry.extract.party"},
|
||||
{name: "merge", value: "npc-registry.merge.party", want: "npc-registry.merge.party"},
|
||||
{name: "normalize", value: "npc-registry.normalize.party", want: "npc-registry.normalize.party"},
|
||||
{name: "whitespace", value: " npc-registry . extract . party ", want: "npc-registry.extract.party"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
got, err := NormalizeSelector(test.value)
|
||||
if err != nil {
|
||||
t.Fatalf("NormalizeSelector(%q) error = %v", test.value, err)
|
||||
}
|
||||
if got != test.want {
|
||||
t.Fatalf("NormalizeSelector(%q) = %q, want %q", test.value, got, test.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestNormalizeSelectorRejectsInvalidForms(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
value string
|
||||
wantErr string
|
||||
}{
|
||||
{name: "empty", value: "", wantErr: "required"},
|
||||
{name: "whitespace", value: " ", wantErr: "required"},
|
||||
{name: "empty first", value: ".party", wantErr: "components"},
|
||||
{name: "empty middle", value: "lane..party", wantErr: "components"},
|
||||
{name: "empty final", value: "lane.", wantErr: "components"},
|
||||
{name: "equals", value: "party=/tmp/party.yml", wantErr: "must not contain"},
|
||||
{name: "invalid stage", value: "lane.chunk.party", wantErr: "extract, merge, or normalize"},
|
||||
{name: "too many components", value: "lane.extract.party.extra", wantErr: "must use"},
|
||||
}
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
_, err := NormalizeSelector(test.value)
|
||||
if err == nil || !strings.Contains(err.Error(), test.wantErr) {
|
||||
t.Fatalf("NormalizeSelector(%q) error = %v, want containing %q", test.value, err, test.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user