{"_id":"@amritk/asyncapi","_rev":"4-b3193c55c464eccdbbf5dbe3bb90f8c4","name":"@amritk/asyncapi","dist-tags":{"latest":"0.3.1"},"versions":{"0.1.0":{"name":"@amritk/asyncapi","version":"0.1.0","keywords":["asyncapi","json-schema","typescript","codegen","mjst"],"author":{"name":"amritk"},"license":"MIT","_id":"@amritk/asyncapi@0.1.0","maintainers":[{"name":"amritk","email":"amrit+spam@hockey-community.com"}],"homepage":"https://github.com/amritk/mjst/tree/main/packages/asyncapi#readme","bugs":{"url":"https://github.com/amritk/mjst/issues"},"dist":{"shasum":"e65b91229e68188a3f373c115dbcc1f8b5d5e295","tarball":"https://registry.npmjs.org/@amritk/asyncapi/-/asyncapi-0.1.0.tgz","fileCount":32,"integrity":"sha512-3v0cGTXcJZ4ADcTkGephnmLliZwpeSctiq22bCYj/g7fD45i0RWrQl9u6l3JwxnBWd/G8FeP6bUFE32y8y9SAA==","signatures":[{"sig":"MEUCIQCMPm9SAE/d32SageoI+WaLvfZ5XcW2RSqEPb5Md1Aj7gIgUqpFq3yaV77ncteSL/Y5Yw0ubcxt/J0n+bEp5EBlQI4=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":64984},"type":"module","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"1f4bf1313967417d33eef93e6a6c553e12d218c6","scripts":{"test":"NODE_ENV=production vitest run --root ../.. packages/asyncapi","build":"tsgo -p tsconfig.build.json && tsc-alias -p tsconfig.build.json -f && node ../../scripts/strip-comments.mjs","types:check":"tsgo -p . --noEmit","prepublishOnly":"node ../../scripts/check-publishable.mjs"},"_npmUser":{"name":"amritk","email":"amrit+spam@hockey-community.com"},"repository":{"url":"git+https://github.com/amritk/mjst.git","type":"git","directory":"packages/asyncapi"},"_npmVersion":"11.16.0","description":"Extract JSON Schemas from AsyncAPI 2.x/3.0 documents for the mjst generators.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"@amritk/helpers":"^0.19.0"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"*":["./dist/*.d.ts"]}},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/asyncapi_0.1.0_1788888574537_0.3962278660016316","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"@amritk/asyncapi","version":"0.2.0","keywords":["asyncapi","json-schema","typescript","codegen","mjst"],"author":{"name":"amritk"},"license":"MIT","_id":"@amritk/asyncapi@0.2.0","maintainers":[{"name":"amritk","email":"amrit+spam@hockey-community.com"}],"homepage":"https://github.com/amritk/mjst/tree/main/packages/asyncapi#readme","bugs":{"url":"https://github.com/amritk/mjst/issues"},"dist":{"shasum":"96859690cb31e9345a6bed022ff65fc19bae345d","tarball":"https://registry.npmjs.org/@amritk/asyncapi/-/asyncapi-0.2.0.tgz","fileCount":40,"integrity":"sha512-SlrsMDx5+urfy182ON0BXsTJCdeliu4DfUlTEc1S8ANJc3jKSl9RiTYvwTAn/Tk53TGopqbVka9wKvDW7lZhNg==","signatures":[{"sig":"MEUCIQDL6Y8/MOCj1mJJbWOcOnud007kzJ2qwBoZd+UzA+s7bwIgdtqHgGQBvvBqlxS3ui1PzpEToAZtFCx378nyygQwjUk=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEYCIQCOIDnoeXsq1DxnoSqXF182ACW1rHCdMpFSDYuNxrWLjwIhANrv8RWZ9+qvEZGQrlQnuHSh2iNc4MPuZQ5eEFj/hwhT","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amritk%2fasyncapi@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":82300},"type":"module","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"e7583dd77a500823367175ac59119f77e7c0a235","scripts":{"test":"NODE_ENV=production vitest run --root ../.. packages/asyncapi","build":"tsgo -p tsconfig.build.json && tsc-alias -p tsconfig.build.json -f && node ../../scripts/strip-comments.mjs","types:check":"tsgo -p . --noEmit","prepublishOnly":"node ../../scripts/check-publishable.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ad21a913-e642-44f2-92bb-f4249c1f158c"}},"repository":{"url":"git+https://github.com/amritk/mjst.git","type":"git","directory":"packages/asyncapi"},"_npmVersion":"11.19.1","description":"Extract JSON Schemas from AsyncAPI 2.x/3.0 documents for the mjst generators.","directories":{},"sideEffects":false,"_nodeVersion":"24.20.0","dependencies":{"@amritk/helpers":"^0.20.0"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"*":["./dist/*.d.ts"]}},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/asyncapi_0.2.0_1788890137757_0.4729713311640724","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@amritk/asyncapi","version":"0.3.0","keywords":["asyncapi","json-schema","typescript","codegen","mjst"],"author":{"name":"amritk"},"license":"MIT","_id":"@amritk/asyncapi@0.3.0","maintainers":[{"name":"amritk","email":"amrit+spam@hockey-community.com"}],"homepage":"https://github.com/amritk/mjst/tree/main/packages/asyncapi#readme","bugs":{"url":"https://github.com/amritk/mjst/issues"},"dist":{"shasum":"cbc7c5ab129c6bdc5e1f51744f37282dede262ef","tarball":"https://registry.npmjs.org/@amritk/asyncapi/-/asyncapi-0.3.0.tgz","fileCount":40,"integrity":"sha512-ePR7KUmyid2rUoBwLxSsmvOXTq0Yh2rYTJ9kULLuQ3FlB0lCGZhkGIvMfG8+Rjd7+ADpI0uV0vqrgWwXFIhjAg==","signatures":[{"sig":"MEUCIQCkRjhGAUWKyCFFKl9Tm05hBfwlB0WbhoT6BaaPCZst8wIgIat1g6/a54cisTopSPGZz8FkslRjxVeayUBwmlYxthU=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"sig":"MEQCIDTvs2mRdafWUwOmaitXLianJ+ha5uDOrK80Oq8Fqdt3AiA2WBNLGTOApwlGOH/Yr63fQ45wkDFYSFHKjdO8vNGtEQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amritk%2fasyncapi@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":89508},"type":"module","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"43832d7a66b87b09af416dc3d38ee65e54bc4797","scripts":{"test":"NODE_ENV=production vitest run --root ../.. packages/asyncapi","build":"tsgo -p tsconfig.build.json && tsc-alias -p tsconfig.build.json -f && node ../../scripts/strip-comments.mjs","types:check":"tsgo -p . --noEmit","prepublishOnly":"node ../../scripts/check-publishable.mjs"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ad21a913-e642-44f2-92bb-f4249c1f158c"}},"repository":{"url":"git+https://github.com/amritk/mjst.git","type":"git","directory":"packages/asyncapi"},"_npmVersion":"11.19.1","description":"Extract JSON Schemas from AsyncAPI 2.x/3.0 documents for the mjst generators.","directories":{},"sideEffects":false,"_nodeVersion":"24.20.0","dependencies":{"@amritk/helpers":"^0.21.0","@amritk/adapters":"^0.6.2"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"*":["./dist/*.d.ts"]}},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/asyncapi_0.3.0_1789154190550_0.27454163281201427","host":"s3://npm-registry-packages-npm-production"}},"0.3.1":{"_id":"@amritk/asyncapi@0.3.1","bugs":{"url":"https://github.com/amritk/mjst/issues"},"dist":{"shasum":"1d54906b726a94ef986668d5143e9f4a3a9f4a23","tarball":"https://registry.npmjs.org/@amritk/asyncapi/-/asyncapi-0.3.1.tgz","fileCount":40,"integrity":"sha512-tM5V/SPguR6LsGp/+Ju4j3KqOfcPuX/GpkocMuo5LtaGTbRgxrNbpjX8aMQKNUm3go0JkKYhC5rZT3QCvPddHQ==","signatures":[{"sig":"MEYCIQD13057t0piBXFXG2zIMdNUd3+9iqja73KvxdzXkO4uSAIhAN6GJDY6OZuHJtY6C6vA5JPC6+HrF5VdeO+U7/JBdOR7","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDq4PPCOYdkZH0wN8dyURThZfbTMQs7pUBXNv6oRMatSwIgT/WLfSyQ1Ueo6nyO+lkGhoebRQ26uTWHLHcPvhh4BXQ="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@amritk%2fasyncapi@0.3.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":89508},"name":"@amritk/asyncapi","type":"module","author":{"name":"amritk"},"engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","default":"./dist/index.js"},"./package.json":"./package.json"},"gitHead":"b04fd323f07856619c953b43f1d917e58623db8b","license":"MIT","scripts":{"test":"NODE_ENV=production vitest run --root ../.. packages/asyncapi","build":"tsgo -p tsconfig.build.json && tsc-alias -p tsconfig.build.json -f && node ../../scripts/strip-comments.mjs","types:check":"tsgo -p . --noEmit","prepublishOnly":"node ../../scripts/check-publishable.mjs"},"version":"0.3.1","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ad21a913-e642-44f2-92bb-f4249c1f158c"}},"homepage":"https://github.com/amritk/mjst/tree/main/packages/asyncapi#readme","keywords":["asyncapi","json-schema","typescript","codegen","mjst"],"repository":{"url":"git+https://github.com/amritk/mjst.git","type":"git","directory":"packages/asyncapi"},"_npmVersion":"11.19.1","description":"Extract JSON Schemas from AsyncAPI 2.x/3.0 documents for the mjst generators.","directories":{},"maintainers":[{"name":"amritk","email":"amrit@scalar.com"}],"sideEffects":false,"_nodeVersion":"24.20.0","dependencies":{"@amritk/helpers":"^0.22.0","@amritk/adapters":"^0.6.3"},"publishConfig":{"access":"public"},"typesVersions":{"*":{"*":["./dist/*.d.ts"]}},"_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/asyncapi_0.3.1_1789752235670_0.09562059025109404"}}},"time":{"created":"2026-09-08T17:29:34.361Z","modified":"2026-09-18T17:23:56.075Z","0.1.0":"2026-09-08T17:29:34.675Z","0.2.0":"2026-09-08T17:55:37.850Z","0.3.0":"2026-09-11T19:16:30.644Z","0.3.1":"2026-09-18T17:23:55.771Z"},"bugs":{"url":"https://github.com/amritk/mjst/issues"},"author":{"name":"amritk"},"license":"MIT","homepage":"https://github.com/amritk/mjst/tree/main/packages/asyncapi#readme","keywords":["asyncapi","json-schema","typescript","codegen","mjst"],"repository":{"url":"git+https://github.com/amritk/mjst.git","type":"git","directory":"packages/asyncapi"},"description":"Extract JSON Schemas from AsyncAPI 2.x/3.0 documents for the mjst generators.","maintainers":[{"name":"amritk","email":"amrit@scalar.com"}],"readme":"<div align=\"center\">\n\n# @amritk/asyncapi\n\n**Extract JSON Schemas — and `@amritk/api` channel contracts — from AsyncAPI 2.x/3.0 documents.**\n\n![status](https://img.shields.io/badge/status-pre--alpha-ef4444?style=flat-square)&nbsp;\n![version](https://img.shields.io/npm/v/@amritk/asyncapi?style=flat-square&logo=npm&logoColor=white&label=version&color=6366f1)&nbsp;\n![license](https://img.shields.io/badge/license-MIT-22c55e?style=flat-square)&nbsp;\n![AsyncAPI](https://img.shields.io/badge/AsyncAPI-2.x%20%7C%203.0-f97316?style=flat-square)&nbsp;\n![node](https://img.shields.io/badge/node-%E2%89%A520-339933?style=flat-square&logo=node.js&logoColor=white)&nbsp;\n![vibe coded](https://img.shields.io/badge/vibe-coded-a855f7?style=flat-square)\n\n</div>\n\n---\n\n## Overview\n\n`@amritk/asyncapi` walks an AsyncAPI document — 2.0 through 2.6, or 3.0 — and pulls every message's payload and headers out as **self-contained JSON Schema 2020-12 documents**, ready for [`@amritk/generate-parsers`](../generate-parsers), [`@amritk/generate-validators`](../generate-validators), [`@amritk/generate-examples`](../generate-examples), or [`@amritk/runtime-validators`](../runtime-validators). It is the extraction layer behind `mjst --input asyncapi`.\n\nWhat \"self-contained\" buys: the AsyncAPI default schema dialect (a draft-07 superset) is upgraded to 2020-12 conventions, OpenAPI-format payloads get `nullable` folded into their `type`, and every `$ref` into the document's `#/components/schemas/...` is rebased into a local `$defs` with the referenced components copied in transitively — so each extracted schema stands alone as a generator input.\n\nIt also projects each channel onto a [`@amritk/api`](../api) **messages contract**: the two directions AsyncAPI declares become `clientToServer`/`serverToClient`, each message's name becomes its wire discriminator value, and the discriminator property is stripped out of the payload — which is exactly the shape `defineMessages` takes. That projection is what `mjst --input asyncapi --message-contracts` writes to disk.\n\nBoth majors normalize into one 3.0-shaped model. Directions are named from the application's point of view (2.x `publish` → `receive`, `subscribe` → `send`), matching [`@amritk/api`](../api)'s message contracts. An Avro `schemaFormat` is **converted**, not skipped — [`@amritk/adapters`](../adapters) already reads Avro, so those payloads reach the generators like any other. A payload in a language nothing here reads (Protobuf, RAML) is skipped per message with a recorded issue, and so is an Avro schema the converter rejects — one bad payload never costs the document's other messages.\n\n---\n\n## Installation\n\n```bash\nnpm install @amritk/asyncapi\n# or\npnpm add @amritk/asyncapi\n# or\nyarn add @amritk/asyncapi\n# or\nbun add @amritk/asyncapi\n```\n\n---\n\n## Usage\n\n```ts\nimport { extractAsyncApi, listMessageSchemas } from '@amritk/asyncapi'\n\n// Parse the document yourself (JSON.parse, @amritk/yaml, ...) — this package\n// takes the already-parsed value and never touches the filesystem or network.\nconst model = extractAsyncApi(document)\n\nfor (const issue of model.issues) {\n  console.warn(`${issue.path}: ${issue.message}`)\n}\n\nfor (const channel of model.channels) {\n  for (const message of channel.messages) {\n    // message.payload / message.headers are self-contained JSON Schema 2020-12\n    console.log(channel.key, message.name, message.direction)\n  }\n}\n\n// Flatten into generator inputs: one { subDir, rootTypeName, schema } per\n// payload/headers, laid out as channels/<channel>/<message>[-headers].\nconst schemas = listMessageSchemas(model)\n```\n\n### Channel contracts\n\n```ts\nimport { buildChannelContract } from '@amritk/asyncapi'\nimport { defineMessages } from '@amritk/api'\n\nfor (const channel of model.channels) {\n  const contract = buildChannelContract(channel)\n  for (const issue of contract.issues) console.warn(`${issue.path}: ${issue.message}`)\n\n  // The two maps are keyed by the value a frame carries on the wire, payloads\n  // already stripped of the tag — hand them straight to defineMessages.\n  const messages = defineMessages({\n    discriminator: contract.discriminator,\n    clientToServer: contract.clientToServer,\n    serverToClient: contract.serverToClient,\n  })\n}\n```\n\nThe discriminator is resolved in priority order: `x-mjst: { discriminator }` on the channel, then the `discriminator` option, then `'type'` (matching `@amritk/api`'s default). The document wins over the option deliberately — one option covers a whole run, and a run may span channels that disagree.\n\n**The key is the tag, not the name.** A payload usually states its own tag — `type: { const: 'bot_added' }` is how a channel of alternatives says which message is which — and that value becomes the contract key, because it is what actually arrives on the wire. The AsyncAPI message *name* is only the fallback for a payload that pins nothing; it is a document-authoring handle, and 2.x messages inside a `oneOf` frequently have none at all. Slack's RTM document names a message `botAdded` and tags it `bot_added`; keying on the name would emit a contract listening for a frame that never comes.\n\nTwo messages that pin the *same* tag in the *same* direction are one frame shape with two descriptions, so the first wins and the second is reported (Slack declares two messages for its single `bot_added` event). A payload that constrains the tag without pinning it to one string — `type: { type: 'string' }`, a multi-member `enum`, a non-string `const` — names no message the runtime could select, and is skipped with an issue.\n\n**Headers are not part of a contract.** `listMessageSchemas` emits a message's `headers` schema as its own generatable tree, but `buildChannelContract` projects payloads only: `@amritk/api` message contracts describe WebSocket frames, which carry no headers of their own. For a Kafka or MQTT document the headers types are still generated (under `<message>-headers/`) — they are simply yours to apply at the broker boundary, not something the socket runtime validates.\n\nCross-file and remote `$ref`s are the loader's job: resolve them first (for example with [`@amritk/resolve-refs`](../resolve-refs)); a still-unresolved external reference is reported as an issue, never fetched.\n\n---\n\n## API\n\n- **`extractAsyncApi(document, options?)`** → `AsyncApiModel` — the normalized document: `version`, `major`, `title?`, `channels` (each with `key`, `address?`, `messages`), and collected `issues`. Throws only when the input is not an AsyncAPI document at all. `options.avroEncoding` picks which JSON shape an Avro payload describes: `'json'` (default) is the decoded object an application works with, `'avro-json'` is the spec's JSON encoding as it travels on the wire.\n- **`listMessageSchemas(model, issues?)`** → `ExtractedSchema[]` — one `{ subDir, rootTypeName, schema }` per generatable payload/headers, with deterministic collision-suffixed directory tokens; collision issues are appended to `model.issues` (or to the `issues` array you pass).\n- **`buildChannelContract(channel, options?)`** → `ChannelContract` — one channel as `{ exportName, discriminator, clientToServer, serverToClient, issues }`, ready for `defineMessages`.\n- **`resolveDiscriminator(channel, override?)`** / **`DEFAULT_DISCRIMINATOR`** — the priority order above, and the `'type'` fallback.\n- **`stripDiscriminator(payload, discriminator)`** → `{ schema, tag? }` or `{ issue }` — the payload with its tag removed plus the value it pinned the tag to, or why neither could be read.\n- **`sanitizeToken(value, fallback)`** — the filesystem- and import-safe token both output layouts name a channel or message with.\n- **`detectAsyncApiVersion(document)`** — the `asyncapi` version and its major, or `undefined`.\n- **`classifySchemaFormat(schemaFormat)`** — which schema language a `schemaFormat` names (`'asyncapi' | 'draft-07' | '2020-12' | 'openapi' | 'avro'`), or `'unsupported'`.\n- **`mergeTraits(target, traits, precedence)`** — trait application as an RFC 7386 JSON Merge Patch (recursive, so nested contributions from both sides survive); `precedence` is `'trait'` for 2.x (traits override the target) or `'target'` for 3.0 (the target wins). Applied before `schemaFormat` is read.\n\n---\n\n## License\n\nMIT\n","readmeFilename":"README.md"}