❣️

【cuetorials】入門 ~ cueでER図自動生成してみるまで❗️

2022/12/05に公開

こちらは「Applibot Advent Calendar 2022」5日目の記事になります.

はじめに

本記事では,cuelang入門~からcuelangを用いた自動生成周りについてまとめます.

まとめ

githubにサンプルコードと解説をまとめています
https://github.com/yuucu/gen-cue-sample/tree/main

簡単なチュートリアルまとめたチートシート

概要

cueとは

https://cuelang.org/

cue言語は型付きでのスキーマ定義やデータバリデーションができる言語です.
jsonやyamlのデータ検証や自動生成元のデータをスキーマ付きで定義したりすることができます.

チュートリアル

導入

公式インストール方法にならい入れてみます.

https://github.com/cue-lang/cue

macのためbrewで入れる.

brew install cue-lang/tap/cue

cueで変換してみる

cueはjsonやyamlに変換することができる.

pureなjsonを書く感じでまったく問題ないです.
一応下のような差分はあるが,cueの方が拡張されていて良い感じです.

  • コメントアウトができる
  • フィールド最後のコンマをつけても良い
  • リスト最後のコンマをつけても良い
test.cue
{
  "name": "yuucu",
  "age": 18,
  // 所持しているアイテム
  "items": [
    "item1",
    "item2",
  ],
}
shell
$ cue export test.cue

コメントや最後のカンマが消えて正しいjsonの形式になっている.

out.json
{
  "name": "yuucu",
  "age": 18,
  "items": [
    "item1",
    "item2"
  ]
}

cueでスキーマ定義をしてみる

以下の型が指定できる.

  null  bool  string  bytes  number  struct  list
                             /   \
                           int  float

構造体の定義は#で書く (#user)

test.cue
#user: {
  "name": string,
  "age": int,
  // 所持しているアイテム
  "items": [...string],
}

you: #user & {
  "name": "yuucu",
  "age": 18,
  "items": [
    "item1",
    "item2",
  ],
}
shell
$ cue export test.cue
out.json
{
    "you": {
        "name": "yuucu",
        "age": 18,
        "items": [
            "item1",
            "item2"
        ]
    }
}

型検証

試しにageに文字列を入れてみると error で知らせてくれる.

shell
$ cue export test.cue
you.age: conflicting values int and "test string" (mismatched types int and string):
    ./test.cue:3:10
    ./test.cue:11:10

expressions

if文を使ってみる

test.cue
#user: {
  name: string,
  age: int,
  if age <= 50 {
    isOld: false,
  }
  if age > 50 {
    isOld: true,
  }
}

you: #user & {
  "name": "hoge",
  "age": 10,
}

me: #user & {
  "name": "hoge",
  "age": 100,
}

ageによってisOldの値を分岐することができる

out.json
{
    "you": {
        "name": "hoge",
        "isOld": false,
        "age": 10
    },
    "me": {
        "name": "hoge",
        "isOld": true,
        "age": 100
    }
}

yaml merge

cue export コマンドでjson/yamlのマージができる

cue export ./*.yaml

サンプルこちら
https://github.com/yuucu/gen-cue-sample/tree/main/sample/merge

template 自動生成

templateに埋め込む機能を使ってみる

template.cue
import "text/template"

tmplHello: """
	Hi! {{.name}}.
	"""

data: {
	name: "yuucu"
}

out: template.Execute(tmplHello, data)
shell
❯ cue export template.cue
{
    "tmplHello": "Hi! {{.name}}.",
    "data": {
        "name": "yuucu"
    },
    "out": "Hi! yuucu."
}

全て出力されてしまうので絞りたい.
ヘルプをみると,-eオプションで評価式を選択できるみたいでした.

❯ cue export fuga.cue -e out --out text
Hi! yuucu.

便利ですね!

go 構造体から.cue生成

cue get goコマンドでできる

.cueから簡単にER図を作ってみる

詳細は↓クリック

data.cue
data.cue
import "text/template"

#Tables: [...#Table]

#Table: {
	name: string
	columns: [...#Column]
}

// 雑にcolumnの定義
#Column: {
	isPrimaryKey: bool | *false
	name:         string
	type:         "string" | "int"
}

data: #Tables

// puml用のtemplate
tmplPuml: """
	@startuml
	{{ range . }}

	entity {{ .name }} {
		{{ range .columns -}}
			{{- if .isPrimaryKey -}}
				{{ .type }} {{ .name }}
			{{- end -}}
		{{- end }}
		---
		{{- range .columns -}}
			{{- if eq .isPrimaryKey false }}
				{{ .type }} {{ .name }}
			{{- end -}}
		{{- end }}
	}

	{{ end }}
	@enduml
	"""

// mermaid用のtemplate
tmplMd: """
	```mermaid
	erDiagram
	{{ range . -}}
		{{ .name }} {
			{{ range .columns -}}
				{{ .type }} {{ .name }}
			{{ end -}}
		}
	{{ end -}}
	```
	"""

// 実データ
data: [
	#Table & {
		name: "user"
		columns: [
			{
				isPrimaryKey: true
				name:         "id"
				type:         "string"
			},
			{
				name: "name"
				type: "string"
			},
			{
				name: "age"
				type: "int"
			},
		]
	},
	#Table & {
		name: "item"
		columns: [
			{
				name:         "id"
				type:         "string"
				isPrimaryKey: true
			},
			{
				name: "name"
				type: "string"
			},
			{
				name: "description"
				type: "string"
			},
		]
	},
]

// output
outPuml: template.Execute(tmplPuml, data)
outMd:   template.Execute(tmplMd, data)

pumlへの出力

(go template力が弱く,インデントがたがたです...)

$ cue export ./data.cue -e outPuml --out text
@startuml


entity user {
        string id
        ---
                        string name
                        int age
}



entity item {
        string id
        ---
                        string name
                        string description
}


@enduml

> で.pumlへ出して,みてみる

mermaidへの出力

$ cue export ./data.cue -e outMd --out text
```mermaid
erDiagram
user {
                string id
                string name
                int age
                }
item {
                string id
                string name
                string description
                }
```

> で.mdへ出して,みてみる

まとめ(再掲)

githubにサンプルコードと解説をまとめています
https://github.com/yuucu/gen-cue-sample/tree/main

簡単なチュートリアルまとめたチートシート

おわりに

便利ですね!
golangから.cueを扱うサンプルを試そうと思っていたのですが,
cueだけで自動生成実現できてしまったので,とてもびっくりです.

lspなりcueのエコシステムが発展することに期待です!

以上,「Applibot Advent Calendar 2022」 5日目の記事でした.

参考記事

https://cuetorials.com/
https://gihyo.jp/article/2022/09/tsukinami-go-02

Discussion