Full Code of pandastrike/jsck for AI

master 944aa33bcc30 cached
107 files
145.5 KB
42.2k tokens
1 symbols
1 requests
Download .txt
Repository: pandastrike/jsck
Branch: master
Commit: 944aa33bcc30
Files: 107
Total size: 145.5 KB

Directory structure:
gitextract__sjmg1fx/

├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── benchmarks/
│   ├── benchmark.coffee
│   ├── draft3/
│   │   ├── index.coffee
│   │   ├── medium/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   └── valid_doc.coffee
│   │   ├── trivial/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   └── valid_doc.coffee
│   │   └── validators.coffee
│   ├── draft4/
│   │   ├── complex/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   ├── test.coffee
│   │   │   └── valid_doc.coffee
│   │   ├── index.coffee
│   │   ├── medium/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   └── valid_doc.coffee
│   │   ├── trivial/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   └── valid_doc.coffee
│   │   └── validators.coffee
│   ├── index.coffee
│   ├── results/
│   │   └── all.txt
│   ├── runner.coffee
│   └── statistics.js
├── doc/
│   ├── README.pfm.md
│   ├── benchmarks.md
│   ├── benchmarks.pfm.md
│   ├── tests.md
│   └── tests.pfm.md
├── examples/
│   └── draft4/
│       ├── advanced.coffee
│       └── basic.coffee
├── package.json
├── schemas/
│   ├── draft-03/
│   │   └── schema.json
│   └── draft-04/
│       └── schema.json
├── src/
│   ├── common/
│   │   ├── arrays.coffee
│   │   ├── comparison.coffee
│   │   ├── numeric.coffee
│   │   ├── objects.coffee
│   │   ├── strings.coffee
│   │   └── type.coffee
│   ├── draft3/
│   │   ├── logical.coffee
│   │   ├── numeric.coffee
│   │   ├── objects.coffee
│   │   └── strings.coffee
│   ├── draft3.coffee
│   ├── draft4/
│   │   ├── logical.coffee
│   │   ├── numeric.coffee
│   │   ├── objects.coffee
│   │   ├── strings.coffee
│   │   └── type.coffee
│   ├── draft4.coffee
│   ├── index.coffee
│   ├── uri.coffee
│   ├── util.coffee
│   └── validator.coffee
├── tasks/
│   ├── build/
│   │   ├── benchmarks.coffee
│   │   ├── browser.coffee
│   │   ├── docs.coffee
│   │   ├── index.coffee
│   │   └── javascript.coffee
│   ├── helpers.coffee
│   ├── update/
│   │   ├── index.coffee
│   │   └── submodules.coffee
│   └── watch/
│       ├── docs.coffee
│       └── src.coffee
└── test/
    ├── .gitignore
    ├── draft3/
    │   ├── builtins.coffee
    │   ├── index.coffee
    │   ├── official.coffee
    │   └── unit/
    │       ├── errors.coffee
    │       ├── index.coffee
    │       ├── references.coffee
    │       └── uri_test.coffee
    ├── draft4/
    │   ├── adhoc.coffee
    │   ├── builtins.coffee
    │   ├── index.coffee
    │   ├── invalid/
    │   │   ├── additionalItems.coffee
    │   │   ├── additionalProperties.coffee
    │   │   ├── allOf.coffee
    │   │   ├── anyOf.coffee
    │   │   ├── dependencies.coffee
    │   │   ├── items.coffee
    │   │   ├── not.coffee
    │   │   ├── numbers.coffee
    │   │   ├── oneOf.coffee
    │   │   ├── patternProperties.coffee
    │   │   ├── properties.coffee
    │   │   ├── required.coffee
    │   │   ├── strings.coffee
    │   │   └── type.coffee
    │   ├── invalid.coffee
    │   ├── official.coffee
    │   ├── unit/
    │   │   ├── errors.coffee
    │   │   ├── index.coffee
    │   │   ├── logical.coffee
    │   │   ├── references.coffee
    │   │   └── uri_test.coffee
    │   ├── valid/
    │   │   ├── basic.coffee
    │   │   ├── definitions.coffee
    │   │   └── properties.coffee
    │   └── valid.coffee
    └── index.coffee

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
lib
node_modules
mine
.ruby-gemset
npm-debug.log
*.tgz



================================================
FILE: .gitmodules
================================================
[submodule "test/JSON-Schema-Test-Suite"]
	path = test/JSON-Schema-Test-Suite
	url = git@github.com:json-schema/JSON-Schema-Test-Suite.git


================================================
FILE: LICENSE
================================================
The MIT License (MIT)

Copyright (c) 2013 Matthew King

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.



================================================
FILE: README.md
================================================
# JSON Schema Compiled checK

JSCK is one of the fastest [JSON Schema](http://json-schema.org) validators for Node.js.
It supports JSON Schema drafts
[3][draft3_doc] and
[4][draft4_doc],
with a few caveats (see the [Coverage section](#coverage) below).


## Installation and Usage

Install with NPM:

    npm install --save jsck


Require:

```coffee
JSCK = require "jsck"
```

JSCK can create validators from multiple schemas, but this requires that
each schema be identified with a URI in a top-level "id" field.  In many
cases, only a single schema is needed, and there is no need to uniquely
identify the schema.  This is the easiest way to use JSCK, as it is a
common pattern.


```coffee
# Construct a validator for a schema lacking an "id" declaration

jsck = new JSCK.draft4
  type: "object"
  properties:
    user:
      type: "object"
      required: ["login"]
      properties:
        login:
          type: "string"
          pattern: "^[\\w\\d_]{3,32}$"
        email:
          type: "string"
          format: "email"

console.log "valid document:", jsck.validate
  user:
    login: "matthew"
    email: "matthew@pandastrike.com"

{errors} = jsck.validate
  user:
    login: "matthew"
    email: "pandastrike.com"

console.log "invalid document:", errors

```



To use Draft 3 schemas:

```.coffee
validator = new JSCK.draft3(schema)
```


See these [advanced usage examples](examples/draft4/advanced.coffee) for help
working with multiple schemas.



## Why JSCK?

JSCK is [faster](#benchmarks) than most other JavaScript/CoffeeScript libraries
for validating JSON Schemas because it "compiles" the schemas. That is, JSCK
generates the tree of functions needed to validate a particular schema when you
construct a validator. The schema is thus traversed only during preparation, and
most of the work of interpreting the schema is done at this time, rather than
for every document submitted for validation. This minimizes the work required
during validation, which leads to substantial performance improvements over
non-compiling validators.



## Coverage

### Draft 4

JSCK passes all tests in the canonical
[JSON Schema Test Suite][canonical], except for these items:

* use of `maxLength` and `minLength` with Unicode surrogate pairs.
* `refRemote` (this is an essential feature we do plan to support)
* `ref`
  * remote ref, containing refs itself
* `uniqueItems`
* `optional/zeroTerminatedFloats`


### Draft 3

Currently passing the canonical [test suite][canonical] for draft3 except for
these items:

* `refRemote`
* `ref`
  * remote ref, containing refs itself
* `uniqueItems`
* `optional/zeroTerminatedFloats`

### Managing resolution scope with the "id" attribute

JSCK does not support the full range of scope manipulations suggested by JSON
Schema drafts 3 and 4.  Scope manipulation is a controversial topic, and with
JSCK we have chosen to play it safe, supporting "id" declarations only in cases
that will (probably) not lead to any ambiguity. Specifically, JSCK uses "id"
declarations only in these cases:

* at the top level of a schema, to provide a namespace for schemas not loaded from URIs.
* non-JSON-pointer fragments (`"id": "#user"`), which serve merely as aliases for specific subschemas, and are thus convenient and unambiguous.

For more information on the topic of the "id" attribute and scope manipulation,
see this issue: https://github.com/json-schema/json-schema/issues/77.


## Contributing

To contribute, hack on it, or run the tests:

```shell
git clone git@github.com:pandastrike/jsck.git
cd jsck
coffee tasks/update
npm install
```

### Tests

JSCK uses the official [JSON Schema Test Suite][canonical] as well as some
custom tests. To run all tests for all versions:

    coffee test

See [this document](doc/tests.md) for more information on working with JSCK tests.


## Benchmarks

JSCK has fairly comprehensive benchmarks which show it to be one of the very
fastest JSON Schema validators available for Node.js. Pull requests welcome, of
course.

Because performance varies (at very least) based on the complexity
of the schema being validated, we run benchmarks against several different
schemas, ranging from quite simple to moderately complex.

For JSON Schema Draft4, we run benchmarks against JSCK, tv4, jayschema,
z-schema, and other validators.  On the
[trivial schema](benchmarks/draft4/trivial/schema.coffee),
our benchmarks produce this relative performance for these validators
(lower is better):

```coffee
ajv : 1
jsen : 2.9
is-my-json-valid : 4.4
Themis (minimal) : 5.2
Themis : 5.3
JSCK : 34.2
z-schema : 48.3
tv4 : 54.4
jayschema : 2507.4
```


For the schema of [medium complexity](benchmarks/draft4/medium/schema.coffee),
our benchmarks produce this relative performance for the tested validators
(lower is better):

```coffee
ajv : 1
is-my-json-valid : 2.8
jsen : 3.0
Themis (minimal) : 11.1
Themis : 11.6
JSCK : 22.0
tv4 : 43.4
z-schema : 46.0
jayschema : 2319.4
```

For the schema of [higher complexity](benchmarks/draft4/complex/schema.coffee),
our benchmarks produce this relative performance for the tested validators
(lower is better):

```coffee
ajv : 1
is-my-json-valid : 1.23
jsen : 1.31
Themis (minimal) : 1.7
Themis : 1.8
JSCK : 4.8
z-schema : 17.2
tv4 : 27.0
jayschema : 1215.1
```

As the complexity of the schema increases, the performance benefits of the
compilation model become more evident.


See [this document](doc/benchmarks.md) for detailed results and information on
running and creating benchmarks.



[draft3_doc]:http://tools.ietf.org/html/draft-zyp-json-schema-03
[draft3_impl]:https://github.com/json-schema/json-schema/tree/master/draft-03
[draft4_doc]:http://tools.ietf.org/html/draft-zyp-json-schema-04
[canonical]:https://github.com/json-schema/JSON-Schema-Test-Suite


================================================
FILE: benchmarks/benchmark.coffee
================================================
microtime = require "microtime"
require "./statistics"

module.exports = class Benchmark

  @compare: (benchmarks, options) ->
    out = {}
    for benchmark in benchmarks
      out[benchmark.name] = benchmark.run(options)
    out

  constructor: (@name, callback) ->
    callback(@)

  setup: (@_setup) ->

  measure: (@_measure) ->

  run: ({samples, warmup}) ->
    console.error "  #{@name}"
    results = []
    subject = @_setup()

    if warmup
      process.stderr.write "  Warming up: "
      for i in [1..warmup]
        @_measure(subject)
        process.stderr.write "."
      process.stderr.write("\n")

    process.stderr.write "  Iterations: "
    for i in [1..samples]
      t0 = microtime.now()
      @_measure(subject)
      t1 = microtime.now()
      results.push (t1 - t0) / 1000
      process.stderr.write "."
    console.error("\n")
    results




================================================
FILE: benchmarks/draft3/index.coffee
================================================
console.log "## Benchmarks for Draft 3"
console.log

require "./trivial/"
require "./medium/"


================================================
FILE: benchmarks/draft3/medium/index.coffee
================================================
validators = require "../validators"
{benchmark} = require("../../runner")(validators)

benchmark {
  name: "Configuration"
  repeats: 128
  schema: require "./schema"
  document: require "./valid_doc"
}





================================================
FILE: benchmarks/draft3/medium/schema.coffee
================================================
module.exports =
  description: "A moderately complex schema with some nesting and value constraints"
  type: "object"
  additionalProperties: false
  properties:

    api_server:
      description: "Settings for the HTTP API server"
      type: "object"
      additionalProperties: false
      required: true
      properties:
        url:
          type: "string"
          format: "uri"
          required: true
        host:
          type: "string"
          required: true
        port:
          type: "integer"
          minimum: 1000
          required: true

    transport:
      description: "Settings for the Redis tranport"
      additionalProperties: false
      required: true
      properties:
        server:
          type: "string"
          required: true
        options:
          type: "object"
        queues:
          properties:
            blocking_timeout:
              type: "integer"
              minimum: 0

    storage:
      description: "Settings for the PostgreSQL storage"
      required: true
      properties:
        server:
          type: "string"
          required: true
        database:
          type: "string"
          required: true
        user:
          type: "string"
          required: true
        options:
          type: "object"

    chain:
      description: "Settings for the Chain.com client"
      required: true
      properties:
        api_key_id:
          type: "string"
          required: true
        api_key_secret:
          type: "string"
          required: true



================================================
FILE: benchmarks/draft3/medium/valid_doc.coffee
================================================
module.exports =
  api_server:
    url: "http://example.com:8998"
    host: "example.com"
    port: 8998

  transport:
    server: "127.0.0.1:6381"
    queues:
      blocking_timeout: 0

  storage:
    server: "127.0.0.1:5432"
    database: "thingy-test"
    user: "thingy-test"
    password: "password"

  chain:
    api_key_id: "cafebabe"
    api_key_secret: "babecafe"




================================================
FILE: benchmarks/draft3/trivial/index.coffee
================================================
validators = require "../validators"
{benchmark} = require("../../runner")(validators)

benchmark {
  name: "Event"
  repeats: 512
  schema: require "./schema"
  document: require "./valid_doc"
}



================================================
FILE: benchmarks/draft3/trivial/schema.coffee
================================================
module.exports =
  description: "A simple schema, exercising very few attributes"
  type: "object"
  additionalProperties: false
  properties:
    origin:
      required: true
      type: "string"
    name:
      type: "string"
      required: true
    tags:
      type: "array"
      items: {type: "string"}
    timestamp:
      type: "integer"
    data: { type: "object" }



================================================
FILE: benchmarks/draft3/trivial/valid_doc.coffee
================================================
module.exports =
  origin: "monkey"
  name: "shines"
  tags: ["in", "the", "closet"]
  timestamp: Date.now()
  data:
    uno: 1
    dos: 2



================================================
FILE: benchmarks/draft3/validators.coffee
================================================
module.exports =

  "JSCK":
    setup: (schema) ->
      JSCK = require "../../src/draft3"
      new JSCK(schema)
    validate: ({validator, schema, document}) ->
      validator.validate(document)
    error: (result) ->
      if result.valid == true
        false
      else
        result.errors


  "amanda":
    setup: (schema) ->
      amanda = require "amanda"
    validate: ({validator, schema, document}) ->
      result = null
      validator.validate document, schema, (error) ->
        result = error
      result
    error: (result) ->
      result || false


  "JSV":
    setup: (schema) ->
      JSV = require("JSV").JSV
      jsv = JSV.createEnvironment("json-schema-draft-03")
      jsv.createSchema(schema)
    validate: ({validator, schema, document}) ->
      validator.validate(document)
    error: (result) ->
      if result.errors.length == 0
        false
      else
        result.errors


  "json-gate":
    setup: (schema) ->
      jsonGateCreateSchema = require("json-gate").createSchema
      jsonGateCreateSchema(schema)
    validate: ({validator, schema, document}) ->
      try
        validator.validate(document)
      catch e
        e
    error: (result) ->
      result || false




================================================
FILE: benchmarks/draft4/complex/index.coffee
================================================
validators = require "../validators"
{benchmark} = require("../../runner")(validators)

benchmark {
  name: "Transaction"
  repeats: 64
  schema: require "./schema"
  document: require "./valid_doc"
}




================================================
FILE: benchmarks/draft4/complex/schema.coffee
================================================

module.exports =
  type: "array"
  items: {$ref: "#transaction"}
  minItems: 1

  definitions:

    base58:
      id: "#base58"
      # https://en.bitcoin.it/wiki/Base58Check_encoding
      type: "string"
      pattern: "^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$"

    hex:
      id: "#hex"
      type: "string"
      pattern: "^[0123456789A-Fa-f]+$"

    tx_id:
      id: "#tx_id"
      allOf: [
        {$ref: "#hex"}
        {
          minLength: 64
          maxLength: 64
        }
      ]

    address:
      id: "#address"
      allOf: [
        {$ref: "#base58"}
        {
          minLength: 34
          maxLength: 34
        }
      ]

    signature:
      id: "#signature"
      allOf: [
        {$ref: "#hex"}
        {
          minLength: 128
          maxLength: 128
        }
      ]


    transaction:
      id: "#transaction"
      additionalProperties: false
      required: ["metadata", "hash", "inputs", "outputs"]
      properties:

        metadata:
          type: "object"
          required: ["amount", "fee"]
          properties:
            amount:
              type: "integer"
            fee:
              type: "integer"
              multipleOf: 10000
            status:
              type: "string"
              enum: ["unsigned", "unconfirmed", "confirmed", "invalid"]
            confirmations:
              type: "integer"
              minimum: 0
            block_time:
              type: "integer"

        version: {type: "integer"}
        lock_time: {type: "integer"}
        hash: {$ref: "#tx_id"}
        inputs:
          type: "array"
          items: {$ref: "#input"}
          minItems: 1
        outputs:
          type: "array"
          items: {$ref: "#output"}
          minItems: 1



    input:
      id: "#input"
      type: "object"
      additionalProperties: false
      required: ["index", "output", "script_sig"]
      properties:
        index:
          type: "integer"
          minimum: 0
        output: {$ref: "#output"}
        sig_hash: {$ref: "#hex"}
        script_sig: {$ref: "#hex"}
        signatures:
          type: "object"
          description: "A dictionary of signatures.  Keys represent keypair names"
          minProperties: 1
          maxProperties: 3
          additionalProperties: {$ref: "#signature"}


    output:
      id: "#output"
      type: "object"
      additionalProperties: false
      required: ["hash", "index", "value", "script"]
      properties:
        hash: {$ref: "#tx_id"}
        index:
          type: "integer"
          minimum: 0
        value:
          type: "integer"
        script:
          type: "object"
          properties:
            type:
              type: "string"
              enum: ["standard", "p2sh"]
            asm:
              type: "string"
        address: {$ref: "#address"}
        metadata:
          type: "object"
          dependencies:
            # if a wallet path is given, the metadata must also contain the
            # HDW public seed values.  Use case would be for verifying that
            # a change output is going to a legit address.
            wallet_path: ["public_seeds"]
          properties:
            wallet_path:
              type: "string"
            public_seeds:
              type: "object"
              minProperties: 1
              maxProperties: 3
              additionalProperties:
                anyOf: [
                  {$ref: "#base58"}
                  {$ref: "#hex"}
                ]



================================================
FILE: benchmarks/draft4/complex/test.coffee
================================================

JSCK = require "../../../src/draft4"
schema = require "./schema"
valid_doc = require "./valid_doc"

schema =
  type: "array"
  items: {$ref: "#smurf"}
  minItems: 1

  definitions:

    smurf:
      id: "#smurf"
      type: "object"


valid_doc = [
  {}
]

jsck = new JSCK(schema)
report = jsck.validate(valid_doc)
console.log "JSCK"
console.log JSON.stringify(report, null, 2)

ZSchema = require("z-schema")
validator = new ZSchema()

console.log "ZSchema"
console.log validator.validate(valid_doc, schema)
console.log validator.getLastErrors()

console.log "JSONSchema"
JSONSchema = require('jsonschema').Validator
validator = new JSONSchema()
{errors} = validator.validate(valid_doc, schema)
console.log errors


================================================
FILE: benchmarks/draft4/complex/valid_doc.coffee
================================================
$ = module.exports = []

$.push
  metadata:
    amount: 38043749285
    fee: 2 * 10000
    status: "confirmed"
    confirmations: 73
    block_time: 1415993584376
  version: 1
  lock_time: 0
  hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"

  inputs: [
    index: 0
    script_sig: "3046022100be69797cf5d784412b1258256eb657c191a04893479dfa2ae5c7f2088c7adbe0022100e6b000bd633b286ed1b9bc7682fe753d9fdad61fbe5da2a6e9444198e33a670f01"
    signatures:
      primary: "3046022100be69797cf5d784412b1258256eb657c191a04893479dfa2ae5c7f2088c7adbe0022100e6b000bd633b286ed1b9bc7682fe753d9fdad61fbe5da2a7"
      cosigner: "a2ad5ebf16dadf9d357ef2867cb9b1de682b336db000b6e0012200ebda7c8802f7c5ea2afd97439840a191c756be6528521b214487d5fc79796eb00122064037"
    output:
      hash: "6b040cd7a4676b5c7b11f144e73c1958c177fcd79e934f6be8ce02c8cd12546d"
      index: 1
      value: 38043749285
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG"

  ]

  outputs: [

    {
      hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"
      index: 0
      value: 38042249285
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG"
      address: "1CRZRBwfuwUaVSPJtd6DBuezbm7XPBHLa1"
      metadata:
        type: "change"
        wallet_path: "m/44/0/1/356"
        public_seeds:
          primary: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"
          cosigner: "xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8"

    }

    {

      hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"
      index: 1
      value: 1500000
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 3bc576e6960a9d45201ba5087e39224d0a05a079 OP_EQUALVERIFY OP_CHECKSIG"
      address: "16T3RPZLmxtXQCgWi1S8kef5Ca6jqXhoeT"
    }
  ]

$.push
  metadata:
    amount: 38043749285
    fee: 2 * 10000
    status: "unconfirmed"
    confirmations: 73
    block_time: 1415993584376
  version: 1
  lock_time: 0
  hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"

  inputs: [
    index: 0
    script_sig: "3046022100be69797cf5d784412b1258256eb657c191a04893479dfa2ae5c7f2088c7adbe0022100e6b000bd633b286ed1b9bc7682fe753d9fdad61fbe5da2a6e9444198e33a670f01"
    output:
      hash: "6b040cd7a4676b5c7b11f144e73c1958c177fcd79e934f6be8ce02c8cd12546d"
      index: 1
      value: 38043749285
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG"

  ]

  outputs: [

    {
      hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"
      index: 0
      value: 38042249285
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG"
      address: "1CRZRBwfuwUaVSPJtd6DBuezbm7XPBHLa1"
      metadata:
        type: "change"

    }

    {

      hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"
      index: 1
      value: 1500000
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 3bc576e6960a9d45201ba5087e39224d0a05a079 OP_EQUALVERIFY OP_CHECKSIG"
      address: "16T3RPZLmxtXQCgWi1S8kef5Ca6jqXhoeT"
    }
  ]

$.push
  metadata:
    amount: 38043749285
    fee: 2 * 10000
    status: "unconfirmed"
    confirmations: 73
    block_time: 1415993584376
  version: 1
  lock_time: 0
  hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"

  inputs: [
    index: 0
    script_sig: "3046022100be69797cf5d784412b1258256eb657c191a04893479dfa2ae5c7f2088c7adbe0022100e6b000bd633b286ed1b9bc7682fe753d9fdad61fbe5da2a6e9444198e33a670f01"
    output:
      hash: "6b040cd7a4676b5c7b11f144e73c1958c177fcd79e934f6be8ce02c8cd12546d"
      index: 1
      value: 38043749285
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG"

  ]

  outputs: [

    {
      hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"
      index: 0
      value: 38042249285
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG"
      address: "1CRZRBwfuwUaVSPJtd6DBuezbm7XPBHLa1"
      metadata:
        type: "change"

    }

    {

      hash: "60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471"
      index: 1
      value: 1500000
      script:
        type: "standard"
        asm: "OP_DUP OP_HASH160 3bc576e6960a9d45201ba5087e39224d0a05a079 OP_EQUALVERIFY OP_CHECKSIG"
      address: "16T3RPZLmxtXQCgWi1S8kef5Ca6jqXhoeT"
    }
  ]



================================================
FILE: benchmarks/draft4/index.coffee
================================================
console.log "## Benchmarks for Draft 4"
console.log

require "./trivial/"
require "./medium/"
require "./complex/"



================================================
FILE: benchmarks/draft4/medium/index.coffee
================================================
validators = require "../validators"
{benchmark} = require("../../runner")(validators)

benchmark {
  name: "Configuration"
  repeats: 256
  schema: require "./schema"
  document: require "./valid_doc"
}



================================================
FILE: benchmarks/draft4/medium/schema.coffee
================================================
module.exports =
  description: "A moderately complex schema with some nesting and value constraints"
  type: "object"
  additionalProperties: false
  required: ["api_server", "transport", "storage", "chain"]
  properties:

    api_server:
      description: "Settings for the HTTP API server"
      type: "object"
      additionalProperties: false
      required: ["url", "host", "port"]
      properties:
        url:
          type: "string"
          format: "uri"
        host:
          type: "string"
        port:
          type: "integer"
          minimum: 1000

    transport:
      description: "Settings for the Redis tranport"
      additionalProperties: false
      required: ["server"]
      properties:
        server:
          type: "string"
        options:
          type: "object"
        queues:
          properties:
            blocking_timeout:
              type: "integer"
              minimum: 0

    storage:
      description: "Settings for the PostgreSQL storage"
      required: ["server", "database", "user"]
      properties:
        server:
          type: "string"
        database:
          type: "string"
        user:
          type: "string"
        options:
          type: "object"

    chain:
      description: "Settings for the Chain.com client"
      required: ["api_key_id", "api_key_secret"]
      properties:
        api_key_id:
          type: "string"
        api_key_secret:
          type: "string"



================================================
FILE: benchmarks/draft4/medium/valid_doc.coffee
================================================
module.exports =
  api_server:
    url: "http://example.com:8998"
    host: "example.com"
    port: 8998

  transport:
    server: "127.0.0.1:6381"
    queues:
      blocking_timeout: 0

  storage:
    server: "127.0.0.1:5432"
    database: "thingy-test"
    user: "thingy-test"
    password: "password"

  chain:
    api_key_id: "cafebabe"
    api_key_secret: "babecafe"




================================================
FILE: benchmarks/draft4/trivial/index.coffee
================================================
validators = require "../validators"
{benchmark} = require("../../runner")(validators)

benchmark {
  name: "Event - Valid document"
  repeats: 1024
  schema: require "./schema"
  document: require "./valid_doc"
}



================================================
FILE: benchmarks/draft4/trivial/schema.coffee
================================================
module.exports =
  description: "A simple schema, exercising very few attributes"
  type: "object"
  additionalProperties: false
  required: ["origin", "name", "tags", "timestamp", "data"]
  properties:
    origin:
      type: "string"
    name:
      type: "string"
    tags:
      type: "array"
      items: {type: "string"}
    timestamp:
      type: "integer"
    data: { type: "object" }



================================================
FILE: benchmarks/draft4/trivial/valid_doc.coffee
================================================
module.exports =
  origin: "monkey"
  name: "shines"
  tags: ["in", "the", "closet"]
  timestamp: Date.now()
  data:
    uno: 1
    dos: 2



================================================
FILE: benchmarks/draft4/validators.coffee
================================================
module.exports =

  "JSCK":
    setup: (schema) ->
      JSCK = require "../../src/draft4"
      new JSCK(schema)
    validate: ({validator, schema, document}) ->
      validator.validate(document)
    error: (result) ->
      if result.valid == true
        false
      else
        result.errors

  "ajv":
    setup: (schema) ->
      ajv = require("ajv")()
      ajv.compile(schema)
    validate: ({validator, schema, document}) ->
      validator(document)
    error: (result) ->
      if result == true
        false
      else
        validator.errors

  "tv4":
    setup: (schema) ->
      require("tv4").tv4
    validate: ({validator, schema, document}) ->
      validator.validateResult(document, schema)
    error: (result) ->
      if result.valid == true
        false
      else
        result.error

  "Themis (minimal)":
    setup: (schema) ->
      Themis = require('themis')
      Themis.validator(schema, {
        enable_defaults: false,
        algorithm: 'none',
        errors: { messages: false, validator_value: false, schema: false } })
    validate: ({validator, schema, document}) ->
      validator(document, '0')
    error: (result) ->
      if result.valid == true
        false
      else
        result.errors

  "Themis":
    setup: (schema) ->
      Themis = require('themis')
      Themis.validator(schema)
    validate: ({validator, schema, document}) ->
      validator(document, '0')
    error: (result) ->
      if result.valid == true
        false
      else
        result.errors

  "jayschema":
    setup: (schema) ->
      JaySchema = require("jayschema")
      new JaySchema()
    validate: ({validator, schema, document}) ->
      validator.validate(document, schema)
    error: (result) ->
      if result.length == 0
        false
      else
        result

  "is-my-json-valid":
    setup: (schema) ->
      require("is-my-json-valid")(schema)
    validate: ({validator, schema, document}) ->
      validator(document)
    error: (result) ->
      if result == true
        false
      else
        validator.errors


  # Putting z-schema last because it appears to be affecting other libs'
  # performance if run first.
  "z-schema":
    setup: (schema) ->
      z = require("z-schema")
      validator = new z()
      url = "http://json-schema.org/draft-04/schema"
      # don't actually download the draft, because GitHub Pages might be down.
      actualDraft = require("fs").readFileSync("./test/json-schema/draft-04/schema", "utf8")
      validator.setRemoteReference(url, JSON.parse(actualDraft))
      validator

    validate: ({validator, schema, document}) ->
      valid = validator.validate(document, schema)
      if valid == false
        validator.getLastErrors()


    error: (result) ->
      result || false

  "jsen":
    setup: (schema) ->
      require("jsen")(schema)
    validate: ({validator, schema, document}) ->
      validator(document)
    error: (result) ->
      if result == true
        false
      else
        validator.errors


================================================
FILE: benchmarks/index.coffee
================================================
require "./draft3/"
require "./draft4/"



================================================
FILE: benchmarks/results/all.txt
================================================
## Benchmarks for Draft 3

Schema: 'Event'.  A simple schema, exercising very few attributes
Sample size: 64
Validations per sample: 512

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  amanda
  Warming up: ................................
  Iterations: ................................................................

  JSV
  Warming up: ................................
  Iterations: ................................................................

  json-gate
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 193.025    max: 202.692    min: 175.945 

  amanda: validations/millisecond
  median: 4.258    max: 4.608    min: 3.778 

  JSV: validations/millisecond
  median: 2.685    max: 2.748    min: 2.43 

  json-gate: validations/millisecond
  median: 82.514    max: 86.036    min: 48.234 

Relative speeds:
JSCK : 1.000
json-gate : 2.339
amanda : 45.337
JSV : 71.896


Schema: 'Configuration'.  A moderately complex schema with some nesting and value constraints
Sample size: 64
Validations per sample: 128

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  amanda
  Warming up: ................................
  Iterations: ................................................................

  JSV
  Warming up: ................................
  Iterations: ................................................................

  json-gate
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 108.936    max: 109.966    min: 85.964 

  amanda: validations/millisecond
  median: 3.788    max: 5.651    min: 2.371 

  JSV: validations/millisecond
  median: 1.344    max: 1.359    min: 1.255 

  json-gate: validations/millisecond
  median: 44.176    max: 45.845    min: 41.803 

Relative speeds:
JSCK : 1.000
json-gate : 2.466
amanda : 28.760
JSV : 81.025

## Benchmarks for Draft 4

Schema: 'Event - Valid document'.  A simple schema, exercising very few attributes
Sample size: 64
Validations per sample: 1024

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  tv4
  Warming up: ................................
  Iterations: ................................................................

  z-schema
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 186.81    max: 191.617    min: 138.716 

  tv4: validations/millisecond
  median: 54.377    max: 55.907    min: 46.942 

  z-schema: validations/millisecond
  median: 93.657    max: 93.979    min: 89.44 

Relative speeds:
JSCK : 1.000
z-schema : 1.995
tv4 : 3.435


Schema: 'Configuration'.  A moderately complex schema with some nesting and value constraints
Sample size: 64
Validations per sample: 256

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  tv4
  Warming up: ................................
  Iterations: ................................................................

  z-schema
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 118.573    max: 119.07    min: 105.22 

  tv4: validations/millisecond
  median: 19.608    max: 20.389    min: 16.505 

  z-schema: validations/millisecond
  median: 40.606    max: 40.934    min: 34.934 

Relative speeds:
JSCK : 1.000
z-schema : 2.920
tv4 : 6.047


Schema: 'Transaction'.  
Sample size: 64
Validations per sample: 64

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  tv4
  Warming up: ................................
  Iterations: ................................................................

  z-schema
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 12.814    max: 14.873    min: 6.984 

  tv4: validations/millisecond
  median: 1.946    max: 1.965    min: 1.832 

  z-schema: validations/millisecond
  median: 3.768    max: 3.836    min: 3.297 

Relative speeds:
JSCK : 1.000
z-schema : 3.401
tv4 : 6.583



================================================
FILE: benchmarks/runner.coffee
================================================
# stdlib
util = require "util"

# our simple benchmarking library
Benchmark = require "./benchmark.coffee"
samples = 64

module.exports = (validators) ->

  benchmark: ({name, schema, document, repeats}) ->

    libraries = []

    for library, {setup, validate, error} of validators

      ## preflight to check for incorrect validation errors
      ## Currently disabled because of issues with z-schema.
      #validator = setup(schema)
      #e = error(validate({validator, schema, document}))
      #if e
        #console.log "Aborting because #{library} declared the document invalid:"
        #console.log e
        #process.exit(1)

      do (setup, validate) ->
        libraries.push new Benchmark library, (bm) ->
          bm.setup ->
            setup(schema)
          bm.measure (validator) ->
            for i in [1..repeats]
              validate({validator, schema, document})


    console.log """

      Schema: '#{name}'.  #{schema.description || ''}
      Sample size: #{samples}
      Validations per sample: #{repeats}

    """


    
    results = Benchmark.compare libraries, {samples, warmup: 32}

    console.log()
    x = for name, result of results
      {median, max, min} = result.summarize()

      console.log "  #{name}: validations/millisecond"
      console.log util.format "  median: %d    max: %d    min: %d ",
        (repeats * 1 / median).toFixed(3),
        (repeats * 1 / min).toFixed(3),
        (repeats * 1 / max).toFixed(3)

      console.log()
      [name, median]

    sorted = x.sort (a, b) ->
      a[1] > b[1]

    fastest = sorted[0]
    ftime = fastest[1]

    console.log "Relative speeds:"
    for [name, time] in x
      console.log name, ":", (time / ftime).toFixed(3)
    console.log()



================================================
FILE: benchmarks/statistics.js
================================================
/****************************************************************************************************
JavaScript Math and Statistics Library

@file		pseudoMathStats.js
@version	1.0
@author 	Paul Ellis
@url        http://code.google.com/p/pseudosavant
@copyright 	Copyright 2010, Paul Ellis
@license    BSD
****************************************************************************************************/


/****************************************************************************************************
Calculates the Standard Deviation of an array
****************************************************************************************************/
Array.prototype.stdDev = function ()
{
    // Calculate Mean
    var mean = this.mean();

    var length = this.length;

    // Calculate Variance
    for (var i = 0, sumOfSquares = 0; i < length; i++)
    {
        sumOfSquares += Math.pow(this[i] - mean, 2);
    }
    var stdDev = Math.sqrt(sumOfSquares / length);

    return stdDev;
}


/****************************************************************************************************
Calculates the Variance of an array
****************************************************************************************************/
Array.prototype.variance = function ()
{
    // Calculate Mean
    var mean = this.mean();

    var length = this.length;

    // Calculate Variance
    for (var i = 0, sumOfSquares = 0; i < length; i++)
    {
        sumOfSquares += Math.pow(this[i] - mean, 2);
    }
    var variance = sumOfSquares / length;

    return variance;
}


/****************************************************************************************************
Sums all values in an array
****************************************************************************************************/
Array.prototype.sum = function ()
{
    for (var i = 0, length = this.length, sum = 0; i < length; sum += this[i++]);
    return sum;
}


/****************************************************************************************************
Calculates the arithmetic mean of an array
****************************************************************************************************/
Array.prototype.mean = function ()
{
    for (var i = 0, length = this.length, sum = 0; i < length; sum += this[i++]);
    var mean = sum / length;
    return mean;
}


/****************************************************************************************************
Returns the highest numeric value of an array
****************************************************************************************************/
Array.prototype.max = function ()
{
  return this.reduceRight(function(i,j){if(j<i){return i}else{return j} });
}


/****************************************************************************************************
Returns the lowest numeric value of an array
****************************************************************************************************/
Array.prototype.min = function ()
{
  return this.reduceRight(function(i,j){if(j>i){return i}else{return j} });
}


/****************************************************************************************************
Calculates the median of an array
****************************************************************************************************/
Array.prototype.median = function ()
{
    var length = this.length;

    if (length % 2 == 1) // Odd
    {
        var middle = Math.floor(length / 2);
        var median = this.sortNumber()[middle];
    }
    else // Even
    {
        var middle = length / 2;
        var sorted = this.sortNumber();
        var median = (sorted[middle-1] + sorted[middle]) / 2;
    }
    return median;
}


/****************************************************************************************************
Returns the array sorted ascendingly, or decendingly if sortNumber(true).
****************************************************************************************************/
Array.prototype.sortNumber = function (invert)
{
    if (invert == true) // Decending
    {
      return this.slice().sort(function (a, b) { return a - b }).reverse(); // Using reverse() is faster than b - a.
    }
    else // Ascending, default
    {
      return this.slice().sort(function (a, b) { return a - b });
    }
}


/****************************************************************************************************
Returns an object containing the most common stats for the array.
****************************************************************************************************/
Array.prototype.summarize = function summarize (places) {
  if (!this.length) { return { error: "no values" }; }
  return {
    max: fixedDecimal(this.max(), places),
    median: fixedDecimal(this.median(), places),
    min: fixedDecimal(this.min(), places),
    mean: fixedDecimal(this.mean(), places),
    stdDev: fixedDecimal(this.stdDev(), places),
    sample_size: this.length,
  };
};


var fixedDecimal = function fixedDecimal (num, numOfDec) {
	var pow10s = Math.pow( 10, numOfDec || 0 );
	return ( numOfDec ) ? Math.round( pow10s * num ) / pow10s : num;
};


/****************************************************************************************************
Lower tail quantile for standard normal distribution function.

Written by Alankar Misra (alankar@digitalsutras.com)
Algorithm by Peter John Acklam (pjacklam@online.no, http://home.online.no/~pjacklam)
****************************************************************************************************/
function normsinv(p)
{
    // Coefficients in rational approximations
    var a = new Array(-3.969683028665376e+01, 2.209460984245205e+02,
                      -2.759285104469687e+02, 1.383577518672690e+02,
                      -3.066479806614716e+01, 2.506628277459239e+00);

    var b = new Array(-5.447609879822406e+01, 1.615858368580409e+02,
                      -1.556989798598866e+02, 6.680131188771972e+01,
                      -1.328068155288572e+01);

    var c = new Array(-7.784894002430293e-03, -3.223964580411365e-01,
                      -2.400758277161838e+00, -2.549732539343734e+00,
                      4.374664141464968e+00, 2.938163982698783e+00);

    var d = new Array(7.784695709041462e-03, 3.224671290700398e-01,
                       2.445134137142996e+00, 3.754408661907416e+00);

    // Define break-points.
    var plow = 0.02425;
    var phigh = 1 - plow;

    // Rational approximation for lower region:
    if (p < plow)
    {
        var q = Math.sqrt(-2 * Math.log(p));
        return (((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);
    }

    // Rational approximation for upper region:
    if (phigh < p)
    {
        var q = Math.sqrt(-2 * Math.log(1 - p));
        return -(((((c[0] * q + c[1]) * q + c[2]) * q + c[3]) * q + c[4]) * q + c[5]) / ((((d[0] * q + d[1]) * q + d[2]) * q + d[3]) * q + 1);
    }

    // Rational approximation for central region:
    var q = p - 0.5;
    var r = q * q;
    return (((((a[0] * r + a[1]) * r + a[2]) * r + a[3]) * r + a[4]) * r + a[5]) * q / (((((b[0] * r + b[1]) * r + b[2]) * r + b[3]) * r + b[4]) * r + 1);
}






================================================
FILE: doc/README.pfm.md
================================================
# JSON Schema Compiled checK

JSCK is one of the fastest [JSON Schema](http://json-schema.org) validators for Node.js.
It supports JSON Schema drafts
[3][draft3_doc] and
[4][draft4_doc],
with a few caveats (see the [Coverage section](#coverage) below).


## Installation and Usage

Install with NPM:

    npm install --save jsck


Require:

```coffee
JSCK = require "jsck"
```

JSCK can create validators from multiple schemas, but this requires that
each schema be identified with a URI in a top-level "id" field.  In many
cases, only a single schema is needed, and there is no need to uniquely
identify the schema.  This is the easiest way to use JSCK, as it is a
common pattern.


```examples/draft4/basic.coffee#L3-29```


To use Draft 3 schemas:

```.coffee
validator = new JSCK.draft3(schema)
```


See these [advanced usage examples](examples/draft4/advanced.coffee) for help
working with multiple schemas.



## Why JSCK?

JSCK is [faster](#benchmarks) than most other JavaScript/CoffeeScript libraries
for validating JSON Schemas because it "compiles" the schemas. That is, JSCK
generates the tree of functions needed to validate a particular schema when you
construct a validator. The schema is thus traversed only during preparation, and
most of the work of interpreting the schema is done at this time, rather than
for every document submitted for validation. This minimizes the work required
during validation, which leads to substantial performance improvements over
non-compiling validators.



## Coverage

### Draft 4

JSCK passes all tests in the canonical
[JSON Schema Test Suite][canonical], except for these items:

* use of `maxLength` and `minLength` with Unicode surrogate pairs.
* `refRemote` (this is an essential feature we do plan to support)
* `ref`
  * remote ref, containing refs itself
* `uniqueItems`
* `optional/zeroTerminatedFloats`


### Draft 3

Currently passing the canonical [test suite][canonical] for draft3 except for
these items:

* `refRemote`
* `ref`
  * remote ref, containing refs itself
* `uniqueItems`
* `optional/zeroTerminatedFloats`

### Managing resolution scope with the "id" attribute

JSCK does not support the full range of scope manipulations suggested by JSON
Schema drafts 3 and 4.  Scope manipulation is a controversial topic, and with
JSCK we have chosen to play it safe, supporting "id" declarations only in cases
that will (probably) not lead to any ambiguity. Specifically, JSCK uses "id"
declarations only in these cases:

* at the top level of a schema, to provide a namespace for schemas not loaded from URIs.
* non-JSON-pointer fragments (`"id": "#user"`), which serve merely as aliases for specific subschemas, and are thus convenient and unambiguous.

For more information on the topic of the "id" attribute and scope manipulation,
see this issue: https://github.com/json-schema/json-schema/issues/77.


## Contributing

To contribute, hack on it, or run the tests:

```shell
git clone git@github.com:pandastrike/jsck.git
cd jsck
coffee tasks/update
npm install
```

### Tests

JSCK uses the official [JSON Schema Test Suite][canonical] as well as some
custom tests. To run all tests for all versions:

    coffee test

See [this document](doc/tests.md) for more information on working with JSCK tests.


## Benchmarks

JSCK has fairly comprehensive benchmarks which show it to be one of the very
fastest JSON Schema validators available for Node.js. Pull requests welcome, of
course.

Because performance varies (at very least) based on the complexity
of the schema being validated, we run benchmarks against several different
schemas, ranging from quite simple to moderately complex.

For JSON Schema Draft4, we run benchmarks against JSCK, tv4, jayschema,
z-schema, and other validators.  On the
[trivial schema](benchmarks/draft4/trivial/schema.coffee),
our benchmarks produce this relative performance for these validators
(lower is better):

```coffee
ajv : 1
jsen : 2.9
is-my-json-valid : 4.4
Themis (minimal) : 5.2
Themis : 5.3
JSCK : 34.2
z-schema : 48.3
tv4 : 54.4
jayschema : 2507.4
```


For the schema of [medium complexity](benchmarks/draft4/medium/schema.coffee),
our benchmarks produce this relative performance for the tested validators
(lower is better):

```coffee
ajv : 1
is-my-json-valid : 2.8
jsen : 3.0
Themis (minimal) : 11.1
Themis : 11.6
JSCK : 22.0
tv4 : 43.4
z-schema : 46.0
jayschema : 2319.4
```

For the schema of [higher complexity](benchmarks/draft4/complex/schema.coffee),
our benchmarks produce this relative performance for the tested validators
(lower is better):

```coffee
ajv : 1
is-my-json-valid : 1.23
jsen : 1.31
Themis (minimal) : 1.7
Themis : 1.8
JSCK : 4.8
z-schema : 17.2
tv4 : 27.0
jayschema : 1215.1
```

As the complexity of the schema increases, the performance benefits of the
compilation model become more evident.


See [this document](doc/benchmarks.md) for detailed results and information on
running and creating benchmarks.



[draft3_doc]:http://tools.ietf.org/html/draft-zyp-json-schema-03
[draft3_impl]:https://github.com/json-schema/json-schema/tree/master/draft-03
[draft4_doc]:http://tools.ietf.org/html/draft-zyp-json-schema-04
[canonical]:https://github.com/json-schema/JSON-Schema-Test-Suite




================================================
FILE: doc/benchmarks.md
================================================
# Benchmarks

JSCK has fairly comprehensive benchmarks which show it to be one of the fastest
JSON Schema validators available for Node.js.

To run the benchmarks immediately after you `git clone` the repo:

```shell
git clone git@github.com:pandastrike/jsck.git && \
git submodule update --init && \
npm install && \
coffee benchmarks/
```

Benchmarking harness and content lives in `benchmarks`, with separate
directories for each draft.  For each draft there are a number of different
benchmarks (contained in subdirectories) that can be run in whole or in part.
This is the basic directory structure:

    benchmarks/
      draft3/
      draft4/
        complex/
        medium/
        trivial/
        index.coffee
        validators.coffee

## Adding Additional Validators

The validators are defined in `validators.coffee`.  Here's an example from
the Draft 4 benchmarks:

```coffee
    setup: (schema) ->
      ajv = require("ajv")()
      ajv.compile(schema)
    validate: ({validator, schema, document}) ->
      validator(document)
    error: (result) ->
      if result == true
        false
      else
        validator.errors

```


The `setup` function returns a validator object usable by the `validate`
function.  The `validate` function performs the actual validation work that
is measured in benchmarking.  The `error` function is used only in the
preflight stage of benchmarking to determine whether the result of the
`validate` function contains any errors. This is useful in making sure that all
the validators are actually operating correctly and thus being compared fairly.



## Adding New Benchmarks

Each individual benchmark consists of a directory containing a schema, a valid
document, and an `index.coffee` file which runs the benchmark.

```coffee
validators = require "../validators"
{benchmark} = require("../../runner")(validators)

benchmark {
  name: "Event - Valid document"
  repeats: 1024
  schema: require "./schema"
  document: require "./valid_doc"
}

```


The "repeats" parameter determines how many times the document will be
validated during a single measurement sample.





## Running Benchmarks

You can run very specific benchmarks, like the medium-complexity benchmarks for draft 3 only, like so:

`coffee benchmarks/draft3/medium`

You can run all benchmarks for a specific JSON Schema draft:

`coffee benchmarks/draft4`

Or, to run all benchmarks:

`coffee benchmarks/`

You should then see something like this:

```txt
## Benchmarks for Draft 3

Schema: 'Event'.  A simple schema, exercising very few attributes
Sample size: 64
Validations per sample: 512

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  amanda
  Warming up: ................................
  Iterations: ................................................................

  JSV
  Warming up: ................................
  Iterations: ................................................................

  json-gate
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 193.025    max: 202.692    min: 175.945 

  amanda: validations/millisecond
  median: 4.258    max: 4.608    min: 3.778 

  JSV: validations/millisecond
  median: 2.685    max: 2.748    min: 2.43 

  json-gate: validations/millisecond
  median: 82.514    max: 86.036    min: 48.234 

Relative speeds:
JSCK : 1.000
json-gate : 2.339
amanda : 45.337
JSV : 71.896


Schema: 'Configuration'.  A moderately complex schema with some nesting and value constraints
Sample size: 64
Validations per sample: 128

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  amanda
  Warming up: ................................
  Iterations: ................................................................

  JSV
  Warming up: ................................
  Iterations: ................................................................

  json-gate
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 108.936    max: 109.966    min: 85.964 

  amanda: validations/millisecond
  median: 3.788    max: 5.651    min: 2.371 

  JSV: validations/millisecond
  median: 1.344    max: 1.359    min: 1.255 

  json-gate: validations/millisecond
  median: 44.176    max: 45.845    min: 41.803 

Relative speeds:
JSCK : 1.000
json-gate : 2.466
amanda : 28.760
JSV : 81.025

## Benchmarks for Draft 4

Schema: 'Event - Valid document'.  A simple schema, exercising very few attributes
Sample size: 64
Validations per sample: 1024

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  tv4
  Warming up: ................................
  Iterations: ................................................................

  z-schema
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 186.81    max: 191.617    min: 138.716 

  tv4: validations/millisecond
  median: 54.377    max: 55.907    min: 46.942 

  z-schema: validations/millisecond
  median: 93.657    max: 93.979    min: 89.44 

Relative speeds:
JSCK : 1.000
z-schema : 1.995
tv4 : 3.435


Schema: 'Configuration'.  A moderately complex schema with some nesting and value constraints
Sample size: 64
Validations per sample: 256

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  tv4
  Warming up: ................................
  Iterations: ................................................................

  z-schema
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 118.573    max: 119.07    min: 105.22 

  tv4: validations/millisecond
  median: 19.608    max: 20.389    min: 16.505 

  z-schema: validations/millisecond
  median: 40.606    max: 40.934    min: 34.934 

Relative speeds:
JSCK : 1.000
z-schema : 2.920
tv4 : 6.047


Schema: 'Transaction'.  
Sample size: 64
Validations per sample: 64

  JSCK
  Warming up: ................................
  Iterations: ................................................................

  tv4
  Warming up: ................................
  Iterations: ................................................................

  z-schema
  Warming up: ................................
  Iterations: ................................................................


  JSCK: validations/millisecond
  median: 12.814    max: 14.873    min: 6.984 

  tv4: validations/millisecond
  median: 1.946    max: 1.965    min: 1.832 

  z-schema: validations/millisecond
  median: 3.768    max: 3.836    min: 3.297 

Relative speeds:
JSCK : 1.000
z-schema : 3.401
tv4 : 6.583

```



================================================
FILE: doc/benchmarks.pfm.md
================================================
# Benchmarks

JSCK has fairly comprehensive benchmarks which show it to be one of the fastest
JSON Schema validators available for Node.js.

To run the benchmarks immediately after you `git clone` the repo:

```shell
git clone git@github.com:pandastrike/jsck.git && \
git submodule update --init && \
npm install && \
coffee benchmarks/
```

Benchmarking harness and content lives in `benchmarks`, with separate
directories for each draft.  For each draft there are a number of different
benchmarks (contained in subdirectories) that can be run in whole or in part.
This is the basic directory structure:

    benchmarks/
      draft3/
      draft4/
        complex/
        medium/
        trivial/
        index.coffee
        validators.coffee

## Adding Additional Validators

The validators are defined in `validators.coffee`.  Here's an example from
the Draft 4 benchmarks:

```benchmarks/draft4/validators.coffee#L16-25```

The `setup` function returns a validator object usable by the `validate`
function.  The `validate` function performs the actual validation work that
is measured in benchmarking.  The `error` function is used only in the
preflight stage of benchmarking to determine whether the result of the
`validate` function contains any errors. This is useful in making sure that all
the validators are actually operating correctly and thus being compared fairly.



## Adding New Benchmarks

Each individual benchmark consists of a directory containing a schema, a valid
document, and an `index.coffee` file which runs the benchmark.

```benchmarks/draft4/trivial/index.coffee```

The "repeats" parameter determines how many times the document will be
validated during a single measurement sample.





## Running Benchmarks

You can run very specific benchmarks, like the medium-complexity benchmarks for draft 3 only, like so:

`coffee benchmarks/draft3/medium`

You can run all benchmarks for a specific JSON Schema draft:

`coffee benchmarks/draft4`

Or, to run all benchmarks:

`coffee benchmarks/`

You should then see something like this:

```benchmarks/results/all.txt```



================================================
FILE: doc/tests.md
================================================
# Testing JSCK

JSCK is developed against several sets of tests:

* the official [JSON Schema Test Suite][canonical]
* tests for schemas that should be considered invalid
* tests for schemas that should be considered valid
* unit tests particular to JSCK

To run all tests for all versions of JSON Schema:

    coffee test


## The official test suite

The good folks behind JSON Schema have provided a language-agnostic test suite,
composed of JSON documents that define schemas and input objects that should be
judged as valid or invalid for each schema. The README for the test suite
provides a
[good overview of the structure](https://github.com/json-schema/JSON-Schema-Test-Suite#structure-of-a-test)
of the JSON test files.

JSCK includes the official test suite as a git submodule at
`test/JSON-Schema-Test-Suite`. Running `coffee tasks/update` will initialize
and/or update the submodule.


As a concrete example, here is the first case for the "items" attribute in Draft 4:

```json
    {
        "description": "a schema given for items",
        "schema": {
            "items": {"type": "integer"}
        },
        "tests": [
            {
                "description": "valid items",
                "data": [ 1, 2, 3 ],
                "valid": true
            },
            {
                "description": "wrong type of items",
                "data": [1, "x"],
                "valid": false
            },
            {
                "description": "ignores non-arrays",
                "data": {"foo" : "bar"},
                "valid": true
            }
        ]
    },

```


Breaking this down

* the case described is for when the value of "items" is a schema
* the schema under consideration does not declare a type for the input data
* if the input data is an array, all of its items must be integers

There are three tests for this case:

* valid input data
* invalid input data
* irrelevant input data


### Running the official tests

To run the official tests for a specific draft:

    coffee test/draft4

It can be difficult to troubleshoot bugs when running hundreds of tests.
To run only the tests for a specific attribute (in this case,
"patternProperties"):

    coffee test/draft4 patternProperties

And to run only a certain test for that attribute, append the (zero-based)
index of the test:

    coffee test/draft4 patternProperties 3


### Ignoring specific tests

The test harness provided by JSCK allows you to ignore specific tests from
the official suite. Here is how we define the ignores for Draft 4:

```coffee
#cmd = "node_modules/.bin/nserver -p 5725 -d test/JSON-Schema-Test-Suite/remotes"
#proc = shell.exec cmd, (code, output) ->
#
#Testify = require "testify"
#Testify.once "done", ->
  #console.log "Shutting down the 'remotes' test server"
  #proc.kill("SIGTERM")

[_node, _script, attribute, test_number] = process.argv

suite {
  attribute
  test_number

  version: "draft4"

  validate: (schema, document) ->
    v = new draft4(schema)
    v.validate(document)


  ignores:
    # Doubtful value for the majority of use cases.
    # https://github.com/pandastrike/jsck/issues/42
    minLength: [
      "one supplementary Unicode code point is not long enough"

```



## Invalid Schemas

A tool for working with JSON Schemas must be able to reject invalid schemas.
The official test suite (at this time) only provides tests data for validating
documents against correctly formed schemas, so JSCK introduces a similar
test format for checking the invalidity of schema definitions.  These tests
are defined as CoffeeScript files in `test/draft{3,4}/invalid/`.  Though we
use CoffeeScript for easy maintenance, the actual content could be represented
as JSON, or YAML, or any other data format.

Here's an example of an invalidity test for the "type" attribute:

```coffee
    {
      description: "string values must be one of the primitive types"
      schemas: [
        type: "bogus"
      ]
    }

```


All of the objects in the `schemas` array are invalid schemas that should
cause JSCK (or any other validation library) to reject the schema.

One of the benefits of using CoffeeScript (or JavaScript, or any other
language) to generate the test content is the ability to use helper functions
to create multiple test schemas:

```coffee
    {
      description: "value MUST be either a string or an array"
      schemas: for value in json_types.except("string", "array")
        {type: value}
    }

```


In the above example, `schemas` is defined using a list comprehension and a 
helper function that generates an invalid schema for all of the primitive JSON
Schema types except those explicitly named.

To run only the invalidity tests:

    coffee test/draft4/invalid.coffee

## Valid Schemas

It is also valuable to have tests for the acceptance of valid schemas that
buggy or overzealous libraries might reject.  JSCK's schema validity tests
are defined as CoffeeScript files in `test/draft{3,4}/valid/`.

As an example, the names of JSON Schema attributes ("properties", "type",
"required", etc.) are not reserved terms.  It is legal to use these strings
as the names of object properties.  During one round of refactoring, JSCK
began rejecting schemas that used JSON Schema attribute names as properties.

To prevent this, a validity test was added:

```coffee

      required:
        type: "object"
        properties:
          required:
            type: "boolean"

      id:
        type: "object"
        properties:
          id:

```



To run only the validity tests:

    coffee test/draft4/valid.coffee


## Unit tests

JSCK also uses a few unit tests to assist in developing and troubleshooting
some of the internal functions, such as scope resolution and URI construction.

To run only the unit tests for a particular draft version:

    coffee test/draft4/unit


[canonical]:https://github.com/json-schema/JSON-Schema-Test-Suite


================================================
FILE: doc/tests.pfm.md
================================================
# Testing JSCK

JSCK is developed against several sets of tests:

* the official [JSON Schema Test Suite][canonical]
* tests for schemas that should be considered invalid
* tests for schemas that should be considered valid
* unit tests particular to JSCK

To run all tests for all versions of JSON Schema:

    coffee test


## The official test suite

The good folks behind JSON Schema have provided a language-agnostic test suite,
composed of JSON documents that define schemas and input objects that should be
judged as valid or invalid for each schema. The README for the test suite
provides a
[good overview of the structure](https://github.com/json-schema/JSON-Schema-Test-Suite#structure-of-a-test)
of the JSON test files.

JSCK includes the official test suite as a git submodule at
`test/JSON-Schema-Test-Suite`. Running `coffee tasks/update` will initialize
and/or update the submodule.


As a concrete example, here is the first case for the "items" attribute in Draft 4:

```test/JSON-Schema-Test-Suite/tests/draft4/items.json#L2-24```

Breaking this down

* the case described is for when the value of "items" is a schema
* the schema under consideration does not declare a type for the input data
* if the input data is an array, all of its items must be integers

There are three tests for this case:

* valid input data
* invalid input data
* irrelevant input data


### Running the official tests

To run the official tests for a specific draft:

    coffee test/draft4

It can be difficult to troubleshoot bugs when running hundreds of tests.
To run only the tests for a specific attribute (in this case,
"patternProperties"):

    coffee test/draft4 patternProperties

And to run only a certain test for that attribute, append the (zero-based)
index of the test:

    coffee test/draft4 patternProperties 3


### Ignoring specific tests

The test harness provided by JSCK allows you to ignore specific tests from
the official suite. Here is how we define the ignores for Draft 4:

```test/draft4/official.coffee#L7-32```


## Invalid Schemas

A tool for working with JSON Schemas must be able to reject invalid schemas.
The official test suite (at this time) only provides tests data for validating
documents against correctly formed schemas, so JSCK introduces a similar
test format for checking the invalidity of schema definitions.  These tests
are defined as CoffeeScript files in `test/draft{3,4}/invalid/`.  Though we
use CoffeeScript for easy maintenance, the actual content could be represented
as JSON, or YAML, or any other data format.

Here's an example of an invalidity test for the "type" attribute:

```test/draft4/invalid/type.coffee#L24-29```

All of the objects in the `schemas` array are invalid schemas that should
cause JSCK (or any other validation library) to reject the schema.

One of the benefits of using CoffeeScript (or JavaScript, or any other
language) to generate the test content is the ability to use helper functions
to create multiple test schemas:

```test/draft4/invalid/type.coffee#L5-9```

In the above example, `schemas` is defined using a list comprehension and a 
helper function that generates an invalid schema for all of the primitive JSON
Schema types except those explicitly named.

To run only the invalidity tests:

    coffee test/draft4/invalid.coffee

## Valid Schemas

It is also valuable to have tests for the acceptance of valid schemas that
buggy or overzealous libraries might reject.  JSCK's schema validity tests
are defined as CoffeeScript files in `test/draft{3,4}/valid/`.

As an example, the names of JSON Schema attributes ("properties", "type",
"required", etc.) are not reserved terms.  It is legal to use these strings
as the names of object properties.  During one round of refactoring, JSCK
began rejecting schemas that used JSON Schema attribute names as properties.

To prevent this, a validity test was added:

```test/draft4/valid/properties.coffee#L5-15```


To run only the validity tests:

    coffee test/draft4/valid.coffee


## Unit tests

JSCK also uses a few unit tests to assist in developing and troubleshooting
some of the internal functions, such as scope resolution and URI construction.

To run only the unit tests for a particular draft version:

    coffee test/draft4/unit


[canonical]:https://github.com/json-schema/JSON-Schema-Test-Suite





================================================
FILE: examples/draft4/advanced.coffee
================================================
JSCK = require("../../src/index")

# using a schema that declares a URI with "id"

jsck = new JSCK.draft4
  $schema: "http://json-schema.org/draft-04/schema#"
  id: "urn:jsck.examples.advanced#"
  definitions:
    user:
      type: "object"
      required: ["login"]
      properties:
        login:
          type: "string"
          pattern: "^[\\w\\d_]{3,32}$"
        email:
          type: "string"

validator = jsck.validator(uri: "urn:jsck.examples.advanced#")
{valid} = validator.validate
  login: "automatthew"
  email: "automatthew@mailinator.com"

console.log "Schema with id:", valid


# validating against a subschema using a JSON Pointer

validator = jsck.validator "urn:jsck.examples.advanced#/definitions/user"
{valid} = validator.validate
  login: "automatthew"
  email: "automatthew@mailinator.com"

console.log "Schema identified by JSON Pointer:", valid


# Adding multiple schemas
#
# You can instantiate JSCK with multiple schemas or add them later
# 
# Instantiation:
# validator = new JSCK(schema1, schema2, schema3)

jsck.add
  id: "urn:jsck.examples.user_list#"
  type: "array"
  items: {$ref: "urn:jsck.examples.advanced#/definitions/user"}

validator = jsck.validator "urn:jsck.examples.user_list#"
{valid} = validator.validate [
  { login: "dyoder" }
  { login: "automatthew" }
]

console.log "Multiple schemas:", valid




================================================
FILE: examples/draft4/basic.coffee
================================================
JSCK = require("../../src/index")

# Construct a validator for a schema lacking an "id" declaration

jsck = new JSCK.draft4
  type: "object"
  properties:
    user:
      type: "object"
      required: ["login"]
      properties:
        login:
          type: "string"
          pattern: "^[\\w\\d_]{3,32}$"
        email:
          type: "string"
          format: "email"

console.log "valid document:", jsck.validate
  user:
    login: "matthew"
    email: "matthew@pandastrike.com"

{errors} = jsck.validate
  user:
    login: "matthew"
    email: "pandastrike.com"

console.log "invalid document:", errors






================================================
FILE: package.json
================================================
{
  "name": "jsck",
  "version": "0.3.2",
  "description": "JSON Schema Compiled checK",
  "scripts": {
    "test": "coffee test",
    "prepublish": "coffee tasks/build"
  },
  "main": "lib/index.js",
  "files": [
    "lib/",
    "schemas/",
    "README.md"
  ],
  "dependencies": {},
  "devDependencies": {
    "ajv": "latest",
    "amanda": "latest",
    "ajv": "^0.6.1",
    "amanda": "~0.5.1",
    "coffee-script": "~1.7",
    "commonjs-everywhere": "^0.9.7",
    "glob": "~3.2.6",
    "is-my-json-valid": "latest",
    "jayschema": "latest",
    "jsen": "latest",
    "json-gate": "latest",
    "json-schema-tests": "^0.1.1",
    "request": "~2.48.0",
    "shelljs": "^0.3.0",
    "simple-http-server": "~0.1.8",
    "testify": "~0.2.11",
    "themis": "latest",
    "tv4": "latest",
    "z-schema": "latest"
  },
  "repository": "git@github.com:pandastrike/jsck.git",
  "author": "Matthew King <matthew@pandastrike.com>",
  "license": "MIT"
}


================================================
FILE: schemas/draft-03/schema.json
================================================
{
	"$schema" : "http://json-schema.org/draft-03/schema#",
	"id" : "http://json-schema.org/draft-03/schema#",
	"type" : "object",
	
	"properties" : {
		"type" : {
			"type" : ["string", "array"],
			"items" : {
				"type" : ["string", {"$ref" : "#"}]
			},
			"uniqueItems" : true,
			"default" : "any"
		},
		
		"properties" : {
			"type" : "object",
			"additionalProperties" : {"$ref" : "#"},
			"default" : {}
		},
		
		"patternProperties" : {
			"type" : "object",
			"additionalProperties" : {"$ref" : "#"},
			"default" : {}
		},
		
		"additionalProperties" : {
			"type" : [{"$ref" : "#"}, "boolean"],
			"default" : {}
		},
		
		"items" : {
			"type" : [{"$ref" : "#"}, "array"],
			"items" : {"$ref" : "#"},
			"default" : {}
		},
		
		"additionalItems" : {
			"type" : [{"$ref" : "#"}, "boolean"],
			"default" : {}
		},
		
		"required" : {
			"type" : "boolean",
			"default" : false
		},
		
		"dependencies" : {
			"type" : "object",
			"additionalProperties" : {
				"type" : ["string", "array", {"$ref" : "#"}],
				"items" : {
					"type" : "string"
				}
			},
			"default" : {}
		},
		
		"minimum" : {
			"type" : "number"
		},
		
		"maximum" : {
			"type" : "number"
		},
		
		"exclusiveMinimum" : {
			"type" : "boolean",
			"default" : false
		},
		
		"exclusiveMaximum" : {
			"type" : "boolean",
			"default" : false
		},
		
		"minItems" : {
			"type" : "integer",
			"minimum" : 0,
			"default" : 0
		},
		
		"maxItems" : {
			"type" : "integer",
			"minimum" : 0
		},
		
		"uniqueItems" : {
			"type" : "boolean",
			"default" : false
		},
		
		"pattern" : {
			"type" : "string",
			"format" : "regex"
		},
		
		"minLength" : {
			"type" : "integer",
			"minimum" : 0,
			"default" : 0
		},
		
		"maxLength" : {
			"type" : "integer"
		},
		
		"enum" : {
			"type" : "array",
			"minItems" : 1,
			"uniqueItems" : true
		},
		
		"default" : {
			"type" : "any"
		},
		
		"title" : {
			"type" : "string"
		},
		
		"description" : {
			"type" : "string"
		},
		
		"format" : {
			"type" : "string"
		},
		
		"divisibleBy" : {
			"type" : "number",
			"minimum" : 0,
			"exclusiveMinimum" : true,
			"default" : 1
		},
		
		"disallow" : {
			"type" : ["string", "array"],
			"items" : {
				"type" : ["string", {"$ref" : "#"}]
			},
			"uniqueItems" : true
		},
		
		"extends" : {
			"type" : [{"$ref" : "#"}, "array"],
			"items" : {"$ref" : "#"},
			"default" : {}
		},
		
		"id" : {
			"type" : "string",
			"format" : "uri"
		},
		
		"$ref" : {
			"type" : "string",
			"format" : "uri"
		},
		
		"$schema" : {
			"type" : "string",
			"format" : "uri"
		}
	},
	
	"dependencies" : {
		"exclusiveMinimum" : "minimum",
		"exclusiveMaximum" : "maximum"
	},
	
	"default" : {}
}

================================================
FILE: schemas/draft-04/schema.json
================================================
{
    "id": "http://json-schema.org/draft-04/schema#",
    "$schema": "http://json-schema.org/draft-04/schema#",
    "description": "Core schema meta-schema",
    "definitions": {
        "schemaArray": {
            "type": "array",
            "minItems": 1,
            "items": { "$ref": "#" }
        },
        "positiveInteger": {
            "type": "integer",
            "minimum": 0
        },
        "positiveIntegerDefault0": {
            "allOf": [ { "$ref": "#/definitions/positiveInteger" }, { "default": 0 } ]
        },
        "simpleTypes": {
            "enum": [ "array", "boolean", "integer", "null", "number", "object", "string" ]
        },
        "stringArray": {
            "type": "array",
            "items": { "type": "string" },
            "minItems": 1,
            "uniqueItems": true
        }
    },
    "type": "object",
    "properties": {
        "id": {
            "type": "string",
            "format": "uri"
        },
        "$schema": {
            "type": "string",
            "format": "uri"
        },
        "title": {
            "type": "string"
        },
        "description": {
            "type": "string"
        },
        "default": {},
        "multipleOf": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true
        },
        "maximum": {
            "type": "number"
        },
        "exclusiveMaximum": {
            "type": "boolean",
            "default": false
        },
        "minimum": {
            "type": "number"
        },
        "exclusiveMinimum": {
            "type": "boolean",
            "default": false
        },
        "maxLength": { "$ref": "#/definitions/positiveInteger" },
        "minLength": { "$ref": "#/definitions/positiveIntegerDefault0" },
        "pattern": {
            "type": "string",
            "format": "regex"
        },
        "additionalItems": {
            "anyOf": [
                { "type": "boolean" },
                { "$ref": "#" }
            ],
            "default": {}
        },
        "items": {
            "anyOf": [
                { "$ref": "#" },
                { "$ref": "#/definitions/schemaArray" }
            ],
            "default": {}
        },
        "maxItems": { "$ref": "#/definitions/positiveInteger" },
        "minItems": { "$ref": "#/definitions/positiveIntegerDefault0" },
        "uniqueItems": {
            "type": "boolean",
            "default": false
        },
        "maxProperties": { "$ref": "#/definitions/positiveInteger" },
        "minProperties": { "$ref": "#/definitions/positiveIntegerDefault0" },
        "required": { "$ref": "#/definitions/stringArray" },
        "additionalProperties": {
            "anyOf": [
                { "type": "boolean" },
                { "$ref": "#" }
            ],
            "default": {}
        },
        "definitions": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        "properties": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        "patternProperties": {
            "type": "object",
            "additionalProperties": { "$ref": "#" },
            "default": {}
        },
        "dependencies": {
            "type": "object",
            "additionalProperties": {
                "anyOf": [
                    { "$ref": "#" },
                    { "$ref": "#/definitions/stringArray" }
                ]
            }
        },
        "enum": {
            "type": "array",
            "minItems": 1,
            "uniqueItems": true
        },
        "type": {
            "anyOf": [
                { "$ref": "#/definitions/simpleTypes" },
                {
                    "type": "array",
                    "items": { "$ref": "#/definitions/simpleTypes" },
                    "minItems": 1,
                    "uniqueItems": true
                }
            ]
        },
        "allOf": { "$ref": "#/definitions/schemaArray" },
        "anyOf": { "$ref": "#/definitions/schemaArray" },
        "oneOf": { "$ref": "#/definitions/schemaArray" },
        "not": { "$ref": "#" }
    },
    "dependencies": {
        "exclusiveMaximum": [ "maximum" ],
        "exclusiveMinimum": [ "minimum" ]
    },
    "default": {}
}


================================================
FILE: src/common/arrays.coffee
================================================
module.exports =

  # handlers

  maxItems: (value, context) ->
    (data, runtime) =>
      if @test_type "array", data
        if data.length > value
          runtime.error context, data, description:
            "Array must have fewer than #{value} items."

  minItems: (value, context) ->
    (data, runtime) =>
      if @test_type "array", data
        if data.length < value
          runtime.error context, data, description:
            "Array must have more than #{value} items."

  items: (definition, context) ->
    if @test_type "array", definition
      test = @_tuple_items definition, context
    else if @test_type "object", definition
      test = @compile(context, definition)
      # TODO check for array data?
      (data, runtime) =>
        for item, i in data
          test item, runtime.child(i)
        null
    else
      throw new Error "The 'items' attribute must be an object or an array"

  _additionalItems: (definition, context) ->
    if @test_type "object", definition
      test = @compile(context, definition)
    else if definition == false
      test = (data, runtime) ->
        runtime.error context, data, description:
          "Array is supposed to be a tuple, but has too many items."
    else if definition == true
      # valid
    else
      throw new Error "The 'additionalItems' attribute must be an object or false"
    (data, runtime) =>
      for item, i in data
        test item, runtime.child(i)
      null

  _tuple_items: (definition, context) ->
    {additionalItems} = context.modifiers

    if additionalItems?
      add_item_test = @_additionalItems additionalItems,
        context.sibling "additionalItems"
    else
      add_item_test = null

    tests = []
    for schema, i in definition
      unless @test_type "object", schema
        throw new Error "The 'items' attribute must be an object or an array"

      tests.push @compile context.child(i), schema

    (data, runtime) =>
      if @test_type "array", data
        for test, i in tests
          test data[i], runtime.child(i)

        if (data.length > tests.length) && add_item_test
          add_item_test data.slice(tests.length), runtime

  uniqueItems: (definition, context) ->
    null



================================================
FILE: src/common/comparison.coffee
================================================
module.exports =

  # handlers

  enum: (definition, context) ->
    # TODO: add more cases to the draft3 test suite for enum.js,
    # as they're not doing full coverage
    if @test_type "array", definition
      (data, runtime) =>
        for value in definition
          return if @equal(data, value)
        values = definition.join ', '
        runtime.error context, data, description:
          "Value must be one of #{values}."
    else
      throw new Error "Value of 'enum' MUST be an Array"

  # helpers

  equal: (got, want) ->
    if want instanceof Array
      @array_equal(got, want)
    else if @is_object(want)
      @object_equal(got, want)
    else
      got == want

  array_equal: (got, want) ->
    return false unless (got instanceof Array)
    return true if want.length == 0
    return false unless got.length == want.length
    for item, i in want
      return false if !@equal(got[i], item)
    true

  object_equal: (got, want) ->
    return false unless @is_object(got)
    return false unless Object.keys(got).length == Object.keys(want).length
    for key, value of want
      return false if !@equal(got[key], value)
    true



================================================
FILE: src/common/numeric.coffee
================================================
module.exports =

  minimum: (value, context) ->
    {modifiers: {exclusiveMinimum}} = context
    if exclusiveMinimum
      (data, runtime) =>
        if @test_type "number", data
          if !(data > value)
            runtime.error context, data, description:
              "Value must be > #{value}."
    else
      (data, runtime) =>
        if @test_type "number", data
          if !(data >= value)
            runtime.error context, data, description:
              "Value must be >= #{value}."

  maximum: (value, context) ->
    {modifiers: {exclusiveMaximum}} = context
    if exclusiveMaximum
      (data, runtime) =>
        if @test_type "number", data
          if !(data < value)
            runtime.error context, data, description:
              "Value must be < #{value}."
    else
      (data, runtime) =>
        if @test_type "number", data
          if !(data <= value)
            runtime.error context, data, description:
              "Value must be <= #{value}."



================================================
FILE: src/common/objects.coffee
================================================
module.exports =

  # handlers

  patternProperties: (definition, context) ->
    {additionalProperties} = context.modifiers
    if additionalProperties
      # The additionalProperties compiler runs the patternProperties
      # validation. This is necessary because properties are not considered
      # additional if they match a pattern.
      return null

    if !@test_type "object", definition
      throw new Error "The 'patternProperties' attribute must be an object"

    if Object.keys(definition).length == 0
      throw new Error "The 'patternProperties' object should not be empty"

    tests = {}
    for pattern, schema of definition
      unless @test_type "object", schema
        throw new Error "Values of 'patternProperties' must be an objects"

      tests[pattern] =
        regex: new RegExp(pattern)
        test: @compile context.child(pattern), schema

    (data, runtime) =>
      for property, value of data
        for pattern, object of tests
          if object.regex.test(property)
            object.test value, runtime.child(property)
      null


  additionalProperties: (definition, context) ->
    # TODO: refactor this method for clarity.  It's likely that this will
    # also improve performance.
    {properties, patternProperties} = context.modifiers
    if @test_type "object", definition
      add_prop_test = @compile(context, definition)
    else if definition == false
      add_prop_test = (data, runtime) =>
        runtime.error context, data, description:
          "Unspecified properties are not allowed on this object."
    else if definition == undefined
      add_prop_test = null
    else
      throw new Error "The 'additionalProperties' attribute must be an object or false"

    patterns = {}
    for pattern, schema of patternProperties
      patterns[pattern] =
        regex: new RegExp(pattern)
        test: @compile(context.sibling("patternProperties").child(pattern), schema)

    (data, runtime) =>
      if @test_type "object", data
        for property, value of data
          explicit = false
          patterned = false
          if properties?[property]
            explicit = true
          if patterns
            for pattern, object of patterns
              if object.regex.test(property)
                patterned = true
                object.test value, runtime.child(property)
          if !explicit && !patterned && add_prop_test
            add_prop_test value, runtime.child(property)
        null





================================================
FILE: src/common/strings.coffee
================================================
module.exports =

  pattern: (pattern, context) ->
    unless @test_type "string", pattern
      throw new Error "Value of 'pattern' must be a string"

    regex = new RegExp(pattern)
    (data, runtime) =>
      if @test_type "string", data
        if !regex.test(data)
          runtime.error context, data, description:
            "String did not match regex pattern."

  minLength: (value, context) ->
    unless @test_type "integer", value
      throw new Error "Value of 'minLength' must be an integer"

    (data, runtime) =>
      if @test_type "string", data
        if !(data.length >= value)
          runtime.error context, data, description:
            "String must be longer than #{value} bytes."

  maxLength: (value, context) ->
    unless @test_type "integer", value
      throw new Error "Value of 'maxLength' must be an integer"

    (data, runtime) =>
      if @test_type "string", data
        if !(data.length <= value)
          runtime.error context, data, description:
            "String must be smaller than #{value} bytes."



================================================
FILE: src/common/type.coffee
================================================
module.exports =

  # handlers

  type: (definition, context) ->
    if @test_type "array", definition
      tests = []
      for type in definition
        do (type) =>
          if @test_type "object", type
            test = @compile context, type
            tests.push (data, runtime) =>
              temp = new runtime.constructor
                pointer: ""
                errors: []
              test data, temp
              temp.errors.length == 0
          else
            tests.push (data, runtime) =>
              @test_type type, data

      (data, runtime) =>
        valid = false
        for test in tests
          if test(data, runtime)
            valid = true
        if valid == false
          runtime.error context, data

    else if @test_type "object", definition
      @compile(context, definition)
    else
      (data, runtime) =>
        if !@test_type definition, data
          runtime.error context, data

  # helpers

  is_object: (data) ->
    data? && (typeof data) == "object" &&
      !(data instanceof Array) &&
      !(data instanceof Date)

  is_primitive: (name) ->
    name in ["integer", "number", "string", "object", "array", "boolean", "null"]

  get_type: (data) ->
    if  typeof(data) == "number" && data % 1 == 0
      return "integer"
    if typeof(data) == "number"
      return "number"
    if typeof(data) == "string"
      return "string"
    if @is_object(data)
      return "object"
    if data instanceof Array
      return "array"
    if typeof data == "boolean"
      return "boolean"
    if data == null
      return "null"

  test_type: (type_name, data) ->
    switch type_name
      when "integer"
        typeof(data) == "number" && data % 1 == 0
      when "number"
        typeof(data) == "number"
      when "string"
        typeof(data) == "string"
      when "object"
        @is_object(data)
      when "array"
        data instanceof Array
      when "boolean"
        typeof data == "boolean"
      when "null"
        data == null
      when "any"
        true
      else
        throw new Error "Bad type: '#{type_name}'"



================================================
FILE: src/draft3/logical.coffee
================================================
URI = require "../uri"
module.exports =

  extends: (schemas, context) ->
    unless @test_type "array", schemas
      schemas = [schemas]

    for schema, i in schemas
      if (ref = schema.$ref)?
        uri = URI.resolve(context.scope, ref)
        parent = @find(uri)
        if !parent
          throw new Error "No schema found for $ref '#{ref}'"
        else
          schemas[i] = parent

    tests = []
    for schema, i in schemas
      new_context = context.child(i)
      tests.push @compile(new_context, schema)

    (data, runtime) =>
      for test in tests
        test data, runtime

  disallow: (definition, context) ->
    if @test_type "array", definition
      tests = []
      for type, i in definition
        do (i) =>
          if @test_type "object", type
            inverse = @compile context, type
            tests.push (data, runtime) =>
              temp = new runtime.constructor
                pointer: ""
                errors: []
              inverse data, temp
              if temp.errors.length == 0
                runtime.error context, data
          else
            tests.push @disallow type, context

      (data, runtime) =>
        for test in tests
          test data, runtime
    else
      (data, runtime) =>
        if @test_type definition, data
          runtime.error context, data



================================================
FILE: src/draft3/numeric.coffee
================================================
module.exports =

  divisibleBy: (value, context) ->
    (data, runtime) =>
      if @test_type "number", data
        if !((data / value) % 1 == 0)
          runtime.error context, data



================================================
FILE: src/draft3/objects.coffee
================================================
module.exports =

  properties: (definition, context) ->
    if !@test_type "object", definition
      throw new Error "The 'properties' attribute must be an object"
    tests = {}
    required = []
    for property, schema of definition
      new_context = context.child(property)
      test = @compile(new_context, schema)
      tests[property] = test
      if schema.required == true
        required.push property

    (data, runtime) =>
      if @test_type "object", data
        for property, value of data
          if (test = tests[property])?
            test value, runtime.child(property)
        for key in required
          if data[key] == undefined
            runtime.error context.child(key).child("required")
        true


  dependencies: (definition, context) ->
    unless @test_type "object", definition
      throw new Error "Value of 'dependencies' must be an object"
    else
      tests = []
      for property, dependency of definition

        if @test_type "string", dependency
          tests.push (data, runtime) =>
            if data[property]? && !data[dependency]?
              runtime.child(property).error context

        else if @test_type "array", dependency
          tests.push (data, runtime) =>
            if data[property]?
              for item in dependency
                if !data[item]?
                  runtime.child(property).error context
              null

        else if @test_type "object", dependency
          fn = @compile context, dependency
          tests.push (data, runtime) =>
            if data[property]
              fn data, runtime
            else
              true

        else
          throw new Error "Invalid dependency"

    (data, runtime) =>
      if @test_type "object", data
        for test in tests
          test data, runtime
        null



================================================
FILE: src/draft3/strings.coffee
================================================
module.exports =

  format: (format_name, context) ->
    if format_name == "regex"
      (data, runtime) =>
        if @test_type "string", data
          try
            new RegExp(data)
          catch error
            runtime.error context, data

    else if regex = format_regexes[format_name]
      do (regex) =>
        (data, runtime) =>
          if @test_type "string", data
            if !regex.test(data)
              runtime.error context, data
    else
      throw new Error "Invalid format_name for 'format'"


# regexes below were derived from
# https://github.com/tdegrunt/jsonschema
#
#Copyright (C) 2012-2013 Tom de Grunt <tom@degrunt.nl>

#Permission is hereby granted, free of charge, to any person obtaining a copy of
#this software and associated documentation files (the "Software"), to deal in
#the Software without restriction, including without limitation the rights to
#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
#of the Software, and to permit persons to whom the Software is furnished to do
#so, subject to the following conditions:

#The above copyright notice and this permission notice shall be included in all
#copies or substantial portions of the Software.

#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.

format_regexes =
  "date-time": /^(\d{4}-(?:0[0-9]|1[0-2])-[0-9]{2}(T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.\d+)?(Z|(\-|\+)[0-9]{2}:[0-9]{2})?)?)$/

  date: /^(\d{4}-(?:0[0-9]|1[0-2])-[0-9]{2})$/

  time: /^\d{2}:\d{2}:\d{2}$/

  email: /^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/

  "ip-address": /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

  ipv6: /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/

  uri: /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/

  color: /^(((#[0-9A-Fa-f]{3,6}))|(aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow)|(rgb\(\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/

  "host-name": /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])){0,3}\.?)$/

  alpha: /^[a-zA-Z]+$/

  alphanumeric: /^[a-zA-Z0-9]+$/

  "utc-millisec": (input) ->
    (typeof input is "string") and parseFloat(input) is parseInt(input, 10) and not isNaN(input)

  style: /\s*(.+?):\s*([^;]+);?/g

  phone: /^\+(?:[0-9] ?){6,14}[0-9]$/


================================================
FILE: src/draft3.coffee
================================================
validator = require("./validator")

module.exports = validator
  schema_uri: "http://json-schema.org/draft-03/schema#"
  mixins: [
    require "./draft3/logical"
    require "./draft3/numeric"
    require "./draft3/objects"
    require "./draft3/strings"
  ]


================================================
FILE: src/draft4/logical.coffee
================================================

module.exports =

  anyOf: (definition, context) ->
    unless @test_type "array", definition
      throw new Error "The 'anyOf' attribute must be an array"
    if definition.length == 0
      throw new Error "The 'anyOf' array may not be empty"

    tests = []
    for schema, i in definition
      unless @test_type "object", schema
        throw new Error "The 'anyOf' array values must be objects"
      new_context = context.child(i)
      tests.push @compile(new_context, schema)

    (data, runtime) =>
      most_items_tested = 0
      best_errors = []
      answer = tests.some (test) =>
        temp = new runtime.constructor
          pointer: ""
          error_pointer: runtime.pointer
          errors: []
        test(data, temp)
        if temp.items_tested && temp.items_tested > most_items_tested
          best_errors = temp.errors
          most_items_tested = temp.items_tested
        temp.errors.length == 0

      unless answer
        if @options.closestMatch
          Array::push.apply runtime.errors, best_errors
        else
          runtime.error context, data



  # Note from author of draft4 on how allOf works w/r/t additionalProperties
  # http://stackoverflow.com/questions/22689900/json-schema-allof-with-additionalproperties/23001194#23001194
  # also https://github.com/fge/json-schema-validator/issues/88
  allOf: (definition, context) ->
    unless @test_type "array", definition
      throw new Error "The 'allOf' attribute must be an array"
    if definition.length == 0
      throw new Error "The 'allOf' array may not be empty"

    # TODO: check for proper error reporting.  Do we need to create new
    # runtimes, contexts, etc.?
    tests = []
    for schema, i in definition
      unless @test_type "object", schema
        throw new Error "The 'allOf' array values must be objects"

      new_context = context.child(i)
      tests.push @compile(new_context, schema)

    (data, runtime) =>
      for test in tests
        test data, runtime
      null

  oneOf: (definition, context) ->
    unless @test_type "array", definition
      throw new Error "The 'oneOf' attribute must be an array"

    if definition.length == 0
      throw new Error "The 'oneOf' array may not be empty"

    tests = []
    for schema, i in definition
      unless @test_type "object", schema
        throw new Error "The 'oneOf' array values must be objects"

      new_context = context.child(i)
      tests.push @compile(new_context, schema)

    # TODO optimize?
    (data, runtime) =>
      valids = 0
      most_items_tested = 0
      best_errors = []
      for test in tests
        temp = new runtime.constructor
          pointer: ""
          error_pointer: runtime.pointer
          errors: []
        test(data, temp)
        if temp.errors.length == 0
          valids++
        else
          if temp.items_tested && temp.items_tested > most_items_tested
            best_errors = temp.errors
            most_items_tested = temp.items_tested

      if valids == 0 && @options.closestMatch
        Array::push.apply runtime.errors, best_errors
      else if valids != 1
        runtime.error context, data


  not: (definition, context) ->
    unless @test_type "object", definition
      throw new Error "The 'not' attribute must be an object"

    inverse = @compile context, definition
    (data, runtime) =>
      temp = new runtime.constructor
        pointer: ""
        errors: []
      inverse data, temp
      if temp.errors.length == 0
        runtime.error context, data



================================================
FILE: src/draft4/numeric.coffee
================================================
module.exports =

  multipleOf: (value, context) ->
    unless @test_type "number", value
      throw new Error "The 'multipleOf' attribute must be a number"

    (data, runtime) =>
      if @test_type "number", data
        if !((data / value) % 1 == 0)
          runtime.error context, data, description:
            "Value `#{data}` is not a multiple of #{value}"



================================================
FILE: src/draft4/objects.coffee
================================================
module.exports =

  # handlers

  required: (definition, context) ->
    unless @test_type "array", definition
      throw new Error "The 'required' attribute must be an array"

    if definition.length == 0
      throw new Error "The 'required' array must have at least one element"

    for property, i in definition
      unless @test_type "string", property
        throw new Error "The 'required' array may only contain strings"

    (data, runtime) =>
      if @test_type "object", data
        for property, i in definition
          if data[property] == undefined
            c = context.child(i)
            c.definition = property
            runtime.error c, undefined, description:
              "Required property '#{property}' is missing"
      null

  properties: (definition, context) ->
    unless @test_type "object", definition
      throw new Error "The 'properties' attribute must be an object"

    tests = {}
    for property, schema of definition
      unless @test_type "object", schema
        throw new Error "The 'properties' attribute must be an object"

      new_context = context.child(property)
      test = @compile(new_context, schema)
      tests[property] = test

    (data, runtime) =>
      if @test_type "object", data
        for property, value of data
          if (test = tests[property])?
            test value, runtime.child(property)
        null



  minProperties: (definition, context) ->
    (data, runtime) =>
      if @test_type "object", data
        if Object.keys(data).length < definition
          runtime.error context, data, description:
            "Object must have at least #{definition} properties."

  maxProperties: (definition, context) ->
    (data, runtime) =>
      if @test_type "object", data
        if Object.keys(data).length > definition
          runtime.error context, data, description:
            "Object cannot have more than #{definition} properties."

  dependencies: (definition, context) ->
    unless @test_type "object", definition
      throw new Error "Value of 'dependencies' must be an object"
    else
      tests = []
      for property, dependency of definition

        if @test_type "array", dependency
          if dependency.length == 0
            throw new Error "Arrays in 'dependencies' may not be empty"

          for name in dependency
            unless @test_type "string", name
              throw new Error "Vales of 'dependencies' arrays must be strings"
          tests.push (data, runtime) =>
            if data[property]?
              for item in dependency
                if !data[item]?
                  runtime.child(property).error context
              null

        else if @test_type "object", dependency
          fn = @compile context, dependency
          tests.push (data, runtime) =>
            if data[property]
              fn data, runtime
            else
              true

        else
          throw new Error "Invalid dependency"

    (data, runtime) =>
      if @test_type "object", data
        for test in tests
          test data, runtime
        null




================================================
FILE: src/draft4/strings.coffee
================================================
module.exports =

  format: (format_name, context) ->
    if format_name == "regex"
      (data, runtime) =>
        if @test_type "string", data
          try
            new RegExp(data)
          catch error
            runtime.error context, data, description:
              "String is not in the #{format_name} format."

    else if regex = format_regexes[format_name]
      do (regex) =>
        (data, runtime) =>
          if @test_type "string", data
            if !regex.test(data)
              runtime.error context, data, description:
                "String is not in the #{format_name} format."
    else
      throw new Error "Invalid format_name for 'format'"


# regexes below were derived from
# https://github.com/tdegrunt/jsonschema
#
#Copyright (C) 2012-2013 Tom de Grunt <tom@degrunt.nl>

#Permission is hereby granted, free of charge, to any person obtaining a copy of
#this software and associated documentation files (the "Software"), to deal in
#the Software without restriction, including without limitation the rights to
#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
#of the Software, and to permit persons to whom the Software is furnished to do
#so, subject to the following conditions:

#The above copyright notice and this permission notice shall be included in all
#copies or substantial portions of the Software.

#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.

format_regexes =
  "date-time": /^(\d{4}-(?:0[0-9]|1[0-2])-[0-9]{2}(T[0-9]{2}:[0-9]{2}:[0-9]{2}(\.\d+)?(Z|(\-|\+)[0-9]{2}:[0-9]{2})?)?)$/

  date: /^(\d{4}-(?:0[0-9]|1[0-2])-[0-9]{2})$/

  time: /^\d{2}:\d{2}:\d{2}$/

  email: /^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!\.)){0,61}[a-zA-Z0-9]?\.)+[a-zA-Z0-9](?:[a-zA-Z0-9\-](?!$)){0,61}[a-zA-Z0-9]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/

  "ipv4": /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/

  ipv6: /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/

  uri: /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\s]*$/

  color: /^(((#[0-9A-Fa-f]{3,6}))|(aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow)|(rgb\(\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*,\s*([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/

  "hostname": /^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])){0,3}\.?)$/

  alpha: /^[a-zA-Z]+$/

  alphanumeric: /^[a-zA-Z0-9]+$/

  "utc-millisec": (input) ->
    (typeof input is "string") and parseFloat(input) is parseInt(input, 10) and not isNaN(input)

  style: /\s*(.+?):\s*([^;]+);?/g

  phone: /^\+(?:[0-9] ?){6,14}[0-9]$/


================================================
FILE: src/draft4/type.coffee
================================================

module.exports =

  # handlers

  type: (definition, context) ->
    if @test_type "array", definition
      if definition.length == 0
        throw new Error "Invalid 'type': arrays may not be empty"

      tests = []
      for type in definition
        unless @is_primitive(type)
          throw new Error "Invalid 'type': #{type} is not a primitive type"
        do (type) =>
          tests.push (data, runtime) =>
            @test_type type, data

      (data, runtime) =>
        valid = false
        for test in tests
          if test(data, runtime)
            valid = true
        if valid == false
          types = definition.join ', '
          runtime.error context, data, description:
            "Expected type to be one of [#{types}] but found `#{@get_type(data)}`"

    else if @test_type "string", definition
      unless @is_primitive(definition)
        throw new Error "Invalid 'type': #{definition} is not a primitive type"
      (data, runtime) =>
        if !@test_type definition, data
          runtime.error context, data, description:
            "Expected type to be `#{definition}` but found `#{@get_type(data)}`"
    else
      throw new Error "The value of 'type' must be a string or an array"



================================================
FILE: src/draft4.coffee
================================================
validator = require("./validator")

module.exports = validator
  schema_uri: "http://json-schema.org/draft-04/schema#"
  mixins: [
    require "./draft4/type"
    require "./draft4/logical"
    require "./draft4/numeric"
    require "./draft4/objects"
    require "./draft4/strings"
  ]


================================================
FILE: src/index.coffee
================================================

module.exports =
  draft3: require "./draft3"
  draft4: require "./draft4"



================================================
FILE: src/uri.coffee
================================================
is_absolute = (string) ->
  /^[\w\d+.-]+:/.test(string)

is_url = (string) ->
  /^[\w\d+.-]+:\/\//.test(string)

resolve = (scope, uri) ->
  if is_absolute(uri)
    uri
  else
    scope = scope.replace /#$/, ""
    if uri.indexOf("#") == 0
      [main, _frag] = scope.split("#")
      main + uri
    else
      if is_url(scope) || scope.indexOf("/") != -1
        scope.replace /\/[^/]+$/, "/#{uri}"
      else
        "#{scope}/#{uri}"

module.exports = {is_absolute, is_url, resolve}


================================================
FILE: src/util.coffee
================================================
module.exports =
  
  escape: (string) ->
    string
      .replace(/~0/g, "~")
      .replace(/~1/g, "/")
      .replace(/%25/g, "%")

  # Used during document validation.  Maintains a list of errors and the
  # JSON pointer for the section of the document.
  Runtime: class Runtime
    constructor: ({@errors, @pointer, @error_pointer, @tested_item}) ->
      @items_tested = 0
      @tested_item ?= => @items_tested++
      @error_pointer ?= @pointer

    child: (token) ->
      new @constructor
        errors: @errors
        pointer: "#{@pointer}/#{token.toString()}"
        error_pointer: "#{@error_pointer}/#{token.toString()}"
        tested_item: @tested_item

    path: ->
      @pointer.slice(2).replace(/\//g, ".")

    error: (context, value, options={}) ->
      e =
        schema:
          pointer: context.pointer
          attribute: context._attribute
          definition: context.definition
        document:
          pointer: @error_pointer
          path: @path()
          value: value
      if options.description?
        e.description = options.description
      @errors.push e


  # Maintains the URI scope and JSON pointer during traversal
  # of a schema.
  Context: class Context

    constructor: ({@pointer, @scope, @_attribute}) ->

    attribute: (name) ->
      new Context
        pointer: "#{@pointer}/#{name.toString()}"
        scope: @scope
        _attribute: name

    child: (token) ->
      new Context
        pointer: "#{@pointer}/#{token.toString()}"
        scope: @scope
        _attribute: @_attribute

    sibling: (token) ->
      pointer = @pointer.replace(/\/.*$/, "/#{token.toString()}")
      new Context
        pointer: pointer
        scope: @scope



================================================
FILE: src/validator.coffee
================================================
URI = require "./uri"

{escape, Runtime, Context} = require "./util"

# Schemas should always be JSON stringifiable, so this is a simple
# method for obtaining a deep clone of one.  This function only gets
# used at schema-compilation time, so there are no performance
# implications unless you are constantly compiling new schemas.
clone = (value) ->
  JSON.parse(JSON.stringify(value))

DEFINITIONS =
  "http://json-schema.org/draft-03/schema#":
    require "../schemas/draft-03/schema.json"
  "http://json-schema.org/draft-04/schema#":
    require "../schemas/draft-04/schema.json"

module.exports = ({schema_uri, mixins}) ->

  SCHEMA_URI = schema_uri

  class Validator

    @modifiers:
      patternProperties: [ "additionalProperties" ]

      additionalProperties: [
        "properties"
        "patternProperties"
      ]

      items: [ "additionalItems" ]

      minimum: [ "exclusiveMinimum" ]
      maximum: [ "exclusiveMaximum" ]


    common_modules =
      "type": require "./common/type"
      "numeric": require "./common/numeric"
      "comparison": require "./common/comparison"
      "arrays": require "./common/arrays"
      "objects": require "./common/objects"
      "strings": require "./common/strings"

    common = for name of common_modules
      mixin = common_modules[name]
      for name, method of mixin
        Validator.prototype[name] = method

    for mixin in mixins
      for name, method of mixin
        Validator.prototype[name] = method


    constructor: (schemas...) ->
      @uris = {}
      @media_types = {}
      @unresolved = {}
      @options = {}

      @add(DEFINITIONS[SCHEMA_URI])
      for schema in schemas
        if schema["$schema"]? && schema["$schema"] != SCHEMA_URI
          throw "This validator doesn't support this JSON schema."
        @add(schema)

    set_options: (args) ->
      @options = args
      return this

    add: (schema) ->
      # Clone the schema to prevent any user changes from affecting JSCK.
      schema = clone(schema)

      if schema.id
        # Make sure the schema id always ends with "#"
        schema.id = schema.id.replace /#?$/, "#"

      # The context keeps track of where we are in the schema while
      # we traverse it for compilation.
      context = new Context
        pointer: schema.id || "#"
        scope: schema.id || "#"

      @compile_references context, schema
      @compile(context, schema)

    validate: (data) ->
      @validator("#").validate(data)

    validator: (arg) ->
      if (schema = @find arg)?
        validate: (data) =>
          errors = []
          runtime = new Runtime {errors, pointer: "#"}
          schema._test(data, runtime)
          if errors.length > 0
            for error in errors
              [base..., attribute] = error.schema.pointer.split("/")
              pointer = base.join("/")
              error.schema.definition ?= @resolve_uri(pointer)?[attribute]
              if error.document.value is undefined
                delete error.document.value

          valid = runtime.errors.length == 0
          {valid, errors}
        toJSON: (args...) ->
          schema
      else
        throw new Error "No schema found for '#{JSON.stringify(arg)}'"


    # Find a registered schema.
    #
    # Takes either a URI string or an options object.
    # Valid options:
    # * uri
    # * mediaType
    find: (arg) ->
      if @test_type "string", arg
        uri = escape(arg)
        #if /required/.test uri
          #for u, def of @uris when /required/.test u
            #console.error u
        @uris[uri]
      else if (uri = arg.uri)?
        uri = escape(uri)
        @uris[uri]
      else if (media_type = arg.mediaType)?
        @media_types[media_type]
      else
        null


    resolve_uri: (uri, scope) ->
      if (schema = @find(uri))?
        if schema.$ref
          @resolve_uri URI.resolve(scope, schema.$ref)
        else
          schema


    register: (uri, schema) ->
      @uris[uri] = schema
      # TODO: enforce uniqueness of types
      if (media_type = schema.mediaType)?
        if media_type != "application/json"
          @media_types[media_type] = schema


    compile_references: (context, schema) ->
      # Make an initial pass over the schema looking for $ref fields,
      # recording their targets for use in actual compilation.
      @schema_references(context, schema)

      # We try a second time to resolve $ref values, because a schema may have
      # been defined after we initially tried to resolve a $ref.
      for ref, {scope, uri} of @unresolved
        if (found_schema = @resolve_uri(uri, scope))?
          delete @unresolved[ref]
          @register ref, found_schema
      if Object.keys(@unresolved).length > 0
        pointers = (uri for key, {uri} of @unresolved)
        throw new Error "Unresolvable $ref values: #{JSON.stringify pointers}"


    schema_references: (context, schema) ->
      if !@test_type "object", schema
        throw new Error "Schema must be an object - #{context.pointer}"

      {scope, pointer} = context
      @register pointer, schema

      # This is one of the two cases where we pay attention to an "id"
      # attribute. The other is top-level id declaration, serving to identify
      # the entire schema.
      #
      # Here, we treat bare fragment identifiers (e.g. "#user") as aliases.
      if schema.id && schema.id.indexOf("#") == 0
        uri = URI.resolve scope, schema.id
        schema.id = uri
        @register uri, schema

      for attribute, definition of schema
        if "$ref" == attribute
          @resolve_reference(context, schema, definition)
        else
          new_context = context.child(attribute)
          if "properties" == attribute
            @properties_references new_context, definition
          else if "items" == attribute
            @items_references new_context, definition
          else if "definitions" == attribute
            @definitions_references new_context, definition
          else if @test_type "object", definition
            @schema_references new_context, definition
          else if attribute in ["allOf", "anyOf", "not"]
            for s, i in definition
              @schema_references new_context.child(i), s


    resolve_reference: (context, schema, definition) ->
      {scope, pointer} = context
      # turn relative refs into absolute URIs
      uri = URI.resolve(scope, definition)

      # When the URI of a $ref is a substring of the present context's URI,
      # we're in a recursive reference situation.
      # Ignore recursive references during this stage.
      if pointer.indexOf(uri + "/") != 0
        if (found_schema = @resolve_uri(uri, scope))?
          delete schema.$ref
          for k, v of found_schema
            schema[k] = v
          @schema_references context, schema
        else
          # Store the unresolvable reference so we can try to resolve
          # it again after having traversed the all schemas.
          @unresolved[pointer] = {scope, uri}


    properties_references: (context, properties) ->
      if !@test_type "object", properties
        throw new Error "Properties must be an object - #{context.pointer}"

      for property, schema of properties
        @schema_references context.child(property), schema

    items_references: (context, definition) ->
      if @test_type "array", definition
        for def, i in definition
          @schema_references context.child(i), def
      else
        @schema_references context, definition

    definitions_references: (context, object) ->
      if !@test_type "object", object
        throw new Error "Value of 'definitions' must be an object - #{context.pointer}"

      for name, schema of object
        @schema_references context.child(name), schema


    compile: (context, schema) ->
      {scope, pointer} = context
      tests = []

      # When the schema contains the $ref attribute, locate the referenced
      # schema and use in place of the present schema.
      if (uri = schema.$ref)?
        if @uris[uri]
          return (args...) =>
            @uris[uri]._test(args...)
        uri = URI.resolve(scope, uri)
        if pointer.indexOf(uri) == 0
          # When the URI of a $ref is a substring of the present context's URI,
          # we're in a recursive reference situation.
          return @recursive_test(schema, context)
        schema = @find(uri)
        if !schema
          throw new Error "No schema found for $ref '#{uri}'"

      for key, definition of schema when key != "_test"
        # Create a child context to track our progress into a new attribute.
        new_context = context.attribute(key)

        if @[key]?
          test = @compile_attribute(new_context, key, schema, definition)
          tests.push(test) if test
        else
          # If the key doesn't correspond to a known attribute name, treat
          # the object as a container of definitions.
          @compile_definitions(new_context, definition)

      test_function = (data, runtime) ->
        return null if typeof(data) == "undefined"
        runtime.tested_item()
        for test in tests
          test(data, runtime)
        null

      # Record the test function for use by such things as @recursive_test.
      @find(pointer)?._test = test_function
      # Also record the function for schemas with "alias" ids.
      if schema.id
        uri = URI.resolve scope, schema.id
        @find(uri)?._test = test_function

      return test_function


    compile_attribute: (context, attribute, schema, definition) ->

      # Some validation attributes can be modified by other attributes
      # at the same level.  E.g. minimum is modified by exclusiveMinimum.
      # Here we check the schema for such auxiliary attributes and stow
      # them in the context, so the primary attribute handler can act
      # on them.
      context.modifiers = {}

      if (modifiers = Validator.modifiers[attribute])?
        for key in modifiers
          context.modifiers[key] = schema[key]

      # Call the attribute's handler.
      # The return value will be a function that validates a document.
      # In rare cases, the attribute handler does not return a test
      # function, because some related attribute performs the test.
      if @[attribute]?
        if (test = @[attribute](definition, context))?
          return test


    compile_definitions: (context, object) ->
      if @is_schema(object)
        @compile(context, object)
      else if @test_type "object", object
        for name, definition of object
          @compile_definitions context.child(name), definition


    is_schema: (object) ->
      object.type? || object.$ref? ||
        object.allOf? || object.anyOf? || object.not?

    recursive_test: (schema, {scope, pointer}) ->
      uri = URI.resolve(scope, schema.$ref)
      if (schema = @find uri)?
        (data, runtime) ->
          schema._test(data, runtime)
      else
        throw new Error "No schema found for $ref '#{uri}'"





================================================
FILE: tasks/build/benchmarks.coffee
================================================
fs = require "fs"
shell = require "shelljs"

result = shell.exec "coffee benchmarks"
fs.writeFileSync "benchmarks/results/all.txt", result.output



================================================
FILE: tasks/build/browser.coffee
================================================
{exec} = require "../helpers"

require "./javascript"

base = "node_modules/.bin/cjsify lib/index.js --no-node --export JSCK"

# https://www.npmjs.com/package/commonjs-everywhere
exec "#{base} -o jsck.js"
exec "#{base} -m -o jsck.min.js"



================================================
FILE: tasks/build/docs.coffee
================================================
{build_docs} = require "../helpers"

build_docs()



================================================
FILE: tasks/build/index.coffee
================================================
require "./javascript"
require "./docs"






================================================
FILE: tasks/build/javascript.coffee
================================================
{exec} = require "../helpers"

exec "mkdir -p lib"
exec "coffee --compile --bare --output lib/ src/"


================================================
FILE: tasks/helpers.coffee
================================================
shell = require "shelljs"

exec = (cmd) ->
  console.log cmd
  shell.exec cmd

docs =
  "doc/README.pfm.md": "README.md"
  "doc/tests.pfm.md": "doc/tests.md"
  "doc/benchmarks.pfm.md": "doc/benchmarks.md"

module.exports =
  exec: exec
  docs: docs

  build_docs: (name) ->
    # pfm is a rubygem for converting Panda Flavored Markdown into
    # GitHub Flavored Markdown.
    #   gem install pfm

    if name
      destination = docs[name]
      exec "pfm #{name} -o #{destination}"
    else
      for source, destination of docs
        exec "pfm #{source} -o #{destination}"




================================================
FILE: tasks/update/index.coffee
================================================
require "./submodules"




================================================
FILE: tasks/update/submodules.coffee
================================================
{exec} = require "../helpers"

exec "git submodule init"
exec "git submodule update"


================================================
FILE: tasks/watch/docs.coffee
================================================
fs = require "fs"
{docs, build_docs} = require "../helpers"

for source, _dest of docs
  do (source) ->
    fs.watchFile source, (curr, prev) ->
      build_docs(source)




================================================
FILE: tasks/watch/src.coffee
================================================
fs = require "fs"
{exec} = require "../helpers"

exec "coffee --compile --watch --bare --output lib/ src/", ->



================================================
FILE: test/.gitignore
================================================
suite
suite.tgz


================================================
FILE: test/draft3/builtins.coffee
================================================
assert = require "assert"
Testify = require "testify"

JSCK = require("../../src/index").draft3


Testify.test "Built in schemas", (context) ->

  context.test "$ref to draft 3 works", ->
    jsck = new JSCK
      type: "object"
      properties:
        foo:
          $ref: "http://json-schema.org/draft-03/schema#"

    report = jsck.validate
      foo:
        properties: {}
    assert.equal report.valid, true

    report = jsck.validate
      foo:
        properties: "smurf"
    assert.equal report.valid, false





================================================
FILE: test/draft3/index.coffee
================================================
require "./unit"
require "./official"
require "./builtins"

# TODO: implement these tests for draft3
#require "./invalid"
#require "./valid"


================================================
FILE: test/draft3/official.coffee
================================================
{draft3} = require "../../src/index"
suite = require "json-schema-tests"

[_node, _script, attribute, test_number] = process.argv

suite {
  attribute
  test_number

  version: "draft3"

  validate: (schema, document) ->
    v = new draft3(schema)
    v.validate(document)

  ignores:
    # Doubtful value for the majority of use cases.
    # https://github.com/pandastrike/jsck/issues/42
    minLength: [
      "one supplementary Unicode code point is not long enough"
    ]
    maxLength: [
      "two supplementary Unicode code points is long enough"
    ]

    # Not supported because of the potential performance implications
    # https://github.com/pandastrike/jsck/issues/2
    uniqueItems: true

    # Impossible to test when using output of JSON.parse
    # https://github.com/pandastrike/jsck/issues/6
    "optional/zeroTerminatedFloats": true
    
    # The following items require fetching of remote schemas.
    # Support for remote references is planned for the next version of JSCK
    refRemote: true
    ref: [
      "remote ref, containing refs itself"
    ]
    definitions: true
}



================================================
FILE: test/draft3/unit/errors.coffee
================================================
assert = require "assert"
Testify = require "testify"

JSCK = require("../../src/index").draft3

jsck = new JSCK
  type: "object"
  additionalProperties:
    type: "object"
    additionalProperties: false
    properties:
      resource:
        required: true
        type: "string"
      url:
        type: "string"

report = jsck.validate
  smurf: {url: 4}

console.log()
console.log report.errors[0].schema.pointer
console.log()


================================================
FILE: test/draft3/unit/index.coffee
================================================
#require "./errors"
require "./references"
require "./uri_test"


================================================
FILE: test/draft3/unit/references.coffee
================================================
assert = require "assert"
Testify = require "testify"

JSCK = require("../../../src/index").draft3


Testify.test "JSCK draft 3 dereferencing", (context) ->

  context.test "Finding by uri", (context) ->
    jsck = new JSCK
      $schema: "http://json-schema.org/draft-03/schema#"
      id: "urn:jsck.test"
      type: "object"
      properties:
        user_list:
          id: "#user_list"
          type: "array"
          items: {$ref: "#/properties/user"}
        user_dict: {$ref: "#/properties/user"}

        user:
          id: "#user"
          type: "object"
          properties:
            name:
              required: true
              type: "string"
            email:
              type: "string"

    context.test "JSON Pointer", ->
      result = jsck.validator("urn:jsck.test#/properties/user").validate {name: "automatthew"}
      assert.equal result.valid, true

    context.test "id fragment", ->
      result = jsck.validator("urn:jsck.test#user").validate {name: "automatthew"}
      assert.equal result.valid, true


  context.test "schema without 'id'", (context) ->

    test_schema =
      definitions:
        schema1:
          id: "#foo"
          type: "string"
          format: "uri"

    jsck = new JSCK(test_schema)
    context.test "JSON pointers", (context) ->

      context.test "Pointer relative to empty URI", ->
        schema = jsck.find "#/foo"
        assert.deepEqual schema, test_schema.schema1



  return
  # FIXME: find out whether these tests fail because of app problems
  # or test problems.

  context.test "find", (context) ->
    test_schema =
      id: "http://x.y.z/rootschema.json#"
      schema1:
        id: "#foo"
      schema2:
        id: "otherschema.json"
        type: "string"
        nested:
          id: "#bar"
        alsonested:
          id: "t/inner.json#a"
      schema3:
        id: "some://where.else/completely#"
      schema4:
        $ref: "#foo"

    jsck = new JSCK(test_schema)

    context.test "JSON pointers", (context) ->

      context.test "Absolute URI", ->
        schema = jsck.find "http://x.y.z/rootschema.json#/schema1"
        assert.deepEqual schema, test_schema.schema1

        schema = jsck.find "http://x.y.z/rootschema.json#/schema2/nested"
        assert.deepEqual schema, test_schema.schema2.nested

    context.test "Setting scope with 'id'", (context) ->

      context.test "works for fragment", ->
        schema = jsck.find "http://x.y.z/rootschema.json#foo"
        assert.deepEqual schema, test_schema.schema1

      context.test "ignores path change", ->
        schema = jsck.find "http://x.y.z/otherschema.json#bar"
        assert.deepEqual schema, undefined

      context.test "ignores nested path change", ->
        schema = jsck.find "http://x.y.z/t/inner.json#a"
        assert.deepEqual schema, undefined

    context.test "Inline reference resolution", ->
      schema = jsck.find "http://x.y.z/rootschema.json#/schema4"
      assert.deepEqual schema, test_schema.schema1






================================================
FILE: test/draft3/unit/uri_test.coffee
================================================
assert = require "assert"
Testify = require "testify"

URI = require "../../../src/uri"

Testify.test "URI helper methods", (context) ->

  context.test "is_absolute", (context) ->

    context.test "URNs", ->
      assert.equal URI.is_absolute("urn:foo:bar:baz"), true
      assert.equal URI.is_absolute("urn"), false

    context.test "URLs", ->
      assert.equal URI.is_absolute("http://example.com:1452/smurf"), true
      assert.equal URI.is_absolute("example.com"), false


  context.test "is_url", ->
    assert.equal URI.is_url("https://monkeyshines.org/x?y=z"), true
    assert.equal URI.is_url("urn:foo:bar/baz,bat"), false


  context.test "resolve", (context) ->

    context.test "URL scope", (context) ->
      scope = "http://pandastrike.com/patchboard.json#"

      context.test "absolute reference", ->
        assert.equal URI.resolve(scope, "http://example.com/schema.json#"),
          "http://example.com/schema.json#"

      context.test "fragment", ->
        assert.equal URI.resolve(scope, "#service"),
          "http://pandastrike.com/patchboard.json#service"

      context.test "root reference", ->
        assert.equal URI.resolve(scope, "#"),
          "http://pandastrike.com/patchboard.json#"

      context.test "fragment reference", ->
        assert.equal URI.resolve(scope, "#/properties/resource"),
          "http://pandastrike.com/patchboard.json#/properties/resource"

      context.test "hierarchical references", ->
        assert.equal URI.resolve(scope, "other.json"),
          "http://pandastrike.com/other.json"

        scope = "http://pandastrike.com/schemas/patchboard.json#"
        assert.equal URI.resolve(scope, "other.json"),
          "http://pandastrike.com/schemas/other.json"

      context.test "scope reference, root reference", ->
        s = "http://pandastrike.com/patchboard.json#/properties/foo"
        assert.equal URI.resolve(s, "#"),
          "http://pandastrike.com/patchboard.json#"


    context.test "URI other than URL scope", (context) ->
      scope = "urn:jsck.anon#"

      context.test "fragment", ->
        assert.equal URI.resolve(scope, "#service"),
          "urn:jsck.anon#service"

      context.test "hierarchical references", ->
        assert.equal URI.resolve(scope, "other.json"),
          "urn:jsck.anon/other.json"



================================================
FILE: test/draft4/adhoc.coffee
================================================
assert = require "assert"
Testify = require "testify"

JSCK = require("../../src/index").draft4


Testify.test "Ad hoc tests", (context) ->

  context.test "undefinedness", (context) ->
    jsck = new JSCK
      $schema: "http://json-schema.org/draft-04/schema#"
      type: "object"
      properties:
        foo:
          type: [ "number" ]

    context.test "valid", ->
      result = jsck.validate
        foo: undefined
      assert.equal result.valid, true

      result = jsck.validate
        foo: 42
      assert.equal result.valid, true

      result = jsck.validate Object.create({foo: 42})
      assert.equal result.valid, true


    context.test "invalid", ->
      result = jsck.validate
        foo: null
      assert.equal result.valid, false

  context.test "issue #94 from SciencePiggy", ->
    jsck = new JSCK
      type: "object"
      required: [ "fullName" ]
      properties:
        fullName:
          type: "string"
        settings:
          $ref: "#/definitions/userSettings"

      definitions:
        userSettings:
          type: "object"
          required: [ "language" ]
          properties:
            language:
              type: "string"

    result = jsck.validate
      fullName: "Homer Simpson"
      settings: null

    assert.equal result.valid, false




================================================
FILE: test/draft4/builtins.coffee
================================================
assert = require "assert"
Testify = require "testify"

JSCK = require("../../src/index").draft4


Testify.test "Built in schemas", (context) ->

  context.test "$ref to draft 4 works", ->
    jsck = new JSCK
      type: "object"
      properties:
        foo:
          $ref: "http://json-schema.org/draft-04/schema#"

    report = jsck.validate
      foo:
        properties: {}
    assert.equal report.valid, true

    report = jsck.validate
      foo:
        properties: "smurf"
    assert.equal report.valid, false




================================================
FILE: test/draft4/index.coffee
================================================
require "./unit"
require "./official"
require "./invalid"
require "./valid"
require "./builtins"


================================================
FILE: test/draft4/invalid/additionalItems.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be either a boolean or an object"
      schemas: for value in json_types.except("boolean", "object")
        # additionalItems only takes effect when the value of 'items' is an array
        items: [ {} ]
        additionalItems: value
    }

  ]





================================================
FILE: test/draft4/invalid/additionalProperties.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be a boolean or an object"
      schemas: for value in json_types.except("boolean", "object")
        additionalProperties: value
    }


  ]



================================================
FILE: test/draft4/invalid/allOf.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be an array"
      schemas: for value in json_types.except("array")
        allOf: value
    }

    {
      description: "array MUST have at least one element"
      schemas: [
        allOf: []
      ]
    }

    {
      description: "elements of the array MUST be objects"
      schemas: for value in json_types.except("object")
        allOf: [ value ]
    }

  ]



================================================
FILE: test/draft4/invalid/anyOf.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be an array"
      schemas: for value in json_types.except("array")
        anyOf: value
    }

    {
      description: "array MUST have at least one element"
      schemas: [
        anyOf: []
      ]
    }

    {
      description: "elements of the array MUST be objects"
      schemas: for value in json_types.except("object")
        anyOf: [ value ]
    }

  ]



================================================
FILE: test/draft4/invalid/dependencies.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be an object"
      schemas: for value in json_types.except("object")
        dependencies: value
    }

    {
      description: "each value MUST be either an object or an array"
      schemas: for value in json_types.except("object", "array")
        dependencies:
          foo: value
    }

    {
      description: "array values must have at least one element"
      schemas: [
        dependencies:
          foo: []
      ]
    }

    {
      description: "array values must contain only strings"
      schemas: [
        dependencies:
          foo: [33]
      ]
    }

  ]



================================================
FILE: test/draft4/invalid/items.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be either an object or an array"
      schemas: for value in json_types.except("object", "array")
        {items: value}
    }

    {
      description: "arrays may only contain objects"
      schemas: for value in json_types.except("object")
        {items: [value]}
    }

  ]




================================================
FILE: test/draft4/invalid/not.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be an object"
      schemas: for value in json_types.except("object")
        not: value
    }

  ]




================================================
FILE: test/draft4/invalid/numbers.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "'multipleOf' value MUST be a number"
      schemas: for value in json_types.except("number", "integer")
        multipleOf: value
    }

  ]





================================================
FILE: test/draft4/invalid/oneOf.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be an array"
      schemas: for value in json_types.except("array")
        oneOf: value
    }

    {
      description: "array MUST have at least one element"
      schemas: [
        oneOf: []
      ]
    }

    {
      description: "elements of the array MUST be objects"
      schemas: for value in json_types.except("object")
        oneOf: [ value ]
    }

  ]




================================================
FILE: test/draft4/invalid/patternProperties.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be an object"
      schemas: for value in json_types.except("object")
        patternProperties: value
    }

    {
      description: "object should not be empty"
      schemas: for value in json_types.except("object")
        patternProperties: {}
    }

    {
      description: "names should be valid regexes"
      schemas: [
        {
          patternProperties:
            "[": {}
        }
      ]
    }

    {
      description: "object values MUST themselves be objects"
      schemas: for value in json_types.except("object")
        patternProperties:
          foo: value
    }


  ]



================================================
FILE: test/draft4/invalid/properties.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be an object"
      schemas: for value in json_types.except("object")
        properties: value
    }

    {
      description: "property values must themselves be objects"
      schemas: for value in json_types.except("object")
        properties:
          big: value
    }

  ]



================================================
FILE: test/draft4/invalid/required.coffee
================================================
module.exports = ({json_types}) ->
  [

    {
      description: "value MUST be an array"
      schemas: for value in json_types.except("array")
        required: value
    }

    {
      description: "the array must have at least one value"
      schemas: [
        required: []
      ]
    }

    {
      description: "the array values must be strings"
      schemas: for value in json_types.except("string")
        required: [value]
    }

  ]






================================================
FILE: test/draft4/invalid/strings.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "'pattern' value must be a string"
      schemas: for value in json_types.except("string")
        pattern: value
    }

    {
      description: "'maxLength' value must be an integer"
      schemas: for value in json_types.except("integer")
        maxLength: value
    }

    {
      description: "'minLength' value must be an integer"
      schemas: for value in json_types.except("integer")
        minLength: value
    }


  ]





================================================
FILE: test/draft4/invalid/type.coffee
================================================
module.exports = ({json_types}) ->

  [

    {
      description: "value MUST be either a string or an array"
      schemas: for value in json_types.except("string", "array")
        {type: value}
    }

    {
      description: "arrays may not be empty"
      schemas: [
        {type: []}
      ]
    }

    {
      description: "arrays may only contain strings"
      schemas: for value in json_types.except("string")
        {type: value}
    }

    {
      description: "string values must be one of the primitive types"
      schemas: [
        type: "bogus"
      ]
    }

  ]



================================================
FILE: test/draft4/invalid.coffee
================================================
glob = require "glob"
assert = require "assert"
Testify = require "testify"

{draft4} = require("../../src/index")

[_, _, single_attr] = process.argv

helpers =
  json_types:
    values:
      integer: 2
      number: 2.1
      string: "foo"
      object: {}
      array: [ ]
      boolean: false
      null: null
    except: (names...) ->
      for name, value of @values when !(name in names)
        value

Testify.test "Rejecting invalid schemas", (context) ->

  files = glob.sync("#{__dirname}/invalid/*.coffee").sort()
  l = "#{__dirname}/invalid/".length

  for file in files
    # chomp .coffee
    attribute_name = file.slice(l, -7)

    if single_attr && attribute_name != single_attr
      continue

    context.test attribute_name, (context) ->
      tests = require(file)
      # Dependency injection, where needed
      if tests.constructor == Function
        tests = tests(helpers)
      for test in tests
        context.test test.description, ->
          for schema in test.schemas
            try
              new draft4(schema)
              context.fail "#{test.description} - #{JSON.stringify schema}"
            catch e
              if test.debug
                console.log "\n", attribute_name, "-", test.description
                console.log schema
                console.log e.stack




================================================
FILE: test/draft4/official.coffee
================================================
{draft4} = require "../../src/index"

suite = require "json-schema-tests"


#shell = require "shelljs"
#cmd = "node_modules/.bin/nserver -p 5725 -d test/JSON-Schema-Test-Suite/remotes"
#proc = shell.exec cmd, (code, output) ->
#
#Testify = require "testify"
#Testify.once "done", ->
  #console.log "Shutting down the 'remotes' test server"
  #proc.kill("SIGTERM")

[_node, _script, attribute, test_number] = process.argv

suite {
  attribute
  test_number

  version: "draft4"

  validate: (schema, document) ->
    v = new draft4(schema)
    v.validate(document)


  ignores:
    # Doubtful value for the majority of use cases.
    # https://github.com/pandastrike/jsck/issues/42
    minLength: [
      "one supplementary Unicode code point is not long enough"
    ]
    maxLength: [
      "two supplementary Unicode code points is long enough"
    ]

    # Not supported because of the potential performance implications
    # https://github.com/pandastrike/jsck/issues/2
    uniqueItems: true

    # Impossible to test when using output of JSON.parse
    # https://github.com/pandastrike/jsck/issues/6
    "optional/zeroTerminatedFloats": true
    
    # The following items require fetching of remote schemas.
    # Support for remote references is planned for the next version of JSCK
    refRemote: true
    ref: [
      "remote ref, containing refs itself"
    ]
    definitions: true
}


================================================
FILE: test/draft4/unit/errors.coffee
================================================
assert = require "assert"
Testify = require "testify"

JSCK = require("../../src/index").draft3

jsck = new JSCK
  type: "object"
  additionalProperties:
    type: "object"
    additionalProperties: false
    properties:
      resource:
        required: true
        type: "string"
      url:
        type: "string"

report = jsck.validate
  smurf: {url: 4}

console.log()
console.log report.errors[0].schema.pointer
console.log()


================================================
FILE: test/draft4/unit/index.coffee
================================================
#require "./errors"
require "./references"
require "./uri_test"


================================================
FILE: test/draft4/unit/logical.coffee
================================================
Testify = require "testify"
assert = require "assert"

JSCK = require("../../../src")

jsck = new JSCK.draft4
  definitions:

    assetType:
      type: "string"
      enum: [
        "vote"
        "image"
        "audio"
        "video"
      ]

    campaign:

      base:
        type: "object"
        properties:
          name:
            type: "string"
          metadata:
            type: "object"
          assetTypes:
            type: "array"
            items: {$ref: "#/definitions/assetType"}
          active:
            type: "boolean"
          startTime:
            type: "string"
            format: "date-time"
          endTime:
            type: "string"
            format: "date-time"

      create:
        allOf: [
          {$ref: "#/definitions/campaign/base"}
          {
            required: ["name", "assetTypes"]
          }
        ]


validator = jsck.validator("#/definitions/campaign/create")

Testify.test "using logical keywords", (context) ->

  context.test "allOf", ->

    {errors} = validator.validate
      name: "foobar"
      assetTypes: ["vote"]
      startTime: "monkey"

    assert.equal errors.length, 0, "Unexpected errors:\n#{JSON.stringify(errors, null, 2)}"

  



================================================
FILE: test/draft4/unit/references.coffee
================================================
assert = require "assert"
Testify = require "testify"

JSCK = require("../../../src/index").draft4


Testify.test "JSCK draft 4 dereferencing", (context) ->

  context.test "Finding by uri", (context) ->
    jsck = new JSCK
      $schema: "http://json-schema.org/draft-04/schema#"
      id: "urn:jsck.test"
      type: "object"
      properties:
        user_list:
          id: "#user_list"
          type: "array"
          items: {$ref: "#/properties/user"}
        user_dict: {$ref: "#/properties/user"}

        user:
          id: "#user"
          type: "object"
          required: ["name"]
          properties:
            name:
              type: "string"
            email:
              type: "string"

    context.test "JSON Pointer", ->
      result = jsck.validator("urn:jsck.test#/properties/user").validate {name: "automatthew"}
      assert.equal result.valid, true

    context.test "id fragment", ->
      result = jsck.validator("urn:jsck.test#user").validate {name: "automatthew"}
      assert.equal result.valid, true


  context.test "schema without 'id'", (context) ->

    test_schema =
      definitions:
        schema1:
          id: "#foo"
          type: "string"
          format: "uri"

    jsck = new JSCK(test_schema)
    context.test "JSON pointers", (context) ->

      context.test "Pointer relative to empty URI", ->
        schema = jsck.find "#/foo"
        assert.deepEqual schema, test_schema.schema1



  return
  # FIXME: find out whether these tests fail because of app problems
  # or test problems.

  context.test "find", (context) ->
    test_schema =
      id: "http://x.y.z/rootschema.json#"
      schema1:
        id: "#foo"
      schema2:
        id: "otherschema.json"
        type: "string"
        nested:
          id: "#bar"
        alsonested:
          id: "t/inner.json#a"
      schema3:
        id: "some://where.else/completely#"
      schema4:
        $ref: "#foo"

    jsck = new JSCK(test_schema)

    context.test "JSON pointers", (context) ->

      context.test "Absolute URI", ->
        schema = jsck.find "http://x.y.z/rootschema.json#/schema1"
        assert.deepEqual schema, test_schema.schema1

        schema = jsck.find "http://x.y.z/rootschema.json#/schema2/nested"
        assert.deepEqual schema, test_schema.schema2.nested

    context.test "Setting scope with 'id'", (context) ->

      context.test "works for fragment", ->
        schema = jsck.find "http://x.y.z/rootschema.json#foo"
        assert.deepEqual schema, test_schema.schema1

      context.test "ignores path change", ->
        schema = jsck.find "http://x.y.z/otherschema.json#bar"
        assert.deepEqual schema, undefined

      context.test "ignores nested path change", ->
        schema = jsck.find "http://x.y.z/t/inner.json#a"
        assert.deepEqual schema, undefined

    context.test "Inline reference resolution", ->
      schema = jsck.find "http://x.y.z/rootschema.json#/schema4"
      assert.deepEqual schema, test_schema.schema1






================================================
FILE: test/draft4/unit/uri_test.coffee
================================================
assert = require "assert"
Testify = require "testify"

URI = require "../../../src/uri"

Testify.test "URI helper methods", (context) ->

  context.test "is_absolute", (context) ->

    context.test "URNs", ->
      assert.equal URI.is_absolute("urn:foo:bar:baz"), true
      assert.equal URI.is_absolute("urn"), false

    context.test "URLs", ->
      assert.equal URI.is_absolute("http://example.com:1452/smurf"), true
      assert.equal URI.is_absolute("example.com"), false


  context.test "is_url", ->
    assert.equal URI.is_url("https://monkeyshines.org/x?y=z"), true
    assert.equal URI.is_url("urn:foo:bar/baz,bat"), false


  context.test "resolve", (context) ->

    context.test "URL scope", (context) ->
      scope = "http://pandastrike.com/patchboard.json#"

      context.test "absolute reference", ->
        assert.equal URI.resolve(scope, "http://example.com/schema.json#"),
          "http://example.com/schema.json#"

      context.test "fragment", ->
        assert.equal URI.resolve(scope, "#service"),
          "http://pandastrike.com/patchboard.json#service"

      context.test "root reference", ->
        assert.equal URI.resolve(scope, "#"),
          "http://pandastrike.com/patchboard.json#"

      context.test "fragment reference", ->
        assert.equal URI.resolve(scope, "#/properties/resource"),
          "http://pandastrike.com/patchboard.json#/properties/resource"

      context.test "hierarchical references", ->
        assert.equal URI.resolve(scope, "other.json"),
          "http://pandastrike.com/other.json"

        scope = "http://pandastrike.com/schemas/patchboard.json#"
        assert.equal URI.resolve(scope, "other.json"),
          "http://pandastrike.com/schemas/other.json"

      context.test "scope reference, root reference", ->
        s = "http://pandastrike.com/patchboard.json#/properties/foo"
        assert.equal URI.resolve(s, "#"),
          "http://pandastrike.com/patchboard.json#"


    context.test "URI other than URL scope", (context) ->
      scope = "urn:jsck.anon#"

      context.test "fragment", ->
        assert.equal URI.resolve(scope, "#service"),
          "urn:jsck.anon#service"

      context.test "hierarchical references", ->
        assert.equal URI.resolve(scope, "other.json"),
          "urn:jsck.anon/other.json"



================================================
FILE: test/draft4/valid/basic.coffee
================================================
module.exports = ({json_types}) ->

  "may contain properties which are not schema keywords":
    schemas:

      "string value":
        monkey: "shines"

      "integer value":
        monkey: 84

      "schema value":
        monkey:
          type: "array"




================================================
FILE: test/draft4/valid/definitions.coffee
================================================
module.exports = ({json_types}) ->

  "known attribute name as key of 'definitions' dictionary":
    schemas:

      required:
        definitions:
          required:
            type: "object"

      id:
        definitions:
          id:
            type: "object"

      items:
        definitions:
          items:
            type: "object"

  "nested definitions":
    schemas:

      foo:
        definitions:
          bar: {type: "string"}
          definitions:
            baz: {type: "string"}


================================================
FILE: test/draft4/valid/properties.coffee
================================================
module.exports = ({json_types}) ->

  "known attribute name":
    schemas:

      required:
        type: "object"
        properties:
          required:
            type: "boolean"

      id:
        type: "object"
        properties:
          id:
            type: "string"

      properties:
        type: "object"
        properties:
          properties: {type: "array"}





================================================
FILE: test/draft4/valid.coffee
================================================
glob = require "glob"
assert = require "assert"
Testify = require "testify"

{draft4} = require("../../src/index")

helpers =
  json_types:
    values:
      integer: 2
      number: 2.1
      string: "foo"
      object: {}
      array: [ ]
      boolean: false
      null: null
    except: (names...) ->
      for name, value of @values when !(name in names)
        value

Testify.test "Accepting valid schemas", (context) ->

  files = glob.sync("#{__dirname}/valid/*.coffee").sort()
  l = "#{__dirname}/valid/".length

  for file in files
    # chomp .coffee
    attribute_name = file.slice(l, -7)

    context.test attribute_name, (context) ->
      tests = require(file)
      # Dependency injection, where needed
      if tests.constructor == Function
        tests = tests(helpers)

      for name, test of tests
        context.test name, (context) ->
          for k, schema of test.schemas
            context.test k, ->
              try
                new draft4(schema)
              catch e
                console.log e.stack
                context.fail(e)





================================================
FILE: test/index.coffee
================================================

require "./draft3/unit"
require "./draft3"

require "./draft4/unit"
require "./draft4"


Download .txt
gitextract__sjmg1fx/

├── .gitignore
├── .gitmodules
├── LICENSE
├── README.md
├── benchmarks/
│   ├── benchmark.coffee
│   ├── draft3/
│   │   ├── index.coffee
│   │   ├── medium/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   └── valid_doc.coffee
│   │   ├── trivial/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   └── valid_doc.coffee
│   │   └── validators.coffee
│   ├── draft4/
│   │   ├── complex/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   ├── test.coffee
│   │   │   └── valid_doc.coffee
│   │   ├── index.coffee
│   │   ├── medium/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   └── valid_doc.coffee
│   │   ├── trivial/
│   │   │   ├── index.coffee
│   │   │   ├── schema.coffee
│   │   │   └── valid_doc.coffee
│   │   └── validators.coffee
│   ├── index.coffee
│   ├── results/
│   │   └── all.txt
│   ├── runner.coffee
│   └── statistics.js
├── doc/
│   ├── README.pfm.md
│   ├── benchmarks.md
│   ├── benchmarks.pfm.md
│   ├── tests.md
│   └── tests.pfm.md
├── examples/
│   └── draft4/
│       ├── advanced.coffee
│       └── basic.coffee
├── package.json
├── schemas/
│   ├── draft-03/
│   │   └── schema.json
│   └── draft-04/
│       └── schema.json
├── src/
│   ├── common/
│   │   ├── arrays.coffee
│   │   ├── comparison.coffee
│   │   ├── numeric.coffee
│   │   ├── objects.coffee
│   │   ├── strings.coffee
│   │   └── type.coffee
│   ├── draft3/
│   │   ├── logical.coffee
│   │   ├── numeric.coffee
│   │   ├── objects.coffee
│   │   └── strings.coffee
│   ├── draft3.coffee
│   ├── draft4/
│   │   ├── logical.coffee
│   │   ├── numeric.coffee
│   │   ├── objects.coffee
│   │   ├── strings.coffee
│   │   └── type.coffee
│   ├── draft4.coffee
│   ├── index.coffee
│   ├── uri.coffee
│   ├── util.coffee
│   └── validator.coffee
├── tasks/
│   ├── build/
│   │   ├── benchmarks.coffee
│   │   ├── browser.coffee
│   │   ├── docs.coffee
│   │   ├── index.coffee
│   │   └── javascript.coffee
│   ├── helpers.coffee
│   ├── update/
│   │   ├── index.coffee
│   │   └── submodules.coffee
│   └── watch/
│       ├── docs.coffee
│       └── src.coffee
└── test/
    ├── .gitignore
    ├── draft3/
    │   ├── builtins.coffee
    │   ├── index.coffee
    │   ├── official.coffee
    │   └── unit/
    │       ├── errors.coffee
    │       ├── index.coffee
    │       ├── references.coffee
    │       └── uri_test.coffee
    ├── draft4/
    │   ├── adhoc.coffee
    │   ├── builtins.coffee
    │   ├── index.coffee
    │   ├── invalid/
    │   │   ├── additionalItems.coffee
    │   │   ├── additionalProperties.coffee
    │   │   ├── allOf.coffee
    │   │   ├── anyOf.coffee
    │   │   ├── dependencies.coffee
    │   │   ├── items.coffee
    │   │   ├── not.coffee
    │   │   ├── numbers.coffee
    │   │   ├── oneOf.coffee
    │   │   ├── patternProperties.coffee
    │   │   ├── properties.coffee
    │   │   ├── required.coffee
    │   │   ├── strings.coffee
    │   │   └── type.coffee
    │   ├── invalid.coffee
    │   ├── official.coffee
    │   ├── unit/
    │   │   ├── errors.coffee
    │   │   ├── index.coffee
    │   │   ├── logical.coffee
    │   │   ├── references.coffee
    │   │   └── uri_test.coffee
    │   ├── valid/
    │   │   ├── basic.coffee
    │   │   ├── definitions.coffee
    │   │   └── properties.coffee
    │   └── valid.coffee
    └── index.coffee
Download .txt
SYMBOL INDEX (1 symbols across 1 files)

FILE: benchmarks/statistics.js
  function normsinv (line 160) | function normsinv(p)
Condensed preview — 107 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (165K chars).
[
  {
    "path": ".gitignore",
    "chars": 56,
    "preview": "lib\nnode_modules\nmine\n.ruby-gemset\nnpm-debug.log\n*.tgz\n\n"
  },
  {
    "path": ".gitmodules",
    "chars": 139,
    "preview": "[submodule \"test/JSON-Schema-Test-Suite\"]\n\tpath = test/JSON-Schema-Test-Suite\n\turl = git@github.com:json-schema/JSON-Sch"
  },
  {
    "path": "LICENSE",
    "chars": 1080,
    "preview": "The MIT License (MIT)\n\nCopyright (c) 2013 Matthew King\n\nPermission is hereby granted, free of charge, to any person obta"
  },
  {
    "path": "README.md",
    "chars": 5783,
    "preview": "# JSON Schema Compiled checK\n\nJSCK is one of the fastest [JSON Schema](http://json-schema.org) validators for Node.js.\nI"
  },
  {
    "path": "benchmarks/benchmark.coffee",
    "chars": 869,
    "preview": "microtime = require \"microtime\"\nrequire \"./statistics\"\n\nmodule.exports = class Benchmark\n\n  @compare: (benchmarks, optio"
  },
  {
    "path": "benchmarks/draft3/index.coffee",
    "chars": 94,
    "preview": "console.log \"## Benchmarks for Draft 3\"\nconsole.log\n\nrequire \"./trivial/\"\nrequire \"./medium/\"\n"
  },
  {
    "path": "benchmarks/draft3/medium/index.coffee",
    "chars": 207,
    "preview": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Configurati"
  },
  {
    "path": "benchmarks/draft3/medium/schema.coffee",
    "chars": 1542,
    "preview": "module.exports =\n  description: \"A moderately complex schema with some nesting and value constraints\"\n  type: \"object\"\n "
  },
  {
    "path": "benchmarks/draft3/medium/valid_doc.coffee",
    "chars": 374,
    "preview": "module.exports =\n  api_server:\n    url: \"http://example.com:8998\"\n    host: \"example.com\"\n    port: 8998\n\n  transport:\n "
  },
  {
    "path": "benchmarks/draft3/trivial/index.coffee",
    "chars": 197,
    "preview": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Event\"\n  re"
  },
  {
    "path": "benchmarks/draft3/trivial/schema.coffee",
    "chars": 376,
    "preview": "module.exports =\n  description: \"A simple schema, exercising very few attributes\"\n  type: \"object\"\n  additionalPropertie"
  },
  {
    "path": "benchmarks/draft3/trivial/valid_doc.coffee",
    "chars": 140,
    "preview": "module.exports =\n  origin: \"monkey\"\n  name: \"shines\"\n  tags: [\"in\", \"the\", \"closet\"]\n  timestamp: Date.now()\n  data:\n   "
  },
  {
    "path": "benchmarks/draft3/validators.coffee",
    "chars": 1219,
    "preview": "module.exports =\n\n  \"JSCK\":\n    setup: (schema) ->\n      JSCK = require \"../../src/draft3\"\n      new JSCK(schema)\n    va"
  },
  {
    "path": "benchmarks/draft4/complex/index.coffee",
    "chars": 203,
    "preview": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Transaction"
  },
  {
    "path": "benchmarks/draft4/complex/schema.coffee",
    "chars": 3512,
    "preview": "\nmodule.exports =\n  type: \"array\"\n  items: {$ref: \"#transaction\"}\n  minItems: 1\n\n  definitions:\n\n    base58:\n      id: \""
  },
  {
    "path": "benchmarks/draft4/complex/test.coffee",
    "chars": 715,
    "preview": "\nJSCK = require \"../../../src/draft4\"\nschema = require \"./schema\"\nvalid_doc = require \"./valid_doc\"\n\nschema =\n  type: \"a"
  },
  {
    "path": "benchmarks/draft4/complex/valid_doc.coffee",
    "chars": 4899,
    "preview": "$ = module.exports = []\n\n$.push\n  metadata:\n    amount: 38043749285\n    fee: 2 * 10000\n    status: \"confirmed\"\n    confi"
  },
  {
    "path": "benchmarks/draft4/index.coffee",
    "chars": 116,
    "preview": "console.log \"## Benchmarks for Draft 4\"\nconsole.log\n\nrequire \"./trivial/\"\nrequire \"./medium/\"\nrequire \"./complex/\"\n\n"
  },
  {
    "path": "benchmarks/draft4/medium/index.coffee",
    "chars": 205,
    "preview": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Configurati"
  },
  {
    "path": "benchmarks/draft4/medium/schema.coffee",
    "chars": 1456,
    "preview": "module.exports =\n  description: \"A moderately complex schema with some nesting and value constraints\"\n  type: \"object\"\n "
  },
  {
    "path": "benchmarks/draft4/medium/valid_doc.coffee",
    "chars": 374,
    "preview": "module.exports =\n  api_server:\n    url: \"http://example.com:8998\"\n    host: \"example.com\"\n    port: 8998\n\n  transport:\n "
  },
  {
    "path": "benchmarks/draft4/trivial/index.coffee",
    "chars": 215,
    "preview": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Event - Val"
  },
  {
    "path": "benchmarks/draft4/trivial/schema.coffee",
    "chars": 394,
    "preview": "module.exports =\n  description: \"A simple schema, exercising very few attributes\"\n  type: \"object\"\n  additionalPropertie"
  },
  {
    "path": "benchmarks/draft4/trivial/valid_doc.coffee",
    "chars": 140,
    "preview": "module.exports =\n  origin: \"monkey\"\n  name: \"shines\"\n  tags: [\"in\", \"the\", \"closet\"]\n  timestamp: Date.now()\n  data:\n   "
  },
  {
    "path": "benchmarks/draft4/validators.coffee",
    "chars": 3011,
    "preview": "module.exports =\n\n  \"JSCK\":\n    setup: (schema) ->\n      JSCK = require \"../../src/draft4\"\n      new JSCK(schema)\n    va"
  },
  {
    "path": "benchmarks/index.coffee",
    "chars": 41,
    "preview": "require \"./draft3/\"\nrequire \"./draft4/\"\n\n"
  },
  {
    "path": "benchmarks/results/all.txt",
    "chars": 4669,
    "preview": "## Benchmarks for Draft 3\n\nSchema: 'Event'.  A simple schema, exercising very few attributes\nSample size: 64\nValidations"
  },
  {
    "path": "benchmarks/runner.coffee",
    "chars": 1748,
    "preview": "# stdlib\nutil = require \"util\"\n\n# our simple benchmarking library\nBenchmark = require \"./benchmark.coffee\"\nsamples = 64\n"
  },
  {
    "path": "benchmarks/statistics.js",
    "chars": 7260,
    "preview": "/****************************************************************************************************\nJavaScript Math an"
  },
  {
    "path": "doc/README.pfm.md",
    "chars": 5233,
    "preview": "# JSON Schema Compiled checK\n\nJSCK is one of the fastest [JSON Schema](http://json-schema.org) validators for Node.js.\nI"
  },
  {
    "path": "doc/benchmarks.md",
    "chars": 7149,
    "preview": "# Benchmarks\n\nJSCK has fairly comprehensive benchmarks which show it to be one of the fastest\nJSON Schema validators ava"
  },
  {
    "path": "doc/benchmarks.pfm.md",
    "chars": 2100,
    "preview": "# Benchmarks\n\nJSCK has fairly comprehensive benchmarks which show it to be one of the fastest\nJSON Schema validators ava"
  },
  {
    "path": "doc/tests.md",
    "chars": 5922,
    "preview": "# Testing JSCK\n\nJSCK is developed against several sets of tests:\n\n* the official [JSON Schema Test Suite][canonical]\n* t"
  },
  {
    "path": "doc/tests.pfm.md",
    "chars": 4354,
    "preview": "# Testing JSCK\n\nJSCK is developed against several sets of tests:\n\n* the official [JSON Schema Test Suite][canonical]\n* t"
  },
  {
    "path": "examples/draft4/advanced.coffee",
    "chars": 1351,
    "preview": "JSCK = require(\"../../src/index\")\n\n# using a schema that declares a URI with \"id\"\n\njsck = new JSCK.draft4\n  $schema: \"ht"
  },
  {
    "path": "examples/draft4/basic.coffee",
    "chars": 616,
    "preview": "JSCK = require(\"../../src/index\")\n\n# Construct a validator for a schema lacking an \"id\" declaration\n\njsck = new JSCK.dra"
  },
  {
    "path": "package.json",
    "chars": 949,
    "preview": "{\n  \"name\": \"jsck\",\n  \"version\": \"0.3.2\",\n  \"description\": \"JSON Schema Compiled checK\",\n  \"scripts\": {\n    \"test\": \"cof"
  },
  {
    "path": "schemas/draft-03/schema.json",
    "chars": 2700,
    "preview": "{\n\t\"$schema\" : \"http://json-schema.org/draft-03/schema#\",\n\t\"id\" : \"http://json-schema.org/draft-03/schema#\",\n\t\"type\" : \""
  },
  {
    "path": "schemas/draft-04/schema.json",
    "chars": 4375,
    "preview": "{\n    \"id\": \"http://json-schema.org/draft-04/schema#\",\n    \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n    \"de"
  },
  {
    "path": "src/common/arrays.coffee",
    "chars": 2223,
    "preview": "module.exports =\n\n  # handlers\n\n  maxItems: (value, context) ->\n    (data, runtime) =>\n      if @test_type \"array\", data"
  },
  {
    "path": "src/common/comparison.coffee",
    "chars": 1161,
    "preview": "module.exports =\n\n  # handlers\n\n  enum: (definition, context) ->\n    # TODO: add more cases to the draft3 test suite for"
  },
  {
    "path": "src/common/numeric.coffee",
    "chars": 992,
    "preview": "module.exports =\n\n  minimum: (value, context) ->\n    {modifiers: {exclusiveMinimum}} = context\n    if exclusiveMinimum\n "
  },
  {
    "path": "src/common/objects.coffee",
    "chars": 2487,
    "preview": "module.exports =\n\n  # handlers\n\n  patternProperties: (definition, context) ->\n    {additionalProperties} = context.modif"
  },
  {
    "path": "src/common/strings.coffee",
    "chars": 1055,
    "preview": "module.exports =\n\n  pattern: (pattern, context) ->\n    unless @test_type \"string\", pattern\n      throw new Error \"Value "
  },
  {
    "path": "src/common/type.coffee",
    "chars": 2103,
    "preview": "module.exports =\n\n  # handlers\n\n  type: (definition, context) ->\n    if @test_type \"array\", definition\n      tests = []\n"
  },
  {
    "path": "src/draft3/logical.coffee",
    "chars": 1343,
    "preview": "URI = require \"../uri\"\nmodule.exports =\n\n  extends: (schemas, context) ->\n    unless @test_type \"array\", schemas\n      s"
  },
  {
    "path": "src/draft3/numeric.coffee",
    "chars": 188,
    "preview": "module.exports =\n\n  divisibleBy: (value, context) ->\n    (data, runtime) =>\n      if @test_type \"number\", data\n        i"
  },
  {
    "path": "src/draft3/objects.coffee",
    "chars": 1834,
    "preview": "module.exports =\n\n  properties: (definition, context) ->\n    if !@test_type \"object\", definition\n      throw new Error \""
  },
  {
    "path": "src/draft3/strings.coffee",
    "chars": 4267,
    "preview": "module.exports =\n\n  format: (format_name, context) ->\n    if format_name == \"regex\"\n      (data, runtime) =>\n        if "
  },
  {
    "path": "src/draft3.coffee",
    "chars": 259,
    "preview": "validator = require(\"./validator\")\n\nmodule.exports = validator\n  schema_uri: \"http://json-schema.org/draft-03/schema#\"\n "
  },
  {
    "path": "src/draft4/logical.coffee",
    "chars": 3529,
    "preview": "\nmodule.exports =\n\n  anyOf: (definition, context) ->\n    unless @test_type \"array\", definition\n      throw new Error \"Th"
  },
  {
    "path": "src/draft4/numeric.coffee",
    "chars": 368,
    "preview": "module.exports =\n\n  multipleOf: (value, context) ->\n    unless @test_type \"number\", value\n      throw new Error \"The 'mu"
  },
  {
    "path": "src/draft4/objects.coffee",
    "chars": 3102,
    "preview": "module.exports =\n\n  # handlers\n\n  required: (definition, context) ->\n    unless @test_type \"array\", definition\n      thr"
  },
  {
    "path": "src/draft4/strings.coffee",
    "chars": 4410,
    "preview": "module.exports =\n\n  format: (format_name, context) ->\n    if format_name == \"regex\"\n      (data, runtime) =>\n        if "
  },
  {
    "path": "src/draft4/type.coffee",
    "chars": 1232,
    "preview": "\nmodule.exports =\n\n  # handlers\n\n  type: (definition, context) ->\n    if @test_type \"array\", definition\n      if definit"
  },
  {
    "path": "src/draft4.coffee",
    "chars": 287,
    "preview": "validator = require(\"./validator\")\n\nmodule.exports = validator\n  schema_uri: \"http://json-schema.org/draft-04/schema#\"\n "
  },
  {
    "path": "src/index.coffee",
    "chars": 77,
    "preview": "\nmodule.exports =\n  draft3: require \"./draft3\"\n  draft4: require \"./draft4\"\n\n"
  },
  {
    "path": "src/uri.coffee",
    "chars": 486,
    "preview": "is_absolute = (string) ->\n  /^[\\w\\d+.-]+:/.test(string)\n\nis_url = (string) ->\n  /^[\\w\\d+.-]+:\\/\\//.test(string)\n\nresolve"
  },
  {
    "path": "src/util.coffee",
    "chars": 1715,
    "preview": "module.exports =\n  \n  escape: (string) ->\n    string\n      .replace(/~0/g, \"~\")\n      .replace(/~1/g, \"/\")\n      .replac"
  },
  {
    "path": "src/validator.coffee",
    "chars": 11035,
    "preview": "URI = require \"./uri\"\n\n{escape, Runtime, Context} = require \"./util\"\n\n# Schemas should always be JSON stringifiable, so "
  },
  {
    "path": "tasks/build/benchmarks.coffee",
    "chars": 147,
    "preview": "fs = require \"fs\"\nshell = require \"shelljs\"\n\nresult = shell.exec \"coffee benchmarks\"\nfs.writeFileSync \"benchmarks/result"
  },
  {
    "path": "tasks/build/browser.coffee",
    "chars": 239,
    "preview": "{exec} = require \"../helpers\"\n\nrequire \"./javascript\"\n\nbase = \"node_modules/.bin/cjsify lib/index.js --no-node --export "
  },
  {
    "path": "tasks/build/docs.coffee",
    "chars": 51,
    "preview": "{build_docs} = require \"../helpers\"\n\nbuild_docs()\n\n"
  },
  {
    "path": "tasks/build/index.coffee",
    "chars": 44,
    "preview": "require \"./javascript\"\nrequire \"./docs\"\n\n\n\n\n"
  },
  {
    "path": "tasks/build/javascript.coffee",
    "chars": 101,
    "preview": "{exec} = require \"../helpers\"\n\nexec \"mkdir -p lib\"\nexec \"coffee --compile --bare --output lib/ src/\"\n"
  },
  {
    "path": "tasks/helpers.coffee",
    "chars": 580,
    "preview": "shell = require \"shelljs\"\n\nexec = (cmd) ->\n  console.log cmd\n  shell.exec cmd\n\ndocs =\n  \"doc/README.pfm.md\": \"README.md\""
  },
  {
    "path": "tasks/update/index.coffee",
    "chars": 25,
    "preview": "require \"./submodules\"\n\n\n"
  },
  {
    "path": "tasks/update/submodules.coffee",
    "chars": 85,
    "preview": "{exec} = require \"../helpers\"\n\nexec \"git submodule init\"\nexec \"git submodule update\"\n"
  },
  {
    "path": "tasks/watch/docs.coffee",
    "chars": 172,
    "preview": "fs = require \"fs\"\n{docs, build_docs} = require \"../helpers\"\n\nfor source, _dest of docs\n  do (source) ->\n    fs.watchFile"
  },
  {
    "path": "tasks/watch/src.coffee",
    "chars": 112,
    "preview": "fs = require \"fs\"\n{exec} = require \"../helpers\"\n\nexec \"coffee --compile --watch --bare --output lib/ src/\", ->\n\n"
  },
  {
    "path": "test/.gitignore",
    "chars": 16,
    "preview": "suite\nsuite.tgz\n"
  },
  {
    "path": "test/draft3/builtins.coffee",
    "chars": 523,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft3\n\n\nTestify.test \"Built in"
  },
  {
    "path": "test/draft3/index.coffee",
    "chars": 141,
    "preview": "require \"./unit\"\nrequire \"./official\"\nrequire \"./builtins\"\n\n# TODO: implement these tests for draft3\n#require \"./invalid"
  },
  {
    "path": "test/draft3/official.coffee",
    "chars": 1103,
    "preview": "{draft3} = require \"../../src/index\"\nsuite = require \"json-schema-tests\"\n\n[_node, _script, attribute, test_number] = pro"
  },
  {
    "path": "test/draft3/unit/errors.coffee",
    "chars": 432,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft3\n\njsck = new JSCK\n  type:"
  },
  {
    "path": "test/draft3/unit/index.coffee",
    "chars": 64,
    "preview": "#require \"./errors\"\nrequire \"./references\"\nrequire \"./uri_test\"\n"
  },
  {
    "path": "test/draft3/unit/references.coffee",
    "chars": 3003,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../../src/index\").draft3\n\n\nTestify.test \"JSCK "
  },
  {
    "path": "test/draft3/unit/uri_test.coffee",
    "chars": 2314,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nURI = require \"../../../src/uri\"\n\nTestify.test \"URI helper method"
  },
  {
    "path": "test/draft4/adhoc.coffee",
    "chars": 1302,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft4\n\n\nTestify.test \"Ad hoc t"
  },
  {
    "path": "test/draft4/builtins.coffee",
    "chars": 522,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft4\n\n\nTestify.test \"Built in"
  },
  {
    "path": "test/draft4/index.coffee",
    "chars": 97,
    "preview": "require \"./unit\"\nrequire \"./official\"\nrequire \"./invalid\"\nrequire \"./valid\"\nrequire \"./builtins\"\n"
  },
  {
    "path": "test/draft4/invalid/additionalItems.coffee",
    "chars": 328,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be either a boolean or an object\"\n      sc"
  },
  {
    "path": "test/draft4/invalid/additionalProperties.coffee",
    "chars": 221,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be a boolean or an object\"\n      schemas: "
  },
  {
    "path": "test/draft4/invalid/allOf.coffee",
    "chars": 446,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an array\"\n      schemas: for value in j"
  },
  {
    "path": "test/draft4/invalid/anyOf.coffee",
    "chars": 446,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an array\"\n      schemas: for value in j"
  },
  {
    "path": "test/draft4/invalid/dependencies.coffee",
    "chars": 661,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an object\"\n      schemas: for value in "
  },
  {
    "path": "test/draft4/invalid/items.coffee",
    "chars": 359,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be either an object or an array\"\n      sch"
  },
  {
    "path": "test/draft4/invalid/not.coffee",
    "chars": 180,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an object\"\n      schemas: for value in "
  },
  {
    "path": "test/draft4/invalid/numbers.coffee",
    "chars": 211,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"'multipleOf' value MUST be a number\"\n      schemas: f"
  },
  {
    "path": "test/draft4/invalid/oneOf.coffee",
    "chars": 447,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an array\"\n      schemas: for value in j"
  },
  {
    "path": "test/draft4/invalid/patternProperties.coffee",
    "chars": 678,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an object\"\n      schemas: for value in "
  },
  {
    "path": "test/draft4/invalid/properties.coffee",
    "chars": 360,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an object\"\n      schemas: for value in "
  },
  {
    "path": "test/draft4/invalid/required.coffee",
    "chars": 452,
    "preview": "module.exports = ({json_types}) ->\n  [\n\n    {\n      description: \"value MUST be an array\"\n      schemas: for value in js"
  },
  {
    "path": "test/draft4/invalid/strings.coffee",
    "chars": 501,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"'pattern' value must be a string\"\n      schemas: for "
  },
  {
    "path": "test/draft4/invalid/type.coffee",
    "chars": 585,
    "preview": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be either a string or an array\"\n      sche"
  },
  {
    "path": "test/draft4/invalid.coffee",
    "chars": 1321,
    "preview": "glob = require \"glob\"\nassert = require \"assert\"\nTestify = require \"testify\"\n\n{draft4} = require(\"../../src/index\")\n\n[_, "
  },
  {
    "path": "test/draft4/official.coffee",
    "chars": 1394,
    "preview": "{draft4} = require \"../../src/index\"\n\nsuite = require \"json-schema-tests\"\n\n\n#shell = require \"shelljs\"\n#cmd = \"node_modu"
  },
  {
    "path": "test/draft4/unit/errors.coffee",
    "chars": 432,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft3\n\njsck = new JSCK\n  type:"
  },
  {
    "path": "test/draft4/unit/index.coffee",
    "chars": 64,
    "preview": "#require \"./errors\"\nrequire \"./references\"\nrequire \"./uri_test\"\n"
  },
  {
    "path": "test/draft4/unit/logical.coffee",
    "chars": 1222,
    "preview": "Testify = require \"testify\"\nassert = require \"assert\"\n\nJSCK = require(\"../../../src\")\n\njsck = new JSCK.draft4\n  definiti"
  },
  {
    "path": "test/draft4/unit/references.coffee",
    "chars": 3003,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../../src/index\").draft4\n\n\nTestify.test \"JSCK "
  },
  {
    "path": "test/draft4/unit/uri_test.coffee",
    "chars": 2314,
    "preview": "assert = require \"assert\"\nTestify = require \"testify\"\n\nURI = require \"../../../src/uri\"\n\nTestify.test \"URI helper method"
  },
  {
    "path": "test/draft4/valid/basic.coffee",
    "chars": 263,
    "preview": "module.exports = ({json_types}) ->\n\n  \"may contain properties which are not schema keywords\":\n    schemas:\n\n      \"strin"
  },
  {
    "path": "test/draft4/valid/definitions.coffee",
    "chars": 507,
    "preview": "module.exports = ({json_types}) ->\n\n  \"known attribute name as key of 'definitions' dictionary\":\n    schemas:\n\n      req"
  },
  {
    "path": "test/draft4/valid/properties.coffee",
    "chars": 381,
    "preview": "module.exports = ({json_types}) ->\n\n  \"known attribute name\":\n    schemas:\n\n      required:\n        type: \"object\"\n     "
  },
  {
    "path": "test/draft4/valid.coffee",
    "chars": 1078,
    "preview": "glob = require \"glob\"\nassert = require \"assert\"\nTestify = require \"testify\"\n\n{draft4} = require(\"../../src/index\")\n\nhelp"
  },
  {
    "path": "test/index.coffee",
    "chars": 90,
    "preview": "\nrequire \"./draft3/unit\"\nrequire \"./draft3\"\n\nrequire \"./draft4/unit\"\nrequire \"./draft4\"\n\n\n"
  }
]

About this extraction

This page contains the full source code of the pandastrike/jsck GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 107 files (145.5 KB), approximately 42.2k tokens, and a symbol index with 1 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!