{"_id":"@absmartly/api-mocks","_rev":"9-2bb13fda1d6e0e02173270c8c8fe61d1","name":"@absmartly/api-mocks","dist-tags":{"beta":"1.0.0-beta.1","latest":"1.0.8"},"versions":{"1.0.0-beta.1":{"name":"@absmartly/api-mocks","version":"1.0.0-beta.1","keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","_id":"@absmartly/api-mocks@1.0.0-beta.1","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"dist":{"shasum":"0746204a8ff77676db7c0b08da9710324b200830","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.0-beta.1.tgz","fileCount":270,"integrity":"sha512-qk07ZIAmdzlOP+I0PhXIWt7PJxIc1wk+R7KBj7RmYc//kYztYnimSpSbeSINVzNsbBt12jHZJVhCIaqcClDc3A==","signatures":[{"sig":"MEYCIQCdH9BlB1zOg5X5sJDvb52n5VmEJBi9fSBxrWOaJoYS6wIhAIinltYAhxF+nr4OOVDEHy/9SlqFKxDHN96iWBUTnkAK","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3395300},"main":"./src/index.ts","type":"module","exports":{".":"./src/index.ts","./server":"./src/server.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"gitHead":"3fa98b1a80dcb6ccbe5a8feec5eb715b26a38883","scripts":{"test":"vitest","pretest":"npm run generate","test:ui":"vitest --ui","generate":"npm run generate:types && npm run generate:handlers","test:run":"vitest run","test:contract":"vitest run contract-tests/schema-validator","test:coverage":"vitest run --coverage","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","prepublishOnly":"npm run generate","generate:handlers":"node scripts/generate-handlers.mjs","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:schemathesis":"schemathesis run --base-url https://sandbox.absmartly.com/v1 --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"_npmUser":{"name":"joalves","email":"jonas@absmartly.com"},"_npmVersion":"11.3.0","description":"OpenAPI-driven mock server and contract testing suite for the ABsmartly API, built on MSW and AJV.","directories":{},"_nodeVersion":"22.15.0","dependencies":{"@apidevtools/json-schema-ref-parser":"^15.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"ajv":"^8.17.1","msw":"^2.12.8","tsx":"^4.21.0","jsdom":"^28.0.0","dotenv":"^17.2.4","vitest":"^4.0.18","js-yaml":"^4.1.1","@vitest/ui":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.1","ajv-formats":"^3.0.1","@types/js-yaml":"^4.0.9","@faker-js/faker":"^10.2.0","openapi-typescript":"^7.10.1"},"_npmOperationalInternal":{"tmp":"tmp/api-mocks_1.0.0-beta.1_1775819176855_0.20893994860555942","host":"s3://npm-registry-packages-npm-production"}},"1.0.0":{"name":"@absmartly/api-mocks","version":"1.0.0","keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","_id":"@absmartly/api-mocks@1.0.0","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"dist":{"shasum":"564dd60b14063b6505c8179140c3b881e073d891","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.0.tgz","fileCount":270,"integrity":"sha512-X8uk111h5VB9HH9J0qv1sumpnqRlVI6YeCcHoY0n3VzTQW5H5mLyd3LpNyjR4X9mWMQBHu/xxYyEiRGwJJQYaw==","signatures":[{"sig":"MEYCIQC959qQWvFnMQWiUaNAyFaqhNMQiWqOagtZFGnWuWZqTgIhAInJ0RH21xh3SuQZndWpFdTQQIRDxAHwa3/hBZSECKac","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3395293},"main":"./src/index.ts","type":"module","exports":{".":"./src/index.ts","./server":"./src/server.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"gitHead":"56e92050303ec431d2f1fb961c3958fbf0907989","scripts":{"test":"vitest","pretest":"npm run generate","test:ui":"vitest --ui","generate":"npm run generate:types && npm run generate:handlers","test:run":"vitest run","test:contract":"vitest run contract-tests/schema-validator","test:coverage":"vitest run --coverage","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","prepublishOnly":"npm run generate","generate:handlers":"node scripts/generate-handlers.mjs","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:schemathesis":"schemathesis run --base-url https://sandbox.absmartly.com/v1 --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"_npmUser":{"name":"joalves","email":"jonas@absmartly.com"},"_npmVersion":"11.3.0","description":"OpenAPI-driven mock server and contract testing suite for the ABsmartly API, built on MSW and AJV.","directories":{},"_nodeVersion":"22.15.0","dependencies":{"ajv":"^8.17.1","ajv-formats":"^3.0.1","@apidevtools/json-schema-ref-parser":"^15.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.8","tsx":"^4.21.0","jsdom":"^28.0.0","dotenv":"^17.2.4","vitest":"^4.0.18","js-yaml":"^4.1.1","@vitest/ui":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.1","@types/js-yaml":"^4.0.9","@faker-js/faker":"^10.2.0","openapi-typescript":"^7.10.1"},"_npmOperationalInternal":{"tmp":"tmp/api-mocks_1.0.0_1775824821070_0.5968709292590881","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@absmartly/api-mocks","version":"1.0.1","keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","_id":"@absmartly/api-mocks@1.0.1","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"dist":{"shasum":"d1c31932107a83f9358455e8830485ef1717f4fa","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.1.tgz","fileCount":270,"integrity":"sha512-8ljhEBq7fegE56twP1TB4gOnWlgbFMTOpFMZzC61DVgvgyNNRRmTv+IOKp++1AHw/JbiJLRVkjTsKrCClnTgqQ==","signatures":[{"sig":"MEQCIA2/8mBvewE3pxbdQwrT7rX1pKfFPykNoOKvvfnLu6hZAiBHkNPojrLwQORBH4tnqhikogMIsHuYVscR6vAs3BOS/A==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3395293},"main":"./src/index.ts","type":"module","exports":{".":"./src/index.ts","./server":"./src/server.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"gitHead":"9ca849bd73ffd6fdc9e540de2217dd958d388c68","scripts":{"test":"vitest","pretest":"npm run generate","test:ui":"vitest --ui","generate":"npm run generate:types && npm run generate:handlers","test:run":"vitest run","test:contract":"vitest run contract-tests/schema-validator","test:coverage":"vitest run --coverage","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","prepublishOnly":"npm run generate","generate:handlers":"node scripts/generate-handlers.mjs","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:schemathesis":"schemathesis run --base-url https://sandbox.absmartly.com/v1 --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5218d460-fbc3-4c13-9752-23f308c38c10"}},"_npmVersion":"11.11.0","description":"OpenAPI-driven mock server and contract testing suite for the ABsmartly API, built on MSW and AJV.","directories":{},"_nodeVersion":"24.14.1","dependencies":{"ajv":"^8.17.1","ajv-formats":"^3.0.1","@apidevtools/json-schema-ref-parser":"^15.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.8","tsx":"^4.21.0","jsdom":"^28.0.0","dotenv":"^17.2.4","vitest":"^4.0.18","js-yaml":"^4.1.1","@vitest/ui":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.1","@types/js-yaml":"^4.0.9","@faker-js/faker":"^10.2.0","openapi-typescript":"^7.10.1"},"_npmOperationalInternal":{"tmp":"tmp/api-mocks_1.0.1_1775826073298_0.24329326374458726","host":"s3://npm-registry-packages-npm-production"}},"1.0.2":{"name":"@absmartly/api-mocks","version":"1.0.2","keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","_id":"@absmartly/api-mocks@1.0.2","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"dist":{"shasum":"6161e1cf64dfb9f63beb3bd6924d9e6809223b71","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.2.tgz","fileCount":270,"integrity":"sha512-RALW8gw1MEdAb7E2GBdWlt0GNZ1FnGkOn/BD7VWcy9yNmTgSWoPSPEU2NPb7Bc0ATIEGweS2ucpJFJ+w+NYNjw==","signatures":[{"sig":"MEUCIQC0BncbzMbvpdIz/Eeh4ihmp9FlDM/MosrkYfoUAHyFrwIgdup3KXHpzjN1wsUSJyieJTxVdXAcElYZvqcM+qeqFbo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3407786},"main":"./src/index.ts","type":"module","exports":{".":"./src/index.ts","./server":"./src/server.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"gitHead":"6390cd828733334359f1978147be2eb9cf8a31dc","scripts":{"test":"vitest","pretest":"npm run generate","test:ui":"vitest --ui","generate":"npm run generate:types && npm run generate:handlers","test:run":"vitest run","test:contract":"vitest run contract-tests/schema-validator","test:coverage":"vitest run --coverage","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","prepublishOnly":"npm run generate","generate:handlers":"node scripts/generate-handlers.mjs","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:schemathesis":"schemathesis run --base-url https://sandbox.absmartly.com/v1 --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5218d460-fbc3-4c13-9752-23f308c38c10"}},"_npmVersion":"11.11.0","description":"OpenAPI-driven mock server, typed factories, and schema validation for the ABsmartly API. Built on [MSW (Mock Service Worker)](https://mswjs.io/) with handlers auto-generated from the ABsmartly OpenAPI specification.","directories":{},"_nodeVersion":"24.14.1","dependencies":{"ajv":"^8.17.1","js-yaml":"^4.1.1","ajv-formats":"^3.0.1","@faker-js/faker":"^10.2.0","@apidevtools/json-schema-ref-parser":"^15.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.8","tsx":"^4.21.0","jsdom":"^28.0.0","dotenv":"^17.2.4","vitest":"^4.0.18","@vitest/ui":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.1","@types/js-yaml":"^4.0.9","openapi-typescript":"^7.10.1"},"peerDependencies":{"msw":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/api-mocks_1.0.2_1775835826094_0.6877221064321075","host":"s3://npm-registry-packages-npm-production"}},"1.0.4":{"name":"@absmartly/api-mocks","version":"1.0.4","keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","_id":"@absmartly/api-mocks@1.0.4","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"dist":{"shasum":"64d1894fd96cb72d6857f62d7ca69eb882111f24","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.4.tgz","fileCount":270,"integrity":"sha512-BTamZiExLspv1s5ODmZxQbroycLEYAuuldBphbKUFH7UgPIcjRGq14lwkM0Qmm0xrYMLk8yTvsiDG/OMQsESBw==","signatures":[{"sig":"MEQCIQCCeuP3FqcWsZxVHcjLYFnUF7RmLFT4JSQi9zVUBtg38QIfLEtBXPp0Bw0cQYjVZXTtFpeZ68wBv8o5V6RnygSobw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3417329},"main":"./src/index.ts","type":"module","exports":{".":"./src/index.ts","./server":"./src/server.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"gitHead":"3af8e90af529e7ef80a81302adeece598a7f9e98","scripts":{"test":"vitest","pretest":"npm run generate","test:ui":"vitest --ui","generate":"npm run generate:types && npm run generate:handlers","test:run":"vitest run","test:contract":"vitest run contract-tests/schema-validator","test:coverage":"vitest run --coverage","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","prepublishOnly":"npm run generate","generate:handlers":"node scripts/generate-handlers.mjs","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:schemathesis":"schemathesis run --base-url https://sandbox.absmartly.com/v1 --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5218d460-fbc3-4c13-9752-23f308c38c10"}},"_npmVersion":"11.11.0","description":"OpenAPI-driven mock server, typed factories, and schema validation for the ABsmartly API. Built on [MSW (Mock Service Worker)](https://mswjs.io/) with handlers auto-generated from the ABsmartly OpenAPI specification.","directories":{},"_nodeVersion":"24.14.1","dependencies":{"ajv":"^8.17.1","js-yaml":"^4.1.1","ajv-formats":"^3.0.1","@faker-js/faker":"^10.2.0","@apidevtools/json-schema-ref-parser":"^15.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.8","tsx":"^4.21.0","jsdom":"^28.0.0","dotenv":"^17.2.4","vitest":"^4.0.18","@vitest/ui":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.1","@types/js-yaml":"^4.0.9","openapi-typescript":"^7.10.1"},"peerDependencies":{"msw":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/api-mocks_1.0.4_1775841111118_0.9957748749034157","host":"s3://npm-registry-packages-npm-production"}},"1.0.5":{"name":"@absmartly/api-mocks","version":"1.0.5","keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","_id":"@absmartly/api-mocks@1.0.5","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"dist":{"shasum":"c866736e131518bcbf7a6ed924a0256bf907b955","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.5.tgz","fileCount":270,"integrity":"sha512-QtxsIfrniv2XieIzXBoNXWM49QROpazVSC8dMFTlJc8+2epItqT1CIUErOAKJCjTkXwlE+MMb5NB0MsxTUNIVw==","signatures":[{"sig":"MEYCIQCMPPIs9psMZHN4IMezFhh1MeZJTB2xVnH3tuEFRmG9gAIhAN/0HmUw/hIYi/JsAhRBm9wOjjtsNPxMlFqWaVaV5p7R","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3420980},"main":"./src/index.ts","type":"module","exports":{".":"./src/index.ts","./server":"./src/server.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"gitHead":"fb0225b5097772b8ab38cd574f380822f07f24a8","scripts":{"test":"vitest","pretest":"npm run generate","test:ui":"vitest --ui","generate":"npm run generate:types && npm run generate:handlers","test:run":"vitest run","test:contract":"vitest run contract-tests/schema-validator","test:coverage":"vitest run --coverage","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","prepublishOnly":"npm run generate","generate:handlers":"node scripts/generate-handlers.mjs","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:schemathesis":"schemathesis run --base-url https://sandbox.absmartly.com/v1 --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5218d460-fbc3-4c13-9752-23f308c38c10"}},"_npmVersion":"11.11.0","description":"OpenAPI-driven mock server, typed factories, and schema validation for the ABsmartly API. Built on [MSW (Mock Service Worker)](https://mswjs.io/) with handlers auto-generated from the ABsmartly OpenAPI specification.","directories":{},"_nodeVersion":"24.14.1","dependencies":{"ajv":"^8.17.1","js-yaml":"^4.1.1","ajv-formats":"^3.0.1","@faker-js/faker":"^10.2.0","@apidevtools/json-schema-ref-parser":"^15.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.8","tsx":"^4.21.0","jsdom":"^28.0.0","dotenv":"^17.2.4","vitest":"^4.0.18","@vitest/ui":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.1","@types/js-yaml":"^4.0.9","openapi-typescript":"^7.10.1"},"peerDependencies":{"msw":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/api-mocks_1.0.5_1775842553972_0.09211833120496249","host":"s3://npm-registry-packages-npm-production"}},"1.0.6":{"name":"@absmartly/api-mocks","version":"1.0.6","keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","_id":"@absmartly/api-mocks@1.0.6","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"dist":{"shasum":"7cf3d5f724a5844629c307b8eca1f62a342059db","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.6.tgz","fileCount":270,"integrity":"sha512-dhLFeIjrZ2D+JGIo9JPKTnKzLLwIkNze1s24ZPs/8H3KqvEC52TuDuWC04PY15q9kjE5G9P3GeyWF/XeqFF9ug==","signatures":[{"sig":"MEUCIQDj/6HGtxRpmH8oj3DloRjdLdlWikjLlLygNW9Rwu4B4wIgXVsJT1mWVsIOtUOmylzI1kvOGcfcbui8I8/lwCy0Ytc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3424458},"main":"./src/index.ts","type":"module","exports":{".":"./src/index.ts","./server":"./src/server.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"gitHead":"d16d506068930776042fa91eea01a339cb311ede","scripts":{"test":"vitest","pretest":"npm run generate","test:ui":"vitest --ui","generate":"npm run generate:types && npm run generate:handlers","test:run":"vitest run","test:contract":"vitest run contract-tests/schema-validator","test:coverage":"vitest run --coverage","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","prepublishOnly":"npm run generate","generate:handlers":"node scripts/generate-handlers.mjs","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:schemathesis":"schemathesis run --base-url https://sandbox.absmartly.com/v1 --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5218d460-fbc3-4c13-9752-23f308c38c10"}},"_npmVersion":"11.11.0","description":"OpenAPI-driven mock server, typed factories, and schema validation for the ABsmartly API. Built on [MSW (Mock Service Worker)](https://mswjs.io/) with handlers auto-generated from the ABsmartly OpenAPI specification.","directories":{},"_nodeVersion":"24.14.1","dependencies":{"ajv":"^8.17.1","js-yaml":"^4.1.1","ajv-formats":"^3.0.1","@faker-js/faker":"^10.2.0","@apidevtools/json-schema-ref-parser":"^15.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.8","tsx":"^4.21.0","jsdom":"^28.0.0","dotenv":"^17.2.4","vitest":"^4.0.18","@vitest/ui":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.1","@types/js-yaml":"^4.0.9","openapi-typescript":"^7.10.1"},"peerDependencies":{"msw":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/api-mocks_1.0.6_1775843316806_0.37215911810711244","host":"s3://npm-registry-packages-npm-production"}},"1.0.7":{"name":"@absmartly/api-mocks","version":"1.0.7","keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","_id":"@absmartly/api-mocks@1.0.7","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"dist":{"shasum":"95a03bd00f405728fb2041b7436fe36c9ecdeb38","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.7.tgz","fileCount":270,"integrity":"sha512-hBjDyKfaQMZDw0bD/HHFzQUCvcjEaci7/Ila72k242cSExLRENqJDQQqTlfupPdkLFFJtU7E081s/U2o6zlF6A==","signatures":[{"sig":"MEQCIBiL41dlYMtdAqVPCQ5WmvtJclKTxYScK5amvZMNl+wGAiA0vKgEyF+wKu3lDLI6EQyrvfHpfZcFGw8SXcrZDKsKxg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":3424768},"main":"./src/index.ts","type":"module","exports":{".":"./src/index.ts","./server":"./src/server.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"gitHead":"49b46339547a37d3cc520fea4a1d420ad40297d1","scripts":{"test":"vitest","pretest":"npm run generate","test:ui":"vitest --ui","generate":"npm run generate:types && npm run generate:handlers","test:run":"vitest run","test:contract":"vitest run contract-tests/schema-validator","test:coverage":"vitest run --coverage","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","prepublishOnly":"npm run generate","generate:handlers":"node scripts/generate-handlers.mjs","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:schemathesis":"schemathesis run --base-url https://sandbox.absmartly.com/v1 --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5218d460-fbc3-4c13-9752-23f308c38c10"}},"_npmVersion":"11.12.1","description":"OpenAPI-driven mock server, typed factories, and schema validation for the ABsmartly API. Built on [MSW (Mock Service Worker)](https://mswjs.io/) with handlers auto-generated from the ABsmartly OpenAPI specification.","directories":{},"_nodeVersion":"24.15.0","dependencies":{"ajv":"^8.17.1","js-yaml":"^4.1.1","ajv-formats":"^3.0.1","@faker-js/faker":"^10.2.0","@apidevtools/json-schema-ref-parser":"^15.2.2"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"msw":"^2.12.8","tsx":"^4.21.0","jsdom":"^28.0.0","dotenv":"^17.2.4","vitest":"^4.0.18","@vitest/ui":"^4.0.18","typescript":"^5.9.3","@types/node":"^25.2.1","@types/js-yaml":"^4.0.9","openapi-typescript":"^7.10.1"},"peerDependencies":{"msw":"^2.0.0"},"_npmOperationalInternal":{"tmp":"tmp/api-mocks_1.0.7_1776942697194_0.04689252520650422","host":"s3://npm-registry-packages-npm-production"}},"1.0.8":{"name":"@absmartly/api-mocks","version":"1.0.8","description":"OpenAPI-driven mock server, typed factories, and schema validation for the ABsmartly API. Built on [MSW (Mock Service Worker)](https://mswjs.io/) with handlers auto-generated from the ABsmartly OpenAPI specification.","main":"./src/index.ts","exports":{".":"./src/index.ts","./handlers":"./src/handlers/index.ts","./factories":"./src/factories/index.ts","./validation":"./src/validation/index.ts","./server":"./src/server.ts","./src/generated/schema":"./src/generated/schema.d.ts"},"scripts":{"generate:types":"openapi-typescript openapi/openapi.yaml -o src/generated/schema.d.ts","generate:handlers":"node scripts/generate-handlers.mjs","generate:tests":"node scripts/generate-live-validation-tests-v2.mjs","generate":"npm run generate:types && npm run generate:handlers && npm run generate:tests","prepublishOnly":"npm run generate","pretest":"npm run generate","test":"vitest","test:ui":"vitest --ui","test:run":"vitest run","test:coverage":"vitest run --coverage","test:contract":"vitest run contract-tests/schema-validator","test:contract:live":"ENABLE_LIVE_API_TESTS=true vitest run contract-tests/live-api-validation","validate:live":"ENABLE_LIVE_API_TESTS=true vitest run src/live-validation","validate:live:report":"tsx src/live-validation/test-runner.ts","validate:comprehensive":"bash scripts/validate-live-api.sh","validate:schemathesis":"[ -n \"$API_BASE_URL\" ] && [ -n \"$API_KEY\" ] && schemathesis run --base-url \"$API_BASE_URL\" --header \"Authorization: Api-Key $API_KEY\" --checks all openapi/openapi.yaml || { echo 'Error: API_BASE_URL and API_KEY env vars required' >&2; exit 1; }","validate:mutations":"bash scripts/run-mutation-tests.sh","validate:mutations:force":"RUN_MUTATION_TESTS=true vitest run src/live-validation-mutations --reporter=./src/live-validation-mutations/endpoint-reporter.ts"},"keywords":["absmartly","api","mocks","msw","openapi","testing"],"author":{"name":"ABsmartly"},"license":"UNLICENSED","publishConfig":{"access":"public"},"type":"module","devDependencies":{"@types/js-yaml":"^4.0.9","@types/node":"^25.2.1","@vitest/ui":"^4.0.18","dotenv":"^17.2.4","jsdom":"^28.0.0","msw":"^2.12.8","openapi-typescript":"^7.10.1","tsx":"^4.21.0","typescript":"^5.9.3","vitest":"^4.0.18"},"peerDependencies":{"msw":"^2.0.0"},"dependencies":{"@apidevtools/json-schema-ref-parser":"^15.2.2","@faker-js/faker":"^10.2.0","ajv":"^8.17.1","ajv-formats":"^3.0.1","js-yaml":"^4.1.1"},"gitHead":"6007ebbf843de424dcb1e02184c696fca5149702","_id":"@absmartly/api-mocks@1.0.8","_nodeVersion":"24.14.1","_npmVersion":"11.11.0","dist":{"integrity":"sha512-eBdRBVuAfmuViYew1IBCAKhwvfXE4hUVvNqudNctpDT3+enpuNXubBfAycv6D1vY63GAKcwZnsq4urL9ecA+SQ==","shasum":"70d567760e53b4c231a6ba72fdb470d0e260c46e","tarball":"https://registry.npmjs.org/@absmartly/api-mocks/-/api-mocks-1.0.8.tgz","fileCount":270,"unpackedSize":3441524,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQC8muLNPxb8aLCsS6ZZ0NIbdBhkJR4JNVafH035+SCikgIhAI6qastIGpCmSKWPbmCfPr4qRzkZzRaaacOTwt4r10fb"}]},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:5218d460-fbc3-4c13-9752-23f308c38c10"}},"directories":{},"maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/api-mocks_1.0.8_1777048756961_0.7389254402085508"},"_hasShrinkwrap":false}},"time":{"created":"2026-04-10T11:06:16.704Z","modified":"2026-04-24T16:39:17.328Z","1.0.0-beta.1":"2026-04-10T11:06:17.099Z","1.0.0":"2026-04-10T12:40:21.220Z","1.0.1":"2026-04-10T13:01:13.539Z","1.0.2":"2026-04-10T15:43:46.276Z","1.0.4":"2026-04-10T17:11:51.344Z","1.0.5":"2026-04-10T17:35:54.315Z","1.0.6":"2026-04-10T17:48:37.084Z","1.0.7":"2026-04-23T11:11:37.387Z","1.0.8":"2026-04-24T16:39:17.151Z"},"author":{"name":"ABsmartly"},"license":"UNLICENSED","keywords":["absmartly","api","mocks","msw","openapi","testing"],"description":"OpenAPI-driven mock server, typed factories, and schema validation for the ABsmartly API. Built on [MSW (Mock Service Worker)](https://mswjs.io/) with handlers auto-generated from the ABsmartly OpenAPI specification.","maintainers":[{"name":"marcioapm","email":"marcioapm@gmail.com"},{"name":"joalves","email":"jonas@absmartly.com"},{"name":"caltheabtester","email":"cal@absmartly.com"},{"name":"marcioabs","email":"marcio@absmartly.com"}],"readme":"# @absmartly/api-mocks\n\nOpenAPI-driven mock server, typed factories, and schema validation for the ABsmartly API. Built on [MSW (Mock Service Worker)](https://mswjs.io/) with handlers auto-generated from the ABsmartly OpenAPI specification.\n\n## Installation\n\n```bash\nnpm install --save-dev @absmartly/api-mocks\n```\n\n**Peer dependency:** This package requires [`msw`](https://mswjs.io/) v2+:\n\n```bash\nnpm install --save-dev msw\n```\n\n## Quick Start\n\n```typescript\nimport { createServer } from '@absmartly/api-mocks/server';\nimport { beforeAll, afterEach, afterAll, test, expect } from 'vitest';\n\nconst server = createServer('https://your-instance.absmartly.com/v1');\n\nbeforeAll(() => server.listen({ onUnhandledRequest: 'bypass' }));\nafterEach(() => server.resetHandlers());\nafterAll(() => server.close());\n\ntest('fetches experiments', async () => {\n  const response = await fetch('https://your-instance.absmartly.com/v1/experiments');\n  const data = await response.json();\n  expect(response.ok).toBe(true);\n});\n```\n\n## Package Exports\n\n| Import path | Description |\n|---|---|\n| `@absmartly/api-mocks` | Everything: factories, handlers, validation, and `createServer` |\n| `@absmartly/api-mocks/server` | `createServer(baseUrl)` -- creates a pre-configured MSW server |\n| `@absmartly/api-mocks/handlers` | MSW request handlers (generated + error simulation) |\n| `@absmartly/api-mocks/factories` | Faker-based factory functions for all API resources |\n| `@absmartly/api-mocks/validation` | Schema validation utilities powered by AJV |\n\n## MSW Mock Server\n\n`createServer(baseUrl)` returns an MSW [`setupServer`](https://mswjs.io/docs/api/setup-server) instance with all generated handlers pre-registered.\n\n```typescript\nimport { createServer } from '@absmartly/api-mocks/server';\n\nconst server = createServer('https://your-instance.absmartly.com/v1');\n```\n\n### Vitest Setup\n\nCreate a setup file to start/stop the server around your tests:\n\n```typescript\n// test/setup.ts\nimport { beforeAll, afterEach, afterAll } from 'vitest';\nimport { createServer } from '@absmartly/api-mocks/server';\n\nconst server = createServer('https://your-instance.absmartly.com/v1');\n\nbeforeAll(() => server.listen({ onUnhandledRequest: 'bypass' }));\nafterEach(() => server.resetHandlers());\nafterAll(() => server.close());\n```\n\nThen reference it in your Vitest config:\n\n```typescript\n// vitest.config.ts\nexport default defineConfig({\n  test: {\n    setupFiles: ['./test/setup.ts'],\n  },\n});\n```\n\n### Pre-configured Server\n\nThe package also exports a pre-configured server instance that reads the base URL from environment variables:\n\n```typescript\nimport { server } from '@absmartly/api-mocks/src/mocks/server';\n```\n\nThe base URL is resolved in this order:\n1. `API_BASE_URL` environment variable\n2. `ABSMARTLY_API_ENDPOINT` environment variable\n3. `https://sandbox.absmartly.com/v1` (placeholder default — only used by MSW mocks, which intercept all requests before they reach the network)\n\n## Handlers\n\n### Generated Handlers\n\nHandlers are auto-generated from the OpenAPI specification. Every endpoint in the spec gets a corresponding MSW handler that returns realistic example data.\n\n```typescript\nimport { createHandlers } from '@absmartly/api-mocks/handlers';\n\nconst handlers = createHandlers('https://your-instance.absmartly.com/v1');\n```\n\nThe generated handlers cover 40+ API resources including experiments, goals, metrics, segments, users, teams, applications, environments, and more.\n\n**How generated handlers work:**\n\n- **GET (list)** -- Returns the static example from the OpenAPI spec\n- **GET (by ID)** -- Clones the example and sets the `id` field from the URL path parameter\n- **POST / PUT / PATCH** -- Clones the example, deep-merges the request body into the response, and validates the request using `withValidation()`\n- **DELETE** -- Returns 204 No Content\n\nThe deep-merge strategy preserves response arrays (arrays from the example response take precedence over arrays in the request body), which ensures list fields always return realistic data.\n\n### Error Simulation Handlers\n\nIn addition to the generated handlers, the package provides error simulation handlers for testing error scenarios:\n\n```typescript\nimport { createErrorHandlers } from '@absmartly/api-mocks/handlers';\n\nconst errorHandlers = createErrorHandlers('https://your-instance.absmartly.com/v1');\n```\n\nThese handlers simulate common error cases:\n\n| Endpoint | Trigger | Response |\n|---|---|---|\n| `POST /experiments` | Missing `name` | 400 -- name is required |\n| `POST /experiments` | `name: \"duplicate_name\"` | 409 -- already exists |\n| `POST /experiments` | Missing `unit_type_id` | 400 -- unit_type_id is required |\n| `PUT /experiments/999/start` | ID = 999 | 400 -- already running |\n| `PUT /experiments/888/stop` | ID = 888 | 400 -- not running |\n| `POST /goals` | Missing `name` | 400 -- name is required |\n| `POST /goals` | `name: \"duplicate\"` | 409 -- already exists |\n| `POST /segments` | Missing `name` or `value_source_attribute` | 400 -- field is required |\n| `DELETE /segments/666` | ID = 666 | 409 -- in use by active experiments |\n| `POST /api_keys` | Missing `name` | 400 -- name is required |\n\n## Factories\n\nAll factories follow the same pattern: `createMock*(overrides?)` returns a single instance, `createMock*s(count)` returns an array. Every factory is typed using the generated TypeScript types from the OpenAPI schema.\n\n```typescript\nimport { createMockExperiment, createMockExperiments } from '@absmartly/api-mocks/factories';\n\n// Single instance with defaults\nconst experiment = createMockExperiment();\n\n// With overrides\nconst experiment = createMockExperiment({\n  name: 'my_test',\n  state: 'running',\n});\n\n// Multiple instances\nconst experiments = createMockExperiments(5);\n```\n\n### Available Factories\n\n| Factory | Type |\n|---|---|\n| `createMockExperiment` / `createMockExperiments` | `ExperimentShort` |\n| `createMockGoal` / `createMockGoals` | `Goal` |\n| `createMockSegment` / `createMockSegments` | `Segment` |\n| `createMockMetric` / `createMockMetrics` | `Metric` |\n| `createMockUser` / `createMockUsers` | `User` |\n| `createMockTeam` / `createMockTeams` | `Team` |\n| `createMockApplication` / `createMockApplications` | `Application` |\n| `createMockEnvironment` / `createMockEnvironments` | `Environment` |\n| `createMockUnitType` / `createMockUnitTypes` | `UnitType` |\n| `createMockApiKey` / `createMockApiKeys` | `ApiKey` |\n| `createMockWebhook` / `createMockWebhooks` | `Webhook` |\n| `createMockRole` / `createMockRoles` | `Role` |\n| `createMockPermission` / `createMockPermissions` | `Permission` |\n| `createMockPermissionCategory` / `createMockPermissionCategories` | `PermissionCategory` |\n| `createMockMetricCategory` / `createMockMetricCategories` | `MetricCategory` |\n| `createMockAlert` / `createMockAlerts` | `Alert` |\n| `createMockNote` / `createMockNotes` | `Note` |\n| `createMockExperimentTag` / `createMockExperimentTags` | `ExperimentTag` |\n| `createMockGoalTag` / `createMockGoalTags` | `GoalTag` |\n| `createMockMetricTag` / `createMockMetricTags` | `MetricTag` |\n\n## Validation\n\nThe validation layer uses [AJV](https://ajv.js.org/) to validate request and response payloads against the OpenAPI schema. All validation functions load and dereference the bundled OpenAPI spec automatically.\n\n### Request Validation (Lenient)\n\n`validateRequest` is intentionally lenient -- it strips `required`, `minItems`, `minProperties`, and `pattern` constraints so you can send partial payloads in tests. It validates structure and types only.\n\n```typescript\nimport { validateRequest } from '@absmartly/api-mocks/validation';\n\nconst result = await validateRequest('/goals', 'POST', {\n  name: 'My Goal',\n});\n// result: { valid: true, errors: [] }\n```\n\n### Response Validation (Strict)\n\n`validateResponse` applies the full schema including all constraints.\n\n```typescript\nimport { validateResponse } from '@absmartly/api-mocks/validation';\n\nconst result = await validateResponse('/goals', 'GET', 200, responseData);\nif (!result.valid) {\n  console.log(result.errors);\n  // [{ path: '/items/0', message: '...', keyword: 'type' }]\n}\n```\n\n### Strict Request/Response Validation\n\nFor when you want full constraint checking on requests too:\n\n```typescript\nimport { validateRequestStrict, validateResponseStrict } from '@absmartly/api-mocks/validation';\n\nconst result = await validateRequestStrict('/goals', 'POST', payload);\n```\n\n`findUnknownProperties` can detect extra properties not defined in the schema:\n\n```typescript\nimport { findUnknownProperties, loadOpenAPISpec } from '@absmartly/api-mocks/validation';\n\nconst spec = await loadOpenAPISpec();\nconst unknowns = findUnknownProperties(data, schema, spec);\n```\n\n### Handler Validation Wrapper\n\n`withValidation` wraps an MSW handler resolver to automatically validate incoming requests (and optionally responses):\n\n```typescript\nimport { withValidation } from '@absmartly/api-mocks/validation';\nimport { http, HttpResponse } from 'msw';\n\nhttp.post(\n  `${baseUrl}/goals`,\n  withValidation('/goals', 'POST', async ({ request }) => {\n    const body = await request.json();\n    return HttpResponse.json({ ok: true, goal: body }, { status: 201 });\n  }, {\n    validateRequests: true,   // default: true\n    validateResponses: false, // default: false\n  })\n);\n```\n\nWhen request validation fails, it returns a 422 response:\n\n```json\n{\n  \"ok\": false,\n  \"error\": \"validation_error\",\n  \"message\": \"Request validation failed\",\n  \"status\": 422,\n  \"details\": [{ \"path\": \"/name\", \"message\": \"must be string\", \"keyword\": \"type\" }]\n}\n```\n\n### Payload Generation\n\n`generatePayloadForEndpoint` creates a minimal valid payload that satisfies the request schema for a given endpoint:\n\n```typescript\nimport { generatePayloadForEndpoint } from '@absmartly/api-mocks/validation';\n\nconst payload = await generatePayloadForEndpoint('/goals', 'POST', {\n  name: 'My Custom Goal',\n});\n```\n\nIt generates sensible defaults for each type (`string` -> `\"test-string\"`, `integer` -> `1`, `date-time` -> `\"2025-01-01T00:00:00.000Z\"`, `email` -> `\"test@example.com\"`, etc.) and deep-merges any overrides you provide.\n\n### Schema Inspection\n\nLower-level functions for working with the OpenAPI spec directly:\n\n```typescript\nimport {\n  loadOpenAPISpec,\n  getSchemaForEndpoint,\n  getRequestSchemaForEndpoint,\n  createValidator,\n  validateAgainstSchema,\n} from '@absmartly/api-mocks/validation';\n\n// Load the full dereferenced spec\nconst spec = await loadOpenAPISpec();\n\n// Get the response schema for a specific endpoint\nconst responseSchema = await getSchemaForEndpoint('/experiments', 'GET', 200);\n\n// Get the request body schema\nconst requestSchema = await getRequestSchemaForEndpoint('/goals', 'POST');\n\n// Compile a reusable validator\nconst validate = createValidator(responseSchema);\nconst isValid = validate(data);\n\n// One-shot validation\nconst result = await validateAgainstSchema(data, schema, { coerceTypes: true });\n```\n\n## OpenAPI Specification\n\nThe package bundles the ABsmartly API OpenAPI 3.0 specification:\n\n```\nopenapi/\n  openapi.yaml              # Main spec (references paths/ and components/)\n  openapi.bundle.yaml       # Fully dereferenced bundle (used at runtime)\n  openapi_with_examples.yaml\n  paths/                    # Per-resource path definitions (44 files)\n  examples/                 # Response examples per resource\n  components/               # Shared schema components\n  live-payloads/            # Sanitized payloads captured from the live API\n```\n\nThe bundled spec at `openapi/openapi.bundle.yaml` is what the validation layer loads at runtime. It has all `$ref` references resolved inline.\n\n## Code Generation\n\nTwo things are auto-generated from the OpenAPI spec and **must be regenerated** whenever the spec changes:\n\n### TypeScript Types\n\n```bash\nnpm run generate:types\n```\n\nRuns `openapi-typescript` to produce `src/generated/schema.d.ts` from `openapi/openapi.yaml`. This file contains TypeScript interfaces for all API paths, operations, and component schemas. All factories are typed using these generated types.\n\n### MSW Handlers\n\n```bash\nnpm run generate:handlers\n```\n\nRuns `scripts/generate-handlers.mjs` to produce one handler file per API resource in `src/handlers/generated/`. The generator:\n\n1. Reads each path from the OpenAPI spec\n2. Extracts response examples (preferring `_200`/`_201` suffixed examples)\n3. Creates MSW handlers for each HTTP method (GET, POST, PUT, DELETE, etc.)\n4. Wraps POST/PUT/PATCH handlers with `withValidation()` for request validation\n5. Generates an `index.ts` that aggregates all resource handlers\n\n### Regenerate Everything\n\n```bash\nnpm run generate\n```\n\nThis runs both `generate:types` and `generate:handlers`. It also runs automatically before `npm test` (via `pretest`) and before `npm publish` (via `prepublishOnly`).\n\n## Testing\n\n### Unit Tests\n\n```bash\nnpm test              # Watch mode\nnpm run test:run      # Single run\nnpm run test:coverage # With coverage report\n```\n\nUnit tests validate the mock server handlers, factories, and validation logic using MSW's in-memory server. No network access required.\n\n### Contract Tests\n\n```bash\nnpm run test:contract\n```\n\nValidates that the mock server responses conform to the OpenAPI schema. Compiles schemas with AJV and checks that generated responses pass validation.\n\n### Live API Validation\n\n```bash\nnpm run validate:live\n```\n\nRuns 40+ test files against the real ABsmartly API, validating that actual API responses match the OpenAPI schema. Requires `API_KEY` and `API_BASE_URL` environment variables (or a `.env.local` file).\n\n```bash\nnpm run validate:live:report   # Generates a markdown report\nnpm run validate:comprehensive # Full validation suite with reports\n```\n\n### Mutation Tests\n\n```bash\nnpm run validate:mutations       # Interactive (asks for confirmation)\nnpm run validate:mutations:force # Non-interactive\n```\n\nFull CRUD lifecycle tests that create, read, update, and delete resources on the live API. Includes automatic cleanup of created resources via a `ResourceTracker`.\n\n### Schemathesis\n\n```bash\nnpm run validate:schemathesis\n```\n\nProperty-based API testing using [Schemathesis](https://github.com/schemathesis/schemathesis). Generates random valid requests from the OpenAPI spec and checks all responses for conformance. Requires Python 3.11+ and the `schemathesis` pip package.\n\n## Environment Variables\n\n| Variable | Description | Default |\n|---|---|---|\n| `API_BASE_URL` | Base URL for the ABsmartly API (required for live tests and scripts) | -- |\n| `ABSMARTLY_API_ENDPOINT` | Alternative base URL variable | -- |\n| `API_KEY` | API key for live API tests | -- |\n| `ABSMARTLY_API_KEY` | Alternative API key variable | -- |\n| `ENABLE_LIVE_API_TESTS` | Set to `true` to enable live API test suites | `false` |\n\nCreate a `.env.local` file for local development:\n\n```\nAPI_KEY=your_api_key_here\nAPI_BASE_URL=https://your-instance.absmartly.com/v1\n```\n\n## CI/CD\n\nPushes to `main` automatically run tests and publish a new patch version to npm via GitHub Actions with [npm trusted publishing](https://docs.npmjs.com/trusted-publishers/) (OIDC -- no tokens required).\n\n## Project Structure\n\n```\nsrc/\n  index.ts                  # Main export aggregator\n  server.ts                 # createServer(baseUrl) factory\n  mocks/\n    server.ts               # Pre-configured MSW server instance\n    handlers.ts             # Handler initialization from env vars\n  handlers/\n    index.ts                # Handler exports and composition\n    errors.ts               # Error simulation handlers\n    generated/              # Auto-generated (one file per resource)\n  factories/                # Faker-based data factories (18 resources)\n  validation/\n    schema-validator.ts     # OpenAPI spec loading and AJV validation\n    request-validator.ts    # Lenient request validation\n    response-validator.ts   # Strict response validation\n    validated-handler.ts    # MSW handler validation wrapper\n    strict-validator.ts     # Strict validation + unknown property detection\n    payload-generator.ts    # Generate valid payloads from schemas\n  generated/\n    schema.d.ts             # Auto-generated TypeScript types\n  __tests__/                # Unit tests\n  contract-tests/           # Schema contract tests\n  live-validation/          # Live API validation tests\n  live-validation-mutations/# CRUD lifecycle mutation tests\nopenapi/\n  openapi.yaml              # Main OpenAPI spec\n  openapi.bundle.yaml       # Dereferenced bundle\n  paths/                    # Per-resource path definitions\n  examples/                 # Response examples\n  components/               # Shared schemas\n  live-payloads/            # Captured live API payloads\nscripts/\n  generate-handlers.mjs     # Handler generation from OpenAPI\n  generate-live-validation-tests-v2.mjs\n  validate-live-api.sh\n  run-mutation-tests.sh\n  sync-examples-from-live.mjs\n```\n\n## License\n\nProprietary - ABsmartly\n","readmeFilename":"README.md"}