{"_id":"json-rest-schema","_rev":"16-a803924214b1ff944153e1197c30c29c","name":"json-rest-schema","dist-tags":{"latest":"1.0.17"},"versions":{"1.0.2":{"name":"json-rest-schema","version":"1.0.2","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.2","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"8bdc9c6c55e4ccb84214b26a593af7e98337b03e","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.2.tgz","fileCount":6,"integrity":"sha512-wG9KzRdOg7OxvLoH+KR8aFFhsXN1KcN28U7RPPJ9HO1Y+o/CQTGKtyUwoLAeyMEUG7ib6K3L66NfuOnERIGamA==","signatures":[{"sig":"MEUCIC8OcVcVBP2EcxyrapQ/6sRiQvqwEumvwlC3bAWP+v8HAiEAp2aWb+Ky9LsyUgURVH2rqbNqLo6RxrM+H3fymNfcePg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":39985},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"1602fb62e767e2d833815725ac1db66e8fa6f23e","scripts":{"lint":"eslint src/","test":"node --experimental-modules --no-warnings example.js","start":"node --experimental-modules --no-warnings example.js","lint:fix":"eslint src/ --fix"},"_npmUser":{"name":"mercmobily","actor":{"name":"mercmobily","type":"user","email":"tonymobily@gmail.com"},"email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.1","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.16.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^8.57.0"},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.2_1751523053560_0.694785734774741","host":"s3://npm-registry-packages-npm-production"}},"1.0.3":{"name":"json-rest-schema","version":"1.0.3","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.3","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"96d522287671db0fa17c32ef5615beda11e5a7dd","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.3.tgz","fileCount":6,"integrity":"sha512-0ZnydASCz0e/W4CbF/ZP4LJpYIJ87UIcBHz4G5H5HMkeqnktA2xt/cgKHxgj6+ZYc0OfC01zRe/4yYkE7Y2wNg==","signatures":[{"sig":"MEUCIQC9wk6dvcUFO9Hc9rXBKIpvHn5GMc/hPK5WNO+Zcq7N9QIgS6WRi243+Qrz4/uLmWGiQER3HeSGehOVb0iQWyxW7BI=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":39985},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"1602fb62e767e2d833815725ac1db66e8fa6f23e","scripts":{"lint":"eslint src/","test":"node --experimental-modules --no-warnings example.js","start":"node --experimental-modules --no-warnings example.js","lint:fix":"eslint src/ --fix"},"_npmUser":{"name":"mercmobily","actor":{"name":"mercmobily","type":"user","email":"tonymobily@gmail.com"},"email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.1","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.16.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^8.57.0"},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.3_1751523734831_0.37231591091330163","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"json-rest-schema","version":"1.0.4","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.4","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"61186ff40fb430e962c995d3f3107bc3f4c4d09c","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.4.tgz","fileCount":6,"integrity":"sha512-BY8IzOCyHaunuaXAPrtNvEPcyLUAfDxp7kNr6x4RwxeN8N6lvW+P1nEOC03vfgNFER6egR3hCCBERxjMb9+nbA==","signatures":[{"sig":"MEUCIFeK8Pwn6gAG4OCGUSJ50yx+aLLR4B+VU7Htt+V8stYzAiEA86y6GxGBsgnbgdJuMvqQnM+jLknfMOoWULX2ISHNV4A=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":40600},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"d506d8f3ae8454ccbb9d429145b0205c54377288","scripts":{"lint":"eslint src/","test":"node --experimental-modules --no-warnings example.js","start":"node --experimental-modules --no-warnings example.js","lint:fix":"eslint src/ --fix"},"_npmUser":{"name":"mercmobily","actor":{"name":"mercmobily","type":"user","email":"tonymobily@gmail.com"},"email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.1","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.16.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^8.57.0"},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.4_1751629513540_0.9149824742430279","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"json-rest-schema","version":"1.0.5","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.5","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"97687f72345e43f4050259fc02103503891acffb","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.5.tgz","fileCount":6,"integrity":"sha512-PU6FiY6KH7h5XkTEI4yEQOJHkiJJmtYCOvrFNttaM8LJ2Zc55zP4kAD2+Xf4MqmrrYpX2GtCd1uYJj+du8/mPA==","signatures":[{"sig":"MEYCIQD3nFwa+u4txFKcsmSaSceFYPP8VaSw1GzJJCc7+sVemgIhAOwl5IjcPxptE4AX9UhHwSANuO7YLYURJSx7ZP8vifv5","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":40600},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"56899a7ea1670a4d8f58c776040e399eade5b2bd","scripts":{"lint":"eslint src/","test":"node --experimental-modules --no-warnings example.js","start":"node --experimental-modules --no-warnings example.js","lint:fix":"eslint src/ --fix"},"_npmUser":{"name":"mercmobily","actor":{"name":"mercmobily","type":"user","email":"tonymobily@gmail.com"},"email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.1","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.16.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^8.57.0"},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.5_1751810405325_0.017292311980077635","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"json-rest-schema","version":"1.0.6","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.6","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"27f7354843316019e1e79a776f64c7d9f6e02aa1","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.6.tgz","fileCount":7,"integrity":"sha512-Gvbx55fWtMPZC5Ka2BughMN6BQgabqllNmc5YV5rlF+vf30hPeXWIRAqtxey7xGF6GMJGWG5EKhx7uzQr6z9wQ==","signatures":[{"sig":"MEUCIF2RUezFEcf3ji1XCKUB9Gn4YEvEW+fKW/VcfPnPPWg/AiEAqMN3cUbV7/AfHZp0qcERxkh1GJs/AOlpnn8asmPN7O8=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":56240},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"bfa72f380d6224e6f809778b5e0b692bfdfb417e","scripts":{"lint":"eslint src/","test":"node --test tests.js test-knex-table-real.js","start":"node example.js","example":"node example.js","lint:fix":"eslint src/ --fix","example:knex":"node knex-table-example.js"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.1","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.16.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^8.57.0","sqlite3":"^5.1.7"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.6_1752203483990_0.20505361723056925","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"json-rest-schema","version":"1.0.7","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.7","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"ee0eb3d2a66e3c029f65769c40f6e582bdca4e06","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.7.tgz","fileCount":7,"integrity":"sha512-mBFZxvl2n7LnJdNovcWWXEBl91sygT9zFbz7dDd6uki0xf99kVEoysaWnEp+2eEleZHPGKHiHZf+JnNtHdDeEA==","signatures":[{"sig":"MEQCIBPv10djez0d5ZkrRskqNdtwsJI5G4edgpurtG1z0GD7AiA4CgaThJAiDtFC/OD5b6EnNernUxYJ6mQcG1HRIRWlWw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":59300},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"757ef95a24fa783aaa74b99994075be6d10c25f1","scripts":{"lint":"eslint src/","test":"node --test tests.js test-knex-table-real.js","start":"node example.js","example":"node example.js","lint:fix":"eslint src/ --fix","example:knex":"node knex-table-example.js"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.1","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.16.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^8.57.0","sqlite3":"^5.1.7"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.7_1752503162469_0.8983947212573211","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"json-rest-schema","version":"1.0.8","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.8","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"beefe07b12f6a079beddce2743e902fb22828aeb","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.8.tgz","fileCount":7,"integrity":"sha512-uSXJd4W1shss6JAjZuivPAEHaaENtyBzFvORuZNg9HaWnnfS8XRvYprmfKTxDWKLXrHtlSn982jBTq5k51ajCA==","signatures":[{"sig":"MEUCIQDqfn5N+D2bZsjlU5fe8sQsZNOvmXyowNb6yTtFKaLbHwIgP1SMyd5YyGNuCzfrAUdnAL74c8KYiZDB/RrLtSM/tqg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":59594},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"5f0b42dba025f16b992ea11be2162cae542b3db1","scripts":{"lint":"eslint src/","test":"node --test tests.js test-knex-table-real.js","start":"node example.js","example":"node example.js","lint:fix":"eslint src/ --fix","example:knex":"node knex-table-example.js"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.1","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.16.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^8.57.0","sqlite3":"^5.1.7"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.8_1753321217616_0.7175208682848344","host":"s3://npm-registry-packages-npm-production"}},"1.0.9":{"name":"json-rest-schema","version":"1.0.9","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.9","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"461221967a0cc6449e84d888f4dd5cc66dda0a7d","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.9.tgz","fileCount":6,"integrity":"sha512-S3jLmxRb3Y+39G8aWe5rVF3uWWociDXVRGm+p8LeloY6nTpcOUFd0Ctu9TcTlI4G7g9Eq8Octa8WDsPaGR4Wdg==","signatures":[{"sig":"MEUCIQCgh6VgosOdU4EBSoqK7W/7p34f4zouhGO682/U1TbXKgIgcbgXJAx0r07wuyPkAgfIRA3GaHQgk7VFjB33FeimK48=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46392},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"2c4a46a498392d73ce5fdae776400450f70f6575","scripts":{"lint":"eslint src/","test":"node --test tests.js test-knex-table-real.js","start":"node example.js","example":"node example.js","lint:fix":"eslint src/ --fix","example:knex":"node knex-table-example.js"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.2","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^8.57.0","sqlite3":"^5.1.7"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.9_1758811501056_0.17347184143280914","host":"s3://npm-registry-packages-npm-production"}},"1.0.10":{"name":"json-rest-schema","version":"1.0.10","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.10","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"d4bd3d1515ca8b3ec6927cc6e2ae92feb05b3f70","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.10.tgz","fileCount":6,"integrity":"sha512-4KhwRQU3E9Nhg67paJuy6qB3ToL5ym+JxvvrmOF1VORlRg52cfX7SxZWxbadV2C3cTFP5AEDdluVms5Z03NUnw==","signatures":[{"sig":"MEUCIQDYB1hmdas8j6U5gwWVnDwxYY0yPutuZ5QZ4DOqzLRWsQIgBaMhnRBgom8BfWqrOXLtWp0lwuiTtVlLD2c0rJAdkAw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46393},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"3aeea3d3c78cad3a3643f84d89c68e8ca2492b90","scripts":{"lint":"eslint src/","test":"node --test tests.js test-knex-table-real.js","start":"node example.js","example":"node example.js","lint:fix":"eslint src/ --fix","example:knex":"node knex-table-example.js"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.2","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^8.57.0","sqlite3":"^5.1.7"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.10_1760408378747_0.46724916823050977","host":"s3://npm-registry-packages-npm-production"}},"1.0.11":{"name":"json-rest-schema","version":"1.0.11","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.11","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"bc3127a2ff8e1700eedda9680539db182bd6b4b8","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.11.tgz","fileCount":6,"integrity":"sha512-U18wodm2O4e4KGzWUv2CxGLVn8RMyKbHsaqOuVtwTProuhvpwTngnXgGHA7cKGA+x0yoOpqC5NYEvQU2f4i9XQ==","signatures":[{"sig":"MEUCIDgnG9INghmihhGy5jMG9KxHpoDAh++MD9RGbBOfB9hcAiEAwSn9m7Vor9SMwKugNW6VKWlbgG0waT5mjU9q+788Sus=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46417},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"fd472725536d2ab9a5418cd98a192d665e223a57","scripts":{"lint":"eslint .","test":"node --test tests.js test-knex-table-real.js","start":"node example.js","example":"node example.js","lint:fix":"eslint . --fix","example:knex":"node knex-table-example.js"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.2","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^9.37.0","sqlite3":"^5.1.7","neostandard":"^0.12.2"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.11_1760415659775_0.15859305882665398","host":"s3://npm-registry-packages-npm-production"}},"1.0.12":{"name":"json-rest-schema","version":"1.0.12","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.12","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises/jsonrestapi-schema#readme","bugs":{"url":"https://mobily-enterprises/jsonrestapi-schema/issues"},"dist":{"shasum":"3de7b498b99413766d4ae7b31c3142bd59bdc5dd","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.12.tgz","fileCount":6,"integrity":"sha512-Qw0cBlSqSL3MObJwTGq2EuKsIR9dh8T3r/kxZ26bzjOpGJrv/28XHa7Q1wrP4uXfSCabVCv7YwI0ennkc02/Ng==","signatures":[{"sig":"MEUCIDCbDFU4Q7KQekKi08eazREBjc70o+ufA5rBW2qKN5qhAiEAkxPqpIRuTjSXLe8vo15+kdOYC7roozqmN/iXTtIWJkM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":46024},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js"},"gitHead":"9c30d3ba7317407a69231515fd58196862b25b34","scripts":{"lint":"eslint .","test":"node --test tests.js test-knex-table-real.js","start":"node example.js","example":"node example.js","lint:fix":"eslint . --fix","example:knex":"node knex-table-example.js"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/jsonrestapi-schema.git","type":"git"},"_npmVersion":"10.8.2","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^9.37.0","sqlite3":"^5.1.7","neostandard":"^0.12.2"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.12_1760420544885_0.49946754829184403","host":"s3://npm-registry-packages-npm-production"}},"1.0.13":{"name":"json-rest-schema","version":"1.0.13","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.13","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises.github.io/json-rest-schema/","bugs":{"url":"https://github.com/mobily-enterprises/json-rest-schema/issues"},"dist":{"shasum":"f5850bd1be1b9fd5ad1799fcd947525eec9f81d3","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.13.tgz","fileCount":14,"integrity":"sha512-HMhG+n8upPiIXEaAuPLaB48XMTBrcC8ETB8APCuzSltB+c1djFMnz83qyEJXiC2GWWtEoHZtMBb4fZPP0FNNMA==","signatures":[{"sig":"MEUCIQCy2+nn1mulcdQV6Vu3ERu1VgCgEjZSyzyDCGVUo6AFRAIgEBmDTjIs9AmInXwmLZ+Mx/dcodSCmAlBmNZIV35m7fE=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":212853},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js","./vue":"./src/adapters/vue.js","./vuetify":"./src/adapters/vuetify.js","./vee-validate":"./src/adapters/vee-validate.js","./react-hook-form":"./src/adapters/react-hook-form.js"},"gitHead":"4aa861bdad532b215f6b96fdad1d13039acb68be","scripts":{"lint":"eslint .","test":"node --test tests.js","start":"node example.js","example":"node example.js","demo:vue":"npm --prefix demos/vue-vuetify run dev","docs:dev":"npm run docs:prepare && vitepress dev docs","lint:fix":"eslint . --fix","demo:react":"npm --prefix demos/react-rhf run dev","docs:build":"node scripts/build-pages-site.mjs","test:demos":"playwright test","pages:build":"npm run docs:build","demo:install":"npm install --prefix demos/react-rhf && npm install --prefix demos/vue-vuetify","docs:prepare":"node scripts/generate-docs-site.mjs","docs:preview":"npm run docs:build && vitepress preview docs","docs:build:vitepress":"npm run docs:prepare && vitepress build docs"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/json-rest-schema.git","type":"git"},"_npmVersion":"11.6.2","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^9.37.0","sqlite3":"^5.1.7","vitepress":"^1.6.4","neostandard":"^0.12.2","@playwright/test":"^1.54.2"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.13_1777466444343_0.4580553930654836","host":"s3://npm-registry-packages-npm-production"}},"1.0.14":{"name":"json-rest-schema","version":"1.0.14","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"GPL-3.0-only","_id":"json-rest-schema@1.0.14","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises.github.io/json-rest-schema/","bugs":{"url":"https://github.com/mobily-enterprises/json-rest-schema/issues"},"dist":{"shasum":"6bb9768f5e544ccd812a81d5fe6cf8bf9445a2e8","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.14.tgz","fileCount":14,"integrity":"sha512-Y081u2guoQwEyy1WXBwxxNBpIxCgQ+GfqmnCwy74+flLrmJU3exiefNVgth5wn3XPanQvuZ46TTMsITl5Yx1eQ==","signatures":[{"sig":"MEYCIQCy6NYdPrpomIDjlv2He1S03fCvKeZux4SKYHS0Olo/EQIhAPaZPv0Huh0RaUBGdWMWoUIBYduOHoinFQ6+EVv/WEAK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":212853},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js","./vue":"./src/adapters/vue.js","./vuetify":"./src/adapters/vuetify.js","./vee-validate":"./src/adapters/vee-validate.js","./react-hook-form":"./src/adapters/react-hook-form.js"},"gitHead":"eeb5f4245dc6a692fe256786dfe5564c07df2f38","scripts":{"lint":"eslint .","test":"node --test tests.js","start":"node example.js","example":"node example.js","demo:vue":"npm --prefix demos/vue-vuetify run dev","docs:dev":"npm run docs:prepare && vitepress dev docs","lint:fix":"eslint . --fix","demo:react":"npm --prefix demos/react-rhf run dev","docs:build":"node scripts/build-pages-site.mjs","test:demos":"playwright test","pages:build":"npm run docs:build","demo:install":"npm install --prefix demos/react-rhf && npm install --prefix demos/vue-vuetify","docs:prepare":"node scripts/generate-docs-site.mjs","docs:preview":"npm run docs:build && vitepress preview docs","docs:build:vitepress":"npm run docs:prepare && vitepress build docs"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://mobily-enterprises/json-rest-schema.git","type":"git"},"_npmVersion":"11.6.2","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"flatted":"^3.3.3"},"_hasShrinkwrap":false,"devDependencies":{"knex":"^3.1.0","eslint":"^9.37.0","sqlite3":"^5.1.7","vitepress":"^1.6.4","neostandard":"^0.12.2","@playwright/test":"^1.54.2"},"peerDependencies":{"knex":">=2.0.0"},"peerDependenciesMeta":{"knex":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.14_1777650051904_0.25850254814425466","host":"s3://npm-registry-packages-npm-production"}},"1.0.15":{"name":"json-rest-schema","version":"1.0.15","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"(GPL-3.0-only OR MIT)","_id":"json-rest-schema@1.0.15","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises.github.io/json-rest-schema/","bugs":{"url":"https://github.com/mobily-enterprises/json-rest-schema/issues"},"dist":{"shasum":"e3e5c161da27d1c0aa8ff67c50cf3f646035c470","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.15.tgz","fileCount":18,"integrity":"sha512-Tm2Mo0BV62NAEp0XJrwZvnpVyAqYDiCL5wF6SnqE4UsKSiufRgkxKpFhC67BJ73bqgyDTfT+vHn4Z5X+1yOekQ==","signatures":[{"sig":"MEQCIGtodvoRTYwNMNi/La0z8JSTkyMMo/ozaJ1P7WSIK8vQAiA0abZar23LBokM3TkmxtHcEizc3bgnWGY5H9kYvWmluw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":253075},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js","./vue":"./src/adapters/vue.js","./vuetify":"./src/adapters/vuetify.js","./vee-validate":"./src/adapters/vee-validate.js","./react-hook-form":"./src/adapters/react-hook-form.js"},"gitHead":"fa4615586e098b8e309dc402c56d6102fc62d124","scripts":{"lint":"eslint .","test":"node --test tests.js","start":"node example.js","example":"node example.js","demo:vue":"npm --prefix demos/vue-vuetify run dev","docs:dev":"npm run docs:prepare && vitepress dev docs","lint:fix":"eslint . --fix","demo:react":"npm --prefix demos/react-rhf run dev","docs:build":"node scripts/build-pages-site.mjs","test:demos":"playwright test","pages:build":"npm run docs:build","demo:install":"npm install --prefix demos/react-rhf && npm install --prefix demos/vue-vuetify","docs:prepare":"node scripts/generate-docs-site.mjs","docs:preview":"npm run docs:build && vitepress preview docs","docs:build:vitepress":"npm run docs:prepare && vitepress build docs"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://github.com/mobily-enterprises/json-rest-schema.git","type":"git"},"_npmVersion":"11.6.2","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"flatted":"^3.4.2"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.37.0","vitepress":"^1.6.4","neostandard":"^0.12.2","@playwright/test":"^1.54.2"},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.15_1778658372575_0.6181160523385691","host":"s3://npm-registry-packages-npm-production"}},"1.0.16":{"name":"json-rest-schema","version":"1.0.16","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"(GPL-3.0-only OR MIT)","_id":"json-rest-schema@1.0.16","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"homepage":"https://mobily-enterprises.github.io/json-rest-schema/","bugs":{"url":"https://github.com/mobily-enterprises/json-rest-schema/issues"},"dist":{"shasum":"6a092dede8f2fd575a613f372c286e78b09fb281","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.16.tgz","fileCount":18,"integrity":"sha512-/K99gIHXcs9n9YqZzwBiY+zAhqY+0lCGAp5G1MVjsWC54oDpoxeUyCa0X52W/TTmXn4RnTPS0caJaBjTQSt4hA==","signatures":[{"sig":"MEUCIQCTwEmmGkHaJiYI6NRFRoo6hAm4vxJ+SXeSpN0Xgnym/AIgL3l43WJI2ks5Rsg3AFqtgwsMHkJI7VIoWaXH/kH+5Rk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":253338},"main":"src/index.js","type":"module","engines":{"node":">=18.0.0"},"exports":{".":"./src/index.js","./vue":"./src/adapters/vue.js","./vuetify":"./src/adapters/vuetify.js","./vee-validate":"./src/adapters/vee-validate.js","./react-hook-form":"./src/adapters/react-hook-form.js"},"gitHead":"c6a7f63e0aad3935302f13fda5cd81c9bca4ddea","scripts":{"lint":"eslint .","test":"node --test tests.js","start":"node example.js","example":"node example.js","demo:vue":"npm --prefix demos/vue-vuetify run dev","docs:dev":"npm run docs:prepare && vitepress dev docs","lint:fix":"eslint . --fix","demo:react":"npm --prefix demos/react-rhf run dev","docs:build":"node scripts/build-pages-site.mjs","test:demos":"playwright test","pages:build":"npm run docs:build","demo:install":"npm install --prefix demos/react-rhf && npm install --prefix demos/vue-vuetify","docs:prepare":"node scripts/generate-docs-site.mjs","docs:preview":"npm run docs:build && vitepress preview docs","docs:build:vitepress":"npm run docs:prepare && vitepress build docs"},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"repository":{"url":"git+https://github.com/mobily-enterprises/json-rest-schema.git","type":"git"},"_npmVersion":"11.6.2","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","directories":{},"_nodeVersion":"20.19.0","dependencies":{"flatted":"^3.4.2"},"_hasShrinkwrap":false,"devDependencies":{"eslint":"^9.37.0","vitepress":"^1.6.4","neostandard":"^0.12.2","@playwright/test":"^1.54.2"},"_npmOperationalInternal":{"tmp":"tmp/json-rest-schema_1.0.16_1779162510210_0.5297993069951812","host":"s3://npm-registry-packages-npm-production"}},"1.0.17":{"name":"json-rest-schema","version":"1.0.17","description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"author":{"name":"Tony Mobily"},"license":"(GPL-3.0-only OR MIT)","homepage":"https://mobily-enterprises.github.io/json-rest-schema/","repository":{"type":"git","url":"git+https://github.com/mobily-enterprises/json-rest-schema.git"},"bugs":{"url":"https://github.com/mobily-enterprises/json-rest-schema/issues"},"type":"module","main":"src/index.js","exports":{".":"./src/index.js","./react-hook-form":"./src/adapters/react-hook-form.js","./vue":"./src/adapters/vue.js","./vuetify":"./src/adapters/vuetify.js","./vee-validate":"./src/adapters/vee-validate.js"},"scripts":{"test":"node --test tests.js","test:demos":"playwright test","example":"node example.js","start":"node example.js","docs:prepare":"node scripts/generate-docs-site.mjs","docs:dev":"npm run docs:prepare && vitepress dev docs","docs:build:vitepress":"npm run docs:prepare && vitepress build docs","docs:build":"node scripts/build-pages-site.mjs","docs:preview":"npm run docs:build && vitepress preview docs","pages:build":"npm run docs:build","demo:install":"npm install --prefix demos/react-rhf && npm install --prefix demos/vue-vuetify","demo:react":"npm --prefix demos/react-rhf run dev","demo:vue":"npm --prefix demos/vue-vuetify run dev","lint":"eslint .","lint:fix":"eslint . --fix"},"dependencies":{"flatted":"^3.4.2"},"devDependencies":{"@playwright/test":"^1.54.2","eslint":"^9.37.0","neostandard":"^0.12.2","vitepress":"^1.6.4"},"engines":{"node":">=18.0.0"},"gitHead":"c6a7f63e0aad3935302f13fda5cd81c9bca4ddea","_id":"json-rest-schema@1.0.17","_nodeVersion":"22.16.0","_npmVersion":"11.14.1","dist":{"integrity":"sha512-wcR0oq3Ztgu+pfYGHWLQDdANZ+duuIXjp1ucBQI7w2nX8Gfph5YjD4AsSuREOS630QP5WvlnBpqHhBfWoWRWuQ==","shasum":"09259c5db26056aaee593013ea3479d47e5ee9c3","tarball":"https://registry.npmjs.org/json-rest-schema/-/json-rest-schema-1.0.17.tgz","fileCount":19,"unpackedSize":261399,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDNeAyCKxDAzgCl5QAeFmv901HZ5ALKaar3/AFcyajitwIgaObwTx1oHAoJwkmb/RwMFaXZpnIKpMFIZ4WAjireiAY="}]},"_npmUser":{"name":"mercmobily","email":"tonymobily@gmail.com"},"directories":{},"maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/json-rest-schema_1.0.17_1786530460189_0.9079478420476264"},"_hasShrinkwrap":false}},"time":{"created":"2025-07-03T06:10:53.559Z","modified":"2026-08-12T10:27:40.474Z","1.0.2":"2025-07-03T06:10:53.728Z","1.0.3":"2025-07-03T06:22:15.010Z","1.0.4":"2025-07-04T11:45:13.679Z","1.0.5":"2025-07-06T14:00:05.538Z","1.0.6":"2025-07-11T03:11:24.205Z","1.0.7":"2025-07-14T14:26:02.624Z","1.0.8":"2025-07-24T01:40:17.928Z","1.0.9":"2025-09-25T14:45:01.240Z","1.0.10":"2025-10-14T02:19:38.930Z","1.0.11":"2025-10-14T04:21:00.032Z","1.0.12":"2025-10-14T05:42:25.063Z","1.0.13":"2026-04-29T12:40:44.545Z","1.0.14":"2026-05-01T15:40:52.063Z","1.0.15":"2026-05-13T07:46:12.743Z","1.0.16":"2026-05-19T03:48:30.363Z","1.0.17":"2026-08-12T10:27:40.329Z"},"bugs":{"url":"https://github.com/mobily-enterprises/json-rest-schema/issues"},"author":{"name":"Tony Mobily"},"license":"(GPL-3.0-only OR MIT)","homepage":"https://mobily-enterprises.github.io/json-rest-schema/","keywords":["schema","validation","json","rest-api","data-validation","type-casting","data-transformation","plugin","javascript"],"repository":{"type":"git","url":"git+https://github.com/mobily-enterprises/json-rest-schema.git"},"description":"A flexible and extensible schema validation library for JavaScript objects, designed for REST APIs and beyond. Features include type casting, data transformation, and a pluggable architecture for custom rules.","maintainers":[{"name":"mercmobily","email":"tonymobily@gmail.com"}],"readme":"# Tutorial\n\nWelcome! This tutorial will walk you through everything you need to know to use the schema validation library effectively. We'll start with the basics and progressively move to more advanced topics like creating your own custom rules.\n\nPublished documentation:\n\n<https://mobily-enterprises.github.io/json-rest-schema/>\n\n## Installation\n\nInstall the package in your app with:\n\n```bash\nnpm install json-rest-schema\n```\n\nIf you are working in this repo and want to run the documentation site locally:\n\n```bash\nnpm install\nnpm run docs:dev\n```\n\nBuild the full static site, including the standalone React and Vue demo apps, with:\n\n```bash\nnpm run docs:build\n```\n\nPreview that built site locally with:\n\n```bash\nnpm run docs:preview\n```\n\n### Upgrading to 1.0.17\n\nVersion 1.0.17 intentionally replaces the old permissive temporal behavior. There are no compatibility aliases or legacy parsers:\n\n* `date`, `time`, and `dateTime` now validate JSON strings and return the exact input string unchanged. They no longer return JavaScript `Date` objects or parse numbers, locale text, SQL datetime strings, or other `Date.parse()` inputs.\n* `date` accepts only a real calendar date written as `YYYY-MM-DD`.\n* `time` accepts an offset-free `HH:MM[:SS[.fraction]]` value.\n* `dateTime` accepts a calendar-valid RFC 3339 datetime with seconds and a mandatory `Z` or `±HH:MM` offset.\n* `timestamp` has been removed. Use `epochMilliseconds` or `epochSeconds`; both accept an integer number or canonical base-10 integer string and return a number.\n* `temporalPrecision` limits fractional-second digits for `time` and `dateTime`. Excess precision is rejected, never truncated.\n* Applied defaults now pass through the normal type and validator pipeline.\n\nUse this prompt with an agent working on an existing application:\n\n> Upgrade this application to `json-rest-schema` 1.0.17 without adding compatibility or legacy parsing. Find every temporal schema field and trace its producers, consumers, HTTP representation, database mapping, defaults, fixtures, and tests. Replace `type: 'timestamp'` with `epochMilliseconds` or `epochSeconds` only after verifying the actual unit. Keep `date` values as valid `YYYY-MM-DD` strings, `time` values as offset-free `HH:MM[:SS[.fraction]]` strings, and `dateTime` values as RFC 3339 strings with seconds and an explicit timezone. Convert JavaScript `Date` objects explicitly at application boundaries; do not make the schema accept them. For `datetime-local` controls, apply the product's intended timezone before producing RFC 3339—do not append `Z` unless the entered value is defined as UTC. Remove code that expects validation to return a `Date` or normalize a temporal string. Make storage adapters translate between these wire strings and database-native values. Update defaults to the new forms. Add tests for impossible dates, timezone-required datetimes, fractional precision, JSON round trips, repeated validation, captured HTTP payloads, and the relevant database round trip. Run the full test, lint, typecheck, and build suites and report every changed temporal contract.\n\nThe published docs site is the best place to read the same manual as shorter chapters for:\n\n* create / replace / patch semantics\n* nested object and array contracts\n* recursive runtime validation and transport export\n* field introspection and path-scoped validation\n* React Hook Form, Vue + Vuetify, and VeeValidate adapters\n* demo app walkthroughs\n\n## Getting Started: Your First Schema\n\nLet's start with a common use case: validating a user registration form.\n\nFirst, import the library's factory function and define the structure of the data you expect.\n\n```javascript\nimport { createSchema } from 'json-rest-schema';\n\n// Define the structure and rules for our user data\nconst userSchema = createSchema({\n  username: { type: 'string', required: true, minLength: 3 },\n  email: { type: 'string', required: true },\n  age: { type: 'number', min: 18, defaultTo: 18 }\n});\n```\n\nNow, let's try to validate an object against this schema.\n\n```javascript\n// An example input object from a form\nconst userInput = {\n  username: '  alex ', // Includes extra whitespace\n  email: 'alex@example.com',\n  age: '25' // Note: age is a string here\n};\n\nconst { validatedObject, errors } = userSchema.create(userInput);\n\n// Check if there were any errors by seeing if the errors object has keys\nif (Object.keys(errors).length > 0) {\n  console.log(\"Validation failed!\");\n  console.log(errors);\n} else {\n  console.log(\"Validation successful!\");\n  console.log(validatedObject);\n}\n```\n\n**What happens here?**\n\n1.  The `age` string `'25'` is **cast** to the number `25` by the `number` type handler.\n2.  The `username` string `'  alex '` is **transformed** by the `string` type handler to `'alex'` (it gets trimmed).\n3.  Since there are no validation errors, the `errors` object will be empty.\n4.  The `validatedObject` will contain the clean, cast, and transformed data.\n\n---\n\n## Validation Results and Error Helpers\n\nThe schema operation methods return an object with two properties: `validatedObject` and `errors`.\n\n### The `validatedObject`\n\nThis object contains the data after all casting and transformations have been applied. It's the \"clean\" version of your input that you should use in the rest of your application (e.g., to save to a database).\n\n### The `errors` Object\n\nThis is your primary tool for handling validation failures.\n\n* **It's a Map, Not an Array:** The `errors` object is a map where keys are the field names that failed. This allows you to instantly check if a specific field has an error: `if (errors.age) { ... }`.\n* **Rich Error Structure:** Each error in the map is a detailed object: `{ code, message, params }`.\n* **Nested paths stay flat:** Nested fields are reported with dotted paths such as `workspace.slug` or `roles.2.id`. That keeps the external error contract simple even when schemas are recursive.\n\nLet's look at an example with invalid data:\n\n```javascript\nconst invalidInput = {\n  username: 'Al', // Fails 'minLength: 3'\n  // email is missing, fails 'required: true'\n  age: 16 // Fails 'min: 18'\n};\n\nconst { validatedObject, errors } = userSchema.create(invalidInput);\n\nconsole.log(JSON.stringify(errors, null, 2));\n```\n\nThe output would look like this:\n\n```json\n{\n  \"username\": {\n    \"field\": \"username\",\n    \"code\": \"MIN_LENGTH\",\n    \"message\": \"Length must be at least 3 characters.\",\n    \"params\": { \"min\": 3, \"actual\": 2 }\n  },\n  \"email\": {\n    \"field\": \"email\",\n    \"code\": \"REQUIRED\",\n    \"message\": \"Field is required\",\n    \"params\": {}\n  },\n  \"age\": {\n    \"field\": \"age\",\n    \"code\": \"MIN_VALUE\",\n    \"message\": \"Value must be at least 18.\",\n    \"params\": { \"min\": 18, \"actual\": 16 }\n  }\n}\n```\n\n* **`code`**: A stable, machine-readable string. Use this in your code for logic (`if (err.code === 'MIN_LENGTH')`).\n* **`message`**: A human-readable message, great for developers or for displaying directly to users in simple cases.\n* **`params`**: Extra context about the failure. This is incredibly useful for creating dynamic error messages (e.g., \"You entered 2 characters, but a minimum of 3 is required.\").\n\n### Error helper utilities\n\nIf you want a few adapter-friendly utilities around that flat error map, import them directly:\n\n```javascript\nimport { createSchema, getError, hasError, nestErrors, flattenErrors } from 'json-rest-schema'\n```\n\n`getError(errors, path)` reads one dotted-path error:\n\n```javascript\nconst slugError = getError(errors, 'workspace.slug')\n```\n\n`hasError(errors, path)` is the small boolean version:\n\n```javascript\nconst showSlugError = hasError(errors, 'workspace.slug')\n```\n\n`nestErrors(errors)` converts the flat map into a nested object/array shape for form libraries that prefer nested field errors:\n\n```javascript\nnestErrors({\n  'workspace.slug': {\n    field: 'workspace.slug',\n    code: 'MIN_LENGTH',\n    message: 'Length must be at least 3 characters.',\n    params: { min: 3, actual: 1 }\n  },\n  'roles.2.label': {\n    field: 'roles.2.label',\n    code: 'REQUIRED',\n    message: 'Field is required',\n    params: {}\n  }\n})\n```\n\nResult:\n\n```javascript\n{\n  workspace: {\n    slug: {\n      field: 'workspace.slug',\n      code: 'MIN_LENGTH',\n      message: 'Length must be at least 3 characters.',\n      params: { min: 3, actual: 1 }\n    }\n  },\n  roles: [\n    ,\n    ,\n    {\n      label: {\n        field: 'roles.2.label',\n        code: 'REQUIRED',\n        message: 'Field is required',\n        params: {}\n      }\n    }\n  ]\n}\n```\n\nThat keeps the runtime contract flat, while still making it easy to adapt into nested UI-state libraries.\n\n`flattenErrors(nestedErrors)` does the reverse when a UI layer gives you nested field errors and you want to normalize them back into the library's flat contract:\n\n```javascript\nflattenErrors({\n  workspace: {\n    slug: {\n      field: 'workspace.slug',\n      code: 'MIN_LENGTH',\n      message: 'Length must be at least 3 characters.',\n      params: { min: 3, actual: 1 }\n    }\n  },\n  roles: [\n    ,\n    ,\n    {\n      label: {\n        field: 'roles.2.label',\n        code: 'REQUIRED',\n        message: 'Field is required',\n        params: {}\n      }\n    }\n  ]\n})\n```\n\nResult:\n\n```javascript\n{\n  'workspace.slug': {\n    field: 'workspace.slug',\n    code: 'MIN_LENGTH',\n    message: 'Length must be at least 3 characters.',\n    params: { min: 3, actual: 1 }\n  },\n  'roles.2.label': {\n    field: 'roles.2.label',\n    code: 'REQUIRED',\n    message: 'Field is required',\n    params: {}\n  }\n}\n```\n\n## Operation Contracts\n\nFor explicit write semantics, the schema instance exposes three synchronous built-in operation methods:\n\n```javascript\nuserSchema.create(input);\nuserSchema.replace(input);\nuserSchema.patch(input);\n```\n\nThey all return the same `{ validatedObject, errors }` shape, but they differ in how omitted fields are treated:\n\n* **`create()`**: validates a create payload, enforces `required`, applies `defaultTo`, and leaves omitted optional fields omitted.\n* **`replace()`**: validates a full replacement payload, enforces `required`, applies `defaultTo`, and preserves omitted fields.\n* **`patch()`**: validates only explicitly provided fields and returns only the normalized fields that were touched.\n\nThese are built-in named operation contracts, not special cases in the engine. If you need a different contract, define a custom operation and the schema will generate a matching method alias automatically.\n\n### Worked operation example\n\nThis is easier to understand with one schema and three calls:\n\n```javascript\nconst profileSchema = createSchema({\n  username: { type: 'string', required: true },\n  bio: { type: 'string' },\n  role: { type: 'string', defaultTo: 'member' }\n})\n```\n\nCalling `create()`:\n\n```javascript\nprofileSchema.create({\n  username: '  alex  '\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    username: 'alex',\n    role: 'member'\n  },\n  errors: {}\n}\n```\n\nCalling `replace()` with the same payload:\n\n```javascript\nprofileSchema.replace({\n  username: '  alex  '\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    username: 'alex',\n    role: 'member'\n  },\n  errors: {}\n}\n```\n\nCalling `patch()` with the same payload:\n\n```javascript\nprofileSchema.patch({\n  username: '  alex  '\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    username: 'alex'\n  },\n  errors: {}\n}\n```\n\nThat difference is the whole point of operation contracts:\n\n* `create()` and `replace()` walk the schema as a contract for the whole object.\n* `patch()` walks only the fields the caller actually touched.\n* Defaults apply on operations that opt into defaults.\n* Missing required fields are only errors on operations that opt into required checks.\n\n## Custom Operations\n\nCustom operations are declared when you create the schema.\n\n```javascript\nconst userSchema = createSchema({\n  id: { type: 'id', required: true },\n  email: { type: 'string', required: true },\n  role: { type: 'string', defaultTo: 'guest' }\n}, {\n  operations: {\n    upsert: {\n      targetFields: 'schema',\n      enforceRequired: false,\n      applyDefaults: true,\n      outputFields: 'validated'\n    }\n  }\n})\n\nconst result = userSchema.upsert({ email: 'alex@example.com' })\nconst sameResult = userSchema.validateWith('upsert', { email: 'alex@example.com' })\n```\n\nOperation aliases are generated automatically from the operation registry, so `create`, `replace`, and `patch` keep working exactly as before. If you intentionally redefine one of those names in `operations`, the built-in behavior is replaced for that schema instance.\n\nSupported operation descriptor keys:\n\n| Key | Allowed Values | Meaning |\n|---|---|---|\n| `targetFields` | `'schema'` or `'input'` | Which fields are validated. `'schema'` walks the schema definition, `'input'` only validates explicitly provided fields. |\n| `enforceRequired` | `true` or `false` | Whether missing `required` fields produce errors. |\n| `applyDefaults` | `true` or `false` | Whether omitted fields with `defaultTo` are materialized into the result. |\n| `outputFields` | `'validated'` or `'input'` | Which field set is considered when building `validatedObject`. `'validated'` follows schema fields, `'input'` follows only explicitly provided fields. |\n| `rejectExplicitUndefined` | `true` or `false` | Whether an explicitly provided `undefined` value is treated as a type error. Defaults to `true`. |\n\nMethod names are generated automatically from operation names. Names that already exist on `Schema` are reserved and rejected. In practice that means names such as `validateWith`, `toJsonSchema`, `getFieldDefinitions`, `getFieldDefinition`, `getFieldMessages`, and `cleanup` cannot be used as operation aliases.\n\n## Field Introspection\n\nSchema instances also expose three read-only introspection helpers:\n\n* `schema.getFieldDefinitions()` returns a frozen snapshot map of the top-level field definitions.\n* `schema.getFieldDefinition(path)` resolves one field definition by dotted path, including nested object fields and numeric array segments such as `roles.0.id`, and returns it as a frozen snapshot.\n* `schema.getFieldMessages(path)` returns the field's `messages` object as a frozen snapshot, or `{}` when none exist.\n\nThese helpers are intentionally inspection-only. They clone the schema metadata they expose so adapter code can read field settings without gaining a back door to mutate runtime validation behavior.\n\nExample:\n\n```javascript\nconst roleSchema = createSchema({\n  id: { type: 'string', required: true }\n})\n\nconst teamSchema = createSchema({\n  name: { type: 'string', required: true },\n  roles: {\n    type: 'array',\n    items: roleSchema\n  }\n})\n\nconst topLevelDefinitions = teamSchema.getFieldDefinitions()\nconst roleIdDefinition = teamSchema.getFieldDefinition('roles.0.id')\nconst roleIdMessages = teamSchema.getFieldMessages('roles.0.id')\n```\n\nIn that example:\n\n* `topLevelDefinitions` contains snapshots for `name` and `roles`\n* `roleIdDefinition` resolves through the array item schema to the nested `id` field\n* `roleIdMessages` returns `{}` because that field did not define a `messages` object\n\nTreat the returned objects as metadata for rendering and adapter logic, not as something to mutate.\n\n## Nested Object, Array, and Object-Bag Contracts\n\nThis library now supports the three nested contract shapes that come up constantly in shared REST payloads, without turning into a generic schema engine:\n\n1. **Nested object fields** with `type: 'object'` and `schema`\n2. **Nested array items** with `type: 'array'` and `items`\n3. **Opaque object bags** with `type: 'object'` and `additionalProperties: true`\n\nThe important design rule is that these are still **application contracts**, not arbitrary JSON Schema fragments.\n\n### Nested object fields\n\nUse a child `Schema` instance when a field should itself be validated as an object.\n\n```javascript\nconst workspaceSummarySchema = createSchema({\n  id: { type: 'id', required: true },\n  slug: { type: 'string', required: true },\n  ownerUserId: { type: 'id', required: true }\n})\n\nconst workspaceSettingsSchema = createSchema({\n  invitesEnabled: { type: 'boolean', required: true }\n})\n\nconst workspaceViewSchema = createSchema({\n  workspace: {\n    type: 'object',\n    required: true,\n    schema: workspaceSummarySchema\n  },\n  settings: {\n    type: 'object',\n    required: true,\n    schema: workspaceSettingsSchema\n  }\n})\n```\n\nHow nested object fields behave:\n\n* The nested schema inherits the parent operation contract.\n* `create()` on the parent runs `create`-style rules inside the child.\n* `patch()` on the parent runs `patch`-style rules inside the child.\n* Errors are reported with dotted paths such as `workspace.slug`.\n* Unknown nested keys are rejected because child schemas are strict by default, just like top-level schemas.\n\nThat operation inheritance is deliberate. A nested object inside a patch payload is usually itself a patch payload.\n\n### Worked nested object example\n\nUsing the schema above:\n\n```javascript\nconst result = workspaceViewSchema.create({\n  workspace: {\n    id: '42',\n    slug: '  main-workspace  ',\n    extra: true\n  },\n  settings: {}\n})\n```\n\n`validatedObject` becomes:\n\n```javascript\n{\n  workspace: {\n    id: 42,\n    slug: 'main-workspace'\n  },\n  settings: {}\n}\n```\n\n`errors` becomes:\n\n```javascript\n{\n  'workspace.ownerUserId': {\n    field: 'workspace.ownerUserId',\n    code: 'REQUIRED',\n    message: 'Field is required',\n    params: {}\n  },\n  'workspace.extra': {\n    field: 'workspace.extra',\n    code: 'FIELD_NOT_ALLOWED',\n    message: 'Field not allowed',\n    params: {}\n  },\n  'settings.invitesEnabled': {\n    field: 'settings.invitesEnabled',\n    code: 'REQUIRED',\n    message: 'Field is required',\n    params: {}\n  }\n}\n```\n\nNow compare that with a nested patch:\n\n```javascript\nworkspaceViewSchema.patch({\n  workspace: {\n    slug: '  sandbox  '\n  }\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    workspace: {\n      slug: 'sandbox'\n    }\n  },\n  errors: {}\n}\n```\n\nNotice what did **not** happen:\n\n* `workspace.id` was not required\n* `workspace.ownerUserId` was not required\n* no defaults were invented\n\nThat is exactly because the child object inherited the parent `patch` contract.\n\n### Nested array items\n\nUse `items` when every array entry should be validated recursively.\n\n```javascript\nconst roleSchema = createSchema({\n  id: { type: 'string', required: true },\n  label: { type: 'string', required: true }\n})\n\nconst roleCatalogSchema = createSchema({\n  roles: {\n    type: 'array',\n    required: true,\n    items: roleSchema\n  },\n  assignableRoleIds: {\n    type: 'array',\n    required: true,\n    items: { type: 'string', minLength: 1 }\n  }\n})\n```\n\nHow array items behave:\n\n* Primitive item definitions are validated item-by-item and normalized in place.\n* If `items` is a nested object schema, each item is validated in `replace` mode.\n* Array item errors use indexed dotted paths such as `roles.0.label`.\n\nThat `replace` rule for object items is intentional. If a client sends the `roles` array in a patch, they are replacing the array field, so each object item still needs to be complete.\n\n### Worked nested array example\n\n```javascript\nconst result = roleCatalogSchema.patch({\n  roles: [\n    { id: 'admin' },\n    { id: 'editor', label: '  Editor  ' }\n  ],\n  assignableRoleIds: [' owner ', '   ', 123]\n})\n```\n\n`validatedObject` becomes:\n\n```javascript\n{\n  roles: [\n    { id: 'admin' },\n    { id: 'editor', label: 'Editor' }\n  ],\n  assignableRoleIds: ['owner', '', '123']\n}\n```\n\n`errors` becomes:\n\n```javascript\n{\n  'roles.0.label': {\n    field: 'roles.0.label',\n    code: 'REQUIRED',\n    message: 'Field is required',\n    params: {}\n  },\n  'assignableRoleIds.1': {\n    field: 'assignableRoleIds.1',\n    code: 'MIN_LENGTH',\n    message: 'Length must be at least 1 characters.',\n    params: { min: 1, actual: 0 }\n  }\n}\n```\n\nThis example shows both supported array styles:\n\n* `roles` uses a child `Schema` instance for structured object items\n* `assignableRoleIds` uses an inline field definition for primitive items\n\n### Opaque object bags\n\nIf a field needs to be “some object, but not one this library owns”, make that explicit:\n\n```javascript\nconst schema = createSchema({\n  metadata: {\n    type: 'object',\n    additionalProperties: true\n  }\n})\n```\n\nThat means:\n\n* the value must be a plain object\n* keys are not validated\n* values pass through untouched\n\nThis is the intended escape hatch for metadata bags and adapter-owned payloads. It is deliberately narrow: `additionalProperties` only supports the literal value `true`. You can combine it with `schema` when you want to validate known child fields while still allowing arbitrary passthrough keys.\n\n## Typed Object Maps\n\nIf you need \"an object whose keys are dynamic, but whose values all follow one contract\", use `values`:\n\n```javascript\nconst schema = createSchema({\n  fieldErrors: {\n    type: 'object',\n    values: {\n      type: 'string',\n      minLength: 1\n    }\n  }\n})\n```\n\nThat means:\n\n* the value must be a plain object\n* keys remain dynamic\n* every value is validated with the provided field definition\n\n`values` can point to either:\n\n* an inline field definition such as `{ type: 'string', minLength: 1 }`\n* a child `Schema` instance when every dynamic value should itself be a structured object contract\n\nWhen `values` points to a child object schema, each dynamic value is validated in `replace` mode for the same reason array object items are: each value is treated as a complete object at that key.\n\n## Known Fields Plus Passthrough Extras\n\nIf you need an object with a few validated child fields but you still want to allow extra keys through unchanged, combine `schema` with `additionalProperties: true`:\n\n```javascript\nconst detailsSchema = createSchema({\n  message: { type: 'string', required: true },\n  fieldErrors: {\n    type: 'object',\n    values: { type: 'string', minLength: 1 },\n    required: false\n  }\n})\n\nconst schema = createSchema({\n  details: {\n    type: 'object',\n    schema: detailsSchema,\n    additionalProperties: true\n  }\n})\n```\n\nThat means:\n\n* known child fields are validated and normalized by `detailsSchema`\n* unknown child fields are preserved unchanged\n* transport export becomes `properties` plus `additionalProperties: true`\n\nWorked example:\n\n```javascript\nconst metadataSchema = createSchema({\n  metadata: {\n    type: 'object',\n    additionalProperties: true\n  }\n})\n```\n\nValid input:\n\n```javascript\nmetadataSchema.patch({\n  metadata: {\n    theme: 'dark',\n    flags: {\n      beta: true\n    }\n  }\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    metadata: {\n      theme: 'dark',\n      flags: {\n        beta: true\n      }\n    }\n  },\n  errors: {}\n}\n```\n\nInvalid input:\n\n```javascript\nmetadataSchema.patch({\n  metadata: ['not-an-object']\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    metadata: ['not-an-object']\n  },\n  errors: {\n    metadata: {\n      field: 'metadata',\n      code: 'TYPE_CAST_FAILED',\n      message: 'Value could not be cast to the required type.',\n      params: {}\n    }\n  }\n}\n```\n\nThat is the intended contract: object-ness is enforced, but the inner bag is not owned by this library.\n\n### Dotted path options for nested fields\n\nBecause nested errors use dotted paths, the opt-out options do too.\n\nSkip a whole nested field:\n\n```javascript\nworkspaceViewSchema.patch({\n  workspace: {\n    slug: 'x'\n  }\n}, {\n  skipFields: ['workspace.slug']\n})\n```\n\nSkip a specific nested validator:\n\n```javascript\nworkspaceViewSchema.patch({\n  workspace: {\n    slug: 'x'\n  }\n}, {\n  skipParams: {\n    'workspace.slug': ['minLength']\n  }\n})\n```\n\nThis keeps the options model flat and consistent with the error map.\n\n## Recursive Schemas\n\nRecursive schema graphs are supported at runtime.\n\nThe important distinction is that the library follows the graph of `Schema` instances, not just one level of nesting. That means a field or array item can point back to the same schema instance, and the runtime will keep validating deeper paths using the same operation rules it would use for any non-recursive nested contract.\n\nThe practical setup rule is simple: self-references are usually wired after the first `createSchema(...)` call, because the variable must exist before another field can point at it.\n\n### Self-recursive object and array example\n\n```javascript\nconst nodeSchema = createSchema({\n  id: { type: 'string', required: true },\n  label: { type: 'string', required: true },\n  parent: { type: 'object', required: false },\n  children: { type: 'array', required: false }\n})\n\nnodeSchema.structure.parent.schema = nodeSchema\nnodeSchema.structure.children.items = nodeSchema\n```\n\nThat creates two different recursive edges:\n\n* `parent` is a nested object field that points back to `nodeSchema`\n* `children.items` is an array of `nodeSchema` objects\n\n### Recursive runtime semantics\n\nThe same rules still apply inside the recursive graph:\n\n* nested object fields such as `parent` inherit the active operation contract\n* array items that are object schemas still use `replace` semantics\n* recursive errors stay in the same flat dotted-path shape as any other nested error\n\nExample:\n\n```javascript\nconst patchParent = nodeSchema.patch({\n  parent: {\n    label: '  Root  '\n  }\n})\n\nconst patchChildren = nodeSchema.patch({\n  children: [\n    { label: 'Only child label' }\n  ]\n})\n```\n\n`patchParent` succeeds with:\n\n```javascript\n{\n  validatedObject: {\n    parent: {\n      label: 'Root'\n    }\n  },\n  errors: {}\n}\n```\n\nThat happens because `parent` is a nested object field and inherits the outer `patch` operation.\n\n`patchChildren` returns:\n\n```javascript\n{\n  validatedObject: {\n    children: [\n      {\n        label: 'Only child label'\n      }\n    ]\n  },\n  errors: {\n    'children.0.id': {\n      field: 'children.0.id',\n      code: 'REQUIRED',\n      message: 'Field is required',\n      params: {}\n    }\n  }\n}\n```\n\nThat happens because array items that point to object schemas are always treated as full replacements.\n\n### Recursive paths, introspection, and transport export\n\nRecursive schemas keep the same dotted-path model everywhere else too:\n\n* `nodeSchema.getFieldDefinition('children.0.label')` resolves correctly\n* `nodeSchema.validateAt('children.0.label', payload)` validates only that selected path\n* recursive transport export is graph-aware rather than stack-recursive\n\n`toJsonSchema()` uses draft-07 `definitions` plus `$ref` for recursive nested contracts, and direct self-recursive object fields point back to `#`. The transport-specific details are covered again in the `Transport JSON Schema Export` chapter below.\n\n## Path-Scoped Validation for Forms and Interactive UIs\n\nFull-object validation is still the right tool for submit boundaries:\n\n```javascript\nconst result = userSchema.create(payload)\n```\n\nBut forms often need something narrower:\n\n* validate one field on blur\n* validate a small step in a wizard\n* normalize only the field the user just touched\n* avoid triggering unrelated sibling errors while the user is still editing\n\nThat is what `validateAt()` and `validatePaths()` are for.\n\n### `validateAt(path, object, options)`\n\nUse `validateAt()` when you want one path.\n\n```javascript\nconst profileSchema = createSchema({\n  name: { type: 'string', required: true, minLength: 3 },\n  role: { type: 'string', defaultTo: 'guest' }\n})\n\nprofileSchema.validateAt('name', {\n  name: '  Alex  '\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedValue: 'Alex',\n  errors: {}\n}\n```\n\nBy default, path validation uses **`patch` semantics**. That means:\n\n* only the selected path is validated\n* missing required siblings do not produce errors\n* defaults do not apply unless you explicitly choose an operation that applies them\n\nIf you want create-style or replace-style behavior for the exact selected path, pass `operation`.\n\n```javascript\nprofileSchema.validateAt('role', {}, { operation: 'create' })\n```\n\nResult:\n\n```javascript\n{\n  validatedValue: 'guest',\n  errors: {}\n}\n```\n\nIf you want required checks for the exact selected field:\n\n```javascript\nprofileSchema.validateAt('name', {}, { operation: 'create' })\n```\n\nResult:\n\n```javascript\n{\n  validatedValue: undefined,\n  errors: {\n    name: {\n      field: 'name',\n      code: 'REQUIRED',\n      message: 'Field is required',\n      params: {}\n    }\n  }\n}\n```\n\n### Nested path example\n\nThis is where path-scoped validation becomes most useful.\n\n```javascript\nconst workspaceSummarySchema = createSchema({\n  id: { type: 'id', required: true },\n  slug: { type: 'string', required: true, minLength: 3 },\n  ownerUserId: { type: 'id', required: true }\n})\n\nconst workspaceSchema = createSchema({\n  workspace: {\n    type: 'object',\n    required: true,\n    schema: workspaceSummarySchema\n  }\n})\n```\n\nValidate only `workspace.slug`:\n\n```javascript\nworkspaceSchema.validateAt('workspace.slug', {\n  workspace: {\n    slug: '  primary  '\n  }\n}, {\n  operation: 'create'\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedValue: 'primary',\n  errors: {}\n}\n```\n\nNotice what did **not** happen:\n\n* `workspace.id` was not required\n* `workspace.ownerUserId` was not required\n* unrelated nested keys were not validated\n\nThat is the point of the API. It validates the **selected path**, not the whole object.\n\nIf you select the whole object path instead:\n\n```javascript\nworkspaceSchema.validateAt('workspace', {\n  workspace: {\n    slug: '  primary  '\n  }\n}, {\n  operation: 'create'\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedValue: {\n    slug: 'primary'\n  },\n  errors: {\n    'workspace.id': {\n      field: 'workspace.id',\n      code: 'REQUIRED',\n      message: 'Field is required',\n      params: {}\n    },\n    'workspace.ownerUserId': {\n      field: 'workspace.ownerUserId',\n      code: 'REQUIRED',\n      message: 'Field is required',\n      params: {}\n    }\n  }\n}\n```\n\nThat distinction is intentional:\n\n* selecting `workspace.slug` validates one field\n* selecting `workspace` validates the whole nested object contract\n\n### `validatePaths(paths, object, options)`\n\nUse `validatePaths()` when you want a subset of fields or a whole form step.\n\n```javascript\nconst stepSchema = createSchema({\n  workspace: {\n    type: 'object',\n    schema: workspaceSummarySchema\n  },\n  status: { type: 'string', defaultTo: 'draft' }\n})\n\nstepSchema.validatePaths([\n  'workspace.slug',\n  'status'\n], {\n  workspace: {\n    slug: '  next  '\n  }\n}, {\n  operation: 'create'\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    workspace: {\n      slug: 'next'\n    },\n    status: 'draft'\n  },\n  errors: {}\n}\n```\n\nThis is useful for:\n\n* wizard-step validation\n* validating only dirty fields\n* validating a form section before moving on\n\n### Path options and compatibility\n\nPath-scoped validation supports the same flat nested option model:\n\n```javascript\nworkspaceSchema.validatePaths([\n  'workspace.slug'\n], {\n  workspace: {\n    slug: 'x'\n  }\n}, {\n  operation: 'patch',\n  skipParams: {\n    'workspace.slug': ['minLength']\n  }\n})\n```\n\n`mode` also works as compatibility sugar for the built-in operations:\n\n```javascript\nworkspaceSchema.validateAt('workspace.slug', values, { mode: 'patch' })\n```\n\n### Form integration guidance\n\nThese APIs are meant to help form adapters, but the library still does **not** become a form framework.\n\nRecommended approach:\n\n* keep raw input state in the UI while the user is typing\n* use `validateAt()` or `validatePaths()` to compute errors and normalized values\n* apply full normalization on submit with `create()`, `replace()`, or `patch()`\n\nThat matters because aggressive normalization during typing can be annoying:\n\n* trimming on every keypress can move the cursor\n* number coercion can fight half-finished input such as `12.`\n* nested defaults can appear before the user has actually submitted anything\n\nSo the intended split is:\n\n* **interactive validation**: `validateAt()` / `validatePaths()`\n* **submit boundary validation**: `create()` / `replace()` / `patch()`\n\n## React Hook Form Resolver\n\nIf you use React Hook Form, this package now ships a dedicated resolver adapter as a separate subpath export:\n\n```javascript\nimport { useForm } from 'react-hook-form'\nimport { createSchema } from 'json-rest-schema'\nimport { jsonRestSchemaResolver } from 'json-rest-schema/react-hook-form'\n```\n\nThat import path is intentional. The resolver lives outside the main schema engine so the core library does not become React-specific.\n\n### Basic usage\n\n```javascript\nconst profileSchema = createSchema({\n  name: { type: 'string', required: true, minLength: 3 },\n  role: { type: 'string', defaultTo: 'guest' }\n})\n\nconst form = useForm({\n  resolver: jsonRestSchemaResolver(profileSchema)\n})\n```\n\nBy default, the resolver uses **`create` semantics** for full-form validation.\n\nThat means:\n\n* required fields are enforced\n* defaults are applied on successful full-form validation\n* the resolver itself returns normalized success values for full-form validation\n\nSo if the user submits:\n\n```javascript\n{\n  name: '  Alex  '\n}\n```\n\nthe resolver will hand React Hook Form a successful value object equivalent to:\n\n```javascript\n{\n  name: 'Alex',\n  role: 'guest'\n}\n```\n\nOne real-world nuance matters here: React Hook Form still owns its internal field\nstate. In practice, that means a successful resolver pass does **not** always mean\nyour submit handler receives a canonical normalized payload directly from RHF's state.\n\nIf you need a final REST-ready payload, run one last schema operation in the submit\nhandler:\n\n```javascript\nconst form = useForm({\n  resolver: jsonRestSchemaResolver(profileSchema)\n})\n\nconst onSubmit = rawValues => {\n  const { validatedObject, errors } = profileSchema.create(rawValues)\n  if (Object.keys(errors).length > 0) return\n\n  saveProfile(validatedObject)\n}\n```\n\nThat split is intentional:\n\n* RHF keeps raw interactive field state\n* the schema owns final normalization at the submit boundary\n* the UI is free to avoid aggressive value rewriting while the user is typing\n\n### Edit forms and custom operations\n\nIf the form is editing an existing resource, use a different operation explicitly.\n\nFor a patch-style form:\n\n```javascript\nconst form = useForm({\n  resolver: jsonRestSchemaResolver(profileSchema, {\n    operation: 'patch'\n  })\n})\n```\n\nYou can also use any custom operation you have registered on the schema:\n\n```javascript\nconst form = useForm({\n  resolver: jsonRestSchemaResolver(profileSchema, {\n    operation: 'upsert'\n  })\n})\n```\n\n### Field-level re-validation behavior\n\nReact Hook Form re-validates one field at a time during user interaction. The resolver uses the core path APIs for that subset validation.\n\nImportant behavior:\n\n* only the selected RHF field names are validated during field-level re-validation\n* sibling required fields do **not** leak into a single-field re-validation pass\n* by default, field-level re-validation keeps **raw form values** instead of forcing normalized values back into the UI while the user is typing\n\nThat default matters because aggressive normalization during typing can feel bad:\n\n* trimmed strings can move the cursor\n* number coercion can fight half-complete input\n* defaults can appear before submit\n\n### Opting into normalized field-level values\n\nIf you explicitly want normalized field values during field-level re-validation, opt in:\n\n```javascript\nconst form = useForm({\n  resolver: jsonRestSchemaResolver(\n    profileSchema,\n    {},\n    { normalizeOnFieldValidation: true }\n  )\n})\n```\n\nThis is opt-in on purpose.\n\n### Returning raw values on success\n\nIf you want successful resolver results to return raw input values instead of normalized values, use `raw: true`:\n\n```javascript\nconst form = useForm({\n  resolver: jsonRestSchemaResolver(\n    profileSchema,\n    {},\n    { raw: true }\n  )\n})\n```\n\nThat applies to successful full-form validation too, so defaults and casts are not pushed into the returned `values` object.\n\n### Error shape\n\nReact Hook Form requires hierarchical nested errors for deep paths. The resolver converts the library's flat dotted-path errors into the structure RHF expects.\n\nFor example, a schema error like:\n\n```javascript\n{\n  'roles.0.label': {\n    field: 'roles.0.label',\n    code: 'REQUIRED',\n    message: 'Field is required',\n    params: {}\n  }\n}\n```\n\nbecomes a React Hook Form error shape equivalent to:\n\n```javascript\n{\n  roles: [\n    {\n      label: {\n        type: 'REQUIRED',\n        message: 'Field is required'\n      }\n    }\n  ]\n}\n```\n\nDirect array-field errors are placed under RHF's `root` key for that field array path.\n\n### Native browser validation\n\nThe resolver also respects React Hook Form's `shouldUseNativeValidation` option. If RHF asks for native validation, the adapter sets `setCustomValidity()` / `reportValidity()` using the schema error messages.\n\n## Vue Form Adapter\n\nIf you use Vue, this package now ships a small adapter layer as a separate subpath export:\n\n```javascript\nimport { useSchemaForm, useSchemaField } from 'json-rest-schema/vue'\n```\n\nThat split is intentional.\n\n* `json-rest-schema/vue` handles schema-aware form orchestration\n* the core schema engine stays framework-agnostic\n\nJust as important: the adapter does **not** import Vue internally.\n\nThey work with:\n\n* plain objects\n* Vue reactive proxies\n* Vue refs such as `ref({ ... })`\n\nThat keeps the published package small and avoids turning Vue into a hard dependency of the core runtime.\n\n### Basic Vue usage\n\nUse `useSchemaForm()` when you already own the form values in Vue state.\n\n```javascript\nimport { reactive } from 'vue'\nimport { createSchema } from 'json-rest-schema'\nimport { useSchemaForm } from 'json-rest-schema/vue'\n\nconst profileSchema = createSchema({\n  name: { type: 'string', required: true, minLength: 3 },\n  role: { type: 'string', defaultTo: 'guest' }\n})\n\nconst values = reactive({\n  name: ''\n})\n\nconst form = useSchemaForm(profileSchema, {\n  values\n})\n```\n\nIf you want Vue to react to adapter-managed error or result updates, pass Vue-owned\ncontainers such as `ref({})`, `reactive({})`, or `ref(null)`:\n\n```javascript\nimport { reactive, ref } from 'vue'\n\nconst values = reactive({\n  name: ''\n})\n\nconst errors = ref({})\nconst lastResult = ref(null)\n\nconst form = useSchemaForm(profileSchema, {\n  values,\n  errors,\n  lastResult\n})\n```\n\nThat keeps reactivity in the Vue app instead of hiding framework state inside the schema library.\n\nImportant behavior:\n\n* full-form validation defaults to **`create`** semantics\n* `form.validate()` returns the usual `{ validatedObject, errors }`\n* `form.errors` stays in the library's flat dotted-path format\n* `form.nestedErrors` gives you the nested object/array form if your Vue layer prefers it\n\nRunning a full validation:\n\n```javascript\nconst result = form.validate()\n```\n\nIf `values` is:\n\n```javascript\n{\n  name: '  Alex  '\n}\n```\n\nthen `result` will be:\n\n```javascript\n{\n  validatedObject: {\n    name: 'Alex',\n    role: 'guest'\n  },\n  errors: {}\n}\n```\n\nThat is the same contract as the core schema engine. The Vue adapter does not invent a second validation format.\n\n### Field-level validation in Vue\n\nFor blur validation, wizard steps, or one-field re-validation, use the path-aware helpers.\n\n```javascript\nconst fieldResult = form.validateField('name')\nconst stepResult = form.validateFields(['name', 'role'])\n```\n\nThis matters because the adapter validates **only the selected paths**.\n\nThat means:\n\n* validating `name` does not suddenly produce `email` or `password` errors\n* nested paths such as `workspace.slug` work the same way as they do in the core APIs\n* bracket paths such as `roles[0].label` are accepted too\n\nIf you want a path-focused helper object, use `useSchemaField()`:\n\n```javascript\nconst nameField = useSchemaField(form, 'name')\n```\n\nIt gives you:\n\n* `nameField.value`\n* `nameField.error`\n* `nameField.hasError`\n* `nameField.message`\n* `nameField.messages`\n* `nameField.validate()`\n* `nameField.clearError()`\n\nExample:\n\n```javascript\nnameField.validate()\nconsole.log(nameField.messages)\n```\n\n### Submit normalization in Vue\n\nThe clean submit path is:\n\n```javascript\nconst submitProfile = form.submit((validatedObject) => {\n  return api.saveProfile(validatedObject)\n})\n```\n\n`submit()` always validates first.\n\nIf validation fails:\n\n* the handler is **not** called\n* the returned value is the validation result\n* `form.errors` is updated\n\nIf validation succeeds:\n\n* the handler receives the normalized `validatedObject`\n* defaults and casts are already applied\n\nThis keeps the same intended split as the rest of the library:\n\n* raw values while the user is typing\n* normalized values at the submit boundary\n\n### Edit forms and custom operations in Vue\n\nIf the form is editing an existing resource, choose a different operation explicitly:\n\n```javascript\nconst form = useSchemaForm(profileSchema, {\n  values,\n  operation: 'patch'\n})\n```\n\nYou can also use a custom schema operation:\n\n```javascript\nconst form = useSchemaForm(profileSchema, {\n  values,\n  operation: 'upsert'\n})\n```\n\nThe adapter routes everything back through the schema operation registry, so custom operations behave the same way here as they do in the core runtime.\n\nIf you render those forms with Vuetify, use the separate bridge below. It stays thin on purpose and translates the Vue adapter's existing validation results into Vuetify-friendly props and rule callbacks.\n\n## Vuetify Bridge\n\nIf you use Vuetify on top of the Vue adapter, import the bridge from its own subpath:\n\n```javascript\nimport { createVuetifyRule, fieldProps, getVuetifyErrorMessages } from 'json-rest-schema/vuetify'\n```\n\nThis split is intentional:\n\n* `json-rest-schema/vue` owns schema-aware form orchestration\n* `json-rest-schema/vuetify` translates those results into Vuetify `rules` and `error-messages`\n* the validation rules still live in the schema layer, not in component glue code\n\n### Vuetify `rules` integration\n\nVuetify's `rules` prop is a natural fit for path-scoped validation.\n\n```javascript\nconst slugRule = createVuetifyRule(form, 'workspace.slug')\n```\n\nThen bind it to a component:\n\n```vue\n<v-text-field\n  v-model=\"values.workspace.slug\"\n  :rules=\"[slugRule]\"\n/>\n```\n\nThat rule:\n\n* clones the current form values\n* injects the field's current candidate value at the selected path\n* runs `validateField(path, ...)`\n* returns either `true` or the schema error message\n\nSo the rule stays a thin bridge. It does not re-implement validation logic.\n\n### Vuetify `fieldProps()` helper\n\nIf you want a compact helper for Vuetify inputs, use `fieldProps()`:\n\n```javascript\nconst slugProps = fieldProps(form, 'workspace.slug')\n```\n\nThen:\n\n```vue\n<v-text-field\n  v-model=\"values.workspace.slug\"\n  v-bind=\"slugProps\"\n/>\n```\n\nBy default, `fieldProps()` returns only a `rules` array.\n\nThat default is deliberate. Vuetify merges `error-messages` with rule-generated messages, so returning both by default would duplicate the same message on screen.\n\nIf you explicitly want manual `error-messages` too, opt in:\n\n```javascript\nconst slugProps = fieldProps(form, 'workspace.slug', {\n  includeErrorMessages: true\n})\n```\n\nThat adds:\n\n* `errorMessages`\n* `error`\n\non top of the generated `rules`.\n\n### Manual Vuetify error messages\n\nIf you only want the message bridge without generated rules, use `getVuetifyErrorMessages()` directly:\n\n```javascript\nconst messages = getVuetifyErrorMessages(form, 'workspace.slug')\n```\n\nThen:\n\n```vue\n<v-text-field\n  v-model=\"values.workspace.slug\"\n  :error-messages=\"getVuetifyErrorMessages(form, 'workspace.slug')\"\n/>\n```\n\nThis is useful when:\n\n* you validate on submit instead of on blur/input\n* you already ran `form.validate()` or `form.validateField()`\n* you want Vuetify to display stored schema errors without re-running rules immediately\n\n### Worked Vue + Vuetify example\n\n```javascript\nimport { reactive } from 'vue'\nimport { createSchema } from 'json-rest-schema'\nimport { useSchemaForm, useSchemaField } from 'json-rest-schema/vue'\nimport { fieldProps } from 'json-rest-schema/vuetify'\n\nconst workspaceSummarySchema = createSchema({\n  id: { type: 'id', required: true },\n  slug: { type: 'string', required: true, minLength: 3 },\n  ownerUserId: { type: 'id', required: true }\n})\n\nconst workspaceSchema = createSchema({\n  workspace: {\n    type: 'object',\n    required: true,\n    schema: workspaceSummarySchema\n  }\n})\n\nconst values = reactive({\n  workspace: {\n    slug: ''\n  }\n})\n\nconst form = useSchemaForm(workspaceSchema, {\n  values,\n  operation: 'patch'\n})\n\nconst slugField = useSchemaField(form, 'workspace.slug')\nconst slugProps = fieldProps(form, 'workspace.slug')\n\nconst saveWorkspace = form.submit(async (validatedObject) => {\n  await api.saveWorkspace(validatedObject)\n})\n```\n\n```vue\n<template>\n  <v-form @submit.prevent=\"saveWorkspace\">\n    <v-text-field\n      v-model=\"values.workspace.slug\"\n      label=\"Workspace slug\"\n      v-bind=\"slugProps\"\n      @blur=\"slugField.validate()\"\n    />\n\n    <v-btn type=\"submit\">Save</v-btn>\n  </v-form>\n</template>\n```\n\nThat example preserves the intended layering:\n\n* the schema owns normalization and validation\n* Vue owns local form state\n* Vuetify owns rendering and input UX\n* submit handlers own business logic and API calls\n\n## Demo Apps and Browser Smoke Tests\n\nThis repo now includes two minimal demo apps documented in `demos/README.md`:\n\n* `demos/react-rhf`\n* `demos/vue-vuetify`\n\nThey alias package imports back to the local source files in this checkout, so they\nalways exercise the current repo state instead of a published npm copy.\n\nWhat each demo proves:\n\n* `demos/react-rhf`: the React Hook Form resolver works in a real browser app, and the submit flow can still perform one final canonical schema pass before handing the payload to your API layer.\n* `demos/vue-vuetify`: the Vue and Vuetify adapters work in a real browser app, including visible Vuetify controls, blur validation, and normalized submit output.\n\nTo install and run them:\n\n```bash\nnpm run demo:install\n```\n\nThen in separate terminals:\n\n```bash\nnpm run demo:react\nnpm run demo:vue\n```\n\nVite will print the local URLs it chose. If the default port is busy, it will pick the next open one automatically.\n\nTo run the browser smoke tests:\n\n```bash\nnpx playwright install chromium\nnpm run test:demos\n```\n\nThe Playwright coverage is intentionally small and concrete:\n\n* the React demo validates through the RHF resolver and performs one final canonical schema submit\n* the Vue demo validates through the Vue and Vuetify adapters and submits a normalized payload in a real browser runtime\n\nSmall troubleshooting notes:\n\n* If a Vuetify control appears blank, make sure you ran the Vue demo's local install step. The demo now declares and imports the Material Design icon font explicitly.\n* If Playwright complains about missing browsers, run `npx playwright install chromium` once from the repo root.\n\n## VeeValidate v5 Bridge\n\nVeeValidate v5 accepts Standard Schema-compatible validators as `validationSchema`.\n\nThat means `json-rest-schema` does not need a heavy VeeValidate-specific runtime adapter. This package now ships a small bridge that wraps a schema instance in the Standard Schema interface VeeValidate already understands.\n\nImport it like this:\n\n```javascript\nimport { useForm } from 'vee-validate'\nimport { createSchema } from 'json-rest-schema'\nimport { toVeeValidateSchema } from 'json-rest-schema/vee-validate'\n```\n\n### Basic usage\n\n```javascript\nconst profileSchema = createSchema({\n  name: { type: 'string', required: true, minLength: 3 },\n  role: { type: 'string', defaultTo: 'guest' }\n})\n\nconst { handleSubmit, errors, values } = useForm({\n  initialValues: {\n    name: ''\n  },\n  validationSchema: toVeeValidateSchema(profileSchema)\n})\n```\n\nThat default bridge uses **`create` semantics**.\n\nSo on successful submit:\n\n* required fields are enforced\n* normalized values are returned\n* defaults are applied to the submitted output\n\nIf the user submits:\n\n```javascript\n{\n  name: '  Alex  '\n}\n```\n\nthen the validated submit payload is equivalent to:\n\n```javascript\n{\n  name: 'Alex',\n  role: 'guest'\n}\n```\n\n### Edit forms and custom operations\n\nIf the form is editing an existing resource, pass the operation explicitly:\n\n```javascript\nconst { handleSubmit } = useForm({\n  initialValues,\n  validationSchema: toVeeValidateSchema(profileSchema, {\n    operation: 'patch'\n  })\n})\n```\n\nCustom operations work too:\n\n```javascript\nconst { handleSubmit } = useForm({\n  initialValues,\n  validationSchema: toVeeValidateSchema(profileSchema, {\n    operation: 'upsert'\n  })\n})\n```\n\n### Important VeeValidate limitation: defaults do not initialize form state\n\nThis is important enough to say clearly:\n\n* the bridge validates and normalizes the schema output\n* VeeValidate still expects you to provide your own `initialValues`\n* schema defaults do **not** automatically populate the form's starting state\n\nSo this is the intended split:\n\n* `initialValues` controls the raw form state\n* `toVeeValidateSchema(...)` controls validation and normalized submit output\n\nIf you want a default field visible in the UI before submit, put it in `initialValues`.\n\nIf you only want the normalized payload to contain the default when the user submits, let the schema apply it.\n\n### Error paths\n\nThe bridge turns the library's flat error map into Standard Schema issues with nested paths.\n\nSo an internal error like:\n\n```javascript\n{\n  'roles.0.label': {\n    field: 'roles.0.label',\n    code: 'REQUIRED',\n    message: 'Field is required',\n    params: {}\n  }\n}\n```\n\nbecomes Standard Schema issues equivalent to:\n\n```javascript\n[\n  {\n    message: 'Field is required',\n    path: ['roles', 0, 'label']\n  }\n]\n```\n\nThat is what lets VeeValidate map nested array/object errors back onto the right field state.\n\n### Worked VeeValidate example\n\n```javascript\nimport { useForm } from 'vee-validate'\nimport { createSchema } from 'json-rest-schema'\nimport { toVeeValidateSchema } from 'json-rest-schema/vee-validate'\n\nconst workspaceSummarySchema = createSchema({\n  id: { type: 'id', required: true },\n  slug: { type: 'string', required: true, minLength: 3 },\n  ownerUserId: { type: 'id', required: true }\n})\n\nconst workspaceSchema = createSchema({\n  workspace: {\n    type: 'object',\n    required: true,\n    schema: workspaceSummarySchema\n  }\n})\n\nconst { defineField, handleSubmit, errors } = useForm({\n  initialValues: {\n    workspace: {\n      slug: ''\n    }\n  },\n  validationSchema: toVeeValidateSchema(workspaceSchema, {\n    operation: 'patch'\n  })\n})\n\nconst [slug, slugAttrs] = defineField('workspace.slug')\n\nconst saveWorkspace = handleSubmit((validatedObject) => {\n  return api.saveWorkspace(validatedObject)\n})\n```\n\n```vue\n<template>\n  <form @submit.prevent=\"saveWorkspace\">\n    <input v-model=\"slug\" v-bind=\"slugAttrs\">\n    <span>{{ errors['workspace.slug'] }}</span>\n    <button type=\"submit\">Save</button>\n  </form>\n</template>\n```\n\nThis keeps the responsibilities clean:\n\n* VeeValidate owns touched/dirty/submit orchestration\n* `json-rest-schema` owns validation and normalization\n* your submit handler owns business logic\n\n## Transport JSON Schema Export\n\n`json-rest-schema` can also export a transport-facing JSON Schema document for adapters that want pre-handler validation.\n\n```javascript\nconst userSchema = createSchema({\n  id: { type: 'id', required: true },\n  email: { type: 'string', required: true },\n  age: { type: 'number', min: 18, defaultTo: 18 },\n  status: { type: 'string', enum: ['draft', 'published'] }\n})\n\nconst createTransportSchema = userSchema.toJsonSchema()\nconst patchTransportSchema = userSchema.toJsonSchema({ operation: 'patch' })\n```\n\nKey points:\n\n* **Draft**: exports draft-07 JSON Schema.\n* **Operation-aware**: `operation: '<name>'` controls the `required` list and whether `defaultTo` is emitted.\n* **Compatibility**: `mode: 'create' | 'replace' | 'patch'` still works as shorthand for the built-in operations.\n* **Transport-facing**: the export is intended for JSON/Ajv/Fastify-style request validation, not for reproducing every in-process coercion path.\n* **Strict field shape**: `additionalProperties` defaults to `false` because runtime validation rejects unknown fields. Override it with `toJsonSchema({ additionalProperties: true })` if needed.\n* **Nested export**: schema-backed nested object contracts are hoisted into draft-07 `definitions` and referenced with `$ref`, so repeated and recursive graphs stay finite. Nested object fields inherit the active operation, while object schemas used as array items or object-map values are exported in `replace` mode.\n* **Recursive graph support**: runtime validation and `toJsonSchema()` both support self-recursive schema graphs. Direct self-recursive object fields point back to `#`, while recursive nested contracts are emitted through `definitions`.\n* **Opaque bags stay opaque**: `type: 'object'` plus `additionalProperties: true` exports as a permissive object field and does not invent child property rules.\n* **Single source of truth**: only rules owned by `json-rest-schema` are exported. External metadata keys from other layers are ignored.\n* **Schema metadata preserved**: schema-owned metadata such as `precision`, `scale`, and `unsigned` is preserved under `x-json-rest-schema.metadata`. `temporalPrecision` is both enforced at runtime/exported as a pattern constraint and preserved as metadata.\n* **Custom rules**: if a custom type or validator needs transport export support, attach a `toJsonSchema()` hook to the handler. If you register a custom validator without that hook, export fails loudly instead of silently drifting.\n\n### Worked nested export example\n\n```javascript\nconst schema = createSchema({\n  workspace: {\n    type: 'object',\n    required: true,\n    schema: workspaceSummarySchema\n  },\n  roles: {\n    type: 'array',\n    items: roleSchema\n  },\n  metadata: {\n    type: 'object',\n    additionalProperties: true\n  }\n})\n```\n\nExporting `schema.toJsonSchema()` gives you:\n\n* `workspace` as a `$ref` to a definition whose `required` fields still inherit the active operation\n* `roles.items` as a `$ref` to a nested object definition exported in `replace` mode\n* `metadata` as `{ type: 'object', additionalProperties: true }`\n* object maps as `{ type: 'object', additionalProperties: <value schema> }`\n* passthrough nested objects as validated `properties` plus `additionalProperties: true`\n\nThat means the transport export stays aligned with runtime semantics:\n\n* nested objects behave like nested contracts even when the runtime schema graph is recursive\n* array object items behave like complete replacements\n* opaque bags stay opaque instead of pretending to be structured\n\n### Worked recursive export example\n\nUsing the same recursive `nodeSchema` from the `Recursive Schemas` chapter above:\n\n```javascript\nconst transportSchema = nodeSchema.toJsonSchema()\n```\n\nKey recursive export behaviors:\n\n* a direct self-recursive object field such as `parent` becomes a reference back to `#`\n* recursive nested contracts reached through array items or dynamic object values are hoisted into `definitions`\n* the exporter stays finite because it tracks schema graph nodes, not just call depth\n\nFor the `parent` field above, the transport shape is:\n\n```javascript\n{\n  allOf: [\n    {\n      $ref: '#'\n    }\n  ],\n  'x-json-rest-schema': {\n    castType: 'object'\n  }\n}\n```\n\nFor the `children.items` edge, the transport shape becomes a `$ref` into `definitions`, and that referenced definition points back to itself for deeper `children.items` recursion.\n\n---\n\n## Common REST Recipes\n\nThis section is intentionally practical. These are the shapes you are likely to define in a real API.\n\n### Recipe: create payload\n\n```javascript\nconst createUserSchema = createSchema({\n  email: { type: 'string', required: true, notEmpty: true, lowercase: true },\n  displayName: { type: 'string', required: true, minLength: 2 },\n  role: { type: 'string', defaultTo: 'member' },\n  marketingOptIn: { type: 'boolean', defaultTo: false }\n})\n```\n\nUse it like this:\n\n```javascript\nconst result = createUserSchema.create({\n  email: '  ALEX@EXAMPLE.COM  ',\n  displayName: '  Alex  '\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    email: 'alex@example.com',\n    displayName: 'Alex',\n    role: 'member',\n    marketingOptIn: false\n  },\n  errors: {}\n}\n```\n\nUse this pattern when:\n\n* the client is creating a new resource\n* missing `required` fields should fail\n* omitted defaults should be materialized\n\n### Recipe: patch payload\n\nUse the same schema, but call `patch()`:\n\n```javascript\nconst result = createUserSchema.patch({\n  displayName: '  Updated Name  '\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    displayName: 'Updated Name'\n  },\n  errors: {}\n}\n```\n\nUse this pattern when:\n\n* the client is updating only a subset of fields\n* missing `required` fields should **not** fail just because they were omitted\n* defaults should **not** be invented during a patch\n\n### Recipe: nested detail response\n\nThis is a common “show one resource” response shape.\n\n```javascript\nconst userSummarySchema = createSchema({\n  id: { type: 'id', required: true },\n  email: { type: 'string', required: true }\n})\n\nconst projectSummarySchema = createSchema({\n  id: { type: 'id', required: true },\n  slug: { type: 'string', required: true }\n})\n\nconst projectDetailSchema = createSchema({\n  project: {\n    type: 'object',\n    required: true,\n    schema: projectSummarySchema\n  },\n  owner: {\n    type: 'object',\n    required: true,\n    schema: userSummarySchema\n  },\n  permissions: {\n    type: 'array',\n    required: true,\n    items: { type: 'string', minLength: 1 }\n  }\n})\n```\n\nValidate it with `create()` or `replace()` depending on your calling style:\n\n```javascript\nconst result = projectDetailSchema.create({\n  project: {\n    id: '10',\n    slug: '  api-redesign  '\n  },\n  owner: {\n    id: '7',\n    email: 'owner@example.com'\n  },\n  permissions: ['read', 'write']\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    project: {\n      id: 10,\n      slug: 'api-redesign'\n    },\n    owner: {\n      id: 7,\n      email: 'owner@example.com'\n    },\n    permissions: ['read', 'write']\n  },\n  errors: {}\n}\n```\n\n### Recipe: list response envelope\n\nThis library validates objects, so for list endpoints the usual pattern is an envelope object instead of a top-level array.\n\n```javascript\nconst workspaceSummarySchema = createSchema({\n  id: { type: 'id', required: true },\n  slug: { type: 'string', required: true },\n  ownerUserId: { type: 'id', required: true }\n})\n\nconst workspaceListSchema = createSchema({\n  items: {\n    type: 'array',\n    required: true,\n    items: workspaceSummarySchema\n  },\n  total: { type: 'integer', required: true, min: 0 }\n})\n```\n\nExample:\n\n```javascript\nconst result = workspaceListSchema.create({\n  items: [\n    { id: '1', slug: 'alpha', ownerUserId: '7' },\n    { id: '2', slug: 'beta', ownerUserId: '9' }\n  ],\n  total: '2'\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    items: [\n      { id: 1, slug: 'alpha', ownerUserId: 7 },\n      { id: 2, slug: 'beta', ownerUserId: 9 }\n    ],\n    total: 2\n  },\n  errors: {}\n}\n```\n\n### Recipe: settings or metadata bag\n\nWhen part of the payload belongs to another layer and should not be field-by-field validated here, use an opaque object bag.\n\n```javascript\nconst updatePreferencesSchema = createSchema({\n  userId: { type: 'id', required: true },\n  preferences: {\n    type: 'object',\n    additionalProperties: true\n  }\n})\n```\n\nExample:\n\n```javascript\nconst result = updatePreferencesSchema.patch({\n  preferences: {\n    theme: 'dark',\n    shortcuts: {\n      save: 'cmd+s'\n    },\n    labs: ['new-sidebar']\n  }\n})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    preferences: {\n      theme: 'dark',\n      shortcuts: {\n        save: 'cmd+s'\n      },\n      labs: ['new-sidebar']\n    }\n  },\n  errors: {}\n}\n```\n\nUse this only when you intentionally want:\n\n* object-ness to be enforced\n* inner keys and values to pass through untouched\n* no nested validation contract owned by this library\n\n### Recipe: custom operation for an upsert-like boundary\n\nSometimes you want “validate the whole shape, apply defaults, but do not require every required field.”\n\n```javascript\nconst accountSchema = createSchema({\n  email: { type: 'string', required: true, lowercase: true },\n  role: { type: 'string', defaultTo: 'member' }\n}, {\n  operations: {\n    upsert: {\n      targetFields: 'schema',\n      enforceRequired: false,\n      applyDefaults: true,\n      outputFields: 'validated'\n    }\n  }\n})\n```\n\nExample:\n\n```javascript\naccountSchema.upsert({})\n```\n\nResult:\n\n```javascript\n{\n  validatedObject: {\n    role: 'member'\n  },\n  errors: {}\n}\n```\n\nThis is useful when the persistence layer or surrounding business logic decides whether the resource already exists, and the schema’s job is only to normalize a shared contract.\n\n---\n\n## Built-in Rules Reference\n\nHere is a complete list of all types and validators available out of the box.\n\n### Built-in Types (Casting Rules)\n\nA field's `type` defines how the input value will be converted before any other validation rules are run.\n\n| Type Name | Description |\n|---|---|\n| `string` | Converts the input to a string. By default, it trims whitespace. Fails if the input is an object or array. |\n| `number` | Converts the input to a finite number. Empty strings, whitespace-only strings, and non-finite values fail validation. |\n| `integer` | Converts the input to a finite integer. Non-integer numeric values fail validation. |\n| `boolean`| Converts the input to a boolean using explicit true/false tokens such as `true`, `false`, `1`, `0`, `yes`, `no`, `on`, and `off`. Unknown values fail validation. |\n| `array` | Ensures the value is an array. If the input is not already an array, it will be wrapped in one (e.g., `'tag1'` becomes `['tag1']`). If `items` is present, every item is validated recursively. |\n| `id` | Parses the value into a positive safe integer identifier. It rejects non-canonical forms such as leading zeroes or strings with junk suffixes. |\n| `date` | Validates a real calendar date in exact `YYYY-MM-DD` form and returns the string unchanged. |\n| `dateTime`| Validates an RFC 3339 datetime with seconds and a mandatory `Z` or `±HH:MM` timezone, then returns the string unchanged. |\n| `time` | Validates an offset-free wall-clock time in `HH:MM[:SS[.fraction]]` form and returns the string unchanged. |\n| `epochMilliseconds`| Converts an integer number or canonical base-10 integer string representing milliseconds since the Unix epoch to a number. Values must fit the JavaScript date range. |\n| `epochSeconds`| Converts an integer number or canonical base-10 integer string representing seconds since the Unix epoch to a number. Values must fit the equivalent JavaScript date range. |\n| `serialize`| Converts any JavaScript value (including objects with circular references) into a single JSON-like string using `flatted`. |\n| `object` | Requires a plain object value. With `schema`, it becomes a nested object contract. With `values`, it becomes a typed object map. With `additionalProperties: true`, it becomes either an opaque pass-through object bag or a passthrough nested object when combined with `schema`. Without any of those options, it is simply a validated plain object value with no child-field rules. |\n| `blob` | Passes the value through unchanged. Intended for binary data like files that don't need casting. |\n| `file` | Converts primitive file-handle-like values to strings and rejects objects or arrays. |\n| `none` | The \"identity\" type. Passes the value through completely unchanged without any casting. |\n\n### Built-in Validators (Validation Parameters)\n\nValidators are rules that run after a value has been cast to its proper type.\n\n| Parameter | Description |\n|---|---|\n| `required: true` | The field must be present in the input object. Fails if the key is `undefined`. |\n| `minLength: <number>` | For `string` types, validates the minimum character length. |\n| `maxLength: <number>` | For `string` types, validates the maximum character length. |\n| `min: <number>` | For `number` types, validates the minimum value. |\n| `max: <number>` | For `number` types, validates the maximum value. |\n| `enum: <array>` | Restricts the field to one of the declared values. Exported as a standard JSON Schema `enum`. |\n| `notEmpty: true` | The field cannot be an empty string (`''`). This is different from `required`, as an empty string is still a defined value. |\n| `length: <number>`| For `string` types, it **truncates** the string to the specified length. For `number` types, it throws an error if the number of digits in the original input exceeds the specified length. |\n| `nullable: true`| Allows the value for this field to be `null`. By default, `null` is not allowed. |\n| `nullOnEmpty: true`| If the input value is an empty string (`''`), it will be cast to `null` before other validators run. |\n| `lowercase: true` | **Transforms** the string to all lowercase. |\n| `uppercase: true` | **Transforms** the string to all uppercase. |\n| `strictBoolean: true` | Restricts a `boolean` field so the original input must already be a real boolean. |\n| `validator: <function>`| Allows you to provide your own **synchronous** custom validation function for complex, one-off logic. |\n| `defaultTo: <value>` | If the field is not present in the input object, this value will be passed through the same type and validator pipeline in validation modes that apply defaults. Can be a value or a function that returns a value. |\n| `unsigned: true` | Passive schema metadata indicating non-negative numeric storage intent. Preserved in transport export metadata. |\n| `precision: <number>` | Passive schema metadata for decimal total digits. Preserved in transport export metadata. |\n| `scale: <number>` | Passive schema metadata for decimal fracti","readmeFilename":"README.md"}