Demonstrate entry-declared import destinations
This commit is contained in:
@@ -43,9 +43,9 @@ type CollectionProfile struct {
|
||||
}
|
||||
|
||||
// LoadCollectionBundle demonstrates one layered collection load. Its main
|
||||
// document owns the application schema version; imported collection metadata,
|
||||
// prompt/profile peers, and an operator prompt-version override use ordinary
|
||||
// destinations and domain fields.
|
||||
// document owns the application schema version; the mounted entry declares
|
||||
// relative destinations for collection metadata, prompt/profile peers, and
|
||||
// their nested imports. The operator version override remains a separate tier.
|
||||
func LoadCollectionBundle() (*configkit.Result[CollectionBundleConfig], error) {
|
||||
files, err := fs.Sub(bundledFiles, "testdata/collection-bundle")
|
||||
if err != nil {
|
||||
@@ -54,7 +54,6 @@ func LoadCollectionBundle() (*configkit.Result[CollectionBundleConfig], error) {
|
||||
bundle := configkit.NewFilesystem("collection bundle", files)
|
||||
collectionDestination := configkit.Keys("collections", "weatherreporter")
|
||||
promptDestination := collectionDestination.Key("prompts")
|
||||
profileDestination := collectionDestination.Key("profiles")
|
||||
return configkit.LoadLayered(
|
||||
configkit.Input{Source: configkit.Bytes("application main", []byte("version: 1\n"))},
|
||||
configkit.LayeredOptions[CollectionBundleConfig]{
|
||||
@@ -69,13 +68,9 @@ func LoadCollectionBundle() (*configkit.Result[CollectionBundleConfig], error) {
|
||||
Validate: validateCollectionBundle,
|
||||
},
|
||||
Underlays: []configkit.Underlay{
|
||||
{Inputs: []configkit.Input{
|
||||
{Source: bundle.File("collections/weather/collection.yml"), Imports: true, Destination: collectionDestination},
|
||||
{Source: bundle.File("collections/weather/prompts/brief.yml"), Destination: promptDestination},
|
||||
{Source: bundle.File("collections/weather/prompts/custom.yml"), Destination: promptDestination},
|
||||
{Source: bundle.File("collections/weather/profiles/compact.yml"), Destination: profileDestination},
|
||||
{Source: bundle.File("collections/weather/profiles/weather.yml"), Destination: profileDestination},
|
||||
}},
|
||||
{Inputs: []configkit.Input{{
|
||||
Source: bundle.File("collections/weather/collection.yml"), Imports: true, Destination: collectionDestination,
|
||||
}}},
|
||||
{Inputs: []configkit.Input{{
|
||||
Source: bundle.File("operators/weather-prompt-version.yml"), Destination: promptDestination,
|
||||
}}},
|
||||
|
||||
@@ -69,22 +69,43 @@ func TestCollectionBundleAssemblesMountedPeersAndResources(t *testing.T) {
|
||||
t.Fatalf("ordinary collection version metadata = %#v, %v", collectionVersion, ok)
|
||||
}
|
||||
var metadataSource configkit.SourceInfo
|
||||
var collectionEntrySource configkit.SourceInfo
|
||||
var versionSource configkit.SourceInfo
|
||||
var parentPromptSource configkit.SourceInfo
|
||||
var promptIndexSource configkit.SourceInfo
|
||||
var profileIndexSource configkit.SourceInfo
|
||||
var promptVersionSource configkit.SourceInfo
|
||||
for _, source := range result.Sources() {
|
||||
switch source.Path {
|
||||
case "collections/weather/collection.yml":
|
||||
collectionEntrySource = source
|
||||
case "collections/weather/metadata.yml":
|
||||
metadataSource = source
|
||||
case "collections/weather/version.yml":
|
||||
versionSource = source
|
||||
case "collections/weather/prompts/index.yml":
|
||||
promptIndexSource = source
|
||||
case "collections/weather/prompts/brief.yml":
|
||||
parentPromptSource = source
|
||||
case "collections/weather/profiles/index.yml":
|
||||
profileIndexSource = source
|
||||
case "operators/weather-prompt-version.yml":
|
||||
promptVersionSource = source
|
||||
}
|
||||
}
|
||||
collectionVersionLocation := collectionVersion.Origin.Locations[0]
|
||||
if metadataSource.ID == "" || collectionVersionLocation.SourceID != metadataSource.ID ||
|
||||
metadataSource.Destination.String() != "/collections/weatherreporter" || collectionVersionLocation.Line != 1 {
|
||||
t.Fatalf("imported collection version source = %#v, %#v", metadataSource, collectionVersionLocation)
|
||||
if collectionEntrySource.ID != "source-2" || collectionEntrySource.Destination.String() != "/collections/weatherreporter" ||
|
||||
metadataSource.ID == "" || metadataSource.Destination.String() != "/collections/weatherreporter" ||
|
||||
metadataSource.ImportedFrom == nil || metadataSource.ImportedFrom.SourceID != collectionEntrySource.ID ||
|
||||
versionSource.ID == "" || collectionVersionLocation.SourceID != versionSource.ID || versionSource.Destination.String() != "/collections/weatherreporter" ||
|
||||
versionSource.ImportedFrom == nil || versionSource.ImportedFrom.SourceID != metadataSource.ID || collectionVersionLocation.Line != 1 {
|
||||
t.Fatalf("nested collection version provenance = entry %#v, metadata %#v, version %#v, location %#v", collectionEntrySource, metadataSource, versionSource, collectionVersionLocation)
|
||||
}
|
||||
if promptIndexSource.ID == "" || promptIndexSource.Destination.String() != "/collections/weatherreporter/prompts" ||
|
||||
promptIndexSource.ImportedFrom == nil || promptIndexSource.ImportedFrom.SourceID != collectionEntrySource.ID ||
|
||||
profileIndexSource.ID == "" || profileIndexSource.Destination.String() != "/collections/weatherreporter/profiles" ||
|
||||
profileIndexSource.ImportedFrom == nil || profileIndexSource.ImportedFrom.SourceID != collectionEntrySource.ID {
|
||||
t.Fatalf("nested prompt/profile placement = prompt %#v profile %#v", promptIndexSource, profileIndexSource)
|
||||
}
|
||||
if promptVersionSource.ID == "" || promptVersionSource.Destination.String() != "/collections/weatherreporter/prompts" || promptVersionSource.UnderlayIndex != 2 {
|
||||
t.Fatalf("prompt version source = %#v", promptVersionSource)
|
||||
|
||||
@@ -9,7 +9,7 @@ import (
|
||||
configkit "gitea.maximumdirect.net/eric/ConfigKit"
|
||||
)
|
||||
|
||||
//go:embed testdata/native-source testdata/layered-bundle testdata/collection-bundle
|
||||
//go:embed testdata/native-source testdata/layered-bundle testdata/collection-bundle testdata/ordinary-imports
|
||||
var bundledFiles embed.FS
|
||||
|
||||
// BundledConfig is a small configuration loaded directly from an embedded file.
|
||||
@@ -18,6 +18,30 @@ type BundledConfig struct {
|
||||
Enabled bool `yaml:"enabled"`
|
||||
}
|
||||
|
||||
type PromptBundleConfig struct {
|
||||
Name string `yaml:"name"`
|
||||
Version string `yaml:"version"`
|
||||
Description string `yaml:"description"`
|
||||
Prompts map[string]BundlePrompt `yaml:"prompts"`
|
||||
}
|
||||
|
||||
type BundlePrompt struct {
|
||||
Summary string `yaml:"summary"`
|
||||
}
|
||||
|
||||
// LoadPromptBundle demonstrates ordinary Load with opt-in imports whose
|
||||
// destinations are declared relative to the entry document.
|
||||
func LoadPromptBundle() (*configkit.Result[PromptBundleConfig], error) {
|
||||
files, err := fs.Sub(bundledFiles, "testdata/ordinary-imports")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return configkit.Load[PromptBundleConfig](
|
||||
configkit.NewFilesystem("prompt bundle", files).File("config.yml"),
|
||||
configkit.Options[PromptBundleConfig]{Imports: true},
|
||||
)
|
||||
}
|
||||
|
||||
// LoadBundled demonstrates a native filesystem source without layered options.
|
||||
func LoadBundled() (*configkit.Result[BundledConfig], error) {
|
||||
files, err := fs.Sub(bundledFiles, "testdata/native-source")
|
||||
|
||||
@@ -20,6 +20,34 @@ func Example_nativeFilesystem() {
|
||||
// Output: embedded false
|
||||
}
|
||||
|
||||
func Example_rootRelativeImports() {
|
||||
result, err := consumers.LoadPromptBundle()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
source := result.Sources()[2]
|
||||
fmt.Println(result.Config.Name, result.Config.Version, result.Config.Prompts["brief"].Summary, source.Destination.String(), err)
|
||||
// Output: Root import example 1.0 A root-loaded prompt. /prompts <nil>
|
||||
}
|
||||
|
||||
func TestPromptBundleUsesRelativeImportDestinations(t *testing.T) {
|
||||
result, err := consumers.LoadPromptBundle()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if result.Config.Name != "Root import example" || result.Config.Version != "1.0" || result.Config.Prompts["brief"].Summary != "A root-loaded prompt." {
|
||||
t.Fatalf("root import result = %#v", result.Config)
|
||||
}
|
||||
sources := result.Sources()
|
||||
if len(sources) != 3 || sources[0].Destination.String() != configkit.Keys().String() ||
|
||||
sources[1].Path != "metadata.yml" || sources[1].Destination.String() != configkit.Keys().String() ||
|
||||
sources[2].Path != "prompts/brief.yml" || sources[2].Destination.String() != "/prompts" ||
|
||||
sources[2].ImportedFrom == nil || sources[2].ImportedFrom.SourceID != sources[0].ID {
|
||||
t.Fatalf("root import sources = %#v", sources)
|
||||
}
|
||||
}
|
||||
|
||||
func Example_layeredCatalog() {
|
||||
result, err := consumers.LoadCatalog(fixture("layered-main", "config.yml"))
|
||||
if err != nil {
|
||||
|
||||
@@ -1,4 +1,9 @@
|
||||
configkit:
|
||||
imports:
|
||||
- path: metadata.yml
|
||||
destination: []
|
||||
- path: prompts/index.yml
|
||||
destination: [prompts]
|
||||
- path: profiles/index.yml
|
||||
destination: [profiles]
|
||||
name: Weather Reporter
|
||||
|
||||
@@ -1,2 +1,4 @@
|
||||
version: "2.4.0"
|
||||
configkit:
|
||||
imports:
|
||||
- path: version.yml
|
||||
description: Imported collection metadata.
|
||||
|
||||
4
examples/consumers/testdata/collection-bundle/collections/weather/profiles/index.yml
vendored
Normal file
4
examples/consumers/testdata/collection-bundle/collections/weather/profiles/index.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
configkit:
|
||||
imports:
|
||||
- path: compact.yml
|
||||
- path: weather.yml
|
||||
4
examples/consumers/testdata/collection-bundle/collections/weather/prompts/index.yml
vendored
Normal file
4
examples/consumers/testdata/collection-bundle/collections/weather/prompts/index.yml
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
configkit:
|
||||
imports:
|
||||
- path: brief.yml
|
||||
- path: custom.yml
|
||||
1
examples/consumers/testdata/collection-bundle/collections/weather/version.yml
vendored
Normal file
1
examples/consumers/testdata/collection-bundle/collections/weather/version.yml
vendored
Normal file
@@ -0,0 +1 @@
|
||||
version: "2.4.0"
|
||||
6
examples/consumers/testdata/ordinary-imports/config.yml
vendored
Normal file
6
examples/consumers/testdata/ordinary-imports/config.yml
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
configkit:
|
||||
imports:
|
||||
- path: metadata.yml
|
||||
- path: prompts/brief.yml
|
||||
destination: [prompts]
|
||||
name: Root import example
|
||||
2
examples/consumers/testdata/ordinary-imports/metadata.yml
vendored
Normal file
2
examples/consumers/testdata/ordinary-imports/metadata.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
version: "1.0"
|
||||
description: Metadata imported into the root document.
|
||||
2
examples/consumers/testdata/ordinary-imports/prompts/brief.yml
vendored
Normal file
2
examples/consumers/testdata/ordinary-imports/prompts/brief.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
brief:
|
||||
summary: A root-loaded prompt.
|
||||
Reference in New Issue
Block a user