{"_id":"@ahmedrowaihi/openapi-recon","_rev":"6-f335ae8e06c019039d3a98895b455365","name":"@ahmedrowaihi/openapi-recon","dist-tags":{"latest":"1.3.0"},"versions":{"1.0.0":{"name":"@ahmedrowaihi/openapi-recon","version":"1.0.0","keywords":["openapi","reverse-engineer","infer","spec","capture","json-schema","typescript"],"author":{"name":"Ahmed Rowaihi","email":"ahmedrowaihi@gmail.com"},"license":"MIT","_id":"@ahmedrowaihi/openapi-recon@1.0.0","maintainers":[{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"}],"homepage":"https://github.com/ahmedrowaihi/contract-kit/tree/main/packages/openapi-recon","bugs":{"url":"https://github.com/ahmedrowaihi/contract-kit/issues"},"dist":{"shasum":"aaef3bb29c922045aacbfd79b79fa9d5cd801f17","tarball":"https://registry.npmjs.org/@ahmedrowaihi/openapi-recon/-/openapi-recon-1.0.0.tgz","fileCount":50,"integrity":"sha512-auF0Dm6NczuIunkLXyY4jKJrms0GKNeiqSCKqBwormxqHPxgkDR32o1GaB/viR+vBvYuinX8UxH3apLPj0/2Jg==","signatures":[{"sig":"MEQCIF0HkzsNcORVDgXI4T9kHZ+Yhd88UOgm9tVEIJaumJOtAiA6kZuVfhJLUIgRUFXc/hNpGhNB5P99l/kf41OXhkC5lQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahmedrowaihi%2fopenapi-recon@1.0.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":70936},"main":"./dist/index.js","type":"module","_from":"file:ahmedrowaihi-openapi-recon-1.0.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"tsc --watch","build":"tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"},"_resolved":"/tmp/9faeb75f9787660f36b224d5238601f1/ahmedrowaihi-openapi-recon-1.0.0.tgz","_integrity":"sha512-auF0Dm6NczuIunkLXyY4jKJrms0GKNeiqSCKqBwormxqHPxgkDR32o1GaB/viR+vBvYuinX8UxH3apLPj0/2Jg==","repository":{"url":"git+https://github.com/ahmedrowaihi/contract-kit.git","type":"git","directory":"packages/openapi-recon"},"_npmVersion":"10.8.2","description":"Reverse-engineer an OpenAPI 3.1 spec from observed HTTP traffic — runtime-agnostic, accepts standard Request/Response, works in browsers, Node, edge runtimes","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^22","@hey-api/shared":"^0.4.1","@hey-api/spec-types":"^0.2.0","@contract-kit/tsconfig":"0.0.0"},"peerDependencies":{"@hey-api/shared":">=0.3.0","@hey-api/spec-types":">=0.2.0"},"_npmOperationalInternal":{"tmp":"tmp/openapi-recon_1.0.0_1777346592750_0.7575303331928998","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @ir-kit/openapi-recon. See https://github.com/ir-kit/ir-kit for migration."},"1.1.0":{"name":"@ahmedrowaihi/openapi-recon","version":"1.1.0","keywords":["openapi","reverse-engineer","infer","spec","capture","json-schema","typescript"],"author":{"name":"Ahmed Rowaihi","email":"ahmedrowaihi@gmail.com"},"license":"MIT","_id":"@ahmedrowaihi/openapi-recon@1.1.0","maintainers":[{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"}],"homepage":"https://github.com/ahmedrowaihi/contract-kit/tree/main/packages/openapi-recon","bugs":{"url":"https://github.com/ahmedrowaihi/contract-kit/issues"},"dist":{"shasum":"e643028d634b207c0a6b51f51a316d6ca7a51a3f","tarball":"https://registry.npmjs.org/@ahmedrowaihi/openapi-recon/-/openapi-recon-1.1.0.tgz","fileCount":50,"integrity":"sha512-SgwlU5U240m8pwbcddExPNjgink81baZ4y5JINr4D+tXV1s1qHCqzrVtB3ZdFuVGsl1VI949tA8C/P9qxC/jdQ==","signatures":[{"sig":"MEYCIQCovgQeInbAYafOd08jVH9bCt9vX285gSwLSDKnFpRh6QIhAMIsygexhPhfIPs2VLdOAZtTmUp1bBKfagpiMW/BX1hp","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahmedrowaihi%2fopenapi-recon@1.1.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":75370},"main":"./dist/index.js","type":"module","_from":"file:ahmedrowaihi-openapi-recon-1.1.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"tsc --watch","build":"tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"},"_resolved":"/tmp/865fb62caa1112ae70c2bc52b33d84eb/ahmedrowaihi-openapi-recon-1.1.0.tgz","_integrity":"sha512-SgwlU5U240m8pwbcddExPNjgink81baZ4y5JINr4D+tXV1s1qHCqzrVtB3ZdFuVGsl1VI949tA8C/P9qxC/jdQ==","repository":{"url":"git+https://github.com/ahmedrowaihi/contract-kit.git","type":"git","directory":"packages/openapi-recon"},"_npmVersion":"10.8.2","description":"Reverse-engineer an OpenAPI 3.1 spec from observed HTTP traffic — runtime-agnostic, accepts standard Request/Response, works in browsers, Node, edge runtimes","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^22","@hey-api/spec-types":"^0.2.0","@ahmedrowaihi/tsconfig":"0.0.0"},"peerDependencies":{"@hey-api/spec-types":">=0.2.0"},"_npmOperationalInternal":{"tmp":"tmp/openapi-recon_1.1.0_1777354793322_0.6533099980552848","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @ir-kit/openapi-recon. See https://github.com/ir-kit/ir-kit for migration."},"1.1.1":{"name":"@ahmedrowaihi/openapi-recon","version":"1.1.1","keywords":["openapi","reverse-engineer","infer","spec","capture","json-schema","typescript"],"author":{"name":"Ahmed Rowaihi","email":"ahmedrowaihi@gmail.com"},"license":"MIT","_id":"@ahmedrowaihi/openapi-recon@1.1.1","maintainers":[{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"}],"homepage":"https://github.com/ahmedrowaihi/contract-kit/tree/main/packages/openapi/recon","bugs":{"url":"https://github.com/ahmedrowaihi/contract-kit/issues"},"dist":{"shasum":"c6dcab6a6358b1a0ed758cf95f1eaee2fdd319fa","tarball":"https://registry.npmjs.org/@ahmedrowaihi/openapi-recon/-/openapi-recon-1.1.1.tgz","fileCount":51,"integrity":"sha512-is0faFzNY2OCAUOr9yMhoOC9HijSBXTBfAeNyaT+GG7ndYAiJj0Oa3vWjRIDwPBVWSbNrleC7S0EA0LgGA9Vyw==","signatures":[{"sig":"MEYCIQChJUidYWnMejIPfgDQZ3g3tWNgI4XMigdF3099povO0gIhAICm8kYpwbGt4eT4ZgQPoksDYr+FL/R5bjPWt3Ny04dH","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahmedrowaihi%2fopenapi-recon@1.1.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":78684},"main":"./dist/index.js","type":"module","_from":"file:ahmedrowaihi-openapi-recon-1.1.1.tgz","types":"./dist/index.d.ts","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"tsc --watch","build":"tsc","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"},"_resolved":"/tmp/a4f45fef3e51b5b8a5eedae326969139/ahmedrowaihi-openapi-recon-1.1.1.tgz","_integrity":"sha512-is0faFzNY2OCAUOr9yMhoOC9HijSBXTBfAeNyaT+GG7ndYAiJj0Oa3vWjRIDwPBVWSbNrleC7S0EA0LgGA9Vyw==","repository":{"url":"git+https://github.com/ahmedrowaihi/contract-kit.git","type":"git","directory":"packages/openapi/recon"},"_npmVersion":"10.8.2","description":"Reverse-engineer an OpenAPI 3.1 spec from observed HTTP traffic — runtime-agnostic, accepts standard Request/Response, works in browsers, Node, edge runtimes","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"@types/node":"^22","@hey-api/spec-types":"^0.2.0","@ahmedrowaihi/tsconfig":"0.0.0"},"peerDependencies":{"@hey-api/spec-types":">=0.2.0"},"_npmOperationalInternal":{"tmp":"tmp/openapi-recon_1.1.1_1777638932017_0.020428465526332262","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @ir-kit/openapi-recon. See https://github.com/ir-kit/ir-kit for migration."},"1.2.0":{"name":"@ahmedrowaihi/openapi-recon","version":"1.2.0","keywords":["openapi","reverse-engineer","infer","spec","capture","json-schema","typescript"],"author":{"name":"Ahmed Rowaihi","email":"ahmedrowaihi@gmail.com"},"license":"MIT","_id":"@ahmedrowaihi/openapi-recon@1.2.0","maintainers":[{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"}],"homepage":"https://github.com/ahmedrowaihi/contract-kit/tree/main/packages/openapi/recon","bugs":{"url":"https://github.com/ahmedrowaihi/contract-kit/issues"},"dist":{"shasum":"6e0629bb6846f08f7afb1f5145182947e9376219","tarball":"https://registry.npmjs.org/@ahmedrowaihi/openapi-recon/-/openapi-recon-1.2.0.tgz","fileCount":59,"integrity":"sha512-KJiDVjEvZ469ReRysv3eN3R6laIGt8Abp4tqc8Sb90CvhE5LeISv4KOAs9Syk0IsBndD2PlYlu9yjv2n82I+Ig==","signatures":[{"sig":"MEYCIQDvotmRvJhWOWViyttl70+5Le1s9UmAWDqCNhfkYmAK3gIhAMCVTH/fb76uYqtGCFBzQgvK7eZHCVljOMEikU/IHb2T","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahmedrowaihi%2fopenapi-recon@1.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":111638},"main":"./dist/index.js","type":"module","_from":"file:ahmedrowaihi-openapi-recon-1.2.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"tsc -p tsconfig.build.json --watch","test":"vitest run","build":"tsc -p tsconfig.build.json","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"},"_resolved":"/tmp/9393e8310e66b93919b4f3767327d59e/ahmedrowaihi-openapi-recon-1.2.0.tgz","_integrity":"sha512-KJiDVjEvZ469ReRysv3eN3R6laIGt8Abp4tqc8Sb90CvhE5LeISv4KOAs9Syk0IsBndD2PlYlu9yjv2n82I+Ig==","repository":{"url":"git+https://github.com/ahmedrowaihi/contract-kit.git","type":"git","directory":"packages/openapi/recon"},"_npmVersion":"10.8.2","description":"Reverse-engineer an OpenAPI 3.1 spec from observed HTTP traffic — runtime-agnostic, accepts standard Request/Response, works in browsers, Node, edge runtimes","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.0","@types/node":"^22","@hey-api/spec-types":"^0.2.0","@ahmedrowaihi/tsconfig":"0.0.0"},"peerDependencies":{"@hey-api/spec-types":">=0.2.0"},"_npmOperationalInternal":{"tmp":"tmp/openapi-recon_1.2.0_1778711187969_0.7009211029892057","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @ir-kit/openapi-recon. See https://github.com/ir-kit/ir-kit for migration."},"1.3.0":{"name":"@ahmedrowaihi/openapi-recon","version":"1.3.0","keywords":["openapi","reverse-engineer","infer","spec","capture","json-schema","typescript"],"author":{"name":"Ahmed Rowaihi","email":"ahmedrowaihi@gmail.com"},"license":"MIT","_id":"@ahmedrowaihi/openapi-recon@1.3.0","maintainers":[{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"}],"homepage":"https://github.com/ahmedrowaihi/contract-kit/tree/main/packages/openapi/recon","bugs":{"url":"https://github.com/ahmedrowaihi/contract-kit/issues"},"bin":{"openapi-recon":"dist/cli.js"},"dist":{"shasum":"4572112ce646d4c78f80c267f925c1f885a5bba9","tarball":"https://registry.npmjs.org/@ahmedrowaihi/openapi-recon/-/openapi-recon-1.3.0.tgz","fileCount":67,"integrity":"sha512-4Zdx6i0ooBGAJ4SDbjb08YOJnxmPaQdG2MQlLkEd7/VJWO91Z0xakF6jtrsgcKbs0NOmkBN/G9O8FdLqaIVAZg==","signatures":[{"sig":"MEUCIQD12zEePCwffK9tks1cnI8LNYg+7Sd3Wu01blGXyrLkkgIgOSVJgfJncQlFAlcdtj8w1S66k1RiY/lyGpVbLeyINnM=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ahmedrowaihi%2fopenapi-recon@1.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":129414},"main":"./dist/index.js","type":"module","_from":"file:ahmedrowaihi-openapi-recon-1.3.0.tgz","types":"./dist/index.d.ts","engines":{"node":">=20.19.0"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"},"./package.json":"./package.json"},"scripts":{"dev":"tsc -p tsconfig.build.json --watch","test":"vitest run --passWithNoTests","build":"tsc -p tsconfig.build.json","typecheck":"tsc --noEmit"},"_npmUser":{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"},"_resolved":"/tmp/3a0a04d530067be09ae3162febdf891f/ahmedrowaihi-openapi-recon-1.3.0.tgz","_integrity":"sha512-4Zdx6i0ooBGAJ4SDbjb08YOJnxmPaQdG2MQlLkEd7/VJWO91Z0xakF6jtrsgcKbs0NOmkBN/G9O8FdLqaIVAZg==","repository":{"url":"git+https://github.com/ahmedrowaihi/contract-kit.git","type":"git","directory":"packages/openapi/recon"},"_npmVersion":"10.8.2","description":"Reverse-engineer an OpenAPI 3.1 spec from observed HTTP traffic — runtime-agnostic, accepts standard Request/Response, works in browsers, Node, edge runtimes","directories":{},"sideEffects":false,"_nodeVersion":"20.20.2","publishConfig":{"access":"public","provenance":true},"_hasShrinkwrap":false,"devDependencies":{"vitest":"^4.0.0","@types/node":"^22","@hey-api/spec-types":"^0.2.0","@ahmedrowaihi/tsconfig":"0.0.0"},"peerDependencies":{"@hey-api/spec-types":">=0.2.0"},"_npmOperationalInternal":{"tmp":"tmp/openapi-recon_1.3.0_1779048915559_0.6554315942634916","host":"s3://npm-registry-packages-npm-production"},"deprecated":"Moved to @ir-kit/openapi-recon. See https://github.com/ir-kit/ir-kit for migration."}},"time":{"created":"2026-04-28T03:23:12.661Z","modified":"2026-05-21T09:19:13.419Z","1.0.0":"2026-04-28T03:23:12.916Z","1.1.0":"2026-04-28T05:39:53.477Z","1.1.1":"2026-05-01T12:35:32.175Z","1.2.0":"2026-05-13T22:26:28.111Z","1.3.0":"2026-05-17T20:15:15.715Z"},"bugs":{"url":"https://github.com/ahmedrowaihi/contract-kit/issues"},"author":{"name":"Ahmed Rowaihi","email":"ahmedrowaihi@gmail.com"},"license":"MIT","homepage":"https://github.com/ahmedrowaihi/contract-kit/tree/main/packages/openapi/recon","keywords":["openapi","reverse-engineer","infer","spec","capture","json-schema","typescript"],"repository":{"url":"git+https://github.com/ahmedrowaihi/contract-kit.git","type":"git","directory":"packages/openapi/recon"},"description":"Reverse-engineer an OpenAPI 3.1 spec from observed HTTP traffic — runtime-agnostic, accepts standard Request/Response, works in browsers, Node, edge runtimes","maintainers":[{"name":"ahmedrowaihi","email":"ahmedrowaihi1@gmail.com"}],"readme":"# @ahmedrowaihi/openapi-recon\n\nReverse-engineer an OpenAPI 3.1 document from observed HTTP traffic. Feed it standard Web Fetch `Request` / `Response` pairs and it folds them into a JSON Schema 2020-12 document with templated paths, per-status response schemas, detected auth schemes, and per-origin grouping.\n\nRuntime-agnostic: works in browsers, Node, Deno, Bun, Cloudflare Workers — anywhere `Request` / `Response` exist. Pure functions, no global state, tree-shakable.\n\nPowers [`@ahmedrowaihi/glean`](../../apps/glean), the Chrome DevTools extension that emits live specs from browsing.\n\n## Install\n\n```bash\npnpm add @ahmedrowaihi/openapi-recon\n```\n\n## Use\n\n```ts\nimport { createRecon } from \"@ahmedrowaihi/openapi-recon\";\n\nconst recon = createRecon({\n  title: \"Petstore\",\n  version: \"0.1.0\",\n});\n\n// Anywhere you observe traffic — e.g. a fetch wrapper, a service-worker, a proxy:\nawait recon.observe(request, response);\n\n// Whenever you want a snapshot:\nconst document = recon.toOpenAPI();\n// → OpenAPIV3_1.Document with paths, components.schemas, components.securitySchemes\n```\n\n`request` / `response` are standard Web Fetch types. Bodies must already be readable — call `.clone()` upstream if you also need to forward the response. Non-JSON bodies are skipped silently.\n\n## What it infers\n\n- **Path templating**: `/pets/42` and `/pets/8` collapse into `/pets/{petId}` with `{ petId: \"string\" }`. Pure-numeric segments become `integer`. Disable via `pathTemplating: false`.\n- **JSON Schema 2020-12** for every observed JSON request and response body, merged across samples (union types, optional fields, enum candidates).\n- **Per-status response schemas**: `200` and `404` keep distinct shapes.\n- **Auth schemes**: `Authorization: Bearer ...` → `bearerAuth`; `X-API-Key: ...` → `apiKeyAuth`; basic auth too. Detected per-operation, deduped at the components level.\n- **Per-origin grouping**: feed traffic from many backends and snapshot one origin at a time:\n\n```ts\nconst justBackend = recon.toOpenAPI({ origin: \"https://api.example.com\" });\n```\n\n## Options\n\n```ts\ncreateRecon({\n  redactHeaders: [\"authorization\", \"cookie\", \"x-api-key\"], // sensible defaults built in\n  pathTemplating: true,\n  title: \"Reverse-engineered API\",\n  version: \"0.0.0\",\n});\n```\n\n## API surface\n\n| Export | Purpose |\n| --- | --- |\n| `createRecon(config?)` | Returns a `Recon` session. |\n| `Recon.observe(req, res)` | Fold one request/response into the running spec. |\n| `Recon.toOpenAPI(opts?)` | Snapshot the current spec (optionally filtered by origin). |\n| `Recon.sampleCount()` / `originStats()` | Telemetry on what's been folded. |\n| `Recon.clear()` / `clearOrigin(origin)` | Reset all state, or just one origin. |\n| `inferSchema(value)` / `mergeSchema(a, b)` | Lower-level building blocks. |\n| `templatePaths(paths)` / `templateSinglePath(...)` | Path templating in isolation. |\n| `sanitizeHeaders(headers, redact?)` / `DEFAULT_REDACTED_HEADERS` | Header redaction helpers. |\n\n## Pairing\n\n- **[`@ahmedrowaihi/glean`](../../apps/glean)** — Chrome DevTools panel that wires this up to the network panel and emits a live, click-to-copy spec.\n- **[`@ahmedrowaihi/openapi-tools/diff`](../openapi-tools)** — diff a freshly recon'd spec against a committed one to spot drift between docs and reality.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}