-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit b620f19
Showing
167 changed files
with
14,951 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
version: '2' | ||
jobs: | ||
build: | ||
working_directory: /go/src/github.com/qri-io/jsonschema | ||
docker: | ||
- image: circleci/golang:1.9 | ||
environment: | ||
GOLANG_ENV: test | ||
PORT: 3000 | ||
environment: | ||
TEST_RESULTS: /tmp/test-results | ||
steps: | ||
- checkout | ||
- run: mkdir -p $TEST_RESULTS | ||
- run: go get github.com/jstemmer/go-junit-report github.com/golang/lint/golint | ||
- run: | ||
name: Install deps | ||
command: > | ||
go get -v -d -u | ||
github.com/jstemmer/go-junit-report | ||
- run: | ||
name: Run Lint Tests | ||
command: golint ./... | ||
- run: | ||
name: Run Tests | ||
command: go test -v -race -coverprofile=coverage.txt -covermode=atomic | ||
- run: | ||
name: Publish coverage info to codecov.io | ||
command: bash <(curl -s https://codecov.io/bash) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
#!/usr/bin/env bash | ||
|
||
set -e | ||
echo "" > coverage.txt | ||
go test -v -race -coverprofile=profile.out -covermode=atomic github.com/qri-io/varName | ||
if [ -f profile.out ]; then | ||
cat profile.out >> coverage.txt | ||
rm profile.out | ||
fi |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.DS_Store | ||
coverage.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
[![Qri](https://img.shields.io/badge/made%20by-qri-magenta.svg?style=flat-square)](https://qri.io) | ||
[![GoDoc](https://godoc.org/github.com/qri-io/varName?status.svg)](http://godoc.org/github.com/qri-io/varName) | ||
[![License](https://img.shields.io/github/license/qri-io/varName.svg?style=flat-square)](./LICENSE) | ||
[![Codecov](https://img.shields.io/codecov/c/github/qri-io/varName.svg?style=flat-square)](https://codecov.io/gh/qri-io/varName) | ||
[![CI](https://img.shields.io/circleci/project/github/qri-io/varName.svg?style=flat-square)](https://circleci.com/gh/qri-io/varName) | ||
[![Go Report Card](https://goreportcard.com/badge/github.com/qri-io/varName)](https://goreportcard.com/report/github.com/qri-io/varName) | ||
|
||
|
||
# varName 🐫🍢🐍 | ||
|
||
Provides utility for converting lengthy titles into condensed but still recognizable variable names | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
codecov: | ||
ci: | ||
- "ci/circle-ci" | ||
notify: | ||
require_ci_to_pass: no | ||
after_n_builds: 2 | ||
coverage: | ||
range: "80...100" | ||
comment: off |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,122 @@ | ||
package jsonschema | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
// Type specifies one of the six json primitive types. | ||
// The value of this keyword MUST be either a string or an array. | ||
// If it is an array, elements of the array MUST be strings and MUST be unique. | ||
// String values MUST be one of the six primitive types ("null", "boolean", "object", "array", "number", or "string"), or | ||
// "integer" which matches any number with a zero fractional part. | ||
// An instance validates if and only if the instance is in any of the sets listed for this keyword. | ||
type Type []string | ||
|
||
// Validate checks to see if input data satisfies the type constraint | ||
func (t Type) Validate(data interface{}) error { | ||
jt := DataType(data) | ||
for _, typestr := range t { | ||
if jt == typestr || jt == "integer" && typestr == "number" { | ||
return nil | ||
} | ||
} | ||
return fmt.Errorf(`expected "%v" to be a %s`, data, jt) | ||
} | ||
|
||
// primitiveTypes is a map of strings to check types against | ||
var primitiveTypes = map[string]bool{ | ||
"null": true, | ||
"boolean": true, | ||
"object": true, | ||
"array": true, | ||
"number": true, | ||
"string": true, | ||
"integer": true, | ||
} | ||
|
||
// UnmarshalJSON implements the json.Unmarshaler interface for Type | ||
func (t *Type) UnmarshalJSON(data []byte) error { | ||
var single string | ||
if err := json.Unmarshal(data, &single); err == nil { | ||
*t = Type{single} | ||
} else { | ||
var set []string | ||
if err := json.Unmarshal(data, &set); err == nil { | ||
*t = Type(set) | ||
} else { | ||
return err | ||
} | ||
} | ||
|
||
for _, pr := range *t { | ||
if !primitiveTypes[pr] { | ||
return fmt.Errorf(`"%s" is not a valid type`, pr) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// MarshalJSON implements the json.Marshaler interface for Type | ||
func (t Type) MarshalJSON() ([]byte, error) { | ||
if len(t) == 1 { | ||
return json.Marshal(t[0]) | ||
} else if len(t) > 1 { | ||
return json.Marshal([]string(t)) | ||
} | ||
return []byte(`""`), nil | ||
} | ||
|
||
// Enum validates successfully against this keyword if its value is equal to one of the | ||
// elements in this keyword's array value. | ||
// Elements in the array SHOULD be unique. | ||
// Elements in the array might be of any value, including null. | ||
type Enum []Const | ||
|
||
// String implements the stringer interface for Enum | ||
func (e Enum) String() string { | ||
str := "[" | ||
for _, c := range e { | ||
str += ", " + c.String() | ||
} | ||
return str + "]" | ||
} | ||
|
||
// Validate implements the Validator interface for Enum | ||
func (e Enum) Validate(data interface{}) error { | ||
for _, v := range e { | ||
if err := v.Validate(data); err == nil { | ||
return nil | ||
} | ||
} | ||
return fmt.Errorf("expected %s to be one of %s", data) | ||
} | ||
|
||
// Const MAY be of any type, including null. | ||
// An instance validates successfully against this keyword if its | ||
// value is equal to the value of the keyword. | ||
type Const []byte | ||
|
||
// String implements the Stringer interface for Const | ||
func (c Const) String() string { | ||
return string(c) | ||
} | ||
|
||
// UnmarshalJSON implements the json.Unmarshaler interface for Const | ||
func (c *Const) UnmarshalJSON(data []byte) error { | ||
*c = data | ||
return nil | ||
} | ||
|
||
// Validate implements the validate interface for Const | ||
func (c Const) Validate(data interface{}) error { | ||
var con interface{} | ||
if err := json.Unmarshal(c, &con); err != nil { | ||
return err | ||
} | ||
if !reflect.DeepEqual(con, data) { | ||
return fmt.Errorf(`%s must equal %s`, string(c), data) | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
package jsonschema | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
// Items MUST be either a valid JSON Schema or an array of valid JSON Schemas. | ||
// This keyword determines how child instances validate for arrays, and does not directly validate the | ||
// immediate instance itself. | ||
// * If "items" is a schema, validation succeeds if all elements in the array successfully validate | ||
// against that schema. | ||
// * If "items" is an array of schemas, validation succeeds if each element of the instance validates | ||
// against the schema at the same position, if any. | ||
// * Omitting this keyword has the same behavior as an empty schema. | ||
type Items struct { | ||
// need to track weather user specficied a singl object or arry | ||
// b/c it affects additionalItems validation semantics | ||
single bool | ||
Schemas []*Schema | ||
} | ||
|
||
// Validate implements the Validator interface for Items | ||
func (it Items) Validate(data interface{}) error { | ||
if arr, ok := data.([]interface{}); ok { | ||
if it.single { | ||
for i, elem := range arr { | ||
if err := it.Schemas[0].Validate(elem); err != nil { | ||
return fmt.Errorf("element %d: %s", i, err.Error()) | ||
} | ||
} | ||
} else { | ||
for i, vs := range it.Schemas { | ||
if i < len(arr) { | ||
if err := vs.Validate(arr[i]); err != nil { | ||
return fmt.Errorf("element %d: %s", i, err.Error()) | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// UnmarshalJSON implements the json.Unmarshaler interface for Items | ||
func (it *Items) UnmarshalJSON(data []byte) error { | ||
s := &Schema{} | ||
if err := json.Unmarshal(data, s); err == nil { | ||
*it = Items{single: true, Schemas: []*Schema{s}} | ||
return nil | ||
} | ||
ss := []*Schema{} | ||
if err := json.Unmarshal(data, &ss); err != nil { | ||
return err | ||
} | ||
*it = Items{Schemas: ss} | ||
return nil | ||
} | ||
|
||
// MarshalJSON implements the json.Marshaler interface for Items | ||
func (it Items) MarshalJSON() ([]byte, error) { | ||
if it.single { | ||
return json.Marshal(it.Schemas[0]) | ||
} | ||
return json.Marshal([]*Schema(it.Schemas)) | ||
} | ||
|
||
// AdditionalItems determines how child instances validate for arrays, and does not directly validate the immediate | ||
// instance itself. | ||
// If "items" is an array of schemas, validation succeeds if every instance element at a position greater than | ||
// the size of "items" validates against "additionalItems". | ||
// Otherwise, "additionalItems" MUST be ignored, as the "items" schema (possibly the default value of an empty schema) is applied to all elements. | ||
// Omitting this keyword has the same behavior as an empty schema. | ||
type AdditionalItems struct { | ||
startIndex int | ||
Schema *Schema | ||
} | ||
|
||
// Validate implements the Validator interface for AdditionalItems | ||
func (a *AdditionalItems) Validate(data interface{}) error { | ||
if a.startIndex >= 0 { | ||
if arr, ok := data.([]interface{}); ok { | ||
for i, elem := range arr { | ||
if i < a.startIndex { | ||
continue | ||
} | ||
if err := a.Schema.Validate(elem); err != nil { | ||
return fmt.Errorf("element %d: %s", i, err.Error()) | ||
} | ||
} | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// UnmarshalJSON implements the json.Unmarshaler interface for AdditionalItems | ||
func (a *AdditionalItems) UnmarshalJSON(data []byte) error { | ||
sch := &Schema{} | ||
if err := json.Unmarshal(data, sch); err != nil { | ||
return err | ||
} | ||
// begin with -1 as default index to prevent AdditionalItems from evaluating | ||
// unless startIndex is explicitly set | ||
*a = AdditionalItems{startIndex: -1, Schema: sch} | ||
return nil | ||
} | ||
|
||
// MaxItems MUST be a non-negative integer. | ||
// An array instance is valid against "maxItems" if its size is less than, or equal to, the value of this keyword. | ||
type MaxItems int | ||
|
||
// Validate implements the Validator interface for MaxItems | ||
func (m MaxItems) Validate(data interface{}) error { | ||
if arr, ok := data.([]interface{}); ok { | ||
if len(arr) > int(m) { | ||
return fmt.Errorf("%d array items exceeds %d max", len(arr), m) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// MinItems MUST be a non-negative integer. | ||
// An array instance is valid against "minItems" if its size is greater than, or equal to, the value of this keyword. | ||
// Omitting this keyword has the same behavior as a value of 0. | ||
type MinItems int | ||
|
||
// Validate implements the Validator interface for MinItems | ||
func (m MinItems) Validate(data interface{}) error { | ||
if arr, ok := data.([]interface{}); ok { | ||
if len(arr) < int(m) { | ||
return fmt.Errorf("%d array items below %d minimum", len(arr), m) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// UniqueItems requires array instance elements be unique | ||
// If this keyword has boolean value false, the instance validates successfully. If it has | ||
// boolean value true, the instance validates successfully if all of its elements are unique. | ||
// Omitting this keyword has the same behavior as a value of false. | ||
type UniqueItems bool | ||
|
||
// Validate implements the Validator interface for UniqueItems | ||
func (u *UniqueItems) Validate(data interface{}) error { | ||
if arr, ok := data.([]interface{}); ok { | ||
found := []interface{}{} | ||
for _, elem := range arr { | ||
for _, f := range found { | ||
if reflect.DeepEqual(f, elem) { | ||
return fmt.Errorf("arry must be unique: %v", arr) | ||
} | ||
} | ||
found = append(found, elem) | ||
} | ||
} | ||
return nil | ||
} | ||
|
||
// Contains validates that an array instance is valid against "contains" if at | ||
// least one of its elements is valid against the given schema. | ||
type Contains Schema | ||
|
||
// Validate implements the Validator interface for Contains | ||
func (c *Contains) Validate(data interface{}) error { | ||
v := Schema(*c) | ||
if arr, ok := data.([]interface{}); ok { | ||
for _, elem := range arr { | ||
if err := v.Validate(elem); err == nil { | ||
return nil | ||
} | ||
} | ||
return fmt.Errorf("expected %v to contain at least one of: %s", data, c) | ||
} | ||
return nil | ||
} | ||
|
||
// UnmarshalJSON implements the json.Unmarshaler interface for Contains | ||
func (c *Contains) UnmarshalJSON(data []byte) error { | ||
var sch Schema | ||
if err := json.Unmarshal(data, &sch); err != nil { | ||
return err | ||
} | ||
*c = Contains(sch) | ||
return nil | ||
} |
Oops, something went wrong.