Skip to content
values-conflictPublic

About

`cue` implemented in pure `jq`

Resources

Stars

0 stars

Watchers

1 watching

Forks

Latest commit

 

History

3 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

jcue

cue implemented in pure jq.

Why?

CUE is a genuinely useful tool for data validation and configuration -- but pulling in a Go binary just to validate some JSON is overkill when jq is already everywhere.

"jcue"?

j for jq, cue for CUE.

Usage

Add jcue.jq somewhere on your jq library path and include "jcue" in any filter. validate($schema) returns its input unchanged on success and throws an error on failure:

$ echo '{"name": "Alice", "age": 30}' | jq -L /path/to/jcue 'include "jcue"; validate({"name": {"$cue": "string"}, "age": {"$cue": "int"}})'
{
  "name": "Alice",
  "age": 30
}
$ echo '{"name": "Alice", "age": "thirty"}' | jq -L /path/to/jcue 'include "jcue"; try validate({"name": {"$cue": "string"}, "age": {"$cue": "int"}}) catch .'
"expected int, got string"

Parsing CUE syntax

from_cue($text) parses a CUE type expression and returns a jcue schema, letting you write schemas in real CUE syntax instead of as JSON. This is the jq equivalent of cue vet -- pipe any JSON through validate(from_cue(...)) to check it against a CUE schema:

$ echo '{"name": "Alice", "age": 30}' | jq -L /path/to/jcue 'include "jcue"; validate(from_cue("{name: string, age: int}"))'
{
  "name": "Alice",
  "age": 30
}
$ echo '{"name": 42}' | jq -L /path/to/jcue 'include "jcue"; try validate(from_cue("{name: string}")) catch .'
"expected string, got number"

Schemas in .cue files load with --rawfile, and multiple files validate with a single glob:

$ cat schema.cue
#Config: {
	host: string
	port: int & >= 1 & <= 65535
}
$ jq -L /path/to/jcue --rawfile schema schema.cue 'include "jcue"; validate(from_cue($schema))' config.json
$ jq -L /path/to/jcue --rawfile schema schema.cue 'include "jcue"; validate(from_cue($schema))' configs/*.json

from_cue handles the full type-expression subset: type keywords (string, int, float, bool, bytes, number), top (_) and bottom (_|_), constraints (>= N, != X, =~ "pat"), conjunction (A & B), disjunction (A | B), default markers (*val | type), open and close({...}) structs, and fixed/variable-length lists ([T, ...], [...T]). Top-level #Name: expr definition syntax is also accepted.

Schema format

Schemas are plain JSON. Abstract types use {"$cue": "kind"} as a type marker; plain objects, arrays, and scalars are structural constraints ("$cue" is a reserved key and cannot appear as a struct field name).

schema accepts
{"$cue": "top"} any value
{"$cue": "bottom"} nothing (always fails)
{"$cue": "null"} null
{"$cue": "bool"} any boolean
{"$cue": "string"} any string
{"$cue": "bytes"} bytes (string in JSON)
{"$cue": "number"} any number
{"$cue": "float"} any number (float bias)
{"$cue": "int"} any integer
{"$cue": ">=", "v": N} number ≥ N
{"$cue": "<=", "v": N} number ≤ N
{"$cue": ">", "v": N} number > N
{"$cue": "<", "v": N} number < N
{"$cue": "!=", "v": X} anything not equal to X
{"$cue": "=~", "v": "pat"} string matching regex
{"$cue": "!~", "v": "pat"} string not matching regex
{"$cue": "&", "of": [...]} value matching all schemas (conjunction)
{"$cue": "|", "of": [...]} value matching any schema (disjunction)
{"$cue": "list", "elem": schema} variable-length list
{"$cue": "close", "v": {...}} closed struct (no extra fields)
plain object (no "$cue") open struct; field names suffixed ? are optional
plain array fixed-length list (element schemas by position)
plain scalar exact value match

About

`cue` implemented in pure `jq`

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages