Categorygithub.com/grafana/cuetsy
modulepackage
0.1.11
Repository: https://github.com/grafana/cuetsy.git
Documentation: pkg.go.dev

# README

Cuetsy Logo

Installation · Usage

cuetsy

Converting CUE objects to their TypeScript equivalent (highly experimental!)

  • CUE makes defining and validating canonical data specification easy
  • TypeScript is dominant in the frontend, but cannot natively benefit from this
  • CUE types often have direct TypeScript equivalents, so cuetsy can bridge this gap

Example

CUETypeScript
DiceFaces: 1 | 2 | 3 | 4 | 5 | 6 @cuetsy(kind="type")

Animal: {
    Name: string
    Sound: string
} @cuetsy(kind="interface")

LeggedAnimal: Animal & {
    Legs: int
} @cuetsy(kind="interface")

Pets: "Cat" | "Dog" | "Horse" @cuetsy(kind="enum")
export type DiceFaces = 1 | 2 | 3 | 4 | 5 | 6;
export interface Animal {
  Name: string;
  Sound: string;
}
export interface LeggedAnimal extends Animal {
  Legs: number;
}
export enum Pets {
  Cat = "Cat",
  Dog = "Dog",
  Horse = "Horse",
}

Status

Cuetsy is experimental. The following are supported:

Installation

Cuetsy can be installed using Go 1.16+

$ go install github.com/grafana/cuetsy/cmd/cuetsy

Usage

cuetsy must be invoked on files as follows:

$ cuetsy [file.cue]

This will create a logically equivalent [file].ts

Alternatively, cuetsy can be used as a library for more customized code generation.

Union Types

CUETypeScript@cuetsy(kind)
DisjunctionUnion Typetype

Union types are expressed in CUE and TypeScript nearly the same way, namely a series of disjunctions (a | b | c):

CUETypeScript
MyUnion: 1 | 2 | 3 | 4 | 5 | 6 @cuetsy(kind="type")
export type MyUnion = 1 | 2 | 3 | 4 | 5 | 6;

Interfaces

CUETypeScript@cuetsy(kind)
StructInterfaceinterface

TypeScript interfaces are expressed as regular structs in CUE.

Caveats:

CUETypeScript
MyInterface: {
    Num: number
    Text: string
    List: [...number]
    Truth: bool
} @cuetsy(kind="interface")
export interface MyInterface {
  List: number[];
  Num: number;
  Text: string;
  Truth: boolean;
}

Inheritance

Interfaces can optionally extend another interface. If a type marked for export as a kind="interface" is unified (whether by & or embedding) with another type marked for export as an interface, it will produce extend in output:

CUETypeScript
AInterface: {
    AField: string
} @cuetsy(kind="interface")

ByUnifying: AInterface & {
    BField: int
} @cuetsy(kind="interface")

ByEmbedding: {
    AInterface
    CField: bool
} @cuetsy(kind="interface")
export interface AInterface {
  AField: string;
}

export interface ByUnifying extends AInterface {
  BField: number;
}

export interface ByEmbedding extends AInterface {
  CField: boolean;
}

Enums

CUETypeScript@cuetsy(kind)
DisjunctionString enums, Numeric enumsenum

TypeScript's enums are union types, and are a mostly-exact mapping of what can be expressed with CUE's disjunctions. Disjunctions may contain only string or numeric values.

For string enums, the member names (keys) of the TypeScript enum are automatically inferred as the titled camel-case variant of their string value, but may be explicitly specified using the memberNames attribute. For a numeric enum, memberNames must be specified.

CUETypeScript
AutoCamel: "foo" | "bar" @cuetsy(kind="enum")
ManualCamel: "foo" | "bar" @cuetsy(kind="enum",memberNames="Foo|Bar")
Arbitrary: "foo" | "bar" @cuetsy(kind="enum",memberNames="Zip|Zap")
Numeric: 0 | 1 | 2 @cuetsy(kind="enum",memberNames="Zero|One|Two")
export enum AutoCamel {
  Bar = 'bar',
  Foo = 'foo',
}

export enum ManualCamel {
  Bar = 'bar',
  Foo = 'foo',
}

export enum Arbitrary {
  Zap = 'bar',
  Zip = 'foo',
}

export enum Numeric {
  One = 1,
  Two = 2,
  Zero = 0,
}

Defaults

CUETypeScript
Defaultsconst

Cuetsy can optionally generate a const for each type that holds default values. For that, mark CUE Default Values to your type definitions:

CUETypeScript
MyUnion: 1 | 2 | *3 @cuetsy(kind="type")

MyEnum: "foo" | *"bar" @cuetsy(kind="enum")

MyInterface: {
    num: int | *6
    txt: string | *"CUE"
    enm: MyDisjEnum
} @cuetsy(kind="interface")
export type MyUnion = 1 | 2 | 3;

export const defaultMyUnion: MyUnion = 3;

export enum MyEnum {
  Bar = 'bar',
  Foo = 'foo',
}

export const defaultMyEnum: MyEnum = MyEnum.Bar;

export interface MyInterface {
  enm: MyDisjEnum;
  num: number;
  txt: string;
}

export const defaultMyInterface: Partial<MyInterface> = {
  enm: MyDisjEnum.Bar,
  num: 6,
  txt: 'CUE',
};

# Packages

No description provided by the author
No description provided by the author

# Functions

Generate takes a cue.Value and generates the corresponding TypeScript for all top-level members of that value that have appropriate @cuetsy attributes.
No description provided by the author
No description provided by the author
IgnoreImportMapper ignores all import paths cuetsy encounters, resulting in no import statements in generated TS output.

# Constants

Any indicates any value, or top.
No description provided by the author
Concrete indicates a concrete scalar value, list or struct.
Constraint indicates a non-concrete scalar value that is more specific, than a top-level type.
Type indicates a top-level specific type, for instance, string, bytes, number, or bool.
TypeAlias targets conversion of a CUE value to a TypeScript `type` declaration, which are called type aliases: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-aliases.
TypeEnum targets conversion of a CUE value to a TypeScript `enum` declaration: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#enums.
TypeInterface targets conversion of a CUE value to a TypeScript `interface` declaration: https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#interfaces.

# Structs

Config governs certain variable behaviors when converting CUE to Typescript.
DeclPair represents a generated type declaration, with its corresponding default declaration.
No description provided by the author
No description provided by the author

# Interfaces

TypeMapper is a general interface to describe a mapping between cue.Value and typescript kinds and types.

# Type aliases

Concreteness is a measure of the level of concreteness of a value, where lower values mean more concrete.
An ImportMapper takes a string containing a CUE import path (e.g.
TSType strings indicate the kind of TypeScript declaration to which a CUE value should be translated.