| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | package codegen | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"bytes" | 
					
						
							|  |  |  | 	"errors" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2022-08-10 21:37:51 +08:00
										 |  |  | 	"io" | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	"os" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 	"strings" | 
					
						
							|  |  |  | 	"testing/fstest" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	cerrors "cuelang.org/go/cue/errors" | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	"cuelang.org/go/pkg/encoding/yaml" | 
					
						
							|  |  |  | 	"github.com/deepmap/oapi-codegen/pkg/codegen" | 
					
						
							|  |  |  | 	"github.com/getkin/kin-openapi/openapi3" | 
					
						
							|  |  |  | 	"github.com/grafana/cuetsy" | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 	tsast "github.com/grafana/cuetsy/ts/ast" | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	"github.com/grafana/grafana/pkg/cuectx" | 
					
						
							|  |  |  | 	"github.com/grafana/thema" | 
					
						
							|  |  |  | 	"github.com/grafana/thema/encoding/openapi" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | // CoremodelDeclaration contains the results of statically analyzing a Grafana
 | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | // directory for a Thema lineage.
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | type CoremodelDeclaration struct { | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	Lineage thema.Lineage | 
					
						
							| 
									
										
										
										
											2022-06-24 03:47:47 +08:00
										 |  |  | 	// Absolute path to the coremodel's coremodel.cue file.
 | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	LineagePath string | 
					
						
							| 
									
										
										
										
											2022-06-24 03:47:47 +08:00
										 |  |  | 	// Path to the coremodel's coremodel.cue file relative to repo root.
 | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	RelativePath string | 
					
						
							|  |  |  | 	// Indicates whether the coremodel is considered canonical or not. Generated
 | 
					
						
							|  |  |  | 	// code from not-yet-canonical coremodels should include appropriate caveats in
 | 
					
						
							|  |  |  | 	// documentation and possibly be hidden from external public API surface areas.
 | 
					
						
							|  |  |  | 	IsCanonical bool | 
					
						
							| 
									
										
										
										
											2022-08-19 18:11:13 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Indicates whether the coremodel represents an API type, and should therefore
 | 
					
						
							|  |  |  | 	// be included in API client code generation.
 | 
					
						
							|  |  |  | 	IsAPIType bool | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ExtractLineage loads a Grafana Thema lineage from the filesystem.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // The provided path must be the absolute path to the file containing the
 | 
					
						
							|  |  |  | // lineage to be loaded.
 | 
					
						
							|  |  |  | //
 | 
					
						
							|  |  |  | // This loading approach is intended primarily for use with code generators, or
 | 
					
						
							|  |  |  | // other use cases external to grafana-server backend. For code within
 | 
					
						
							|  |  |  | // grafana-server, prefer lineage loaders provided in e.g. pkg/coremodel/*.
 | 
					
						
							| 
									
										
										
										
											2022-10-11 16:45:07 +08:00
										 |  |  | func ExtractLineage(path string, rt *thema.Runtime) (*CoremodelDeclaration, error) { | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if !filepath.IsAbs(path) { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("must provide an absolute path, got %q", path) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 	ec := &CoremodelDeclaration{ | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 		LineagePath: path, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var find func(path string) (string, error) | 
					
						
							|  |  |  | 	find = func(path string) (string, error) { | 
					
						
							|  |  |  | 		parent := filepath.Dir(path) | 
					
						
							|  |  |  | 		if parent == path { | 
					
						
							|  |  |  | 			return "", errors.New("grafana root directory could not be found") | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		fp := filepath.Join(path, "go.mod") | 
					
						
							|  |  |  | 		if _, err := os.Stat(fp); err == nil { | 
					
						
							|  |  |  | 			return path, nil | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		return find(parent) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	groot, err := find(path) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return ec, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	f, err := os.Open(ec.LineagePath) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("could not open lineage file at %s: %w", path, err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-10 21:37:51 +08:00
										 |  |  | 	byt, err := io.ReadAll(f) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fs := fstest.MapFS{ | 
					
						
							| 
									
										
										
										
											2022-06-24 03:47:47 +08:00
										 |  |  | 		"coremodel.cue": &fstest.MapFile{ | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 			Data: byt, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	// ec.RelativePath, err = filepath.Rel(groot, filepath.Dir(path))
 | 
					
						
							|  |  |  | 	ec.RelativePath, err = filepath.Rel(groot, path) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		// should be unreachable, since we rootclimbed to find groot above
 | 
					
						
							|  |  |  | 		panic(err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	ec.RelativePath = filepath.ToSlash(ec.RelativePath) | 
					
						
							| 
									
										
										
										
											2022-10-11 16:45:07 +08:00
										 |  |  | 	ec.Lineage, err = cuectx.LoadGrafanaInstancesWithThema(filepath.Dir(ec.RelativePath), fs, rt) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return ec, err | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	ec.IsCanonical = isCanonical(ec.Lineage.Name()) | 
					
						
							| 
									
										
										
										
											2022-08-19 18:11:13 +08:00
										 |  |  | 	ec.IsAPIType = isAPIType(ec.Lineage.Name()) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	return ec, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-15 21:47:04 +08:00
										 |  |  | // toTemplateObj extracts creates a struct with all the useful strings for template generation.
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | func (cd *CoremodelDeclaration) toTemplateObj() tplVars { | 
					
						
							|  |  |  | 	lin := cd.Lineage | 
					
						
							| 
									
										
										
										
											2022-06-15 21:47:04 +08:00
										 |  |  | 	sch := thema.SchemaP(lin, thema.LatestVersion(lin)) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return tplVars{ | 
					
						
							|  |  |  | 		Name:        lin.Name(), | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 		LineagePath: cd.RelativePath, | 
					
						
							|  |  |  | 		PkgPath:     filepath.ToSlash(filepath.Join("github.com/grafana/grafana", filepath.Dir(cd.RelativePath))), | 
					
						
							| 
									
										
										
										
											2022-06-15 21:47:04 +08:00
										 |  |  | 		TitleName:   strings.Title(lin.Name()), // nolint
 | 
					
						
							|  |  |  | 		LatestSeqv:  sch.Version()[0], | 
					
						
							|  |  |  | 		LatestSchv:  sch.Version()[1], | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | func isCanonical(name string) bool { | 
					
						
							|  |  |  | 	return canonicalCoremodels[name] | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-19 18:11:13 +08:00
										 |  |  | func isAPIType(name string) bool { | 
					
						
							|  |  |  | 	return !nonAPITypes[name] | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-15 21:47:04 +08:00
										 |  |  | // FIXME specifying coremodel canonicality DOES NOT belong here - it should be part of the coremodel declaration.
 | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | var canonicalCoremodels = map[string]bool{ | 
					
						
							|  |  |  | 	"dashboard": false, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-19 18:11:13 +08:00
										 |  |  | // FIXME this also needs to be moved into coremodel metadata
 | 
					
						
							|  |  |  | var nonAPITypes = map[string]bool{ | 
					
						
							|  |  |  | 	"pluginmeta": true, | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | // PathVersion returns the string path element to use for the latest schema.
 | 
					
						
							|  |  |  | // "x" if not yet canonical, otherwise, "v<major>"
 | 
					
						
							|  |  |  | func (cd *CoremodelDeclaration) PathVersion() string { | 
					
						
							|  |  |  | 	if !cd.IsCanonical { | 
					
						
							|  |  |  | 		return "x" | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return fmt.Sprintf("v%v", thema.LatestVersion(cd.Lineage)[0]) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-24 03:47:47 +08:00
										 |  |  | // GenerateGoCoremodel generates a standard Go model struct and coremodel
 | 
					
						
							|  |  |  | // implementation from a coremodel CUE declaration.
 | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // The provided path must be a directory. Generated code files will be written
 | 
					
						
							|  |  |  | // to that path. The final element of the path must match the Lineage.Name().
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | func (cd *CoremodelDeclaration) GenerateGoCoremodel(path string) (WriteDiffer, error) { | 
					
						
							| 
									
										
										
										
											2022-10-11 16:45:07 +08:00
										 |  |  | 	lin, rt := cd.Lineage, cd.Lineage.Runtime() | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	_, name := filepath.Split(path) | 
					
						
							|  |  |  | 	if name != lin.Name() { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("lineage name %q must match final element of path, got %q", lin.Name(), path) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	sch := thema.SchemaP(lin, thema.LatestVersion(lin)) | 
					
						
							|  |  |  | 	f, err := openapi.GenerateSchema(sch, nil) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("thema openapi generation failed: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-10-11 16:45:07 +08:00
										 |  |  | 	str, err := yaml.Marshal(rt.Context().BuildFile(f)) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("cue-yaml marshaling failed: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	loader := openapi3.NewLoader() | 
					
						
							|  |  |  | 	oT, err := loader.LoadFromData([]byte(str)) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("loading generated openapi failed; %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	var importbuf bytes.Buffer | 
					
						
							|  |  |  | 	if err = tmpls.Lookup("coremodel_imports.tmpl").Execute(&importbuf, tvars_coremodel_imports{ | 
					
						
							|  |  |  | 		PackageName: lin.Name(), | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("error executing imports template: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	gostr, err := codegen.Generate(oT, lin.Name(), codegen.Options{ | 
					
						
							|  |  |  | 		GenerateTypes: true, | 
					
						
							|  |  |  | 		SkipPrune:     true, | 
					
						
							|  |  |  | 		SkipFmt:       true, | 
					
						
							|  |  |  | 		UserTemplates: map[string]string{ | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 			"imports.tmpl": importbuf.String(), | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 			"typedef.tmpl": tmplTypedef, | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	}) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("openapi generation failed: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	buf := new(bytes.Buffer) | 
					
						
							|  |  |  | 	if err = tmpls.Lookup("autogen_header.tmpl").Execute(buf, tvars_autogen_header{ | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 		LineagePath:   cd.RelativePath, | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 		GeneratorPath: "pkg/framework/coremodel/gen.go", // FIXME hardcoding is not OK
 | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("error executing header template: %w", err) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	fmt.Fprint(buf, "\n", gostr) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 	vars := cd.toTemplateObj() | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	err = tmpls.Lookup("addenda.tmpl").Execute(buf, vars) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 		panic(err) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	fullp := filepath.Join(path, fmt.Sprintf("%s_gen.go", lin.Name())) | 
					
						
							|  |  |  | 	byt, err := postprocessGoFile(genGoFile{ | 
					
						
							|  |  |  | 		path:   fullp, | 
					
						
							| 
									
										
											  
											
												Reconcile coremodels, entities, objects under new kind framework (#56492)
* Update thema to latest
* Deal with s/Library/*Runtime/
* Commit new, working results of codegen
* We like pointers now
* Always take runtime arg for NewBase()
* Sketchy handwavy pass at entity meta framework
* Little nibbles
* Update pkg/framework/coremodel/entityframework.cue
Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
* Move file into new framework location
* Introduce loaders, Go code
* Complete rename to kind
* Flesh out framework, add svg/dashboard examples
* Cruft removal
* Remove generated kind go files from gitignore
* Refine maturity concept, add SlotKind
* Update embed and go deps
* Export PrefixWithGrafanaCUE
* Make the loader actually work, holy crap
* Many small tweaks to type.cue
* Add Apache 2 licensing exceptions for kinds
* Add new kinds dir, start of generator
* Roll back to earlier oapi-codegen
* Introduce new grafana-specific CUE loaders
* Introduce new tidy code generators framework
* Catch up kind framework with tinkering
* Add slices for the generators
* Add write/verify step to main generator
* Many renames
* Split up kind framework cue files
* Use kind.Decl within generated kinds
* Create kind.SomeDecl wrapper type to cache lineages
* Better names again
* Get one generated implemented, hopefully
* Copy dashboard schema into new kind.cue
* Small fixes to make the initial gen work
* Put svg kind in its new home
* Add generated Go dashboard type
* More renames and cleanups
* Add base kind registry and generator
* Stop blacklisting *_gen.go files
This is not the Go best practice, anyway. All we actually want to ignore
for enterprise is generated wire files.
* Change codegen output directories
pkg/kind -> pkg/kinds
pkg/registry/kindreg -> pkg/registry/corekind
* Rename pkg/framework/kind to pkg/kindsys
* Add core structured kind generator
* Add plural and machine names to kind spec
* Copy playlist over to kind system
* Consolidate kindsys files
* Add raw kind generator
* Update CODEOWNERS for kind framework
* Touch up comments a bit
* More docs tweaks
* Remove generated types to reduce noise for review
* Split each generator into its own file
* Rename Slot kind to Composable kind
* Add handwavy types for customkind loading
* Guard against init calls to framework loader
* First pass at doc on extending the kind system
* Improve attribute example in docs
* Fix wire imports
* Add basic TS types generator
* Fix composable kind category def
* No need for a separate file with generate directive
* Catch dashboard schema up
* Rename generator types to something saner and generic
* Make version configurable in ts/go generators
* Add CommonMeta to ease property access
* Add kindsys prop indicating whether lineage is group
* Put all kind categories back in a single file
* Finish with kindsys group props
* Refactor maturity progression per discussion
- Replace "committed" with "merged"
- All kindcats can use all maturity levels, at least for now
* Convert ts veneer index generator to modular system
* Move over to new jennywrites framework
* Strip down old coremodel generator
* Use public version of jennywrites
* Pull latest thema
* Commit generated Go types
* Add header injection postprocessor
* Move sdboyer/jennywrites to grafana/codejen
* Tweak header output
* Remove dashboard and playlist coremodels
* Fix up backend dashboards devenv test
* Fix TS import patterns to new gen filename
* Update internal imports, remove coremodel registry
* Fix compilation errors, wire generation
* Export and replace the prefix dropper
* More Go struct and field name changes
* Last name fixes, hopefully
* Fix lint errors
* Last lint error
Co-authored-by: Artur Wierzbicki <wierzbicki.artur.94@gmail.com>
											
										 
											2022-11-11 04:36:40 +08:00
										 |  |  | 		walker: PrefixDropper(strings.Title(lin.Name())), | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 		in:     buf.Bytes(), | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	wd := NewWriteDiffer() | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 	wd[fullp] = byt | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return wd, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-15 21:47:04 +08:00
										 |  |  | type tplVars struct { | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	Name                   string | 
					
						
							| 
									
										
										
										
											2022-06-15 21:47:04 +08:00
										 |  |  | 	LineagePath, PkgPath   string | 
					
						
							|  |  |  | 	TitleName              string | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	LatestSeqv, LatestSchv uint | 
					
						
							|  |  |  | 	IsComposed             bool | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | func (cd *CoremodelDeclaration) GenerateTypescriptCoremodel() (*tsast.File, error) { | 
					
						
							| 
									
										
										
										
											2022-11-15 21:48:31 +08:00
										 |  |  | 	schv := cd.Lineage.Latest().Underlying() | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 	tf, err := cuetsy.GenerateAST(schv, cuetsy.Config{ | 
					
						
							|  |  |  | 		Export: true, | 
					
						
							|  |  |  | 	}) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 		return nil, fmt.Errorf("cuetsy tf gen failed: %w", err) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 	top, err := cuetsy.GenerateSingleAST(strings.Title(cd.Lineage.Name()), schv, cuetsy.TypeInterface) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 		return nil, fmt.Errorf("cuetsy top gen failed: %s", cerrors.Details(err, nil)) | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 	buf := new(bytes.Buffer) | 
					
						
							|  |  |  | 	if err := tmpls.Lookup("autogen_header.tmpl").Execute(buf, tvars_autogen_header{ | 
					
						
							|  |  |  | 		LineagePath:   cd.RelativePath, | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | 		GeneratorPath: "pkg/framework/coremodel/gen.go", // FIXME hardcoding is not OK
 | 
					
						
							|  |  |  | 	}); err != nil { | 
					
						
							|  |  |  | 		return nil, fmt.Errorf("error executing header template: %w", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 	tf.Doc = &tsast.Comment{ | 
					
						
							|  |  |  | 		Text: buf.String(), | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-26 23:26:18 +08:00
										 |  |  | 	// TODO until cuetsy can toposort its outputs, put the top/parent type at the bottom of the file.
 | 
					
						
							|  |  |  | 	tf.Nodes = append(tf.Nodes, top.T) | 
					
						
							|  |  |  | 	if top.D != nil { | 
					
						
							|  |  |  | 		tf.Nodes = append(tf.Nodes, top.D) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return tf, nil | 
					
						
							| 
									
										
										
										
											2022-05-27 09:21:37 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-06-15 21:47:04 +08:00
										 |  |  | var tmplTypedef = `{{range .Types}} | 
					
						
							| 
									
										
										
										
											2022-09-14 22:15:09 +08:00
										 |  |  | {{ with .Schema.Description }}{{ . }}{{ else }}// {{.TypeName}} is the Go representation of a {{.JsonName}}.{{ end }}
 | 
					
						
							| 
									
										
										
										
											2022-06-15 21:47:04 +08:00
										 |  |  | //
 | 
					
						
							|  |  |  | // THIS TYPE IS INTENDED FOR INTERNAL USE BY THE GRAFANA BACKEND, AND IS SUBJECT TO BREAKING CHANGES.
 | 
					
						
							|  |  |  | // Equivalent Go types at stable import paths are provided in https://github.com/grafana/grok.
 | 
					
						
							|  |  |  | type {{.TypeName}} {{if and (opts.AliasTypes) (.CanAlias)}}={{end}} {{.Schema.TypeDecl}} | 
					
						
							|  |  |  | {{end}} | 
					
						
							|  |  |  | ` |