Skip to content

Commit

Permalink
Merge pull request #188 from grafana/use-proper-schema-value
Browse files Browse the repository at this point in the history
Use _#schema to generate TS files
  • Loading branch information
spinillos committed Jul 26, 2023
2 parents ed06357 + 9ac6e2f commit e35caab
Show file tree
Hide file tree
Showing 29 changed files with 422 additions and 29 deletions.
47 changes: 21 additions & 26 deletions encoding/typescript/gen.go
Expand Up @@ -64,41 +64,36 @@ func GenerateTypes(sch thema.Schema, cfg *TypeConfig) (*ast.File, error) {
}
if cfg.CuetsyConfig == nil {
cfg.CuetsyConfig = &cuetsy.Config{
Export: true,
ImportMapper: cuetsy.IgnoreImportMapper,
Export: true,
}
}
if cfg.RootName == "" {
cfg.RootName = strings.Title(sch.Lineage().Name())
}

file := &ts.File{}
for _, path := range []cue.Selector{cue.Str("schema"), cue.Hid("_join", "github.com/grafana/thema")} {
schdef := sch.Underlying().LookupPath(cue.MakePath(path))
// Cuetsy only accepts structs as root file, otherwise it fails.
// _join could be _ and we can skip it when it happens to avoid to break the whole generation process.
if schdef.IncompleteKind() != cue.StructKind {
continue
schdef := sch.Underlying().LookupPath(cue.MakePath(cue.Hid("_#schema", "github.com/grafana/thema")))
tf, err := cuetsy.GenerateAST(schdef, *cfg.CuetsyConfig)
if err != nil {
return nil, fmt.Errorf("generating TS for child elements of schema failed: %w", err)
}

file := &ts.File{
Nodes: tf.Nodes,
}

if !cfg.Group {
as := cuetsy.TypeInterface
if cfg.RootAsType {
as = cuetsy.TypeAlias
}
tf, err := cuetsy.GenerateAST(schdef, *cfg.CuetsyConfig)
top, err := cuetsy.GenerateSingleAST(cfg.RootName, schdef, as)
if err != nil {
return nil, fmt.Errorf("generating TS for child elements of schema failed: %w", err)
return nil, fmt.Errorf("generating TS for schema root failed: %w", err)
}

file.Nodes = append(file.Nodes, tf.Nodes...)

if !cfg.Group {
as := cuetsy.TypeInterface
if cfg.RootAsType {
as = cuetsy.TypeAlias
}
top, err := cuetsy.GenerateSingleAST(cfg.RootName, schdef, as)
if err != nil {
return nil, fmt.Errorf("generating TS for schema root failed: %w", err)
}
file.Nodes = append(file.Nodes, top.T)
if top.D != nil {
file.Nodes = append(file.Nodes, top.D)
}
file.Nodes = append(file.Nodes, top.T)
if top.D != nil {
file.Nodes = append(file.Nodes, top.D)
}
}

Expand Down
61 changes: 61 additions & 0 deletions encoding/typescript/ts_test.go
@@ -0,0 +1,61 @@
package typescript

import (
"github.com/stretchr/testify/require"
"testing"

"cuelang.org/go/cue/cuecontext"
"github.com/grafana/thema"
"github.com/grafana/thema/internal/txtartest/bindlin"
"github.com/grafana/thema/internal/txtartest/vanilla"
)

func TestGenerate(t *testing.T) {
test := vanilla.TxTarTest{
Root: "../../testdata/lineage",
Name: "encoding/typescript/TestGenerate",
ThemaFS: thema.CueJointFS,
Skip: map[string]string{
"lineage/refexscalar": "bounds constraints are not supported as they lack a direct typescript equivalent",
"lineage/refscalar": "bounds constraints are not supported as they lack a direct typescript equivalent",
},
}

ctx := cuecontext.New()
rt := thema.NewRuntime(ctx)

table := []struct {
name string
cfg *TypeConfig
}{
{
name: "nilcfg",
cfg: nil,
},
}

for _, tb := range table {
t.Run(tb.name, func(t *testing.T) {
testcpy := test
testcpy.Name += "/" + tb.name
testcpy.Run(t, func(tc *vanilla.Test) {
if testing.Short() && tc.HasTag("slow") {
t.Skip("case is tagged #slow, skipping for -short")
}
lin, err := bindlin.BindTxtarLineage(tc, rt)
if err != nil {
tc.Fatal(err)
}

for sch := lin.First(); sch != nil; sch = sch.Successor() {
f, err := GenerateTypes(sch, tb.cfg)
if err != nil {
tc.Fatal(err)
}
_, err = tc.Write([]byte(f.String())) //nolint:gosec,errcheck
require.NoError(t, err)
}
})
})
}
}
2 changes: 1 addition & 1 deletion go.mod
Expand Up @@ -14,7 +14,7 @@ require (
github.com/getkin/kin-openapi v0.115.0
github.com/golangci/lint-1 v0.0.0-20181222135242-d2cdd8c08219
github.com/google/go-cmp v0.5.8
github.com/grafana/cuetsy v0.1.10
github.com/grafana/cuetsy v0.1.11
github.com/labstack/echo/v4 v4.9.1
github.com/matryer/moq v0.2.7
github.com/spf13/cobra v1.4.0
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Expand Up @@ -110,8 +110,8 @@ github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
github.com/gorilla/websocket v1.4.1/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
github.com/grafana/cuetsy v0.1.10 h1:+W9/7roI8LorL+D1RJhKGdhsTZ81adrK9dHS0r7qsXs=
github.com/grafana/cuetsy v0.1.10/go.mod h1:Ix97+CPD8ws9oSSxR3/Lf4ahU1I4Np83kjJmDVnLZvc=
github.com/grafana/cuetsy v0.1.11 h1:I3IwBhF+UaQxRM79HnImtrAn8REGdb5M3+C4QrYHoWk=
github.com/grafana/cuetsy v0.1.11/go.mod h1:Ix97+CPD8ws9oSSxR3/Lf4ahU1I4Np83kjJmDVnLZvc=
github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
Expand Down
55 changes: 55 additions & 0 deletions testdata/lineage/basic-multiversion.txtar
Expand Up @@ -1840,3 +1840,58 @@ type Basicmultiversion struct {

// BasicmultiversionWithDefault defines model for Basicmultiversion.WithDefault.
type BasicmultiversionWithDefault string
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Basic-Multiversion {
init: string;
}
export interface Basic-Multiversion {
init: string;
optional?: number;
}
export interface Basic-Multiversion {
init: string;
optional?: number;
withDefault?: ('foo' | 'bar');
}

export const defaultBasic-Multiversion: Partial<Basic-Multiversion> = {
withDefault: 'foo',
};
export interface Basic-Multiversion {
init: string;
optional?: number;
withDefault?: ('foo' | 'bar' | 'baz');
}

export const defaultBasic-Multiversion: Partial<Basic-Multiversion> = {
withDefault: 'foo',
};
export interface Basic-Multiversion {
optional?: number;
renamed: string;
withDefault: ('foo' | 'bar' | 'baz');
}

export const defaultBasic-Multiversion: Partial<Basic-Multiversion> = {
withDefault: 'bar',
};
export interface Basic-Multiversion {
optional?: number;
renamed: string;
withDefault: ('foo' | 'bar' | 'baz' | 'bing');
}

export const defaultBasic-Multiversion: Partial<Basic-Multiversion> = {
withDefault: 'bar',
};
export interface Basic-Multiversion {
optional?: number;
toObj: {
init: string;
};
withDefault: ('foo' | 'bar' | 'baz' | 'bing');
}

export const defaultBasic-Multiversion: Partial<Basic-Multiversion> = {
withDefault: 'bar',
};
5 changes: 5 additions & 0 deletions testdata/lineage/embedexref.txtar
Expand Up @@ -189,3 +189,8 @@ type EmbedexrefRefField2 int
Schema count: 1
Schema versions: 0.0
Lenses count: 0
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Embedexref {
refField1: string;
refField2: 42;
}
5 changes: 5 additions & 0 deletions testdata/lineage/embedref.txtar
Expand Up @@ -314,3 +314,8 @@ type Embedref struct {

// EmbedrefRefField2 defines model for Embedref.RefField2.
type EmbedrefRefField2 int
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Embedref {
refField1: string;
refField2: 42;
}
26 changes: 26 additions & 0 deletions testdata/lineage/expand.txtar
Expand Up @@ -687,3 +687,29 @@ type Expand struct {

// ExpandWithDefault defines model for Expand.WithDefault.
type ExpandWithDefault string
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Expand {
init: string;
}
export interface Expand {
init: string;
optional?: number;
}
export interface Expand {
init: string;
optional?: number;
withDefault?: ('foo' | 'bar');
}

export const defaultExpand: Partial<Expand> = {
withDefault: 'foo',
};
export interface Expand {
init: string;
optional?: number;
withDefault?: ('foo' | 'bar' | 'baz');
}

export const defaultExpand: Partial<Expand> = {
withDefault: 'foo',
};
10 changes: 10 additions & 0 deletions testdata/lineage/go-any.txtar
Expand Up @@ -314,3 +314,13 @@ type Goany struct {
} `json:"structVal"`
Value any `json:"value"`
}
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Go-Any {
emptyMap: Record<string, unknown>;
optional?: (string | boolean);
structVal: {
inner: (string | number);
innerOptional?: unknown;
};
value: (string | boolean);
}
6 changes: 6 additions & 0 deletions testdata/lineage/join/embedref.txtar
Expand Up @@ -218,3 +218,9 @@ type Embedref struct {

// EmbedrefRefField2 defines model for Embedref.RefField2.
type EmbedrefRefField2 int
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Embedref {
foo: string;
refField1: string;
refField2: 42;
}
10 changes: 10 additions & 0 deletions testdata/lineage/join/exref.txtar
Expand Up @@ -268,3 +268,13 @@ type Exref struct {
Ref ExRef `json:"ref"`
Refdef ExRefDef `json:"refdef"`
}
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Exref {
foo: string;
ref: {
normalField: string;
};
refdef: {
defField: string;
};
}
16 changes: 16 additions & 0 deletions testdata/lineage/join/nearoptional.txtar
Expand Up @@ -276,3 +276,19 @@ type Nearoptional struct {
} `json:"astruct,omitempty"`
Notoptional int32 `json:"notoptional"`
}
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Nearoptional {
abool?: boolean;
abytes?: string;
alist?: Array<string>;
anint?: number;
astring?: string;
astruct?: {
nested: string;
};
notoptional: number;
}

export const defaultNearoptional: Partial<Nearoptional> = {
alist: [],
};
4 changes: 4 additions & 0 deletions testdata/lineage/join/onenone.txtar
Expand Up @@ -122,3 +122,7 @@ package onenone

// Foo defines model for foo.
type Foo = string
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Onenone {
foo: string;
}
5 changes: 5 additions & 0 deletions testdata/lineage/join/oneone.txtar
Expand Up @@ -149,3 +149,8 @@ type Oneone struct {
Bar string `json:"bar"`
Foo string `json:"foo"`
}
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Oneone {
bar: string;
foo: string;
}
7 changes: 7 additions & 0 deletions testdata/lineage/join/onestruct.txtar
Expand Up @@ -185,3 +185,10 @@ type AField struct {

// Foo defines model for foo.
type Foo = string
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Onestruct {
aField: {
defLitField: string;
};
foo: string;
}
4 changes: 4 additions & 0 deletions testdata/lineage/join/repeat.txtar
Expand Up @@ -123,3 +123,7 @@ package repeat
type Repeat struct {
Foo string `json:"foo"`
}
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Repeat {
foo: string;
}
20 changes: 20 additions & 0 deletions testdata/lineage/maps.txtar
Expand Up @@ -605,3 +605,23 @@ type ValPrimitive map[string]bool
type ValStruct map[string]struct {
Foo string `json:"foo"`
}
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Maps {
aComplexMap?: {
foo: string;
};
optValList?: Record<string, Array<string>>;
optValPrimitive?: Record<string, boolean>;
optValStruct?: Record<string, {
foo: string,
}>;
refValue: Record<string, {
foo: string,
}>;
someField: Record<string, boolean>;
valList: Record<string, Array<string>>;
valPrimitive: Record<string, boolean>;
valStruct: Record<string, {
foo: string,
}>;
}
16 changes: 16 additions & 0 deletions testdata/lineage/nearoptional.txtar
Expand Up @@ -294,3 +294,19 @@ type Nearoptional struct {
} `json:"astruct,omitempty"`
Notoptional int32 `json:"notoptional"`
}
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Nearoptional {
abool?: boolean;
abytes?: string;
alist?: Array<string>;
anint?: number;
astring?: string;
astruct?: {
nested: string;
};
notoptional: number;
}

export const defaultNearoptional: Partial<Nearoptional> = {
alist: [],
};
4 changes: 4 additions & 0 deletions testdata/lineage/noref.txtar
Expand Up @@ -224,3 +224,7 @@ type Baz struct {

// SomeField defines model for someField.
type SomeField = string
-- out/encoding/typescript/TestGenerate/nilcfg --
export interface Noref {
someField: string;
}

0 comments on commit e35caab

Please sign in to comment.