[
  {
    "path": ".gitignore",
    "content": "lib\nnode_modules\nmine\n.ruby-gemset\nnpm-debug.log\n*.tgz\n\n"
  },
  {
    "path": ".gitmodules",
    "content": "[submodule \"test/JSON-Schema-Test-Suite\"]\n\tpath = test/JSON-Schema-Test-Suite\n\turl = git@github.com:json-schema/JSON-Schema-Test-Suite.git\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2013 Matthew King\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in\nall copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN\nTHE SOFTWARE.\n\n"
  },
  {
    "path": "README.md",
    "content": "# JSON Schema Compiled checK\n\nJSCK is one of the fastest [JSON Schema](http://json-schema.org) validators for Node.js.\nIt supports JSON Schema drafts\n[3][draft3_doc] and\n[4][draft4_doc],\nwith a few caveats (see the [Coverage section](#coverage) below).\n\n\n## Installation and Usage\n\nInstall with NPM:\n\n    npm install --save jsck\n\n\nRequire:\n\n```coffee\nJSCK = require \"jsck\"\n```\n\nJSCK can create validators from multiple schemas, but this requires that\neach schema be identified with a URI in a top-level \"id\" field.  In many\ncases, only a single schema is needed, and there is no need to uniquely\nidentify the schema.  This is the easiest way to use JSCK, as it is a\ncommon pattern.\n\n\n```coffee\n# Construct a validator for a schema lacking an \"id\" declaration\n\njsck = new JSCK.draft4\n  type: \"object\"\n  properties:\n    user:\n      type: \"object\"\n      required: [\"login\"]\n      properties:\n        login:\n          type: \"string\"\n          pattern: \"^[\\\\w\\\\d_]{3,32}$\"\n        email:\n          type: \"string\"\n          format: \"email\"\n\nconsole.log \"valid document:\", jsck.validate\n  user:\n    login: \"matthew\"\n    email: \"matthew@pandastrike.com\"\n\n{errors} = jsck.validate\n  user:\n    login: \"matthew\"\n    email: \"pandastrike.com\"\n\nconsole.log \"invalid document:\", errors\n\n```\n\n\n\nTo use Draft 3 schemas:\n\n```.coffee\nvalidator = new JSCK.draft3(schema)\n```\n\n\nSee these [advanced usage examples](examples/draft4/advanced.coffee) for help\nworking with multiple schemas.\n\n\n\n## Why JSCK?\n\nJSCK is [faster](#benchmarks) than most other JavaScript/CoffeeScript libraries\nfor validating JSON Schemas because it \"compiles\" the schemas. That is, JSCK\ngenerates the tree of functions needed to validate a particular schema when you\nconstruct a validator. The schema is thus traversed only during preparation, and\nmost of the work of interpreting the schema is done at this time, rather than\nfor every document submitted for validation. This minimizes the work required\nduring validation, which leads to substantial performance improvements over\nnon-compiling validators.\n\n\n\n## Coverage\n\n### Draft 4\n\nJSCK passes all tests in the canonical\n[JSON Schema Test Suite][canonical], except for these items:\n\n* use of `maxLength` and `minLength` with Unicode surrogate pairs.\n* `refRemote` (this is an essential feature we do plan to support)\n* `ref`\n  * remote ref, containing refs itself\n* `uniqueItems`\n* `optional/zeroTerminatedFloats`\n\n\n### Draft 3\n\nCurrently passing the canonical [test suite][canonical] for draft3 except for\nthese items:\n\n* `refRemote`\n* `ref`\n  * remote ref, containing refs itself\n* `uniqueItems`\n* `optional/zeroTerminatedFloats`\n\n### Managing resolution scope with the \"id\" attribute\n\nJSCK does not support the full range of scope manipulations suggested by JSON\nSchema drafts 3 and 4.  Scope manipulation is a controversial topic, and with\nJSCK we have chosen to play it safe, supporting \"id\" declarations only in cases\nthat will (probably) not lead to any ambiguity. Specifically, JSCK uses \"id\"\ndeclarations only in these cases:\n\n* at the top level of a schema, to provide a namespace for schemas not loaded from URIs.\n* non-JSON-pointer fragments (`\"id\": \"#user\"`), which serve merely as aliases for specific subschemas, and are thus convenient and unambiguous.\n\nFor more information on the topic of the \"id\" attribute and scope manipulation,\nsee this issue: https://github.com/json-schema/json-schema/issues/77.\n\n\n## Contributing\n\nTo contribute, hack on it, or run the tests:\n\n```shell\ngit clone git@github.com:pandastrike/jsck.git\ncd jsck\ncoffee tasks/update\nnpm install\n```\n\n### Tests\n\nJSCK uses the official [JSON Schema Test Suite][canonical] as well as some\ncustom tests. To run all tests for all versions:\n\n    coffee test\n\nSee [this document](doc/tests.md) for more information on working with JSCK tests.\n\n\n## Benchmarks\n\nJSCK has fairly comprehensive benchmarks which show it to be one of the very\nfastest JSON Schema validators available for Node.js. Pull requests welcome, of\ncourse.\n\nBecause performance varies (at very least) based on the complexity\nof the schema being validated, we run benchmarks against several different\nschemas, ranging from quite simple to moderately complex.\n\nFor JSON Schema Draft4, we run benchmarks against JSCK, tv4, jayschema,\nz-schema, and other validators.  On the\n[trivial schema](benchmarks/draft4/trivial/schema.coffee),\nour benchmarks produce this relative performance for these validators\n(lower is better):\n\n```coffee\najv : 1\njsen : 2.9\nis-my-json-valid : 4.4\nThemis (minimal) : 5.2\nThemis : 5.3\nJSCK : 34.2\nz-schema : 48.3\ntv4 : 54.4\njayschema : 2507.4\n```\n\n\nFor the schema of [medium complexity](benchmarks/draft4/medium/schema.coffee),\nour benchmarks produce this relative performance for the tested validators\n(lower is better):\n\n```coffee\najv : 1\nis-my-json-valid : 2.8\njsen : 3.0\nThemis (minimal) : 11.1\nThemis : 11.6\nJSCK : 22.0\ntv4 : 43.4\nz-schema : 46.0\njayschema : 2319.4\n```\n\nFor the schema of [higher complexity](benchmarks/draft4/complex/schema.coffee),\nour benchmarks produce this relative performance for the tested validators\n(lower is better):\n\n```coffee\najv : 1\nis-my-json-valid : 1.23\njsen : 1.31\nThemis (minimal) : 1.7\nThemis : 1.8\nJSCK : 4.8\nz-schema : 17.2\ntv4 : 27.0\njayschema : 1215.1\n```\n\nAs the complexity of the schema increases, the performance benefits of the\ncompilation model become more evident.\n\n\nSee [this document](doc/benchmarks.md) for detailed results and information on\nrunning and creating benchmarks.\n\n\n\n[draft3_doc]:http://tools.ietf.org/html/draft-zyp-json-schema-03\n[draft3_impl]:https://github.com/json-schema/json-schema/tree/master/draft-03\n[draft4_doc]:http://tools.ietf.org/html/draft-zyp-json-schema-04\n[canonical]:https://github.com/json-schema/JSON-Schema-Test-Suite\n"
  },
  {
    "path": "benchmarks/benchmark.coffee",
    "content": "microtime = require \"microtime\"\nrequire \"./statistics\"\n\nmodule.exports = class Benchmark\n\n  @compare: (benchmarks, options) ->\n    out = {}\n    for benchmark in benchmarks\n      out[benchmark.name] = benchmark.run(options)\n    out\n\n  constructor: (@name, callback) ->\n    callback(@)\n\n  setup: (@_setup) ->\n\n  measure: (@_measure) ->\n\n  run: ({samples, warmup}) ->\n    console.error \"  #{@name}\"\n    results = []\n    subject = @_setup()\n\n    if warmup\n      process.stderr.write \"  Warming up: \"\n      for i in [1..warmup]\n        @_measure(subject)\n        process.stderr.write \".\"\n      process.stderr.write(\"\\n\")\n\n    process.stderr.write \"  Iterations: \"\n    for i in [1..samples]\n      t0 = microtime.now()\n      @_measure(subject)\n      t1 = microtime.now()\n      results.push (t1 - t0) / 1000\n      process.stderr.write \".\"\n    console.error(\"\\n\")\n    results\n\n\n"
  },
  {
    "path": "benchmarks/draft3/index.coffee",
    "content": "console.log \"## Benchmarks for Draft 3\"\nconsole.log\n\nrequire \"./trivial/\"\nrequire \"./medium/\"\n"
  },
  {
    "path": "benchmarks/draft3/medium/index.coffee",
    "content": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Configuration\"\n  repeats: 128\n  schema: require \"./schema\"\n  document: require \"./valid_doc\"\n}\n\n\n\n"
  },
  {
    "path": "benchmarks/draft3/medium/schema.coffee",
    "content": "module.exports =\n  description: \"A moderately complex schema with some nesting and value constraints\"\n  type: \"object\"\n  additionalProperties: false\n  properties:\n\n    api_server:\n      description: \"Settings for the HTTP API server\"\n      type: \"object\"\n      additionalProperties: false\n      required: true\n      properties:\n        url:\n          type: \"string\"\n          format: \"uri\"\n          required: true\n        host:\n          type: \"string\"\n          required: true\n        port:\n          type: \"integer\"\n          minimum: 1000\n          required: true\n\n    transport:\n      description: \"Settings for the Redis tranport\"\n      additionalProperties: false\n      required: true\n      properties:\n        server:\n          type: \"string\"\n          required: true\n        options:\n          type: \"object\"\n        queues:\n          properties:\n            blocking_timeout:\n              type: \"integer\"\n              minimum: 0\n\n    storage:\n      description: \"Settings for the PostgreSQL storage\"\n      required: true\n      properties:\n        server:\n          type: \"string\"\n          required: true\n        database:\n          type: \"string\"\n          required: true\n        user:\n          type: \"string\"\n          required: true\n        options:\n          type: \"object\"\n\n    chain:\n      description: \"Settings for the Chain.com client\"\n      required: true\n      properties:\n        api_key_id:\n          type: \"string\"\n          required: true\n        api_key_secret:\n          type: \"string\"\n          required: true\n\n"
  },
  {
    "path": "benchmarks/draft3/medium/valid_doc.coffee",
    "content": "module.exports =\n  api_server:\n    url: \"http://example.com:8998\"\n    host: \"example.com\"\n    port: 8998\n\n  transport:\n    server: \"127.0.0.1:6381\"\n    queues:\n      blocking_timeout: 0\n\n  storage:\n    server: \"127.0.0.1:5432\"\n    database: \"thingy-test\"\n    user: \"thingy-test\"\n    password: \"password\"\n\n  chain:\n    api_key_id: \"cafebabe\"\n    api_key_secret: \"babecafe\"\n\n\n"
  },
  {
    "path": "benchmarks/draft3/trivial/index.coffee",
    "content": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Event\"\n  repeats: 512\n  schema: require \"./schema\"\n  document: require \"./valid_doc\"\n}\n\n"
  },
  {
    "path": "benchmarks/draft3/trivial/schema.coffee",
    "content": "module.exports =\n  description: \"A simple schema, exercising very few attributes\"\n  type: \"object\"\n  additionalProperties: false\n  properties:\n    origin:\n      required: true\n      type: \"string\"\n    name:\n      type: \"string\"\n      required: true\n    tags:\n      type: \"array\"\n      items: {type: \"string\"}\n    timestamp:\n      type: \"integer\"\n    data: { type: \"object\" }\n\n"
  },
  {
    "path": "benchmarks/draft3/trivial/valid_doc.coffee",
    "content": "module.exports =\n  origin: \"monkey\"\n  name: \"shines\"\n  tags: [\"in\", \"the\", \"closet\"]\n  timestamp: Date.now()\n  data:\n    uno: 1\n    dos: 2\n\n"
  },
  {
    "path": "benchmarks/draft3/validators.coffee",
    "content": "module.exports =\n\n  \"JSCK\":\n    setup: (schema) ->\n      JSCK = require \"../../src/draft3\"\n      new JSCK(schema)\n    validate: ({validator, schema, document}) ->\n      validator.validate(document)\n    error: (result) ->\n      if result.valid == true\n        false\n      else\n        result.errors\n\n\n  \"amanda\":\n    setup: (schema) ->\n      amanda = require \"amanda\"\n    validate: ({validator, schema, document}) ->\n      result = null\n      validator.validate document, schema, (error) ->\n        result = error\n      result\n    error: (result) ->\n      result || false\n\n\n  \"JSV\":\n    setup: (schema) ->\n      JSV = require(\"JSV\").JSV\n      jsv = JSV.createEnvironment(\"json-schema-draft-03\")\n      jsv.createSchema(schema)\n    validate: ({validator, schema, document}) ->\n      validator.validate(document)\n    error: (result) ->\n      if result.errors.length == 0\n        false\n      else\n        result.errors\n\n\n  \"json-gate\":\n    setup: (schema) ->\n      jsonGateCreateSchema = require(\"json-gate\").createSchema\n      jsonGateCreateSchema(schema)\n    validate: ({validator, schema, document}) ->\n      try\n        validator.validate(document)\n      catch e\n        e\n    error: (result) ->\n      result || false\n\n\n"
  },
  {
    "path": "benchmarks/draft4/complex/index.coffee",
    "content": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Transaction\"\n  repeats: 64\n  schema: require \"./schema\"\n  document: require \"./valid_doc\"\n}\n\n\n"
  },
  {
    "path": "benchmarks/draft4/complex/schema.coffee",
    "content": "\nmodule.exports =\n  type: \"array\"\n  items: {$ref: \"#transaction\"}\n  minItems: 1\n\n  definitions:\n\n    base58:\n      id: \"#base58\"\n      # https://en.bitcoin.it/wiki/Base58Check_encoding\n      type: \"string\"\n      pattern: \"^[123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz]+$\"\n\n    hex:\n      id: \"#hex\"\n      type: \"string\"\n      pattern: \"^[0123456789A-Fa-f]+$\"\n\n    tx_id:\n      id: \"#tx_id\"\n      allOf: [\n        {$ref: \"#hex\"}\n        {\n          minLength: 64\n          maxLength: 64\n        }\n      ]\n\n    address:\n      id: \"#address\"\n      allOf: [\n        {$ref: \"#base58\"}\n        {\n          minLength: 34\n          maxLength: 34\n        }\n      ]\n\n    signature:\n      id: \"#signature\"\n      allOf: [\n        {$ref: \"#hex\"}\n        {\n          minLength: 128\n          maxLength: 128\n        }\n      ]\n\n\n    transaction:\n      id: \"#transaction\"\n      additionalProperties: false\n      required: [\"metadata\", \"hash\", \"inputs\", \"outputs\"]\n      properties:\n\n        metadata:\n          type: \"object\"\n          required: [\"amount\", \"fee\"]\n          properties:\n            amount:\n              type: \"integer\"\n            fee:\n              type: \"integer\"\n              multipleOf: 10000\n            status:\n              type: \"string\"\n              enum: [\"unsigned\", \"unconfirmed\", \"confirmed\", \"invalid\"]\n            confirmations:\n              type: \"integer\"\n              minimum: 0\n            block_time:\n              type: \"integer\"\n\n        version: {type: \"integer\"}\n        lock_time: {type: \"integer\"}\n        hash: {$ref: \"#tx_id\"}\n        inputs:\n          type: \"array\"\n          items: {$ref: \"#input\"}\n          minItems: 1\n        outputs:\n          type: \"array\"\n          items: {$ref: \"#output\"}\n          minItems: 1\n\n\n\n    input:\n      id: \"#input\"\n      type: \"object\"\n      additionalProperties: false\n      required: [\"index\", \"output\", \"script_sig\"]\n      properties:\n        index:\n          type: \"integer\"\n          minimum: 0\n        output: {$ref: \"#output\"}\n        sig_hash: {$ref: \"#hex\"}\n        script_sig: {$ref: \"#hex\"}\n        signatures:\n          type: \"object\"\n          description: \"A dictionary of signatures.  Keys represent keypair names\"\n          minProperties: 1\n          maxProperties: 3\n          additionalProperties: {$ref: \"#signature\"}\n\n\n    output:\n      id: \"#output\"\n      type: \"object\"\n      additionalProperties: false\n      required: [\"hash\", \"index\", \"value\", \"script\"]\n      properties:\n        hash: {$ref: \"#tx_id\"}\n        index:\n          type: \"integer\"\n          minimum: 0\n        value:\n          type: \"integer\"\n        script:\n          type: \"object\"\n          properties:\n            type:\n              type: \"string\"\n              enum: [\"standard\", \"p2sh\"]\n            asm:\n              type: \"string\"\n        address: {$ref: \"#address\"}\n        metadata:\n          type: \"object\"\n          dependencies:\n            # if a wallet path is given, the metadata must also contain the\n            # HDW public seed values.  Use case would be for verifying that\n            # a change output is going to a legit address.\n            wallet_path: [\"public_seeds\"]\n          properties:\n            wallet_path:\n              type: \"string\"\n            public_seeds:\n              type: \"object\"\n              minProperties: 1\n              maxProperties: 3\n              additionalProperties:\n                anyOf: [\n                  {$ref: \"#base58\"}\n                  {$ref: \"#hex\"}\n                ]\n\n"
  },
  {
    "path": "benchmarks/draft4/complex/test.coffee",
    "content": "\nJSCK = require \"../../../src/draft4\"\nschema = require \"./schema\"\nvalid_doc = require \"./valid_doc\"\n\nschema =\n  type: \"array\"\n  items: {$ref: \"#smurf\"}\n  minItems: 1\n\n  definitions:\n\n    smurf:\n      id: \"#smurf\"\n      type: \"object\"\n\n\nvalid_doc = [\n  {}\n]\n\njsck = new JSCK(schema)\nreport = jsck.validate(valid_doc)\nconsole.log \"JSCK\"\nconsole.log JSON.stringify(report, null, 2)\n\nZSchema = require(\"z-schema\")\nvalidator = new ZSchema()\n\nconsole.log \"ZSchema\"\nconsole.log validator.validate(valid_doc, schema)\nconsole.log validator.getLastErrors()\n\nconsole.log \"JSONSchema\"\nJSONSchema = require('jsonschema').Validator\nvalidator = new JSONSchema()\n{errors} = validator.validate(valid_doc, schema)\nconsole.log errors\n"
  },
  {
    "path": "benchmarks/draft4/complex/valid_doc.coffee",
    "content": "$ = module.exports = []\n\n$.push\n  metadata:\n    amount: 38043749285\n    fee: 2 * 10000\n    status: \"confirmed\"\n    confirmations: 73\n    block_time: 1415993584376\n  version: 1\n  lock_time: 0\n  hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n\n  inputs: [\n    index: 0\n    script_sig: \"3046022100be69797cf5d784412b1258256eb657c191a04893479dfa2ae5c7f2088c7adbe0022100e6b000bd633b286ed1b9bc7682fe753d9fdad61fbe5da2a6e9444198e33a670f01\"\n    signatures:\n      primary: \"3046022100be69797cf5d784412b1258256eb657c191a04893479dfa2ae5c7f2088c7adbe0022100e6b000bd633b286ed1b9bc7682fe753d9fdad61fbe5da2a7\"\n      cosigner: \"a2ad5ebf16dadf9d357ef2867cb9b1de682b336db000b6e0012200ebda7c8802f7c5ea2afd97439840a191c756be6528521b214487d5fc79796eb00122064037\"\n    output:\n      hash: \"6b040cd7a4676b5c7b11f144e73c1958c177fcd79e934f6be8ce02c8cd12546d\"\n      index: 1\n      value: 38043749285\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG\"\n\n  ]\n\n  outputs: [\n\n    {\n      hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n      index: 0\n      value: 38042249285\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG\"\n      address: \"1CRZRBwfuwUaVSPJtd6DBuezbm7XPBHLa1\"\n      metadata:\n        type: \"change\"\n        wallet_path: \"m/44/0/1/356\"\n        public_seeds:\n          primary: \"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8\"\n          cosigner: \"xpub661MyMwAqRbcFtXgS5sYJABqqG9YLmC4Q1Rdap9gSE8NqtwybGhePY2gZ29ESFjqJoCu1Rupje8YtGqsefD265TMg7usUDFdp6W1EGMcet8\"\n\n    }\n\n    {\n\n      hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n      index: 1\n      value: 1500000\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 3bc576e6960a9d45201ba5087e39224d0a05a079 OP_EQUALVERIFY OP_CHECKSIG\"\n      address: \"16T3RPZLmxtXQCgWi1S8kef5Ca6jqXhoeT\"\n    }\n  ]\n\n$.push\n  metadata:\n    amount: 38043749285\n    fee: 2 * 10000\n    status: \"unconfirmed\"\n    confirmations: 73\n    block_time: 1415993584376\n  version: 1\n  lock_time: 0\n  hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n\n  inputs: [\n    index: 0\n    script_sig: \"3046022100be69797cf5d784412b1258256eb657c191a04893479dfa2ae5c7f2088c7adbe0022100e6b000bd633b286ed1b9bc7682fe753d9fdad61fbe5da2a6e9444198e33a670f01\"\n    output:\n      hash: \"6b040cd7a4676b5c7b11f144e73c1958c177fcd79e934f6be8ce02c8cd12546d\"\n      index: 1\n      value: 38043749285\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG\"\n\n  ]\n\n  outputs: [\n\n    {\n      hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n      index: 0\n      value: 38042249285\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG\"\n      address: \"1CRZRBwfuwUaVSPJtd6DBuezbm7XPBHLa1\"\n      metadata:\n        type: \"change\"\n\n    }\n\n    {\n\n      hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n      index: 1\n      value: 1500000\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 3bc576e6960a9d45201ba5087e39224d0a05a079 OP_EQUALVERIFY OP_CHECKSIG\"\n      address: \"16T3RPZLmxtXQCgWi1S8kef5Ca6jqXhoeT\"\n    }\n  ]\n\n$.push\n  metadata:\n    amount: 38043749285\n    fee: 2 * 10000\n    status: \"unconfirmed\"\n    confirmations: 73\n    block_time: 1415993584376\n  version: 1\n  lock_time: 0\n  hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n\n  inputs: [\n    index: 0\n    script_sig: \"3046022100be69797cf5d784412b1258256eb657c191a04893479dfa2ae5c7f2088c7adbe0022100e6b000bd633b286ed1b9bc7682fe753d9fdad61fbe5da2a6e9444198e33a670f01\"\n    output:\n      hash: \"6b040cd7a4676b5c7b11f144e73c1958c177fcd79e934f6be8ce02c8cd12546d\"\n      index: 1\n      value: 38043749285\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG\"\n\n  ]\n\n  outputs: [\n\n    {\n      hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n      index: 0\n      value: 38042249285\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 7d4e6d55e1dffb0df85f509343451d170d147551 OP_EQUALVERIFY OP_CHECKSIG\"\n      address: \"1CRZRBwfuwUaVSPJtd6DBuezbm7XPBHLa1\"\n      metadata:\n        type: \"change\"\n\n    }\n\n    {\n\n      hash: \"60c1f1a3160042152114e2bba45600a5045711c3a8a458016248acec59653471\"\n      index: 1\n      value: 1500000\n      script:\n        type: \"standard\"\n        asm: \"OP_DUP OP_HASH160 3bc576e6960a9d45201ba5087e39224d0a05a079 OP_EQUALVERIFY OP_CHECKSIG\"\n      address: \"16T3RPZLmxtXQCgWi1S8kef5Ca6jqXhoeT\"\n    }\n  ]\n\n"
  },
  {
    "path": "benchmarks/draft4/index.coffee",
    "content": "console.log \"## Benchmarks for Draft 4\"\nconsole.log\n\nrequire \"./trivial/\"\nrequire \"./medium/\"\nrequire \"./complex/\"\n\n"
  },
  {
    "path": "benchmarks/draft4/medium/index.coffee",
    "content": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Configuration\"\n  repeats: 256\n  schema: require \"./schema\"\n  document: require \"./valid_doc\"\n}\n\n"
  },
  {
    "path": "benchmarks/draft4/medium/schema.coffee",
    "content": "module.exports =\n  description: \"A moderately complex schema with some nesting and value constraints\"\n  type: \"object\"\n  additionalProperties: false\n  required: [\"api_server\", \"transport\", \"storage\", \"chain\"]\n  properties:\n\n    api_server:\n      description: \"Settings for the HTTP API server\"\n      type: \"object\"\n      additionalProperties: false\n      required: [\"url\", \"host\", \"port\"]\n      properties:\n        url:\n          type: \"string\"\n          format: \"uri\"\n        host:\n          type: \"string\"\n        port:\n          type: \"integer\"\n          minimum: 1000\n\n    transport:\n      description: \"Settings for the Redis tranport\"\n      additionalProperties: false\n      required: [\"server\"]\n      properties:\n        server:\n          type: \"string\"\n        options:\n          type: \"object\"\n        queues:\n          properties:\n            blocking_timeout:\n              type: \"integer\"\n              minimum: 0\n\n    storage:\n      description: \"Settings for the PostgreSQL storage\"\n      required: [\"server\", \"database\", \"user\"]\n      properties:\n        server:\n          type: \"string\"\n        database:\n          type: \"string\"\n        user:\n          type: \"string\"\n        options:\n          type: \"object\"\n\n    chain:\n      description: \"Settings for the Chain.com client\"\n      required: [\"api_key_id\", \"api_key_secret\"]\n      properties:\n        api_key_id:\n          type: \"string\"\n        api_key_secret:\n          type: \"string\"\n\n"
  },
  {
    "path": "benchmarks/draft4/medium/valid_doc.coffee",
    "content": "module.exports =\n  api_server:\n    url: \"http://example.com:8998\"\n    host: \"example.com\"\n    port: 8998\n\n  transport:\n    server: \"127.0.0.1:6381\"\n    queues:\n      blocking_timeout: 0\n\n  storage:\n    server: \"127.0.0.1:5432\"\n    database: \"thingy-test\"\n    user: \"thingy-test\"\n    password: \"password\"\n\n  chain:\n    api_key_id: \"cafebabe\"\n    api_key_secret: \"babecafe\"\n\n\n"
  },
  {
    "path": "benchmarks/draft4/trivial/index.coffee",
    "content": "validators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Event - Valid document\"\n  repeats: 1024\n  schema: require \"./schema\"\n  document: require \"./valid_doc\"\n}\n\n"
  },
  {
    "path": "benchmarks/draft4/trivial/schema.coffee",
    "content": "module.exports =\n  description: \"A simple schema, exercising very few attributes\"\n  type: \"object\"\n  additionalProperties: false\n  required: [\"origin\", \"name\", \"tags\", \"timestamp\", \"data\"]\n  properties:\n    origin:\n      type: \"string\"\n    name:\n      type: \"string\"\n    tags:\n      type: \"array\"\n      items: {type: \"string\"}\n    timestamp:\n      type: \"integer\"\n    data: { type: \"object\" }\n\n"
  },
  {
    "path": "benchmarks/draft4/trivial/valid_doc.coffee",
    "content": "module.exports =\n  origin: \"monkey\"\n  name: \"shines\"\n  tags: [\"in\", \"the\", \"closet\"]\n  timestamp: Date.now()\n  data:\n    uno: 1\n    dos: 2\n\n"
  },
  {
    "path": "benchmarks/draft4/validators.coffee",
    "content": "module.exports =\n\n  \"JSCK\":\n    setup: (schema) ->\n      JSCK = require \"../../src/draft4\"\n      new JSCK(schema)\n    validate: ({validator, schema, document}) ->\n      validator.validate(document)\n    error: (result) ->\n      if result.valid == true\n        false\n      else\n        result.errors\n\n  \"ajv\":\n    setup: (schema) ->\n      ajv = require(\"ajv\")()\n      ajv.compile(schema)\n    validate: ({validator, schema, document}) ->\n      validator(document)\n    error: (result) ->\n      if result == true\n        false\n      else\n        validator.errors\n\n  \"tv4\":\n    setup: (schema) ->\n      require(\"tv4\").tv4\n    validate: ({validator, schema, document}) ->\n      validator.validateResult(document, schema)\n    error: (result) ->\n      if result.valid == true\n        false\n      else\n        result.error\n\n  \"Themis (minimal)\":\n    setup: (schema) ->\n      Themis = require('themis')\n      Themis.validator(schema, {\n        enable_defaults: false,\n        algorithm: 'none',\n        errors: { messages: false, validator_value: false, schema: false } })\n    validate: ({validator, schema, document}) ->\n      validator(document, '0')\n    error: (result) ->\n      if result.valid == true\n        false\n      else\n        result.errors\n\n  \"Themis\":\n    setup: (schema) ->\n      Themis = require('themis')\n      Themis.validator(schema)\n    validate: ({validator, schema, document}) ->\n      validator(document, '0')\n    error: (result) ->\n      if result.valid == true\n        false\n      else\n        result.errors\n\n  \"jayschema\":\n    setup: (schema) ->\n      JaySchema = require(\"jayschema\")\n      new JaySchema()\n    validate: ({validator, schema, document}) ->\n      validator.validate(document, schema)\n    error: (result) ->\n      if result.length == 0\n        false\n      else\n        result\n\n  \"is-my-json-valid\":\n    setup: (schema) ->\n      require(\"is-my-json-valid\")(schema)\n    validate: ({validator, schema, document}) ->\n      validator(document)\n    error: (result) ->\n      if result == true\n        false\n      else\n        validator.errors\n\n\n  # Putting z-schema last because it appears to be affecting other libs'\n  # performance if run first.\n  \"z-schema\":\n    setup: (schema) ->\n      z = require(\"z-schema\")\n      validator = new z()\n      url = \"http://json-schema.org/draft-04/schema\"\n      # don't actually download the draft, because GitHub Pages might be down.\n      actualDraft = require(\"fs\").readFileSync(\"./test/json-schema/draft-04/schema\", \"utf8\")\n      validator.setRemoteReference(url, JSON.parse(actualDraft))\n      validator\n\n    validate: ({validator, schema, document}) ->\n      valid = validator.validate(document, schema)\n      if valid == false\n        validator.getLastErrors()\n\n\n    error: (result) ->\n      result || false\n\n  \"jsen\":\n    setup: (schema) ->\n      require(\"jsen\")(schema)\n    validate: ({validator, schema, document}) ->\n      validator(document)\n    error: (result) ->\n      if result == true\n        false\n      else\n        validator.errors\n"
  },
  {
    "path": "benchmarks/index.coffee",
    "content": "require \"./draft3/\"\nrequire \"./draft4/\"\n\n"
  },
  {
    "path": "benchmarks/results/all.txt",
    "content": "## Benchmarks for Draft 3\n\nSchema: 'Event'.  A simple schema, exercising very few attributes\nSample size: 64\nValidations per sample: 512\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  amanda\n  Warming up: ................................\n  Iterations: ................................................................\n\n  JSV\n  Warming up: ................................\n  Iterations: ................................................................\n\n  json-gate\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 193.025    max: 202.692    min: 175.945 \n\n  amanda: validations/millisecond\n  median: 4.258    max: 4.608    min: 3.778 \n\n  JSV: validations/millisecond\n  median: 2.685    max: 2.748    min: 2.43 \n\n  json-gate: validations/millisecond\n  median: 82.514    max: 86.036    min: 48.234 \n\nRelative speeds:\nJSCK : 1.000\njson-gate : 2.339\namanda : 45.337\nJSV : 71.896\n\n\nSchema: 'Configuration'.  A moderately complex schema with some nesting and value constraints\nSample size: 64\nValidations per sample: 128\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  amanda\n  Warming up: ................................\n  Iterations: ................................................................\n\n  JSV\n  Warming up: ................................\n  Iterations: ................................................................\n\n  json-gate\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 108.936    max: 109.966    min: 85.964 \n\n  amanda: validations/millisecond\n  median: 3.788    max: 5.651    min: 2.371 \n\n  JSV: validations/millisecond\n  median: 1.344    max: 1.359    min: 1.255 \n\n  json-gate: validations/millisecond\n  median: 44.176    max: 45.845    min: 41.803 \n\nRelative speeds:\nJSCK : 1.000\njson-gate : 2.466\namanda : 28.760\nJSV : 81.025\n\n## Benchmarks for Draft 4\n\nSchema: 'Event - Valid document'.  A simple schema, exercising very few attributes\nSample size: 64\nValidations per sample: 1024\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  tv4\n  Warming up: ................................\n  Iterations: ................................................................\n\n  z-schema\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 186.81    max: 191.617    min: 138.716 \n\n  tv4: validations/millisecond\n  median: 54.377    max: 55.907    min: 46.942 \n\n  z-schema: validations/millisecond\n  median: 93.657    max: 93.979    min: 89.44 \n\nRelative speeds:\nJSCK : 1.000\nz-schema : 1.995\ntv4 : 3.435\n\n\nSchema: 'Configuration'.  A moderately complex schema with some nesting and value constraints\nSample size: 64\nValidations per sample: 256\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  tv4\n  Warming up: ................................\n  Iterations: ................................................................\n\n  z-schema\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 118.573    max: 119.07    min: 105.22 \n\n  tv4: validations/millisecond\n  median: 19.608    max: 20.389    min: 16.505 \n\n  z-schema: validations/millisecond\n  median: 40.606    max: 40.934    min: 34.934 \n\nRelative speeds:\nJSCK : 1.000\nz-schema : 2.920\ntv4 : 6.047\n\n\nSchema: 'Transaction'.  \nSample size: 64\nValidations per sample: 64\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  tv4\n  Warming up: ................................\n  Iterations: ................................................................\n\n  z-schema\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 12.814    max: 14.873    min: 6.984 \n\n  tv4: validations/millisecond\n  median: 1.946    max: 1.965    min: 1.832 \n\n  z-schema: validations/millisecond\n  median: 3.768    max: 3.836    min: 3.297 \n\nRelative speeds:\nJSCK : 1.000\nz-schema : 3.401\ntv4 : 6.583\n\n"
  },
  {
    "path": "benchmarks/runner.coffee",
    "content": "# stdlib\nutil = require \"util\"\n\n# our simple benchmarking library\nBenchmark = require \"./benchmark.coffee\"\nsamples = 64\n\nmodule.exports = (validators) ->\n\n  benchmark: ({name, schema, document, repeats}) ->\n\n    libraries = []\n\n    for library, {setup, validate, error} of validators\n\n      ## preflight to check for incorrect validation errors\n      ## Currently disabled because of issues with z-schema.\n      #validator = setup(schema)\n      #e = error(validate({validator, schema, document}))\n      #if e\n        #console.log \"Aborting because #{library} declared the document invalid:\"\n        #console.log e\n        #process.exit(1)\n\n      do (setup, validate) ->\n        libraries.push new Benchmark library, (bm) ->\n          bm.setup ->\n            setup(schema)\n          bm.measure (validator) ->\n            for i in [1..repeats]\n              validate({validator, schema, document})\n\n\n    console.log \"\"\"\n\n      Schema: '#{name}'.  #{schema.description || ''}\n      Sample size: #{samples}\n      Validations per sample: #{repeats}\n\n    \"\"\"\n\n\n    \n    results = Benchmark.compare libraries, {samples, warmup: 32}\n\n    console.log()\n    x = for name, result of results\n      {median, max, min} = result.summarize()\n\n      console.log \"  #{name}: validations/millisecond\"\n      console.log util.format \"  median: %d    max: %d    min: %d \",\n        (repeats * 1 / median).toFixed(3),\n        (repeats * 1 / min).toFixed(3),\n        (repeats * 1 / max).toFixed(3)\n\n      console.log()\n      [name, median]\n\n    sorted = x.sort (a, b) ->\n      a[1] > b[1]\n\n    fastest = sorted[0]\n    ftime = fastest[1]\n\n    console.log \"Relative speeds:\"\n    for [name, time] in x\n      console.log name, \":\", (time / ftime).toFixed(3)\n    console.log()\n\n"
  },
  {
    "path": "benchmarks/statistics.js",
    "content": "/****************************************************************************************************\nJavaScript Math and Statistics Library\n\n@file\t\tpseudoMathStats.js\n@version\t1.0\n@author \tPaul Ellis\n@url        http://code.google.com/p/pseudosavant\n@copyright \tCopyright 2010, Paul Ellis\n@license    BSD\n****************************************************************************************************/\n\n\n/****************************************************************************************************\nCalculates the Standard Deviation of an array\n****************************************************************************************************/\nArray.prototype.stdDev = function ()\n{\n    // Calculate Mean\n    var mean = this.mean();\n\n    var length = this.length;\n\n    // Calculate Variance\n    for (var i = 0, sumOfSquares = 0; i < length; i++)\n    {\n        sumOfSquares += Math.pow(this[i] - mean, 2);\n    }\n    var stdDev = Math.sqrt(sumOfSquares / length);\n\n    return stdDev;\n}\n\n\n/****************************************************************************************************\nCalculates the Variance of an array\n****************************************************************************************************/\nArray.prototype.variance = function ()\n{\n    // Calculate Mean\n    var mean = this.mean();\n\n    var length = this.length;\n\n    // Calculate Variance\n    for (var i = 0, sumOfSquares = 0; i < length; i++)\n    {\n        sumOfSquares += Math.pow(this[i] - mean, 2);\n    }\n    var variance = sumOfSquares / length;\n\n    return variance;\n}\n\n\n/****************************************************************************************************\nSums all values in an array\n****************************************************************************************************/\nArray.prototype.sum = function ()\n{\n    for (var i = 0, length = this.length, sum = 0; i < length; sum += this[i++]);\n    return sum;\n}\n\n\n/****************************************************************************************************\nCalculates the arithmetic mean of an array\n****************************************************************************************************/\nArray.prototype.mean = function ()\n{\n    for (var i = 0, length = this.length, sum = 0; i < length; sum += this[i++]);\n    var mean = sum / length;\n    return mean;\n}\n\n\n/****************************************************************************************************\nReturns the highest numeric value of an array\n****************************************************************************************************/\nArray.prototype.max = function ()\n{\n  return this.reduceRight(function(i,j){if(j<i){return i}else{return j} });\n}\n\n\n/****************************************************************************************************\nReturns the lowest numeric value of an array\n****************************************************************************************************/\nArray.prototype.min = function ()\n{\n  return this.reduceRight(function(i,j){if(j>i){return i}else{return j} });\n}\n\n\n/****************************************************************************************************\nCalculates the median of an array\n****************************************************************************************************/\nArray.prototype.median = function ()\n{\n    var length = this.length;\n\n    if (length % 2 == 1) // Odd\n    {\n        var middle = Math.floor(length / 2);\n        var median = this.sortNumber()[middle];\n    }\n    else // Even\n    {\n        var middle = length / 2;\n        var sorted = this.sortNumber();\n        var median = (sorted[middle-1] + sorted[middle]) / 2;\n    }\n    return median;\n}\n\n\n/****************************************************************************************************\nReturns the array sorted ascendingly, or decendingly if sortNumber(true).\n****************************************************************************************************/\nArray.prototype.sortNumber = function (invert)\n{\n    if (invert == true) // Decending\n    {\n      return this.slice().sort(function (a, b) { return a - b }).reverse(); // Using reverse() is faster than b - a.\n    }\n    else // Ascending, default\n    {\n      return this.slice().sort(function (a, b) { return a - b });\n    }\n}\n\n\n/****************************************************************************************************\nReturns an object containing the most common stats for the array.\n****************************************************************************************************/\nArray.prototype.summarize = function summarize (places) {\n  if (!this.length) { return { error: \"no values\" }; }\n  return {\n    max: fixedDecimal(this.max(), places),\n    median: fixedDecimal(this.median(), places),\n    min: fixedDecimal(this.min(), places),\n    mean: fixedDecimal(this.mean(), places),\n    stdDev: fixedDecimal(this.stdDev(), places),\n    sample_size: this.length,\n  };\n};\n\n\nvar fixedDecimal = function fixedDecimal (num, numOfDec) {\n\tvar pow10s = Math.pow( 10, numOfDec || 0 );\n\treturn ( numOfDec ) ? Math.round( pow10s * num ) / pow10s : num;\n};\n\n\n/****************************************************************************************************\nLower tail quantile for standard normal distribution function.\n\nWritten by Alankar Misra (alankar@digitalsutras.com)\nAlgorithm by Peter John Acklam (pjacklam@online.no, http://home.online.no/~pjacklam)\n****************************************************************************************************/\nfunction normsinv(p)\n{\n    // Coefficients in rational approximations\n    var a = new Array(-3.969683028665376e+01, 2.209460984245205e+02,\n                      -2.759285104469687e+02, 1.383577518672690e+02,\n                      -3.066479806614716e+01, 2.506628277459239e+00);\n\n    var b = new Array(-5.447609879822406e+01, 1.615858368580409e+02,\n                      -1.556989798598866e+02, 6.680131188771972e+01,\n                      -1.328068155288572e+01);\n\n    var c = new Array(-7.784894002430293e-03, -3.223964580411365e-01,\n                      -2.400758277161838e+00, -2.549732539343734e+00,\n                      4.374664141464968e+00, 2.938163982698783e+00);\n\n    var d = new Array(7.784695709041462e-03, 3.224671290700398e-01,\n                       2.445134137142996e+00, 3.754408661907416e+00);\n\n    // Define break-points.\n    var plow = 0.02425;\n    var phigh = 1 - plow;\n\n    // Rational approximation for lower region:\n    if (p < plow)\n    {\n        var q = Math.sqrt(-2 * Math.log(p));\n        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);\n    }\n\n    // Rational approximation for upper region:\n    if (phigh < p)\n    {\n        var q = Math.sqrt(-2 * Math.log(1 - p));\n        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);\n    }\n\n    // Rational approximation for central region:\n    var q = p - 0.5;\n    var r = q * q;\n    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);\n}\n\n\n\n\n"
  },
  {
    "path": "doc/README.pfm.md",
    "content": "# JSON Schema Compiled checK\n\nJSCK is one of the fastest [JSON Schema](http://json-schema.org) validators for Node.js.\nIt supports JSON Schema drafts\n[3][draft3_doc] and\n[4][draft4_doc],\nwith a few caveats (see the [Coverage section](#coverage) below).\n\n\n## Installation and Usage\n\nInstall with NPM:\n\n    npm install --save jsck\n\n\nRequire:\n\n```coffee\nJSCK = require \"jsck\"\n```\n\nJSCK can create validators from multiple schemas, but this requires that\neach schema be identified with a URI in a top-level \"id\" field.  In many\ncases, only a single schema is needed, and there is no need to uniquely\nidentify the schema.  This is the easiest way to use JSCK, as it is a\ncommon pattern.\n\n\n```examples/draft4/basic.coffee#L3-29```\n\n\nTo use Draft 3 schemas:\n\n```.coffee\nvalidator = new JSCK.draft3(schema)\n```\n\n\nSee these [advanced usage examples](examples/draft4/advanced.coffee) for help\nworking with multiple schemas.\n\n\n\n## Why JSCK?\n\nJSCK is [faster](#benchmarks) than most other JavaScript/CoffeeScript libraries\nfor validating JSON Schemas because it \"compiles\" the schemas. That is, JSCK\ngenerates the tree of functions needed to validate a particular schema when you\nconstruct a validator. The schema is thus traversed only during preparation, and\nmost of the work of interpreting the schema is done at this time, rather than\nfor every document submitted for validation. This minimizes the work required\nduring validation, which leads to substantial performance improvements over\nnon-compiling validators.\n\n\n\n## Coverage\n\n### Draft 4\n\nJSCK passes all tests in the canonical\n[JSON Schema Test Suite][canonical], except for these items:\n\n* use of `maxLength` and `minLength` with Unicode surrogate pairs.\n* `refRemote` (this is an essential feature we do plan to support)\n* `ref`\n  * remote ref, containing refs itself\n* `uniqueItems`\n* `optional/zeroTerminatedFloats`\n\n\n### Draft 3\n\nCurrently passing the canonical [test suite][canonical] for draft3 except for\nthese items:\n\n* `refRemote`\n* `ref`\n  * remote ref, containing refs itself\n* `uniqueItems`\n* `optional/zeroTerminatedFloats`\n\n### Managing resolution scope with the \"id\" attribute\n\nJSCK does not support the full range of scope manipulations suggested by JSON\nSchema drafts 3 and 4.  Scope manipulation is a controversial topic, and with\nJSCK we have chosen to play it safe, supporting \"id\" declarations only in cases\nthat will (probably) not lead to any ambiguity. Specifically, JSCK uses \"id\"\ndeclarations only in these cases:\n\n* at the top level of a schema, to provide a namespace for schemas not loaded from URIs.\n* non-JSON-pointer fragments (`\"id\": \"#user\"`), which serve merely as aliases for specific subschemas, and are thus convenient and unambiguous.\n\nFor more information on the topic of the \"id\" attribute and scope manipulation,\nsee this issue: https://github.com/json-schema/json-schema/issues/77.\n\n\n## Contributing\n\nTo contribute, hack on it, or run the tests:\n\n```shell\ngit clone git@github.com:pandastrike/jsck.git\ncd jsck\ncoffee tasks/update\nnpm install\n```\n\n### Tests\n\nJSCK uses the official [JSON Schema Test Suite][canonical] as well as some\ncustom tests. To run all tests for all versions:\n\n    coffee test\n\nSee [this document](doc/tests.md) for more information on working with JSCK tests.\n\n\n## Benchmarks\n\nJSCK has fairly comprehensive benchmarks which show it to be one of the very\nfastest JSON Schema validators available for Node.js. Pull requests welcome, of\ncourse.\n\nBecause performance varies (at very least) based on the complexity\nof the schema being validated, we run benchmarks against several different\nschemas, ranging from quite simple to moderately complex.\n\nFor JSON Schema Draft4, we run benchmarks against JSCK, tv4, jayschema,\nz-schema, and other validators.  On the\n[trivial schema](benchmarks/draft4/trivial/schema.coffee),\nour benchmarks produce this relative performance for these validators\n(lower is better):\n\n```coffee\najv : 1\njsen : 2.9\nis-my-json-valid : 4.4\nThemis (minimal) : 5.2\nThemis : 5.3\nJSCK : 34.2\nz-schema : 48.3\ntv4 : 54.4\njayschema : 2507.4\n```\n\n\nFor the schema of [medium complexity](benchmarks/draft4/medium/schema.coffee),\nour benchmarks produce this relative performance for the tested validators\n(lower is better):\n\n```coffee\najv : 1\nis-my-json-valid : 2.8\njsen : 3.0\nThemis (minimal) : 11.1\nThemis : 11.6\nJSCK : 22.0\ntv4 : 43.4\nz-schema : 46.0\njayschema : 2319.4\n```\n\nFor the schema of [higher complexity](benchmarks/draft4/complex/schema.coffee),\nour benchmarks produce this relative performance for the tested validators\n(lower is better):\n\n```coffee\najv : 1\nis-my-json-valid : 1.23\njsen : 1.31\nThemis (minimal) : 1.7\nThemis : 1.8\nJSCK : 4.8\nz-schema : 17.2\ntv4 : 27.0\njayschema : 1215.1\n```\n\nAs the complexity of the schema increases, the performance benefits of the\ncompilation model become more evident.\n\n\nSee [this document](doc/benchmarks.md) for detailed results and information on\nrunning and creating benchmarks.\n\n\n\n[draft3_doc]:http://tools.ietf.org/html/draft-zyp-json-schema-03\n[draft3_impl]:https://github.com/json-schema/json-schema/tree/master/draft-03\n[draft4_doc]:http://tools.ietf.org/html/draft-zyp-json-schema-04\n[canonical]:https://github.com/json-schema/JSON-Schema-Test-Suite\n\n\n"
  },
  {
    "path": "doc/benchmarks.md",
    "content": "# Benchmarks\n\nJSCK has fairly comprehensive benchmarks which show it to be one of the fastest\nJSON Schema validators available for Node.js.\n\nTo run the benchmarks immediately after you `git clone` the repo:\n\n```shell\ngit clone git@github.com:pandastrike/jsck.git && \\\ngit submodule update --init && \\\nnpm install && \\\ncoffee benchmarks/\n```\n\nBenchmarking harness and content lives in `benchmarks`, with separate\ndirectories for each draft.  For each draft there are a number of different\nbenchmarks (contained in subdirectories) that can be run in whole or in part.\nThis is the basic directory structure:\n\n    benchmarks/\n      draft3/\n      draft4/\n        complex/\n        medium/\n        trivial/\n        index.coffee\n        validators.coffee\n\n## Adding Additional Validators\n\nThe validators are defined in `validators.coffee`.  Here's an example from\nthe Draft 4 benchmarks:\n\n```coffee\n    setup: (schema) ->\n      ajv = require(\"ajv\")()\n      ajv.compile(schema)\n    validate: ({validator, schema, document}) ->\n      validator(document)\n    error: (result) ->\n      if result == true\n        false\n      else\n        validator.errors\n\n```\n\n\nThe `setup` function returns a validator object usable by the `validate`\nfunction.  The `validate` function performs the actual validation work that\nis measured in benchmarking.  The `error` function is used only in the\npreflight stage of benchmarking to determine whether the result of the\n`validate` function contains any errors. This is useful in making sure that all\nthe validators are actually operating correctly and thus being compared fairly.\n\n\n\n## Adding New Benchmarks\n\nEach individual benchmark consists of a directory containing a schema, a valid\ndocument, and an `index.coffee` file which runs the benchmark.\n\n```coffee\nvalidators = require \"../validators\"\n{benchmark} = require(\"../../runner\")(validators)\n\nbenchmark {\n  name: \"Event - Valid document\"\n  repeats: 1024\n  schema: require \"./schema\"\n  document: require \"./valid_doc\"\n}\n\n```\n\n\nThe \"repeats\" parameter determines how many times the document will be\nvalidated during a single measurement sample.\n\n\n\n\n\n## Running Benchmarks\n\nYou can run very specific benchmarks, like the medium-complexity benchmarks for draft 3 only, like so:\n\n`coffee benchmarks/draft3/medium`\n\nYou can run all benchmarks for a specific JSON Schema draft:\n\n`coffee benchmarks/draft4`\n\nOr, to run all benchmarks:\n\n`coffee benchmarks/`\n\nYou should then see something like this:\n\n```txt\n## Benchmarks for Draft 3\n\nSchema: 'Event'.  A simple schema, exercising very few attributes\nSample size: 64\nValidations per sample: 512\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  amanda\n  Warming up: ................................\n  Iterations: ................................................................\n\n  JSV\n  Warming up: ................................\n  Iterations: ................................................................\n\n  json-gate\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 193.025    max: 202.692    min: 175.945 \n\n  amanda: validations/millisecond\n  median: 4.258    max: 4.608    min: 3.778 \n\n  JSV: validations/millisecond\n  median: 2.685    max: 2.748    min: 2.43 \n\n  json-gate: validations/millisecond\n  median: 82.514    max: 86.036    min: 48.234 \n\nRelative speeds:\nJSCK : 1.000\njson-gate : 2.339\namanda : 45.337\nJSV : 71.896\n\n\nSchema: 'Configuration'.  A moderately complex schema with some nesting and value constraints\nSample size: 64\nValidations per sample: 128\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  amanda\n  Warming up: ................................\n  Iterations: ................................................................\n\n  JSV\n  Warming up: ................................\n  Iterations: ................................................................\n\n  json-gate\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 108.936    max: 109.966    min: 85.964 \n\n  amanda: validations/millisecond\n  median: 3.788    max: 5.651    min: 2.371 \n\n  JSV: validations/millisecond\n  median: 1.344    max: 1.359    min: 1.255 \n\n  json-gate: validations/millisecond\n  median: 44.176    max: 45.845    min: 41.803 \n\nRelative speeds:\nJSCK : 1.000\njson-gate : 2.466\namanda : 28.760\nJSV : 81.025\n\n## Benchmarks for Draft 4\n\nSchema: 'Event - Valid document'.  A simple schema, exercising very few attributes\nSample size: 64\nValidations per sample: 1024\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  tv4\n  Warming up: ................................\n  Iterations: ................................................................\n\n  z-schema\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 186.81    max: 191.617    min: 138.716 \n\n  tv4: validations/millisecond\n  median: 54.377    max: 55.907    min: 46.942 \n\n  z-schema: validations/millisecond\n  median: 93.657    max: 93.979    min: 89.44 \n\nRelative speeds:\nJSCK : 1.000\nz-schema : 1.995\ntv4 : 3.435\n\n\nSchema: 'Configuration'.  A moderately complex schema with some nesting and value constraints\nSample size: 64\nValidations per sample: 256\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  tv4\n  Warming up: ................................\n  Iterations: ................................................................\n\n  z-schema\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 118.573    max: 119.07    min: 105.22 \n\n  tv4: validations/millisecond\n  median: 19.608    max: 20.389    min: 16.505 \n\n  z-schema: validations/millisecond\n  median: 40.606    max: 40.934    min: 34.934 \n\nRelative speeds:\nJSCK : 1.000\nz-schema : 2.920\ntv4 : 6.047\n\n\nSchema: 'Transaction'.  \nSample size: 64\nValidations per sample: 64\n\n  JSCK\n  Warming up: ................................\n  Iterations: ................................................................\n\n  tv4\n  Warming up: ................................\n  Iterations: ................................................................\n\n  z-schema\n  Warming up: ................................\n  Iterations: ................................................................\n\n\n  JSCK: validations/millisecond\n  median: 12.814    max: 14.873    min: 6.984 \n\n  tv4: validations/millisecond\n  median: 1.946    max: 1.965    min: 1.832 \n\n  z-schema: validations/millisecond\n  median: 3.768    max: 3.836    min: 3.297 \n\nRelative speeds:\nJSCK : 1.000\nz-schema : 3.401\ntv4 : 6.583\n\n```\n\n"
  },
  {
    "path": "doc/benchmarks.pfm.md",
    "content": "# Benchmarks\n\nJSCK has fairly comprehensive benchmarks which show it to be one of the fastest\nJSON Schema validators available for Node.js.\n\nTo run the benchmarks immediately after you `git clone` the repo:\n\n```shell\ngit clone git@github.com:pandastrike/jsck.git && \\\ngit submodule update --init && \\\nnpm install && \\\ncoffee benchmarks/\n```\n\nBenchmarking harness and content lives in `benchmarks`, with separate\ndirectories for each draft.  For each draft there are a number of different\nbenchmarks (contained in subdirectories) that can be run in whole or in part.\nThis is the basic directory structure:\n\n    benchmarks/\n      draft3/\n      draft4/\n        complex/\n        medium/\n        trivial/\n        index.coffee\n        validators.coffee\n\n## Adding Additional Validators\n\nThe validators are defined in `validators.coffee`.  Here's an example from\nthe Draft 4 benchmarks:\n\n```benchmarks/draft4/validators.coffee#L16-25```\n\nThe `setup` function returns a validator object usable by the `validate`\nfunction.  The `validate` function performs the actual validation work that\nis measured in benchmarking.  The `error` function is used only in the\npreflight stage of benchmarking to determine whether the result of the\n`validate` function contains any errors. This is useful in making sure that all\nthe validators are actually operating correctly and thus being compared fairly.\n\n\n\n## Adding New Benchmarks\n\nEach individual benchmark consists of a directory containing a schema, a valid\ndocument, and an `index.coffee` file which runs the benchmark.\n\n```benchmarks/draft4/trivial/index.coffee```\n\nThe \"repeats\" parameter determines how many times the document will be\nvalidated during a single measurement sample.\n\n\n\n\n\n## Running Benchmarks\n\nYou can run very specific benchmarks, like the medium-complexity benchmarks for draft 3 only, like so:\n\n`coffee benchmarks/draft3/medium`\n\nYou can run all benchmarks for a specific JSON Schema draft:\n\n`coffee benchmarks/draft4`\n\nOr, to run all benchmarks:\n\n`coffee benchmarks/`\n\nYou should then see something like this:\n\n```benchmarks/results/all.txt```\n\n"
  },
  {
    "path": "doc/tests.md",
    "content": "# Testing JSCK\n\nJSCK is developed against several sets of tests:\n\n* the official [JSON Schema Test Suite][canonical]\n* tests for schemas that should be considered invalid\n* tests for schemas that should be considered valid\n* unit tests particular to JSCK\n\nTo run all tests for all versions of JSON Schema:\n\n    coffee test\n\n\n## The official test suite\n\nThe good folks behind JSON Schema have provided a language-agnostic test suite,\ncomposed of JSON documents that define schemas and input objects that should be\njudged as valid or invalid for each schema. The README for the test suite\nprovides a\n[good overview of the structure](https://github.com/json-schema/JSON-Schema-Test-Suite#structure-of-a-test)\nof the JSON test files.\n\nJSCK includes the official test suite as a git submodule at\n`test/JSON-Schema-Test-Suite`. Running `coffee tasks/update` will initialize\nand/or update the submodule.\n\n\nAs a concrete example, here is the first case for the \"items\" attribute in Draft 4:\n\n```json\n    {\n        \"description\": \"a schema given for items\",\n        \"schema\": {\n            \"items\": {\"type\": \"integer\"}\n        },\n        \"tests\": [\n            {\n                \"description\": \"valid items\",\n                \"data\": [ 1, 2, 3 ],\n                \"valid\": true\n            },\n            {\n                \"description\": \"wrong type of items\",\n                \"data\": [1, \"x\"],\n                \"valid\": false\n            },\n            {\n                \"description\": \"ignores non-arrays\",\n                \"data\": {\"foo\" : \"bar\"},\n                \"valid\": true\n            }\n        ]\n    },\n\n```\n\n\nBreaking this down\n\n* the case described is for when the value of \"items\" is a schema\n* the schema under consideration does not declare a type for the input data\n* if the input data is an array, all of its items must be integers\n\nThere are three tests for this case:\n\n* valid input data\n* invalid input data\n* irrelevant input data\n\n\n### Running the official tests\n\nTo run the official tests for a specific draft:\n\n    coffee test/draft4\n\nIt can be difficult to troubleshoot bugs when running hundreds of tests.\nTo run only the tests for a specific attribute (in this case,\n\"patternProperties\"):\n\n    coffee test/draft4 patternProperties\n\nAnd to run only a certain test for that attribute, append the (zero-based)\nindex of the test:\n\n    coffee test/draft4 patternProperties 3\n\n\n### Ignoring specific tests\n\nThe test harness provided by JSCK allows you to ignore specific tests from\nthe official suite. Here is how we define the ignores for Draft 4:\n\n```coffee\n#cmd = \"node_modules/.bin/nserver -p 5725 -d test/JSON-Schema-Test-Suite/remotes\"\n#proc = shell.exec cmd, (code, output) ->\n#\n#Testify = require \"testify\"\n#Testify.once \"done\", ->\n  #console.log \"Shutting down the 'remotes' test server\"\n  #proc.kill(\"SIGTERM\")\n\n[_node, _script, attribute, test_number] = process.argv\n\nsuite {\n  attribute\n  test_number\n\n  version: \"draft4\"\n\n  validate: (schema, document) ->\n    v = new draft4(schema)\n    v.validate(document)\n\n\n  ignores:\n    # Doubtful value for the majority of use cases.\n    # https://github.com/pandastrike/jsck/issues/42\n    minLength: [\n      \"one supplementary Unicode code point is not long enough\"\n\n```\n\n\n\n## Invalid Schemas\n\nA tool for working with JSON Schemas must be able to reject invalid schemas.\nThe official test suite (at this time) only provides tests data for validating\ndocuments against correctly formed schemas, so JSCK introduces a similar\ntest format for checking the invalidity of schema definitions.  These tests\nare defined as CoffeeScript files in `test/draft{3,4}/invalid/`.  Though we\nuse CoffeeScript for easy maintenance, the actual content could be represented\nas JSON, or YAML, or any other data format.\n\nHere's an example of an invalidity test for the \"type\" attribute:\n\n```coffee\n    {\n      description: \"string values must be one of the primitive types\"\n      schemas: [\n        type: \"bogus\"\n      ]\n    }\n\n```\n\n\nAll of the objects in the `schemas` array are invalid schemas that should\ncause JSCK (or any other validation library) to reject the schema.\n\nOne of the benefits of using CoffeeScript (or JavaScript, or any other\nlanguage) to generate the test content is the ability to use helper functions\nto create multiple test schemas:\n\n```coffee\n    {\n      description: \"value MUST be either a string or an array\"\n      schemas: for value in json_types.except(\"string\", \"array\")\n        {type: value}\n    }\n\n```\n\n\nIn the above example, `schemas` is defined using a list comprehension and a \nhelper function that generates an invalid schema for all of the primitive JSON\nSchema types except those explicitly named.\n\nTo run only the invalidity tests:\n\n    coffee test/draft4/invalid.coffee\n\n## Valid Schemas\n\nIt is also valuable to have tests for the acceptance of valid schemas that\nbuggy or overzealous libraries might reject.  JSCK's schema validity tests\nare defined as CoffeeScript files in `test/draft{3,4}/valid/`.\n\nAs an example, the names of JSON Schema attributes (\"properties\", \"type\",\n\"required\", etc.) are not reserved terms.  It is legal to use these strings\nas the names of object properties.  During one round of refactoring, JSCK\nbegan rejecting schemas that used JSON Schema attribute names as properties.\n\nTo prevent this, a validity test was added:\n\n```coffee\n\n      required:\n        type: \"object\"\n        properties:\n          required:\n            type: \"boolean\"\n\n      id:\n        type: \"object\"\n        properties:\n          id:\n\n```\n\n\n\nTo run only the validity tests:\n\n    coffee test/draft4/valid.coffee\n\n\n## Unit tests\n\nJSCK also uses a few unit tests to assist in developing and troubleshooting\nsome of the internal functions, such as scope resolution and URI construction.\n\nTo run only the unit tests for a particular draft version:\n\n    coffee test/draft4/unit\n\n\n[canonical]:https://github.com/json-schema/JSON-Schema-Test-Suite\n"
  },
  {
    "path": "doc/tests.pfm.md",
    "content": "# Testing JSCK\n\nJSCK is developed against several sets of tests:\n\n* the official [JSON Schema Test Suite][canonical]\n* tests for schemas that should be considered invalid\n* tests for schemas that should be considered valid\n* unit tests particular to JSCK\n\nTo run all tests for all versions of JSON Schema:\n\n    coffee test\n\n\n## The official test suite\n\nThe good folks behind JSON Schema have provided a language-agnostic test suite,\ncomposed of JSON documents that define schemas and input objects that should be\njudged as valid or invalid for each schema. The README for the test suite\nprovides a\n[good overview of the structure](https://github.com/json-schema/JSON-Schema-Test-Suite#structure-of-a-test)\nof the JSON test files.\n\nJSCK includes the official test suite as a git submodule at\n`test/JSON-Schema-Test-Suite`. Running `coffee tasks/update` will initialize\nand/or update the submodule.\n\n\nAs a concrete example, here is the first case for the \"items\" attribute in Draft 4:\n\n```test/JSON-Schema-Test-Suite/tests/draft4/items.json#L2-24```\n\nBreaking this down\n\n* the case described is for when the value of \"items\" is a schema\n* the schema under consideration does not declare a type for the input data\n* if the input data is an array, all of its items must be integers\n\nThere are three tests for this case:\n\n* valid input data\n* invalid input data\n* irrelevant input data\n\n\n### Running the official tests\n\nTo run the official tests for a specific draft:\n\n    coffee test/draft4\n\nIt can be difficult to troubleshoot bugs when running hundreds of tests.\nTo run only the tests for a specific attribute (in this case,\n\"patternProperties\"):\n\n    coffee test/draft4 patternProperties\n\nAnd to run only a certain test for that attribute, append the (zero-based)\nindex of the test:\n\n    coffee test/draft4 patternProperties 3\n\n\n### Ignoring specific tests\n\nThe test harness provided by JSCK allows you to ignore specific tests from\nthe official suite. Here is how we define the ignores for Draft 4:\n\n```test/draft4/official.coffee#L7-32```\n\n\n## Invalid Schemas\n\nA tool for working with JSON Schemas must be able to reject invalid schemas.\nThe official test suite (at this time) only provides tests data for validating\ndocuments against correctly formed schemas, so JSCK introduces a similar\ntest format for checking the invalidity of schema definitions.  These tests\nare defined as CoffeeScript files in `test/draft{3,4}/invalid/`.  Though we\nuse CoffeeScript for easy maintenance, the actual content could be represented\nas JSON, or YAML, or any other data format.\n\nHere's an example of an invalidity test for the \"type\" attribute:\n\n```test/draft4/invalid/type.coffee#L24-29```\n\nAll of the objects in the `schemas` array are invalid schemas that should\ncause JSCK (or any other validation library) to reject the schema.\n\nOne of the benefits of using CoffeeScript (or JavaScript, or any other\nlanguage) to generate the test content is the ability to use helper functions\nto create multiple test schemas:\n\n```test/draft4/invalid/type.coffee#L5-9```\n\nIn the above example, `schemas` is defined using a list comprehension and a \nhelper function that generates an invalid schema for all of the primitive JSON\nSchema types except those explicitly named.\n\nTo run only the invalidity tests:\n\n    coffee test/draft4/invalid.coffee\n\n## Valid Schemas\n\nIt is also valuable to have tests for the acceptance of valid schemas that\nbuggy or overzealous libraries might reject.  JSCK's schema validity tests\nare defined as CoffeeScript files in `test/draft{3,4}/valid/`.\n\nAs an example, the names of JSON Schema attributes (\"properties\", \"type\",\n\"required\", etc.) are not reserved terms.  It is legal to use these strings\nas the names of object properties.  During one round of refactoring, JSCK\nbegan rejecting schemas that used JSON Schema attribute names as properties.\n\nTo prevent this, a validity test was added:\n\n```test/draft4/valid/properties.coffee#L5-15```\n\n\nTo run only the validity tests:\n\n    coffee test/draft4/valid.coffee\n\n\n## Unit tests\n\nJSCK also uses a few unit tests to assist in developing and troubleshooting\nsome of the internal functions, such as scope resolution and URI construction.\n\nTo run only the unit tests for a particular draft version:\n\n    coffee test/draft4/unit\n\n\n[canonical]:https://github.com/json-schema/JSON-Schema-Test-Suite\n\n\n\n"
  },
  {
    "path": "examples/draft4/advanced.coffee",
    "content": "JSCK = require(\"../../src/index\")\n\n# using a schema that declares a URI with \"id\"\n\njsck = new JSCK.draft4\n  $schema: \"http://json-schema.org/draft-04/schema#\"\n  id: \"urn:jsck.examples.advanced#\"\n  definitions:\n    user:\n      type: \"object\"\n      required: [\"login\"]\n      properties:\n        login:\n          type: \"string\"\n          pattern: \"^[\\\\w\\\\d_]{3,32}$\"\n        email:\n          type: \"string\"\n\nvalidator = jsck.validator(uri: \"urn:jsck.examples.advanced#\")\n{valid} = validator.validate\n  login: \"automatthew\"\n  email: \"automatthew@mailinator.com\"\n\nconsole.log \"Schema with id:\", valid\n\n\n# validating against a subschema using a JSON Pointer\n\nvalidator = jsck.validator \"urn:jsck.examples.advanced#/definitions/user\"\n{valid} = validator.validate\n  login: \"automatthew\"\n  email: \"automatthew@mailinator.com\"\n\nconsole.log \"Schema identified by JSON Pointer:\", valid\n\n\n# Adding multiple schemas\n#\n# You can instantiate JSCK with multiple schemas or add them later\n# \n# Instantiation:\n# validator = new JSCK(schema1, schema2, schema3)\n\njsck.add\n  id: \"urn:jsck.examples.user_list#\"\n  type: \"array\"\n  items: {$ref: \"urn:jsck.examples.advanced#/definitions/user\"}\n\nvalidator = jsck.validator \"urn:jsck.examples.user_list#\"\n{valid} = validator.validate [\n  { login: \"dyoder\" }\n  { login: \"automatthew\" }\n]\n\nconsole.log \"Multiple schemas:\", valid\n\n\n"
  },
  {
    "path": "examples/draft4/basic.coffee",
    "content": "JSCK = require(\"../../src/index\")\n\n# Construct a validator for a schema lacking an \"id\" declaration\n\njsck = new JSCK.draft4\n  type: \"object\"\n  properties:\n    user:\n      type: \"object\"\n      required: [\"login\"]\n      properties:\n        login:\n          type: \"string\"\n          pattern: \"^[\\\\w\\\\d_]{3,32}$\"\n        email:\n          type: \"string\"\n          format: \"email\"\n\nconsole.log \"valid document:\", jsck.validate\n  user:\n    login: \"matthew\"\n    email: \"matthew@pandastrike.com\"\n\n{errors} = jsck.validate\n  user:\n    login: \"matthew\"\n    email: \"pandastrike.com\"\n\nconsole.log \"invalid document:\", errors\n\n\n\n\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"jsck\",\n  \"version\": \"0.3.2\",\n  \"description\": \"JSON Schema Compiled checK\",\n  \"scripts\": {\n    \"test\": \"coffee test\",\n    \"prepublish\": \"coffee tasks/build\"\n  },\n  \"main\": \"lib/index.js\",\n  \"files\": [\n    \"lib/\",\n    \"schemas/\",\n    \"README.md\"\n  ],\n  \"dependencies\": {},\n  \"devDependencies\": {\n    \"ajv\": \"latest\",\n    \"amanda\": \"latest\",\n    \"ajv\": \"^0.6.1\",\n    \"amanda\": \"~0.5.1\",\n    \"coffee-script\": \"~1.7\",\n    \"commonjs-everywhere\": \"^0.9.7\",\n    \"glob\": \"~3.2.6\",\n    \"is-my-json-valid\": \"latest\",\n    \"jayschema\": \"latest\",\n    \"jsen\": \"latest\",\n    \"json-gate\": \"latest\",\n    \"json-schema-tests\": \"^0.1.1\",\n    \"request\": \"~2.48.0\",\n    \"shelljs\": \"^0.3.0\",\n    \"simple-http-server\": \"~0.1.8\",\n    \"testify\": \"~0.2.11\",\n    \"themis\": \"latest\",\n    \"tv4\": \"latest\",\n    \"z-schema\": \"latest\"\n  },\n  \"repository\": \"git@github.com:pandastrike/jsck.git\",\n  \"author\": \"Matthew King <matthew@pandastrike.com>\",\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "schemas/draft-03/schema.json",
    "content": "{\n\t\"$schema\" : \"http://json-schema.org/draft-03/schema#\",\n\t\"id\" : \"http://json-schema.org/draft-03/schema#\",\n\t\"type\" : \"object\",\n\t\n\t\"properties\" : {\n\t\t\"type\" : {\n\t\t\t\"type\" : [\"string\", \"array\"],\n\t\t\t\"items\" : {\n\t\t\t\t\"type\" : [\"string\", {\"$ref\" : \"#\"}]\n\t\t\t},\n\t\t\t\"uniqueItems\" : true,\n\t\t\t\"default\" : \"any\"\n\t\t},\n\t\t\n\t\t\"properties\" : {\n\t\t\t\"type\" : \"object\",\n\t\t\t\"additionalProperties\" : {\"$ref\" : \"#\"},\n\t\t\t\"default\" : {}\n\t\t},\n\t\t\n\t\t\"patternProperties\" : {\n\t\t\t\"type\" : \"object\",\n\t\t\t\"additionalProperties\" : {\"$ref\" : \"#\"},\n\t\t\t\"default\" : {}\n\t\t},\n\t\t\n\t\t\"additionalProperties\" : {\n\t\t\t\"type\" : [{\"$ref\" : \"#\"}, \"boolean\"],\n\t\t\t\"default\" : {}\n\t\t},\n\t\t\n\t\t\"items\" : {\n\t\t\t\"type\" : [{\"$ref\" : \"#\"}, \"array\"],\n\t\t\t\"items\" : {\"$ref\" : \"#\"},\n\t\t\t\"default\" : {}\n\t\t},\n\t\t\n\t\t\"additionalItems\" : {\n\t\t\t\"type\" : [{\"$ref\" : \"#\"}, \"boolean\"],\n\t\t\t\"default\" : {}\n\t\t},\n\t\t\n\t\t\"required\" : {\n\t\t\t\"type\" : \"boolean\",\n\t\t\t\"default\" : false\n\t\t},\n\t\t\n\t\t\"dependencies\" : {\n\t\t\t\"type\" : \"object\",\n\t\t\t\"additionalProperties\" : {\n\t\t\t\t\"type\" : [\"string\", \"array\", {\"$ref\" : \"#\"}],\n\t\t\t\t\"items\" : {\n\t\t\t\t\t\"type\" : \"string\"\n\t\t\t\t}\n\t\t\t},\n\t\t\t\"default\" : {}\n\t\t},\n\t\t\n\t\t\"minimum\" : {\n\t\t\t\"type\" : \"number\"\n\t\t},\n\t\t\n\t\t\"maximum\" : {\n\t\t\t\"type\" : \"number\"\n\t\t},\n\t\t\n\t\t\"exclusiveMinimum\" : {\n\t\t\t\"type\" : \"boolean\",\n\t\t\t\"default\" : false\n\t\t},\n\t\t\n\t\t\"exclusiveMaximum\" : {\n\t\t\t\"type\" : \"boolean\",\n\t\t\t\"default\" : false\n\t\t},\n\t\t\n\t\t\"minItems\" : {\n\t\t\t\"type\" : \"integer\",\n\t\t\t\"minimum\" : 0,\n\t\t\t\"default\" : 0\n\t\t},\n\t\t\n\t\t\"maxItems\" : {\n\t\t\t\"type\" : \"integer\",\n\t\t\t\"minimum\" : 0\n\t\t},\n\t\t\n\t\t\"uniqueItems\" : {\n\t\t\t\"type\" : \"boolean\",\n\t\t\t\"default\" : false\n\t\t},\n\t\t\n\t\t\"pattern\" : {\n\t\t\t\"type\" : \"string\",\n\t\t\t\"format\" : \"regex\"\n\t\t},\n\t\t\n\t\t\"minLength\" : {\n\t\t\t\"type\" : \"integer\",\n\t\t\t\"minimum\" : 0,\n\t\t\t\"default\" : 0\n\t\t},\n\t\t\n\t\t\"maxLength\" : {\n\t\t\t\"type\" : \"integer\"\n\t\t},\n\t\t\n\t\t\"enum\" : {\n\t\t\t\"type\" : \"array\",\n\t\t\t\"minItems\" : 1,\n\t\t\t\"uniqueItems\" : true\n\t\t},\n\t\t\n\t\t\"default\" : {\n\t\t\t\"type\" : \"any\"\n\t\t},\n\t\t\n\t\t\"title\" : {\n\t\t\t\"type\" : \"string\"\n\t\t},\n\t\t\n\t\t\"description\" : {\n\t\t\t\"type\" : \"string\"\n\t\t},\n\t\t\n\t\t\"format\" : {\n\t\t\t\"type\" : \"string\"\n\t\t},\n\t\t\n\t\t\"divisibleBy\" : {\n\t\t\t\"type\" : \"number\",\n\t\t\t\"minimum\" : 0,\n\t\t\t\"exclusiveMinimum\" : true,\n\t\t\t\"default\" : 1\n\t\t},\n\t\t\n\t\t\"disallow\" : {\n\t\t\t\"type\" : [\"string\", \"array\"],\n\t\t\t\"items\" : {\n\t\t\t\t\"type\" : [\"string\", {\"$ref\" : \"#\"}]\n\t\t\t},\n\t\t\t\"uniqueItems\" : true\n\t\t},\n\t\t\n\t\t\"extends\" : {\n\t\t\t\"type\" : [{\"$ref\" : \"#\"}, \"array\"],\n\t\t\t\"items\" : {\"$ref\" : \"#\"},\n\t\t\t\"default\" : {}\n\t\t},\n\t\t\n\t\t\"id\" : {\n\t\t\t\"type\" : \"string\",\n\t\t\t\"format\" : \"uri\"\n\t\t},\n\t\t\n\t\t\"$ref\" : {\n\t\t\t\"type\" : \"string\",\n\t\t\t\"format\" : \"uri\"\n\t\t},\n\t\t\n\t\t\"$schema\" : {\n\t\t\t\"type\" : \"string\",\n\t\t\t\"format\" : \"uri\"\n\t\t}\n\t},\n\t\n\t\"dependencies\" : {\n\t\t\"exclusiveMinimum\" : \"minimum\",\n\t\t\"exclusiveMaximum\" : \"maximum\"\n\t},\n\t\n\t\"default\" : {}\n}"
  },
  {
    "path": "schemas/draft-04/schema.json",
    "content": "{\n    \"id\": \"http://json-schema.org/draft-04/schema#\",\n    \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n    \"description\": \"Core schema meta-schema\",\n    \"definitions\": {\n        \"schemaArray\": {\n            \"type\": \"array\",\n            \"minItems\": 1,\n            \"items\": { \"$ref\": \"#\" }\n        },\n        \"positiveInteger\": {\n            \"type\": \"integer\",\n            \"minimum\": 0\n        },\n        \"positiveIntegerDefault0\": {\n            \"allOf\": [ { \"$ref\": \"#/definitions/positiveInteger\" }, { \"default\": 0 } ]\n        },\n        \"simpleTypes\": {\n            \"enum\": [ \"array\", \"boolean\", \"integer\", \"null\", \"number\", \"object\", \"string\" ]\n        },\n        \"stringArray\": {\n            \"type\": \"array\",\n            \"items\": { \"type\": \"string\" },\n            \"minItems\": 1,\n            \"uniqueItems\": true\n        }\n    },\n    \"type\": \"object\",\n    \"properties\": {\n        \"id\": {\n            \"type\": \"string\",\n            \"format\": \"uri\"\n        },\n        \"$schema\": {\n            \"type\": \"string\",\n            \"format\": \"uri\"\n        },\n        \"title\": {\n            \"type\": \"string\"\n        },\n        \"description\": {\n            \"type\": \"string\"\n        },\n        \"default\": {},\n        \"multipleOf\": {\n            \"type\": \"number\",\n            \"minimum\": 0,\n            \"exclusiveMinimum\": true\n        },\n        \"maximum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMaximum\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"minimum\": {\n            \"type\": \"number\"\n        },\n        \"exclusiveMinimum\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"maxLength\": { \"$ref\": \"#/definitions/positiveInteger\" },\n        \"minLength\": { \"$ref\": \"#/definitions/positiveIntegerDefault0\" },\n        \"pattern\": {\n            \"type\": \"string\",\n            \"format\": \"regex\"\n        },\n        \"additionalItems\": {\n            \"anyOf\": [\n                { \"type\": \"boolean\" },\n                { \"$ref\": \"#\" }\n            ],\n            \"default\": {}\n        },\n        \"items\": {\n            \"anyOf\": [\n                { \"$ref\": \"#\" },\n                { \"$ref\": \"#/definitions/schemaArray\" }\n            ],\n            \"default\": {}\n        },\n        \"maxItems\": { \"$ref\": \"#/definitions/positiveInteger\" },\n        \"minItems\": { \"$ref\": \"#/definitions/positiveIntegerDefault0\" },\n        \"uniqueItems\": {\n            \"type\": \"boolean\",\n            \"default\": false\n        },\n        \"maxProperties\": { \"$ref\": \"#/definitions/positiveInteger\" },\n        \"minProperties\": { \"$ref\": \"#/definitions/positiveIntegerDefault0\" },\n        \"required\": { \"$ref\": \"#/definitions/stringArray\" },\n        \"additionalProperties\": {\n            \"anyOf\": [\n                { \"type\": \"boolean\" },\n                { \"$ref\": \"#\" }\n            ],\n            \"default\": {}\n        },\n        \"definitions\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"properties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"patternProperties\": {\n            \"type\": \"object\",\n            \"additionalProperties\": { \"$ref\": \"#\" },\n            \"default\": {}\n        },\n        \"dependencies\": {\n            \"type\": \"object\",\n            \"additionalProperties\": {\n                \"anyOf\": [\n                    { \"$ref\": \"#\" },\n                    { \"$ref\": \"#/definitions/stringArray\" }\n                ]\n            }\n        },\n        \"enum\": {\n            \"type\": \"array\",\n            \"minItems\": 1,\n            \"uniqueItems\": true\n        },\n        \"type\": {\n            \"anyOf\": [\n                { \"$ref\": \"#/definitions/simpleTypes\" },\n                {\n                    \"type\": \"array\",\n                    \"items\": { \"$ref\": \"#/definitions/simpleTypes\" },\n                    \"minItems\": 1,\n                    \"uniqueItems\": true\n                }\n            ]\n        },\n        \"allOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"anyOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"oneOf\": { \"$ref\": \"#/definitions/schemaArray\" },\n        \"not\": { \"$ref\": \"#\" }\n    },\n    \"dependencies\": {\n        \"exclusiveMaximum\": [ \"maximum\" ],\n        \"exclusiveMinimum\": [ \"minimum\" ]\n    },\n    \"default\": {}\n}\n"
  },
  {
    "path": "src/common/arrays.coffee",
    "content": "module.exports =\n\n  # handlers\n\n  maxItems: (value, context) ->\n    (data, runtime) =>\n      if @test_type \"array\", data\n        if data.length > value\n          runtime.error context, data, description:\n            \"Array must have fewer than #{value} items.\"\n\n  minItems: (value, context) ->\n    (data, runtime) =>\n      if @test_type \"array\", data\n        if data.length < value\n          runtime.error context, data, description:\n            \"Array must have more than #{value} items.\"\n\n  items: (definition, context) ->\n    if @test_type \"array\", definition\n      test = @_tuple_items definition, context\n    else if @test_type \"object\", definition\n      test = @compile(context, definition)\n      # TODO check for array data?\n      (data, runtime) =>\n        for item, i in data\n          test item, runtime.child(i)\n        null\n    else\n      throw new Error \"The 'items' attribute must be an object or an array\"\n\n  _additionalItems: (definition, context) ->\n    if @test_type \"object\", definition\n      test = @compile(context, definition)\n    else if definition == false\n      test = (data, runtime) ->\n        runtime.error context, data, description:\n          \"Array is supposed to be a tuple, but has too many items.\"\n    else if definition == true\n      # valid\n    else\n      throw new Error \"The 'additionalItems' attribute must be an object or false\"\n    (data, runtime) =>\n      for item, i in data\n        test item, runtime.child(i)\n      null\n\n  _tuple_items: (definition, context) ->\n    {additionalItems} = context.modifiers\n\n    if additionalItems?\n      add_item_test = @_additionalItems additionalItems,\n        context.sibling \"additionalItems\"\n    else\n      add_item_test = null\n\n    tests = []\n    for schema, i in definition\n      unless @test_type \"object\", schema\n        throw new Error \"The 'items' attribute must be an object or an array\"\n\n      tests.push @compile context.child(i), schema\n\n    (data, runtime) =>\n      if @test_type \"array\", data\n        for test, i in tests\n          test data[i], runtime.child(i)\n\n        if (data.length > tests.length) && add_item_test\n          add_item_test data.slice(tests.length), runtime\n\n  uniqueItems: (definition, context) ->\n    null\n\n"
  },
  {
    "path": "src/common/comparison.coffee",
    "content": "module.exports =\n\n  # handlers\n\n  enum: (definition, context) ->\n    # TODO: add more cases to the draft3 test suite for enum.js,\n    # as they're not doing full coverage\n    if @test_type \"array\", definition\n      (data, runtime) =>\n        for value in definition\n          return if @equal(data, value)\n        values = definition.join ', '\n        runtime.error context, data, description:\n          \"Value must be one of #{values}.\"\n    else\n      throw new Error \"Value of 'enum' MUST be an Array\"\n\n  # helpers\n\n  equal: (got, want) ->\n    if want instanceof Array\n      @array_equal(got, want)\n    else if @is_object(want)\n      @object_equal(got, want)\n    else\n      got == want\n\n  array_equal: (got, want) ->\n    return false unless (got instanceof Array)\n    return true if want.length == 0\n    return false unless got.length == want.length\n    for item, i in want\n      return false if !@equal(got[i], item)\n    true\n\n  object_equal: (got, want) ->\n    return false unless @is_object(got)\n    return false unless Object.keys(got).length == Object.keys(want).length\n    for key, value of want\n      return false if !@equal(got[key], value)\n    true\n\n"
  },
  {
    "path": "src/common/numeric.coffee",
    "content": "module.exports =\n\n  minimum: (value, context) ->\n    {modifiers: {exclusiveMinimum}} = context\n    if exclusiveMinimum\n      (data, runtime) =>\n        if @test_type \"number\", data\n          if !(data > value)\n            runtime.error context, data, description:\n              \"Value must be > #{value}.\"\n    else\n      (data, runtime) =>\n        if @test_type \"number\", data\n          if !(data >= value)\n            runtime.error context, data, description:\n              \"Value must be >= #{value}.\"\n\n  maximum: (value, context) ->\n    {modifiers: {exclusiveMaximum}} = context\n    if exclusiveMaximum\n      (data, runtime) =>\n        if @test_type \"number\", data\n          if !(data < value)\n            runtime.error context, data, description:\n              \"Value must be < #{value}.\"\n    else\n      (data, runtime) =>\n        if @test_type \"number\", data\n          if !(data <= value)\n            runtime.error context, data, description:\n              \"Value must be <= #{value}.\"\n\n"
  },
  {
    "path": "src/common/objects.coffee",
    "content": "module.exports =\n\n  # handlers\n\n  patternProperties: (definition, context) ->\n    {additionalProperties} = context.modifiers\n    if additionalProperties\n      # The additionalProperties compiler runs the patternProperties\n      # validation. This is necessary because properties are not considered\n      # additional if they match a pattern.\n      return null\n\n    if !@test_type \"object\", definition\n      throw new Error \"The 'patternProperties' attribute must be an object\"\n\n    if Object.keys(definition).length == 0\n      throw new Error \"The 'patternProperties' object should not be empty\"\n\n    tests = {}\n    for pattern, schema of definition\n      unless @test_type \"object\", schema\n        throw new Error \"Values of 'patternProperties' must be an objects\"\n\n      tests[pattern] =\n        regex: new RegExp(pattern)\n        test: @compile context.child(pattern), schema\n\n    (data, runtime) =>\n      for property, value of data\n        for pattern, object of tests\n          if object.regex.test(property)\n            object.test value, runtime.child(property)\n      null\n\n\n  additionalProperties: (definition, context) ->\n    # TODO: refactor this method for clarity.  It's likely that this will\n    # also improve performance.\n    {properties, patternProperties} = context.modifiers\n    if @test_type \"object\", definition\n      add_prop_test = @compile(context, definition)\n    else if definition == false\n      add_prop_test = (data, runtime) =>\n        runtime.error context, data, description:\n          \"Unspecified properties are not allowed on this object.\"\n    else if definition == undefined\n      add_prop_test = null\n    else\n      throw new Error \"The 'additionalProperties' attribute must be an object or false\"\n\n    patterns = {}\n    for pattern, schema of patternProperties\n      patterns[pattern] =\n        regex: new RegExp(pattern)\n        test: @compile(context.sibling(\"patternProperties\").child(pattern), schema)\n\n    (data, runtime) =>\n      if @test_type \"object\", data\n        for property, value of data\n          explicit = false\n          patterned = false\n          if properties?[property]\n            explicit = true\n          if patterns\n            for pattern, object of patterns\n              if object.regex.test(property)\n                patterned = true\n                object.test value, runtime.child(property)\n          if !explicit && !patterned && add_prop_test\n            add_prop_test value, runtime.child(property)\n        null\n\n\n\n"
  },
  {
    "path": "src/common/strings.coffee",
    "content": "module.exports =\n\n  pattern: (pattern, context) ->\n    unless @test_type \"string\", pattern\n      throw new Error \"Value of 'pattern' must be a string\"\n\n    regex = new RegExp(pattern)\n    (data, runtime) =>\n      if @test_type \"string\", data\n        if !regex.test(data)\n          runtime.error context, data, description:\n            \"String did not match regex pattern.\"\n\n  minLength: (value, context) ->\n    unless @test_type \"integer\", value\n      throw new Error \"Value of 'minLength' must be an integer\"\n\n    (data, runtime) =>\n      if @test_type \"string\", data\n        if !(data.length >= value)\n          runtime.error context, data, description:\n            \"String must be longer than #{value} bytes.\"\n\n  maxLength: (value, context) ->\n    unless @test_type \"integer\", value\n      throw new Error \"Value of 'maxLength' must be an integer\"\n\n    (data, runtime) =>\n      if @test_type \"string\", data\n        if !(data.length <= value)\n          runtime.error context, data, description:\n            \"String must be smaller than #{value} bytes.\"\n\n"
  },
  {
    "path": "src/common/type.coffee",
    "content": "module.exports =\n\n  # handlers\n\n  type: (definition, context) ->\n    if @test_type \"array\", definition\n      tests = []\n      for type in definition\n        do (type) =>\n          if @test_type \"object\", type\n            test = @compile context, type\n            tests.push (data, runtime) =>\n              temp = new runtime.constructor\n                pointer: \"\"\n                errors: []\n              test data, temp\n              temp.errors.length == 0\n          else\n            tests.push (data, runtime) =>\n              @test_type type, data\n\n      (data, runtime) =>\n        valid = false\n        for test in tests\n          if test(data, runtime)\n            valid = true\n        if valid == false\n          runtime.error context, data\n\n    else if @test_type \"object\", definition\n      @compile(context, definition)\n    else\n      (data, runtime) =>\n        if !@test_type definition, data\n          runtime.error context, data\n\n  # helpers\n\n  is_object: (data) ->\n    data? && (typeof data) == \"object\" &&\n      !(data instanceof Array) &&\n      !(data instanceof Date)\n\n  is_primitive: (name) ->\n    name in [\"integer\", \"number\", \"string\", \"object\", \"array\", \"boolean\", \"null\"]\n\n  get_type: (data) ->\n    if  typeof(data) == \"number\" && data % 1 == 0\n      return \"integer\"\n    if typeof(data) == \"number\"\n      return \"number\"\n    if typeof(data) == \"string\"\n      return \"string\"\n    if @is_object(data)\n      return \"object\"\n    if data instanceof Array\n      return \"array\"\n    if typeof data == \"boolean\"\n      return \"boolean\"\n    if data == null\n      return \"null\"\n\n  test_type: (type_name, data) ->\n    switch type_name\n      when \"integer\"\n        typeof(data) == \"number\" && data % 1 == 0\n      when \"number\"\n        typeof(data) == \"number\"\n      when \"string\"\n        typeof(data) == \"string\"\n      when \"object\"\n        @is_object(data)\n      when \"array\"\n        data instanceof Array\n      when \"boolean\"\n        typeof data == \"boolean\"\n      when \"null\"\n        data == null\n      when \"any\"\n        true\n      else\n        throw new Error \"Bad type: '#{type_name}'\"\n\n"
  },
  {
    "path": "src/draft3/logical.coffee",
    "content": "URI = require \"../uri\"\nmodule.exports =\n\n  extends: (schemas, context) ->\n    unless @test_type \"array\", schemas\n      schemas = [schemas]\n\n    for schema, i in schemas\n      if (ref = schema.$ref)?\n        uri = URI.resolve(context.scope, ref)\n        parent = @find(uri)\n        if !parent\n          throw new Error \"No schema found for $ref '#{ref}'\"\n        else\n          schemas[i] = parent\n\n    tests = []\n    for schema, i in schemas\n      new_context = context.child(i)\n      tests.push @compile(new_context, schema)\n\n    (data, runtime) =>\n      for test in tests\n        test data, runtime\n\n  disallow: (definition, context) ->\n    if @test_type \"array\", definition\n      tests = []\n      for type, i in definition\n        do (i) =>\n          if @test_type \"object\", type\n            inverse = @compile context, type\n            tests.push (data, runtime) =>\n              temp = new runtime.constructor\n                pointer: \"\"\n                errors: []\n              inverse data, temp\n              if temp.errors.length == 0\n                runtime.error context, data\n          else\n            tests.push @disallow type, context\n\n      (data, runtime) =>\n        for test in tests\n          test data, runtime\n    else\n      (data, runtime) =>\n        if @test_type definition, data\n          runtime.error context, data\n\n"
  },
  {
    "path": "src/draft3/numeric.coffee",
    "content": "module.exports =\n\n  divisibleBy: (value, context) ->\n    (data, runtime) =>\n      if @test_type \"number\", data\n        if !((data / value) % 1 == 0)\n          runtime.error context, data\n\n"
  },
  {
    "path": "src/draft3/objects.coffee",
    "content": "module.exports =\n\n  properties: (definition, context) ->\n    if !@test_type \"object\", definition\n      throw new Error \"The 'properties' attribute must be an object\"\n    tests = {}\n    required = []\n    for property, schema of definition\n      new_context = context.child(property)\n      test = @compile(new_context, schema)\n      tests[property] = test\n      if schema.required == true\n        required.push property\n\n    (data, runtime) =>\n      if @test_type \"object\", data\n        for property, value of data\n          if (test = tests[property])?\n            test value, runtime.child(property)\n        for key in required\n          if data[key] == undefined\n            runtime.error context.child(key).child(\"required\")\n        true\n\n\n  dependencies: (definition, context) ->\n    unless @test_type \"object\", definition\n      throw new Error \"Value of 'dependencies' must be an object\"\n    else\n      tests = []\n      for property, dependency of definition\n\n        if @test_type \"string\", dependency\n          tests.push (data, runtime) =>\n            if data[property]? && !data[dependency]?\n              runtime.child(property).error context\n\n        else if @test_type \"array\", dependency\n          tests.push (data, runtime) =>\n            if data[property]?\n              for item in dependency\n                if !data[item]?\n                  runtime.child(property).error context\n              null\n\n        else if @test_type \"object\", dependency\n          fn = @compile context, dependency\n          tests.push (data, runtime) =>\n            if data[property]\n              fn data, runtime\n            else\n              true\n\n        else\n          throw new Error \"Invalid dependency\"\n\n    (data, runtime) =>\n      if @test_type \"object\", data\n        for test in tests\n          test data, runtime\n        null\n\n"
  },
  {
    "path": "src/draft3/strings.coffee",
    "content": "module.exports =\n\n  format: (format_name, context) ->\n    if format_name == \"regex\"\n      (data, runtime) =>\n        if @test_type \"string\", data\n          try\n            new RegExp(data)\n          catch error\n            runtime.error context, data\n\n    else if regex = format_regexes[format_name]\n      do (regex) =>\n        (data, runtime) =>\n          if @test_type \"string\", data\n            if !regex.test(data)\n              runtime.error context, data\n    else\n      throw new Error \"Invalid format_name for 'format'\"\n\n\n# regexes below were derived from\n# https://github.com/tdegrunt/jsonschema\n#\n#Copyright (C) 2012-2013 Tom de Grunt <tom@degrunt.nl>\n\n#Permission is hereby granted, free of charge, to any person obtaining a copy of\n#this software and associated documentation files (the \"Software\"), to deal in\n#the Software without restriction, including without limitation the rights to\n#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n#of the Software, and to permit persons to whom the Software is furnished to do\n#so, subject to the following conditions:\n\n#The above copyright notice and this permission notice shall be included in all\n#copies or substantial portions of the Software.\n\n#THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n#SOFTWARE.\n\nformat_regexes =\n  \"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})?)?)$/\n\n  date: /^(\\d{4}-(?:0[0-9]|1[0-2])-[0-9]{2})$/\n\n  time: /^\\d{2}:\\d{2}:\\d{2}$/\n\n  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])\\]))$/\n\n  \"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]?)$/\n\n  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*$/\n\n  uri: /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\\s]*$/\n\n  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*\\)))$/\n\n  \"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}\\.?)$/\n\n  alpha: /^[a-zA-Z]+$/\n\n  alphanumeric: /^[a-zA-Z0-9]+$/\n\n  \"utc-millisec\": (input) ->\n    (typeof input is \"string\") and parseFloat(input) is parseInt(input, 10) and not isNaN(input)\n\n  style: /\\s*(.+?):\\s*([^;]+);?/g\n\n  phone: /^\\+(?:[0-9] ?){6,14}[0-9]$/\n"
  },
  {
    "path": "src/draft3.coffee",
    "content": "validator = require(\"./validator\")\n\nmodule.exports = validator\n  schema_uri: \"http://json-schema.org/draft-03/schema#\"\n  mixins: [\n    require \"./draft3/logical\"\n    require \"./draft3/numeric\"\n    require \"./draft3/objects\"\n    require \"./draft3/strings\"\n  ]\n"
  },
  {
    "path": "src/draft4/logical.coffee",
    "content": "\nmodule.exports =\n\n  anyOf: (definition, context) ->\n    unless @test_type \"array\", definition\n      throw new Error \"The 'anyOf' attribute must be an array\"\n    if definition.length == 0\n      throw new Error \"The 'anyOf' array may not be empty\"\n\n    tests = []\n    for schema, i in definition\n      unless @test_type \"object\", schema\n        throw new Error \"The 'anyOf' array values must be objects\"\n      new_context = context.child(i)\n      tests.push @compile(new_context, schema)\n\n    (data, runtime) =>\n      most_items_tested = 0\n      best_errors = []\n      answer = tests.some (test) =>\n        temp = new runtime.constructor\n          pointer: \"\"\n          error_pointer: runtime.pointer\n          errors: []\n        test(data, temp)\n        if temp.items_tested && temp.items_tested > most_items_tested\n          best_errors = temp.errors\n          most_items_tested = temp.items_tested\n        temp.errors.length == 0\n\n      unless answer\n        if @options.closestMatch\n          Array::push.apply runtime.errors, best_errors\n        else\n          runtime.error context, data\n\n\n\n  # Note from author of draft4 on how allOf works w/r/t additionalProperties\n  # http://stackoverflow.com/questions/22689900/json-schema-allof-with-additionalproperties/23001194#23001194\n  # also https://github.com/fge/json-schema-validator/issues/88\n  allOf: (definition, context) ->\n    unless @test_type \"array\", definition\n      throw new Error \"The 'allOf' attribute must be an array\"\n    if definition.length == 0\n      throw new Error \"The 'allOf' array may not be empty\"\n\n    # TODO: check for proper error reporting.  Do we need to create new\n    # runtimes, contexts, etc.?\n    tests = []\n    for schema, i in definition\n      unless @test_type \"object\", schema\n        throw new Error \"The 'allOf' array values must be objects\"\n\n      new_context = context.child(i)\n      tests.push @compile(new_context, schema)\n\n    (data, runtime) =>\n      for test in tests\n        test data, runtime\n      null\n\n  oneOf: (definition, context) ->\n    unless @test_type \"array\", definition\n      throw new Error \"The 'oneOf' attribute must be an array\"\n\n    if definition.length == 0\n      throw new Error \"The 'oneOf' array may not be empty\"\n\n    tests = []\n    for schema, i in definition\n      unless @test_type \"object\", schema\n        throw new Error \"The 'oneOf' array values must be objects\"\n\n      new_context = context.child(i)\n      tests.push @compile(new_context, schema)\n\n    # TODO optimize?\n    (data, runtime) =>\n      valids = 0\n      most_items_tested = 0\n      best_errors = []\n      for test in tests\n        temp = new runtime.constructor\n          pointer: \"\"\n          error_pointer: runtime.pointer\n          errors: []\n        test(data, temp)\n        if temp.errors.length == 0\n          valids++\n        else\n          if temp.items_tested && temp.items_tested > most_items_tested\n            best_errors = temp.errors\n            most_items_tested = temp.items_tested\n\n      if valids == 0 && @options.closestMatch\n        Array::push.apply runtime.errors, best_errors\n      else if valids != 1\n        runtime.error context, data\n\n\n  not: (definition, context) ->\n    unless @test_type \"object\", definition\n      throw new Error \"The 'not' attribute must be an object\"\n\n    inverse = @compile context, definition\n    (data, runtime) =>\n      temp = new runtime.constructor\n        pointer: \"\"\n        errors: []\n      inverse data, temp\n      if temp.errors.length == 0\n        runtime.error context, data\n\n"
  },
  {
    "path": "src/draft4/numeric.coffee",
    "content": "module.exports =\n\n  multipleOf: (value, context) ->\n    unless @test_type \"number\", value\n      throw new Error \"The 'multipleOf' attribute must be a number\"\n\n    (data, runtime) =>\n      if @test_type \"number\", data\n        if !((data / value) % 1 == 0)\n          runtime.error context, data, description:\n            \"Value `#{data}` is not a multiple of #{value}\"\n\n"
  },
  {
    "path": "src/draft4/objects.coffee",
    "content": "module.exports =\n\n  # handlers\n\n  required: (definition, context) ->\n    unless @test_type \"array\", definition\n      throw new Error \"The 'required' attribute must be an array\"\n\n    if definition.length == 0\n      throw new Error \"The 'required' array must have at least one element\"\n\n    for property, i in definition\n      unless @test_type \"string\", property\n        throw new Error \"The 'required' array may only contain strings\"\n\n    (data, runtime) =>\n      if @test_type \"object\", data\n        for property, i in definition\n          if data[property] == undefined\n            c = context.child(i)\n            c.definition = property\n            runtime.error c, undefined, description:\n              \"Required property '#{property}' is missing\"\n      null\n\n  properties: (definition, context) ->\n    unless @test_type \"object\", definition\n      throw new Error \"The 'properties' attribute must be an object\"\n\n    tests = {}\n    for property, schema of definition\n      unless @test_type \"object\", schema\n        throw new Error \"The 'properties' attribute must be an object\"\n\n      new_context = context.child(property)\n      test = @compile(new_context, schema)\n      tests[property] = test\n\n    (data, runtime) =>\n      if @test_type \"object\", data\n        for property, value of data\n          if (test = tests[property])?\n            test value, runtime.child(property)\n        null\n\n\n\n  minProperties: (definition, context) ->\n    (data, runtime) =>\n      if @test_type \"object\", data\n        if Object.keys(data).length < definition\n          runtime.error context, data, description:\n            \"Object must have at least #{definition} properties.\"\n\n  maxProperties: (definition, context) ->\n    (data, runtime) =>\n      if @test_type \"object\", data\n        if Object.keys(data).length > definition\n          runtime.error context, data, description:\n            \"Object cannot have more than #{definition} properties.\"\n\n  dependencies: (definition, context) ->\n    unless @test_type \"object\", definition\n      throw new Error \"Value of 'dependencies' must be an object\"\n    else\n      tests = []\n      for property, dependency of definition\n\n        if @test_type \"array\", dependency\n          if dependency.length == 0\n            throw new Error \"Arrays in 'dependencies' may not be empty\"\n\n          for name in dependency\n            unless @test_type \"string\", name\n              throw new Error \"Vales of 'dependencies' arrays must be strings\"\n          tests.push (data, runtime) =>\n            if data[property]?\n              for item in dependency\n                if !data[item]?\n                  runtime.child(property).error context\n              null\n\n        else if @test_type \"object\", dependency\n          fn = @compile context, dependency\n          tests.push (data, runtime) =>\n            if data[property]\n              fn data, runtime\n            else\n              true\n\n        else\n          throw new Error \"Invalid dependency\"\n\n    (data, runtime) =>\n      if @test_type \"object\", data\n        for test in tests\n          test data, runtime\n        null\n\n\n"
  },
  {
    "path": "src/draft4/strings.coffee",
    "content": "module.exports =\n\n  format: (format_name, context) ->\n    if format_name == \"regex\"\n      (data, runtime) =>\n        if @test_type \"string\", data\n          try\n            new RegExp(data)\n          catch error\n            runtime.error context, data, description:\n              \"String is not in the #{format_name} format.\"\n\n    else if regex = format_regexes[format_name]\n      do (regex) =>\n        (data, runtime) =>\n          if @test_type \"string\", data\n            if !regex.test(data)\n              runtime.error context, data, description:\n                \"String is not in the #{format_name} format.\"\n    else\n      throw new Error \"Invalid format_name for 'format'\"\n\n\n# regexes below were derived from\n# https://github.com/tdegrunt/jsonschema\n#\n#Copyright (C) 2012-2013 Tom de Grunt <tom@degrunt.nl>\n\n#Permission is hereby granted, free of charge, to any person obtaining a copy of\n#this software and associated documentation files (the \"Software\"), to deal in\n#the Software without restriction, including without limitation the rights to\n#use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies\n#of the Software, and to permit persons to whom the Software is furnished to do\n#so, subject to the following conditions:\n\n#The above copyright notice and this permission notice shall be included in all\n#copies or substantial portions of the Software.\n\n#THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n#SOFTWARE.\n\nformat_regexes =\n  \"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})?)?)$/\n\n  date: /^(\\d{4}-(?:0[0-9]|1[0-2])-[0-9]{2})$/\n\n  time: /^\\d{2}:\\d{2}:\\d{2}$/\n\n  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])\\]))$/\n\n  \"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]?)$/\n\n  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*$/\n\n  uri: /^[a-zA-Z][a-zA-Z0-9+-.]*:[^\\s]*$/\n\n  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*\\)))$/\n\n  \"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}\\.?)$/\n\n  alpha: /^[a-zA-Z]+$/\n\n  alphanumeric: /^[a-zA-Z0-9]+$/\n\n  \"utc-millisec\": (input) ->\n    (typeof input is \"string\") and parseFloat(input) is parseInt(input, 10) and not isNaN(input)\n\n  style: /\\s*(.+?):\\s*([^;]+);?/g\n\n  phone: /^\\+(?:[0-9] ?){6,14}[0-9]$/\n"
  },
  {
    "path": "src/draft4/type.coffee",
    "content": "\nmodule.exports =\n\n  # handlers\n\n  type: (definition, context) ->\n    if @test_type \"array\", definition\n      if definition.length == 0\n        throw new Error \"Invalid 'type': arrays may not be empty\"\n\n      tests = []\n      for type in definition\n        unless @is_primitive(type)\n          throw new Error \"Invalid 'type': #{type} is not a primitive type\"\n        do (type) =>\n          tests.push (data, runtime) =>\n            @test_type type, data\n\n      (data, runtime) =>\n        valid = false\n        for test in tests\n          if test(data, runtime)\n            valid = true\n        if valid == false\n          types = definition.join ', '\n          runtime.error context, data, description:\n            \"Expected type to be one of [#{types}] but found `#{@get_type(data)}`\"\n\n    else if @test_type \"string\", definition\n      unless @is_primitive(definition)\n        throw new Error \"Invalid 'type': #{definition} is not a primitive type\"\n      (data, runtime) =>\n        if !@test_type definition, data\n          runtime.error context, data, description:\n            \"Expected type to be `#{definition}` but found `#{@get_type(data)}`\"\n    else\n      throw new Error \"The value of 'type' must be a string or an array\"\n\n"
  },
  {
    "path": "src/draft4.coffee",
    "content": "validator = require(\"./validator\")\n\nmodule.exports = validator\n  schema_uri: \"http://json-schema.org/draft-04/schema#\"\n  mixins: [\n    require \"./draft4/type\"\n    require \"./draft4/logical\"\n    require \"./draft4/numeric\"\n    require \"./draft4/objects\"\n    require \"./draft4/strings\"\n  ]\n"
  },
  {
    "path": "src/index.coffee",
    "content": "\nmodule.exports =\n  draft3: require \"./draft3\"\n  draft4: require \"./draft4\"\n\n"
  },
  {
    "path": "src/uri.coffee",
    "content": "is_absolute = (string) ->\n  /^[\\w\\d+.-]+:/.test(string)\n\nis_url = (string) ->\n  /^[\\w\\d+.-]+:\\/\\//.test(string)\n\nresolve = (scope, uri) ->\n  if is_absolute(uri)\n    uri\n  else\n    scope = scope.replace /#$/, \"\"\n    if uri.indexOf(\"#\") == 0\n      [main, _frag] = scope.split(\"#\")\n      main + uri\n    else\n      if is_url(scope) || scope.indexOf(\"/\") != -1\n        scope.replace /\\/[^/]+$/, \"/#{uri}\"\n      else\n        \"#{scope}/#{uri}\"\n\nmodule.exports = {is_absolute, is_url, resolve}\n"
  },
  {
    "path": "src/util.coffee",
    "content": "module.exports =\n  \n  escape: (string) ->\n    string\n      .replace(/~0/g, \"~\")\n      .replace(/~1/g, \"/\")\n      .replace(/%25/g, \"%\")\n\n  # Used during document validation.  Maintains a list of errors and the\n  # JSON pointer for the section of the document.\n  Runtime: class Runtime\n    constructor: ({@errors, @pointer, @error_pointer, @tested_item}) ->\n      @items_tested = 0\n      @tested_item ?= => @items_tested++\n      @error_pointer ?= @pointer\n\n    child: (token) ->\n      new @constructor\n        errors: @errors\n        pointer: \"#{@pointer}/#{token.toString()}\"\n        error_pointer: \"#{@error_pointer}/#{token.toString()}\"\n        tested_item: @tested_item\n\n    path: ->\n      @pointer.slice(2).replace(/\\//g, \".\")\n\n    error: (context, value, options={}) ->\n      e =\n        schema:\n          pointer: context.pointer\n          attribute: context._attribute\n          definition: context.definition\n        document:\n          pointer: @error_pointer\n          path: @path()\n          value: value\n      if options.description?\n        e.description = options.description\n      @errors.push e\n\n\n  # Maintains the URI scope and JSON pointer during traversal\n  # of a schema.\n  Context: class Context\n\n    constructor: ({@pointer, @scope, @_attribute}) ->\n\n    attribute: (name) ->\n      new Context\n        pointer: \"#{@pointer}/#{name.toString()}\"\n        scope: @scope\n        _attribute: name\n\n    child: (token) ->\n      new Context\n        pointer: \"#{@pointer}/#{token.toString()}\"\n        scope: @scope\n        _attribute: @_attribute\n\n    sibling: (token) ->\n      pointer = @pointer.replace(/\\/.*$/, \"/#{token.toString()}\")\n      new Context\n        pointer: pointer\n        scope: @scope\n\n"
  },
  {
    "path": "src/validator.coffee",
    "content": "URI = require \"./uri\"\n\n{escape, Runtime, Context} = require \"./util\"\n\n# Schemas should always be JSON stringifiable, so this is a simple\n# method for obtaining a deep clone of one.  This function only gets\n# used at schema-compilation time, so there are no performance\n# implications unless you are constantly compiling new schemas.\nclone = (value) ->\n  JSON.parse(JSON.stringify(value))\n\nDEFINITIONS =\n  \"http://json-schema.org/draft-03/schema#\":\n    require \"../schemas/draft-03/schema.json\"\n  \"http://json-schema.org/draft-04/schema#\":\n    require \"../schemas/draft-04/schema.json\"\n\nmodule.exports = ({schema_uri, mixins}) ->\n\n  SCHEMA_URI = schema_uri\n\n  class Validator\n\n    @modifiers:\n      patternProperties: [ \"additionalProperties\" ]\n\n      additionalProperties: [\n        \"properties\"\n        \"patternProperties\"\n      ]\n\n      items: [ \"additionalItems\" ]\n\n      minimum: [ \"exclusiveMinimum\" ]\n      maximum: [ \"exclusiveMaximum\" ]\n\n\n    common_modules =\n      \"type\": require \"./common/type\"\n      \"numeric\": require \"./common/numeric\"\n      \"comparison\": require \"./common/comparison\"\n      \"arrays\": require \"./common/arrays\"\n      \"objects\": require \"./common/objects\"\n      \"strings\": require \"./common/strings\"\n\n    common = for name of common_modules\n      mixin = common_modules[name]\n      for name, method of mixin\n        Validator.prototype[name] = method\n\n    for mixin in mixins\n      for name, method of mixin\n        Validator.prototype[name] = method\n\n\n    constructor: (schemas...) ->\n      @uris = {}\n      @media_types = {}\n      @unresolved = {}\n      @options = {}\n\n      @add(DEFINITIONS[SCHEMA_URI])\n      for schema in schemas\n        if schema[\"$schema\"]? && schema[\"$schema\"] != SCHEMA_URI\n          throw \"This validator doesn't support this JSON schema.\"\n        @add(schema)\n\n    set_options: (args) ->\n      @options = args\n      return this\n\n    add: (schema) ->\n      # Clone the schema to prevent any user changes from affecting JSCK.\n      schema = clone(schema)\n\n      if schema.id\n        # Make sure the schema id always ends with \"#\"\n        schema.id = schema.id.replace /#?$/, \"#\"\n\n      # The context keeps track of where we are in the schema while\n      # we traverse it for compilation.\n      context = new Context\n        pointer: schema.id || \"#\"\n        scope: schema.id || \"#\"\n\n      @compile_references context, schema\n      @compile(context, schema)\n\n    validate: (data) ->\n      @validator(\"#\").validate(data)\n\n    validator: (arg) ->\n      if (schema = @find arg)?\n        validate: (data) =>\n          errors = []\n          runtime = new Runtime {errors, pointer: \"#\"}\n          schema._test(data, runtime)\n          if errors.length > 0\n            for error in errors\n              [base..., attribute] = error.schema.pointer.split(\"/\")\n              pointer = base.join(\"/\")\n              error.schema.definition ?= @resolve_uri(pointer)?[attribute]\n              if error.document.value is undefined\n                delete error.document.value\n\n          valid = runtime.errors.length == 0\n          {valid, errors}\n        toJSON: (args...) ->\n          schema\n      else\n        throw new Error \"No schema found for '#{JSON.stringify(arg)}'\"\n\n\n    # Find a registered schema.\n    #\n    # Takes either a URI string or an options object.\n    # Valid options:\n    # * uri\n    # * mediaType\n    find: (arg) ->\n      if @test_type \"string\", arg\n        uri = escape(arg)\n        #if /required/.test uri\n          #for u, def of @uris when /required/.test u\n            #console.error u\n        @uris[uri]\n      else if (uri = arg.uri)?\n        uri = escape(uri)\n        @uris[uri]\n      else if (media_type = arg.mediaType)?\n        @media_types[media_type]\n      else\n        null\n\n\n    resolve_uri: (uri, scope) ->\n      if (schema = @find(uri))?\n        if schema.$ref\n          @resolve_uri URI.resolve(scope, schema.$ref)\n        else\n          schema\n\n\n    register: (uri, schema) ->\n      @uris[uri] = schema\n      # TODO: enforce uniqueness of types\n      if (media_type = schema.mediaType)?\n        if media_type != \"application/json\"\n          @media_types[media_type] = schema\n\n\n    compile_references: (context, schema) ->\n      # Make an initial pass over the schema looking for $ref fields,\n      # recording their targets for use in actual compilation.\n      @schema_references(context, schema)\n\n      # We try a second time to resolve $ref values, because a schema may have\n      # been defined after we initially tried to resolve a $ref.\n      for ref, {scope, uri} of @unresolved\n        if (found_schema = @resolve_uri(uri, scope))?\n          delete @unresolved[ref]\n          @register ref, found_schema\n      if Object.keys(@unresolved).length > 0\n        pointers = (uri for key, {uri} of @unresolved)\n        throw new Error \"Unresolvable $ref values: #{JSON.stringify pointers}\"\n\n\n    schema_references: (context, schema) ->\n      if !@test_type \"object\", schema\n        throw new Error \"Schema must be an object - #{context.pointer}\"\n\n      {scope, pointer} = context\n      @register pointer, schema\n\n      # This is one of the two cases where we pay attention to an \"id\"\n      # attribute. The other is top-level id declaration, serving to identify\n      # the entire schema.\n      #\n      # Here, we treat bare fragment identifiers (e.g. \"#user\") as aliases.\n      if schema.id && schema.id.indexOf(\"#\") == 0\n        uri = URI.resolve scope, schema.id\n        schema.id = uri\n        @register uri, schema\n\n      for attribute, definition of schema\n        if \"$ref\" == attribute\n          @resolve_reference(context, schema, definition)\n        else\n          new_context = context.child(attribute)\n          if \"properties\" == attribute\n            @properties_references new_context, definition\n          else if \"items\" == attribute\n            @items_references new_context, definition\n          else if \"definitions\" == attribute\n            @definitions_references new_context, definition\n          else if @test_type \"object\", definition\n            @schema_references new_context, definition\n          else if attribute in [\"allOf\", \"anyOf\", \"not\"]\n            for s, i in definition\n              @schema_references new_context.child(i), s\n\n\n    resolve_reference: (context, schema, definition) ->\n      {scope, pointer} = context\n      # turn relative refs into absolute URIs\n      uri = URI.resolve(scope, definition)\n\n      # When the URI of a $ref is a substring of the present context's URI,\n      # we're in a recursive reference situation.\n      # Ignore recursive references during this stage.\n      if pointer.indexOf(uri + \"/\") != 0\n        if (found_schema = @resolve_uri(uri, scope))?\n          delete schema.$ref\n          for k, v of found_schema\n            schema[k] = v\n          @schema_references context, schema\n        else\n          # Store the unresolvable reference so we can try to resolve\n          # it again after having traversed the all schemas.\n          @unresolved[pointer] = {scope, uri}\n\n\n    properties_references: (context, properties) ->\n      if !@test_type \"object\", properties\n        throw new Error \"Properties must be an object - #{context.pointer}\"\n\n      for property, schema of properties\n        @schema_references context.child(property), schema\n\n    items_references: (context, definition) ->\n      if @test_type \"array\", definition\n        for def, i in definition\n          @schema_references context.child(i), def\n      else\n        @schema_references context, definition\n\n    definitions_references: (context, object) ->\n      if !@test_type \"object\", object\n        throw new Error \"Value of 'definitions' must be an object - #{context.pointer}\"\n\n      for name, schema of object\n        @schema_references context.child(name), schema\n\n\n    compile: (context, schema) ->\n      {scope, pointer} = context\n      tests = []\n\n      # When the schema contains the $ref attribute, locate the referenced\n      # schema and use in place of the present schema.\n      if (uri = schema.$ref)?\n        if @uris[uri]\n          return (args...) =>\n            @uris[uri]._test(args...)\n        uri = URI.resolve(scope, uri)\n        if pointer.indexOf(uri) == 0\n          # When the URI of a $ref is a substring of the present context's URI,\n          # we're in a recursive reference situation.\n          return @recursive_test(schema, context)\n        schema = @find(uri)\n        if !schema\n          throw new Error \"No schema found for $ref '#{uri}'\"\n\n      for key, definition of schema when key != \"_test\"\n        # Create a child context to track our progress into a new attribute.\n        new_context = context.attribute(key)\n\n        if @[key]?\n          test = @compile_attribute(new_context, key, schema, definition)\n          tests.push(test) if test\n        else\n          # If the key doesn't correspond to a known attribute name, treat\n          # the object as a container of definitions.\n          @compile_definitions(new_context, definition)\n\n      test_function = (data, runtime) ->\n        return null if typeof(data) == \"undefined\"\n        runtime.tested_item()\n        for test in tests\n          test(data, runtime)\n        null\n\n      # Record the test function for use by such things as @recursive_test.\n      @find(pointer)?._test = test_function\n      # Also record the function for schemas with \"alias\" ids.\n      if schema.id\n        uri = URI.resolve scope, schema.id\n        @find(uri)?._test = test_function\n\n      return test_function\n\n\n    compile_attribute: (context, attribute, schema, definition) ->\n\n      # Some validation attributes can be modified by other attributes\n      # at the same level.  E.g. minimum is modified by exclusiveMinimum.\n      # Here we check the schema for such auxiliary attributes and stow\n      # them in the context, so the primary attribute handler can act\n      # on them.\n      context.modifiers = {}\n\n      if (modifiers = Validator.modifiers[attribute])?\n        for key in modifiers\n          context.modifiers[key] = schema[key]\n\n      # Call the attribute's handler.\n      # The return value will be a function that validates a document.\n      # In rare cases, the attribute handler does not return a test\n      # function, because some related attribute performs the test.\n      if @[attribute]?\n        if (test = @[attribute](definition, context))?\n          return test\n\n\n    compile_definitions: (context, object) ->\n      if @is_schema(object)\n        @compile(context, object)\n      else if @test_type \"object\", object\n        for name, definition of object\n          @compile_definitions context.child(name), definition\n\n\n    is_schema: (object) ->\n      object.type? || object.$ref? ||\n        object.allOf? || object.anyOf? || object.not?\n\n    recursive_test: (schema, {scope, pointer}) ->\n      uri = URI.resolve(scope, schema.$ref)\n      if (schema = @find uri)?\n        (data, runtime) ->\n          schema._test(data, runtime)\n      else\n        throw new Error \"No schema found for $ref '#{uri}'\"\n\n\n\n"
  },
  {
    "path": "tasks/build/benchmarks.coffee",
    "content": "fs = require \"fs\"\nshell = require \"shelljs\"\n\nresult = shell.exec \"coffee benchmarks\"\nfs.writeFileSync \"benchmarks/results/all.txt\", result.output\n\n"
  },
  {
    "path": "tasks/build/browser.coffee",
    "content": "{exec} = require \"../helpers\"\n\nrequire \"./javascript\"\n\nbase = \"node_modules/.bin/cjsify lib/index.js --no-node --export JSCK\"\n\n# https://www.npmjs.com/package/commonjs-everywhere\nexec \"#{base} -o jsck.js\"\nexec \"#{base} -m -o jsck.min.js\"\n\n"
  },
  {
    "path": "tasks/build/docs.coffee",
    "content": "{build_docs} = require \"../helpers\"\n\nbuild_docs()\n\n"
  },
  {
    "path": "tasks/build/index.coffee",
    "content": "require \"./javascript\"\nrequire \"./docs\"\n\n\n\n\n"
  },
  {
    "path": "tasks/build/javascript.coffee",
    "content": "{exec} = require \"../helpers\"\n\nexec \"mkdir -p lib\"\nexec \"coffee --compile --bare --output lib/ src/\"\n"
  },
  {
    "path": "tasks/helpers.coffee",
    "content": "shell = require \"shelljs\"\n\nexec = (cmd) ->\n  console.log cmd\n  shell.exec cmd\n\ndocs =\n  \"doc/README.pfm.md\": \"README.md\"\n  \"doc/tests.pfm.md\": \"doc/tests.md\"\n  \"doc/benchmarks.pfm.md\": \"doc/benchmarks.md\"\n\nmodule.exports =\n  exec: exec\n  docs: docs\n\n  build_docs: (name) ->\n    # pfm is a rubygem for converting Panda Flavored Markdown into\n    # GitHub Flavored Markdown.\n    #   gem install pfm\n\n    if name\n      destination = docs[name]\n      exec \"pfm #{name} -o #{destination}\"\n    else\n      for source, destination of docs\n        exec \"pfm #{source} -o #{destination}\"\n\n\n"
  },
  {
    "path": "tasks/update/index.coffee",
    "content": "require \"./submodules\"\n\n\n"
  },
  {
    "path": "tasks/update/submodules.coffee",
    "content": "{exec} = require \"../helpers\"\n\nexec \"git submodule init\"\nexec \"git submodule update\"\n"
  },
  {
    "path": "tasks/watch/docs.coffee",
    "content": "fs = require \"fs\"\n{docs, build_docs} = require \"../helpers\"\n\nfor source, _dest of docs\n  do (source) ->\n    fs.watchFile source, (curr, prev) ->\n      build_docs(source)\n\n\n"
  },
  {
    "path": "tasks/watch/src.coffee",
    "content": "fs = require \"fs\"\n{exec} = require \"../helpers\"\n\nexec \"coffee --compile --watch --bare --output lib/ src/\", ->\n\n"
  },
  {
    "path": "test/.gitignore",
    "content": "suite\nsuite.tgz\n"
  },
  {
    "path": "test/draft3/builtins.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft3\n\n\nTestify.test \"Built in schemas\", (context) ->\n\n  context.test \"$ref to draft 3 works\", ->\n    jsck = new JSCK\n      type: \"object\"\n      properties:\n        foo:\n          $ref: \"http://json-schema.org/draft-03/schema#\"\n\n    report = jsck.validate\n      foo:\n        properties: {}\n    assert.equal report.valid, true\n\n    report = jsck.validate\n      foo:\n        properties: \"smurf\"\n    assert.equal report.valid, false\n\n\n\n"
  },
  {
    "path": "test/draft3/index.coffee",
    "content": "require \"./unit\"\nrequire \"./official\"\nrequire \"./builtins\"\n\n# TODO: implement these tests for draft3\n#require \"./invalid\"\n#require \"./valid\"\n"
  },
  {
    "path": "test/draft3/official.coffee",
    "content": "{draft3} = require \"../../src/index\"\nsuite = require \"json-schema-tests\"\n\n[_node, _script, attribute, test_number] = process.argv\n\nsuite {\n  attribute\n  test_number\n\n  version: \"draft3\"\n\n  validate: (schema, document) ->\n    v = new draft3(schema)\n    v.validate(document)\n\n  ignores:\n    # Doubtful value for the majority of use cases.\n    # https://github.com/pandastrike/jsck/issues/42\n    minLength: [\n      \"one supplementary Unicode code point is not long enough\"\n    ]\n    maxLength: [\n      \"two supplementary Unicode code points is long enough\"\n    ]\n\n    # Not supported because of the potential performance implications\n    # https://github.com/pandastrike/jsck/issues/2\n    uniqueItems: true\n\n    # Impossible to test when using output of JSON.parse\n    # https://github.com/pandastrike/jsck/issues/6\n    \"optional/zeroTerminatedFloats\": true\n    \n    # The following items require fetching of remote schemas.\n    # Support for remote references is planned for the next version of JSCK\n    refRemote: true\n    ref: [\n      \"remote ref, containing refs itself\"\n    ]\n    definitions: true\n}\n\n"
  },
  {
    "path": "test/draft3/unit/errors.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft3\n\njsck = new JSCK\n  type: \"object\"\n  additionalProperties:\n    type: \"object\"\n    additionalProperties: false\n    properties:\n      resource:\n        required: true\n        type: \"string\"\n      url:\n        type: \"string\"\n\nreport = jsck.validate\n  smurf: {url: 4}\n\nconsole.log()\nconsole.log report.errors[0].schema.pointer\nconsole.log()\n"
  },
  {
    "path": "test/draft3/unit/index.coffee",
    "content": "#require \"./errors\"\nrequire \"./references\"\nrequire \"./uri_test\"\n"
  },
  {
    "path": "test/draft3/unit/references.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../../src/index\").draft3\n\n\nTestify.test \"JSCK draft 3 dereferencing\", (context) ->\n\n  context.test \"Finding by uri\", (context) ->\n    jsck = new JSCK\n      $schema: \"http://json-schema.org/draft-03/schema#\"\n      id: \"urn:jsck.test\"\n      type: \"object\"\n      properties:\n        user_list:\n          id: \"#user_list\"\n          type: \"array\"\n          items: {$ref: \"#/properties/user\"}\n        user_dict: {$ref: \"#/properties/user\"}\n\n        user:\n          id: \"#user\"\n          type: \"object\"\n          properties:\n            name:\n              required: true\n              type: \"string\"\n            email:\n              type: \"string\"\n\n    context.test \"JSON Pointer\", ->\n      result = jsck.validator(\"urn:jsck.test#/properties/user\").validate {name: \"automatthew\"}\n      assert.equal result.valid, true\n\n    context.test \"id fragment\", ->\n      result = jsck.validator(\"urn:jsck.test#user\").validate {name: \"automatthew\"}\n      assert.equal result.valid, true\n\n\n  context.test \"schema without 'id'\", (context) ->\n\n    test_schema =\n      definitions:\n        schema1:\n          id: \"#foo\"\n          type: \"string\"\n          format: \"uri\"\n\n    jsck = new JSCK(test_schema)\n    context.test \"JSON pointers\", (context) ->\n\n      context.test \"Pointer relative to empty URI\", ->\n        schema = jsck.find \"#/foo\"\n        assert.deepEqual schema, test_schema.schema1\n\n\n\n  return\n  # FIXME: find out whether these tests fail because of app problems\n  # or test problems.\n\n  context.test \"find\", (context) ->\n    test_schema =\n      id: \"http://x.y.z/rootschema.json#\"\n      schema1:\n        id: \"#foo\"\n      schema2:\n        id: \"otherschema.json\"\n        type: \"string\"\n        nested:\n          id: \"#bar\"\n        alsonested:\n          id: \"t/inner.json#a\"\n      schema3:\n        id: \"some://where.else/completely#\"\n      schema4:\n        $ref: \"#foo\"\n\n    jsck = new JSCK(test_schema)\n\n    context.test \"JSON pointers\", (context) ->\n\n      context.test \"Absolute URI\", ->\n        schema = jsck.find \"http://x.y.z/rootschema.json#/schema1\"\n        assert.deepEqual schema, test_schema.schema1\n\n        schema = jsck.find \"http://x.y.z/rootschema.json#/schema2/nested\"\n        assert.deepEqual schema, test_schema.schema2.nested\n\n    context.test \"Setting scope with 'id'\", (context) ->\n\n      context.test \"works for fragment\", ->\n        schema = jsck.find \"http://x.y.z/rootschema.json#foo\"\n        assert.deepEqual schema, test_schema.schema1\n\n      context.test \"ignores path change\", ->\n        schema = jsck.find \"http://x.y.z/otherschema.json#bar\"\n        assert.deepEqual schema, undefined\n\n      context.test \"ignores nested path change\", ->\n        schema = jsck.find \"http://x.y.z/t/inner.json#a\"\n        assert.deepEqual schema, undefined\n\n    context.test \"Inline reference resolution\", ->\n      schema = jsck.find \"http://x.y.z/rootschema.json#/schema4\"\n      assert.deepEqual schema, test_schema.schema1\n\n\n\n\n"
  },
  {
    "path": "test/draft3/unit/uri_test.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nURI = require \"../../../src/uri\"\n\nTestify.test \"URI helper methods\", (context) ->\n\n  context.test \"is_absolute\", (context) ->\n\n    context.test \"URNs\", ->\n      assert.equal URI.is_absolute(\"urn:foo:bar:baz\"), true\n      assert.equal URI.is_absolute(\"urn\"), false\n\n    context.test \"URLs\", ->\n      assert.equal URI.is_absolute(\"http://example.com:1452/smurf\"), true\n      assert.equal URI.is_absolute(\"example.com\"), false\n\n\n  context.test \"is_url\", ->\n    assert.equal URI.is_url(\"https://monkeyshines.org/x?y=z\"), true\n    assert.equal URI.is_url(\"urn:foo:bar/baz,bat\"), false\n\n\n  context.test \"resolve\", (context) ->\n\n    context.test \"URL scope\", (context) ->\n      scope = \"http://pandastrike.com/patchboard.json#\"\n\n      context.test \"absolute reference\", ->\n        assert.equal URI.resolve(scope, \"http://example.com/schema.json#\"),\n          \"http://example.com/schema.json#\"\n\n      context.test \"fragment\", ->\n        assert.equal URI.resolve(scope, \"#service\"),\n          \"http://pandastrike.com/patchboard.json#service\"\n\n      context.test \"root reference\", ->\n        assert.equal URI.resolve(scope, \"#\"),\n          \"http://pandastrike.com/patchboard.json#\"\n\n      context.test \"fragment reference\", ->\n        assert.equal URI.resolve(scope, \"#/properties/resource\"),\n          \"http://pandastrike.com/patchboard.json#/properties/resource\"\n\n      context.test \"hierarchical references\", ->\n        assert.equal URI.resolve(scope, \"other.json\"),\n          \"http://pandastrike.com/other.json\"\n\n        scope = \"http://pandastrike.com/schemas/patchboard.json#\"\n        assert.equal URI.resolve(scope, \"other.json\"),\n          \"http://pandastrike.com/schemas/other.json\"\n\n      context.test \"scope reference, root reference\", ->\n        s = \"http://pandastrike.com/patchboard.json#/properties/foo\"\n        assert.equal URI.resolve(s, \"#\"),\n          \"http://pandastrike.com/patchboard.json#\"\n\n\n    context.test \"URI other than URL scope\", (context) ->\n      scope = \"urn:jsck.anon#\"\n\n      context.test \"fragment\", ->\n        assert.equal URI.resolve(scope, \"#service\"),\n          \"urn:jsck.anon#service\"\n\n      context.test \"hierarchical references\", ->\n        assert.equal URI.resolve(scope, \"other.json\"),\n          \"urn:jsck.anon/other.json\"\n\n"
  },
  {
    "path": "test/draft4/adhoc.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft4\n\n\nTestify.test \"Ad hoc tests\", (context) ->\n\n  context.test \"undefinedness\", (context) ->\n    jsck = new JSCK\n      $schema: \"http://json-schema.org/draft-04/schema#\"\n      type: \"object\"\n      properties:\n        foo:\n          type: [ \"number\" ]\n\n    context.test \"valid\", ->\n      result = jsck.validate\n        foo: undefined\n      assert.equal result.valid, true\n\n      result = jsck.validate\n        foo: 42\n      assert.equal result.valid, true\n\n      result = jsck.validate Object.create({foo: 42})\n      assert.equal result.valid, true\n\n\n    context.test \"invalid\", ->\n      result = jsck.validate\n        foo: null\n      assert.equal result.valid, false\n\n  context.test \"issue #94 from SciencePiggy\", ->\n    jsck = new JSCK\n      type: \"object\"\n      required: [ \"fullName\" ]\n      properties:\n        fullName:\n          type: \"string\"\n        settings:\n          $ref: \"#/definitions/userSettings\"\n\n      definitions:\n        userSettings:\n          type: \"object\"\n          required: [ \"language\" ]\n          properties:\n            language:\n              type: \"string\"\n\n    result = jsck.validate\n      fullName: \"Homer Simpson\"\n      settings: null\n\n    assert.equal result.valid, false\n\n\n"
  },
  {
    "path": "test/draft4/builtins.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft4\n\n\nTestify.test \"Built in schemas\", (context) ->\n\n  context.test \"$ref to draft 4 works\", ->\n    jsck = new JSCK\n      type: \"object\"\n      properties:\n        foo:\n          $ref: \"http://json-schema.org/draft-04/schema#\"\n\n    report = jsck.validate\n      foo:\n        properties: {}\n    assert.equal report.valid, true\n\n    report = jsck.validate\n      foo:\n        properties: \"smurf\"\n    assert.equal report.valid, false\n\n\n"
  },
  {
    "path": "test/draft4/index.coffee",
    "content": "require \"./unit\"\nrequire \"./official\"\nrequire \"./invalid\"\nrequire \"./valid\"\nrequire \"./builtins\"\n"
  },
  {
    "path": "test/draft4/invalid/additionalItems.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be either a boolean or an object\"\n      schemas: for value in json_types.except(\"boolean\", \"object\")\n        # additionalItems only takes effect when the value of 'items' is an array\n        items: [ {} ]\n        additionalItems: value\n    }\n\n  ]\n\n\n\n"
  },
  {
    "path": "test/draft4/invalid/additionalProperties.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be a boolean or an object\"\n      schemas: for value in json_types.except(\"boolean\", \"object\")\n        additionalProperties: value\n    }\n\n\n  ]\n\n"
  },
  {
    "path": "test/draft4/invalid/allOf.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an array\"\n      schemas: for value in json_types.except(\"array\")\n        allOf: value\n    }\n\n    {\n      description: \"array MUST have at least one element\"\n      schemas: [\n        allOf: []\n      ]\n    }\n\n    {\n      description: \"elements of the array MUST be objects\"\n      schemas: for value in json_types.except(\"object\")\n        allOf: [ value ]\n    }\n\n  ]\n\n"
  },
  {
    "path": "test/draft4/invalid/anyOf.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an array\"\n      schemas: for value in json_types.except(\"array\")\n        anyOf: value\n    }\n\n    {\n      description: \"array MUST have at least one element\"\n      schemas: [\n        anyOf: []\n      ]\n    }\n\n    {\n      description: \"elements of the array MUST be objects\"\n      schemas: for value in json_types.except(\"object\")\n        anyOf: [ value ]\n    }\n\n  ]\n\n"
  },
  {
    "path": "test/draft4/invalid/dependencies.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an object\"\n      schemas: for value in json_types.except(\"object\")\n        dependencies: value\n    }\n\n    {\n      description: \"each value MUST be either an object or an array\"\n      schemas: for value in json_types.except(\"object\", \"array\")\n        dependencies:\n          foo: value\n    }\n\n    {\n      description: \"array values must have at least one element\"\n      schemas: [\n        dependencies:\n          foo: []\n      ]\n    }\n\n    {\n      description: \"array values must contain only strings\"\n      schemas: [\n        dependencies:\n          foo: [33]\n      ]\n    }\n\n  ]\n\n"
  },
  {
    "path": "test/draft4/invalid/items.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be either an object or an array\"\n      schemas: for value in json_types.except(\"object\", \"array\")\n        {items: value}\n    }\n\n    {\n      description: \"arrays may only contain objects\"\n      schemas: for value in json_types.except(\"object\")\n        {items: [value]}\n    }\n\n  ]\n\n\n"
  },
  {
    "path": "test/draft4/invalid/not.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an object\"\n      schemas: for value in json_types.except(\"object\")\n        not: value\n    }\n\n  ]\n\n\n"
  },
  {
    "path": "test/draft4/invalid/numbers.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"'multipleOf' value MUST be a number\"\n      schemas: for value in json_types.except(\"number\", \"integer\")\n        multipleOf: value\n    }\n\n  ]\n\n\n\n"
  },
  {
    "path": "test/draft4/invalid/oneOf.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an array\"\n      schemas: for value in json_types.except(\"array\")\n        oneOf: value\n    }\n\n    {\n      description: \"array MUST have at least one element\"\n      schemas: [\n        oneOf: []\n      ]\n    }\n\n    {\n      description: \"elements of the array MUST be objects\"\n      schemas: for value in json_types.except(\"object\")\n        oneOf: [ value ]\n    }\n\n  ]\n\n\n"
  },
  {
    "path": "test/draft4/invalid/patternProperties.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an object\"\n      schemas: for value in json_types.except(\"object\")\n        patternProperties: value\n    }\n\n    {\n      description: \"object should not be empty\"\n      schemas: for value in json_types.except(\"object\")\n        patternProperties: {}\n    }\n\n    {\n      description: \"names should be valid regexes\"\n      schemas: [\n        {\n          patternProperties:\n            \"[\": {}\n        }\n      ]\n    }\n\n    {\n      description: \"object values MUST themselves be objects\"\n      schemas: for value in json_types.except(\"object\")\n        patternProperties:\n          foo: value\n    }\n\n\n  ]\n\n"
  },
  {
    "path": "test/draft4/invalid/properties.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be an object\"\n      schemas: for value in json_types.except(\"object\")\n        properties: value\n    }\n\n    {\n      description: \"property values must themselves be objects\"\n      schemas: for value in json_types.except(\"object\")\n        properties:\n          big: value\n    }\n\n  ]\n\n"
  },
  {
    "path": "test/draft4/invalid/required.coffee",
    "content": "module.exports = ({json_types}) ->\n  [\n\n    {\n      description: \"value MUST be an array\"\n      schemas: for value in json_types.except(\"array\")\n        required: value\n    }\n\n    {\n      description: \"the array must have at least one value\"\n      schemas: [\n        required: []\n      ]\n    }\n\n    {\n      description: \"the array values must be strings\"\n      schemas: for value in json_types.except(\"string\")\n        required: [value]\n    }\n\n  ]\n\n\n\n\n"
  },
  {
    "path": "test/draft4/invalid/strings.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"'pattern' value must be a string\"\n      schemas: for value in json_types.except(\"string\")\n        pattern: value\n    }\n\n    {\n      description: \"'maxLength' value must be an integer\"\n      schemas: for value in json_types.except(\"integer\")\n        maxLength: value\n    }\n\n    {\n      description: \"'minLength' value must be an integer\"\n      schemas: for value in json_types.except(\"integer\")\n        minLength: value\n    }\n\n\n  ]\n\n\n\n"
  },
  {
    "path": "test/draft4/invalid/type.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  [\n\n    {\n      description: \"value MUST be either a string or an array\"\n      schemas: for value in json_types.except(\"string\", \"array\")\n        {type: value}\n    }\n\n    {\n      description: \"arrays may not be empty\"\n      schemas: [\n        {type: []}\n      ]\n    }\n\n    {\n      description: \"arrays may only contain strings\"\n      schemas: for value in json_types.except(\"string\")\n        {type: value}\n    }\n\n    {\n      description: \"string values must be one of the primitive types\"\n      schemas: [\n        type: \"bogus\"\n      ]\n    }\n\n  ]\n\n"
  },
  {
    "path": "test/draft4/invalid.coffee",
    "content": "glob = require \"glob\"\nassert = require \"assert\"\nTestify = require \"testify\"\n\n{draft4} = require(\"../../src/index\")\n\n[_, _, single_attr] = process.argv\n\nhelpers =\n  json_types:\n    values:\n      integer: 2\n      number: 2.1\n      string: \"foo\"\n      object: {}\n      array: [ ]\n      boolean: false\n      null: null\n    except: (names...) ->\n      for name, value of @values when !(name in names)\n        value\n\nTestify.test \"Rejecting invalid schemas\", (context) ->\n\n  files = glob.sync(\"#{__dirname}/invalid/*.coffee\").sort()\n  l = \"#{__dirname}/invalid/\".length\n\n  for file in files\n    # chomp .coffee\n    attribute_name = file.slice(l, -7)\n\n    if single_attr && attribute_name != single_attr\n      continue\n\n    context.test attribute_name, (context) ->\n      tests = require(file)\n      # Dependency injection, where needed\n      if tests.constructor == Function\n        tests = tests(helpers)\n      for test in tests\n        context.test test.description, ->\n          for schema in test.schemas\n            try\n              new draft4(schema)\n              context.fail \"#{test.description} - #{JSON.stringify schema}\"\n            catch e\n              if test.debug\n                console.log \"\\n\", attribute_name, \"-\", test.description\n                console.log schema\n                console.log e.stack\n\n\n"
  },
  {
    "path": "test/draft4/official.coffee",
    "content": "{draft4} = require \"../../src/index\"\n\nsuite = require \"json-schema-tests\"\n\n\n#shell = require \"shelljs\"\n#cmd = \"node_modules/.bin/nserver -p 5725 -d test/JSON-Schema-Test-Suite/remotes\"\n#proc = shell.exec cmd, (code, output) ->\n#\n#Testify = require \"testify\"\n#Testify.once \"done\", ->\n  #console.log \"Shutting down the 'remotes' test server\"\n  #proc.kill(\"SIGTERM\")\n\n[_node, _script, attribute, test_number] = process.argv\n\nsuite {\n  attribute\n  test_number\n\n  version: \"draft4\"\n\n  validate: (schema, document) ->\n    v = new draft4(schema)\n    v.validate(document)\n\n\n  ignores:\n    # Doubtful value for the majority of use cases.\n    # https://github.com/pandastrike/jsck/issues/42\n    minLength: [\n      \"one supplementary Unicode code point is not long enough\"\n    ]\n    maxLength: [\n      \"two supplementary Unicode code points is long enough\"\n    ]\n\n    # Not supported because of the potential performance implications\n    # https://github.com/pandastrike/jsck/issues/2\n    uniqueItems: true\n\n    # Impossible to test when using output of JSON.parse\n    # https://github.com/pandastrike/jsck/issues/6\n    \"optional/zeroTerminatedFloats\": true\n    \n    # The following items require fetching of remote schemas.\n    # Support for remote references is planned for the next version of JSCK\n    refRemote: true\n    ref: [\n      \"remote ref, containing refs itself\"\n    ]\n    definitions: true\n}\n"
  },
  {
    "path": "test/draft4/unit/errors.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../src/index\").draft3\n\njsck = new JSCK\n  type: \"object\"\n  additionalProperties:\n    type: \"object\"\n    additionalProperties: false\n    properties:\n      resource:\n        required: true\n        type: \"string\"\n      url:\n        type: \"string\"\n\nreport = jsck.validate\n  smurf: {url: 4}\n\nconsole.log()\nconsole.log report.errors[0].schema.pointer\nconsole.log()\n"
  },
  {
    "path": "test/draft4/unit/index.coffee",
    "content": "#require \"./errors\"\nrequire \"./references\"\nrequire \"./uri_test\"\n"
  },
  {
    "path": "test/draft4/unit/logical.coffee",
    "content": "Testify = require \"testify\"\nassert = require \"assert\"\n\nJSCK = require(\"../../../src\")\n\njsck = new JSCK.draft4\n  definitions:\n\n    assetType:\n      type: \"string\"\n      enum: [\n        \"vote\"\n        \"image\"\n        \"audio\"\n        \"video\"\n      ]\n\n    campaign:\n\n      base:\n        type: \"object\"\n        properties:\n          name:\n            type: \"string\"\n          metadata:\n            type: \"object\"\n          assetTypes:\n            type: \"array\"\n            items: {$ref: \"#/definitions/assetType\"}\n          active:\n            type: \"boolean\"\n          startTime:\n            type: \"string\"\n            format: \"date-time\"\n          endTime:\n            type: \"string\"\n            format: \"date-time\"\n\n      create:\n        allOf: [\n          {$ref: \"#/definitions/campaign/base\"}\n          {\n            required: [\"name\", \"assetTypes\"]\n          }\n        ]\n\n\nvalidator = jsck.validator(\"#/definitions/campaign/create\")\n\nTestify.test \"using logical keywords\", (context) ->\n\n  context.test \"allOf\", ->\n\n    {errors} = validator.validate\n      name: \"foobar\"\n      assetTypes: [\"vote\"]\n      startTime: \"monkey\"\n\n    assert.equal errors.length, 0, \"Unexpected errors:\\n#{JSON.stringify(errors, null, 2)}\"\n\n  \n\n"
  },
  {
    "path": "test/draft4/unit/references.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nJSCK = require(\"../../../src/index\").draft4\n\n\nTestify.test \"JSCK draft 4 dereferencing\", (context) ->\n\n  context.test \"Finding by uri\", (context) ->\n    jsck = new JSCK\n      $schema: \"http://json-schema.org/draft-04/schema#\"\n      id: \"urn:jsck.test\"\n      type: \"object\"\n      properties:\n        user_list:\n          id: \"#user_list\"\n          type: \"array\"\n          items: {$ref: \"#/properties/user\"}\n        user_dict: {$ref: \"#/properties/user\"}\n\n        user:\n          id: \"#user\"\n          type: \"object\"\n          required: [\"name\"]\n          properties:\n            name:\n              type: \"string\"\n            email:\n              type: \"string\"\n\n    context.test \"JSON Pointer\", ->\n      result = jsck.validator(\"urn:jsck.test#/properties/user\").validate {name: \"automatthew\"}\n      assert.equal result.valid, true\n\n    context.test \"id fragment\", ->\n      result = jsck.validator(\"urn:jsck.test#user\").validate {name: \"automatthew\"}\n      assert.equal result.valid, true\n\n\n  context.test \"schema without 'id'\", (context) ->\n\n    test_schema =\n      definitions:\n        schema1:\n          id: \"#foo\"\n          type: \"string\"\n          format: \"uri\"\n\n    jsck = new JSCK(test_schema)\n    context.test \"JSON pointers\", (context) ->\n\n      context.test \"Pointer relative to empty URI\", ->\n        schema = jsck.find \"#/foo\"\n        assert.deepEqual schema, test_schema.schema1\n\n\n\n  return\n  # FIXME: find out whether these tests fail because of app problems\n  # or test problems.\n\n  context.test \"find\", (context) ->\n    test_schema =\n      id: \"http://x.y.z/rootschema.json#\"\n      schema1:\n        id: \"#foo\"\n      schema2:\n        id: \"otherschema.json\"\n        type: \"string\"\n        nested:\n          id: \"#bar\"\n        alsonested:\n          id: \"t/inner.json#a\"\n      schema3:\n        id: \"some://where.else/completely#\"\n      schema4:\n        $ref: \"#foo\"\n\n    jsck = new JSCK(test_schema)\n\n    context.test \"JSON pointers\", (context) ->\n\n      context.test \"Absolute URI\", ->\n        schema = jsck.find \"http://x.y.z/rootschema.json#/schema1\"\n        assert.deepEqual schema, test_schema.schema1\n\n        schema = jsck.find \"http://x.y.z/rootschema.json#/schema2/nested\"\n        assert.deepEqual schema, test_schema.schema2.nested\n\n    context.test \"Setting scope with 'id'\", (context) ->\n\n      context.test \"works for fragment\", ->\n        schema = jsck.find \"http://x.y.z/rootschema.json#foo\"\n        assert.deepEqual schema, test_schema.schema1\n\n      context.test \"ignores path change\", ->\n        schema = jsck.find \"http://x.y.z/otherschema.json#bar\"\n        assert.deepEqual schema, undefined\n\n      context.test \"ignores nested path change\", ->\n        schema = jsck.find \"http://x.y.z/t/inner.json#a\"\n        assert.deepEqual schema, undefined\n\n    context.test \"Inline reference resolution\", ->\n      schema = jsck.find \"http://x.y.z/rootschema.json#/schema4\"\n      assert.deepEqual schema, test_schema.schema1\n\n\n\n\n"
  },
  {
    "path": "test/draft4/unit/uri_test.coffee",
    "content": "assert = require \"assert\"\nTestify = require \"testify\"\n\nURI = require \"../../../src/uri\"\n\nTestify.test \"URI helper methods\", (context) ->\n\n  context.test \"is_absolute\", (context) ->\n\n    context.test \"URNs\", ->\n      assert.equal URI.is_absolute(\"urn:foo:bar:baz\"), true\n      assert.equal URI.is_absolute(\"urn\"), false\n\n    context.test \"URLs\", ->\n      assert.equal URI.is_absolute(\"http://example.com:1452/smurf\"), true\n      assert.equal URI.is_absolute(\"example.com\"), false\n\n\n  context.test \"is_url\", ->\n    assert.equal URI.is_url(\"https://monkeyshines.org/x?y=z\"), true\n    assert.equal URI.is_url(\"urn:foo:bar/baz,bat\"), false\n\n\n  context.test \"resolve\", (context) ->\n\n    context.test \"URL scope\", (context) ->\n      scope = \"http://pandastrike.com/patchboard.json#\"\n\n      context.test \"absolute reference\", ->\n        assert.equal URI.resolve(scope, \"http://example.com/schema.json#\"),\n          \"http://example.com/schema.json#\"\n\n      context.test \"fragment\", ->\n        assert.equal URI.resolve(scope, \"#service\"),\n          \"http://pandastrike.com/patchboard.json#service\"\n\n      context.test \"root reference\", ->\n        assert.equal URI.resolve(scope, \"#\"),\n          \"http://pandastrike.com/patchboard.json#\"\n\n      context.test \"fragment reference\", ->\n        assert.equal URI.resolve(scope, \"#/properties/resource\"),\n          \"http://pandastrike.com/patchboard.json#/properties/resource\"\n\n      context.test \"hierarchical references\", ->\n        assert.equal URI.resolve(scope, \"other.json\"),\n          \"http://pandastrike.com/other.json\"\n\n        scope = \"http://pandastrike.com/schemas/patchboard.json#\"\n        assert.equal URI.resolve(scope, \"other.json\"),\n          \"http://pandastrike.com/schemas/other.json\"\n\n      context.test \"scope reference, root reference\", ->\n        s = \"http://pandastrike.com/patchboard.json#/properties/foo\"\n        assert.equal URI.resolve(s, \"#\"),\n          \"http://pandastrike.com/patchboard.json#\"\n\n\n    context.test \"URI other than URL scope\", (context) ->\n      scope = \"urn:jsck.anon#\"\n\n      context.test \"fragment\", ->\n        assert.equal URI.resolve(scope, \"#service\"),\n          \"urn:jsck.anon#service\"\n\n      context.test \"hierarchical references\", ->\n        assert.equal URI.resolve(scope, \"other.json\"),\n          \"urn:jsck.anon/other.json\"\n\n"
  },
  {
    "path": "test/draft4/valid/basic.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  \"may contain properties which are not schema keywords\":\n    schemas:\n\n      \"string value\":\n        monkey: \"shines\"\n\n      \"integer value\":\n        monkey: 84\n\n      \"schema value\":\n        monkey:\n          type: \"array\"\n\n\n"
  },
  {
    "path": "test/draft4/valid/definitions.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  \"known attribute name as key of 'definitions' dictionary\":\n    schemas:\n\n      required:\n        definitions:\n          required:\n            type: \"object\"\n\n      id:\n        definitions:\n          id:\n            type: \"object\"\n\n      items:\n        definitions:\n          items:\n            type: \"object\"\n\n  \"nested definitions\":\n    schemas:\n\n      foo:\n        definitions:\n          bar: {type: \"string\"}\n          definitions:\n            baz: {type: \"string\"}\n"
  },
  {
    "path": "test/draft4/valid/properties.coffee",
    "content": "module.exports = ({json_types}) ->\n\n  \"known attribute name\":\n    schemas:\n\n      required:\n        type: \"object\"\n        properties:\n          required:\n            type: \"boolean\"\n\n      id:\n        type: \"object\"\n        properties:\n          id:\n            type: \"string\"\n\n      properties:\n        type: \"object\"\n        properties:\n          properties: {type: \"array\"}\n\n\n\n"
  },
  {
    "path": "test/draft4/valid.coffee",
    "content": "glob = require \"glob\"\nassert = require \"assert\"\nTestify = require \"testify\"\n\n{draft4} = require(\"../../src/index\")\n\nhelpers =\n  json_types:\n    values:\n      integer: 2\n      number: 2.1\n      string: \"foo\"\n      object: {}\n      array: [ ]\n      boolean: false\n      null: null\n    except: (names...) ->\n      for name, value of @values when !(name in names)\n        value\n\nTestify.test \"Accepting valid schemas\", (context) ->\n\n  files = glob.sync(\"#{__dirname}/valid/*.coffee\").sort()\n  l = \"#{__dirname}/valid/\".length\n\n  for file in files\n    # chomp .coffee\n    attribute_name = file.slice(l, -7)\n\n    context.test attribute_name, (context) ->\n      tests = require(file)\n      # Dependency injection, where needed\n      if tests.constructor == Function\n        tests = tests(helpers)\n\n      for name, test of tests\n        context.test name, (context) ->\n          for k, schema of test.schemas\n            context.test k, ->\n              try\n                new draft4(schema)\n              catch e\n                console.log e.stack\n                context.fail(e)\n\n\n\n"
  },
  {
    "path": "test/index.coffee",
    "content": "\nrequire \"./draft3/unit\"\nrequire \"./draft3\"\n\nrequire \"./draft4/unit\"\nrequire \"./draft4\"\n\n\n"
  }
]