cuelang.org/go@v0.13.0/cue/load/example_test.go (about)

     1  // Copyright 2023 The CUE Authors
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package load_test
    16  
    17  import (
    18  	"fmt"
    19  	"os"
    20  	"path/filepath"
    21  
    22  	"golang.org/x/tools/txtar"
    23  
    24  	"cuelang.org/go/cue"
    25  	"cuelang.org/go/cue/cuecontext"
    26  	"cuelang.org/go/cue/load"
    27  	"cuelang.org/go/mod/modregistrytest"
    28  )
    29  
    30  // Note that these examples may not be runnable on pkg.go.dev,
    31  // as they expect files to be present inside testdata.
    32  // Using cue/load with real files on disk keeps the example realistic
    33  // and enables the user to easily tweak the code to their needs.
    34  
    35  func Example() {
    36  	// Load the package "example" relative to the directory testdata/testmod.
    37  	// Akin to loading via: cd testdata/testmod && cue export ./example
    38  	insts := load.Instances([]string{"./example"}, &load.Config{
    39  		Dir: filepath.Join("testdata", "testmod"),
    40  		Env: []string{}, // or nil to use os.Environ
    41  	})
    42  
    43  	// testdata/testmod/example just has one file without any build tags,
    44  	// so we get a single instance as a result.
    45  	fmt.Println("Number of instances:", len(insts))
    46  	inst := insts[0]
    47  	if err := inst.Err; err != nil {
    48  		fmt.Println(err)
    49  		return
    50  	}
    51  	fmt.Println("Instance module:", inst.Module)
    52  	fmt.Println("Instance import path:", inst.ImportPath)
    53  	fmt.Println()
    54  
    55  	// Inspect the syntax trees.
    56  	fmt.Println("Source files:")
    57  	for _, file := range inst.Files {
    58  		fmt.Println(filepath.Base(file.Filename), "with", len(file.Decls), "declarations")
    59  	}
    60  	fmt.Println()
    61  
    62  	// Build the instance into a value.
    63  	// We can also use BuildInstances for many instances at once.
    64  	ctx := cuecontext.New()
    65  	val := ctx.BuildInstance(inst)
    66  	if err := val.Err(); err != nil {
    67  		fmt.Println(err)
    68  		return
    69  	}
    70  
    71  	// Inspect the contents of the value, such as one string field.
    72  	fieldStr, err := val.LookupPath(cue.MakePath(cue.Str("output"))).String()
    73  	if err != nil {
    74  		fmt.Println(err)
    75  		return
    76  	}
    77  	fmt.Println("Field string:", fieldStr)
    78  
    79  	// Output:
    80  	// Number of instances: 1
    81  	// Instance module: mod.test/test@v0
    82  	// Instance import path: mod.test/test/example@v0
    83  	//
    84  	// Source files:
    85  	// example.cue with 3 declarations
    86  	//
    87  	// Field string: Hello Joe
    88  }
    89  
    90  func Example_externalModules() {
    91  	// setUpModulesExample starts a temporary in-memory registry,
    92  	// populates it with an example module, and sets CUE_REGISTRY to refer to it.
    93  	// Users can leave [load.Config.Env] empty to use the default registry,
    94  	// or set one globally with os.Setenv("CUE_REGISTRY", "registry.myorg.com").
    95  	env, cleanup := setUpModulesExample()
    96  	defer cleanup()
    97  
    98  	insts := load.Instances([]string{"."}, &load.Config{
    99  		Dir: filepath.Join("testdata", "testmod-external"),
   100  		Env: env, // or nil to use os.Environ
   101  	})
   102  	inst := insts[0]
   103  	if err := inst.Err; err != nil {
   104  		fmt.Println(err)
   105  		return
   106  	}
   107  	ctx := cuecontext.New()
   108  	val := ctx.BuildInstance(inst)
   109  	if err := val.Err(); err != nil {
   110  		fmt.Println(err)
   111  		return
   112  	}
   113  
   114  	// Inspect the contents of the value, such as one string field.
   115  	fieldStr, err := val.LookupPath(cue.MakePath(cue.Str("output"))).String()
   116  	if err != nil {
   117  		fmt.Println(err)
   118  		return
   119  	}
   120  	fmt.Println("Field string:", fieldStr)
   121  	// Output:
   122  	// Field string: hello, world
   123  }
   124  
   125  func setUpModulesExample() (env []string, cleanup func()) {
   126  	registryFS, err := txtar.FS(txtar.Parse([]byte(`
   127  -- foo.example_v0.0.1/cue.mod/module.cue --
   128  module: "foo.example@v0"
   129  language: version: "v0.8.0"
   130  -- foo.example_v0.0.1/bar/bar.cue --
   131  package bar
   132  
   133  value: "world"
   134  `)))
   135  	if err != nil {
   136  		panic(err)
   137  	}
   138  	registry, err := modregistrytest.New(registryFS, "")
   139  	if err != nil {
   140  		panic(err)
   141  	}
   142  	env = append(env, "CUE_REGISTRY="+registry.Host()+"+insecure")
   143  	// We also set up a temporary cache directory to fetch and extract modules into.
   144  	dir, err := os.MkdirTemp("", "")
   145  	if err != nil {
   146  		panic(err)
   147  	}
   148  	env = append(env, "CUE_CACHE_DIR="+dir)
   149  	return env, registry.Close
   150  }