{"_id":"asyncapi-cable","_rev":"5-a5c8c1e9626edbcc2772f5745c127875","name":"asyncapi-cable","dist-tags":{"latest":"0.3.0"},"versions":{"0.1.0":{"name":"asyncapi-cable","version":"0.1.0","keywords":["asyncapi","anycable","actioncable","codegen","websocket","vue","react"],"license":"MIT","_id":"asyncapi-cable@0.1.0","maintainers":[{"name":"martenk","email":"marten@klitzke.xyz"}],"homepage":"https://github.com/101skills-gmbh/asyncapi-cable#readme","bugs":{"url":"https://github.com/101skills-gmbh/asyncapi-cable/issues"},"bin":{"asyncapi-cable":"bin/cli.mjs"},"dist":{"shasum":"e19c319a90fc5899917222608aa3ddb70556cf33","tarball":"https://registry.npmjs.org/asyncapi-cable/-/asyncapi-cable-0.1.0.tgz","fileCount":6,"integrity":"sha512-OTCbiFlEgugCvCzEze/5NTRXXzV4grGvIgcHKE6/lG1PSlFs6ck/Ms4O53iEJmTVOla9iMRUoCtNkN3RTF3LKw==","signatures":[{"sig":"MEUCIQDQFncBgz/P2QXxr9k8LF93t6nfDAyb8Nl+ztAgxKtk7QIgae6biwLBqGIu+Sd7sGz2kNz7/ykPCUi68hCBswTCHwY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":23041},"type":"module","engines":{"node":">=20"},"exports":{".":{"types":"./src/index.d.mts","default":"./src/index.mjs"}},"gitHead":"401614b036ecc6906f9c869cf822c41d339f52bc","scripts":{"test":"node --test"},"_npmUser":{"name":"martenk","email":"marten@klitzke.xyz"},"repository":{"url":"git+https://github.com/101skills-gmbh/asyncapi-cable.git","type":"git"},"_npmVersion":"11.6.1","description":"Generate typed AnyCable channel clients from an AsyncAPI 3.0 document (Vue + React presets).","directories":{},"_nodeVersion":"24.11.0","dependencies":{"@asyncapi/parser":"^3.6.0","@asyncapi/modelina":"^5.10.1"},"_hasShrinkwrap":false,"peerDependencies":{"vue":">=3.4.0","react":">=18.0.0","@anycable/core":">=1.1.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/asyncapi-cable_0.1.0_1783444264581_0.881239392839928","host":"s3://npm-registry-packages-npm-production"}},"0.2.0":{"name":"asyncapi-cable","version":"0.2.0","keywords":["asyncapi","anycable","actioncable","codegen","websocket","vue","react"],"license":"MIT","_id":"asyncapi-cable@0.2.0","maintainers":[{"name":"martenk","email":"marten@klitzke.xyz"}],"homepage":"https://github.com/101skills-gmbh/asyncapi-cable#readme","bugs":{"url":"https://github.com/101skills-gmbh/asyncapi-cable/issues"},"bin":{"asyncapi-cable":"bin/cli.mjs"},"dist":{"shasum":"eb961659df786230bcc29034d7f0c279e2ec111d","tarball":"https://registry.npmjs.org/asyncapi-cable/-/asyncapi-cable-0.2.0.tgz","fileCount":6,"integrity":"sha512-IgqAxfCoKT09I1wSCvSOekcdVqxCqc4wWOxI7PuLKpwWzhngX30wKPVWaneJQX5+AnBtXIaII+RF12dvS9uW+g==","signatures":[{"sig":"MEYCIQDCOhnQT2NEXpMb30iQ6kYX1td2DwGuVY1JLss/ZDIqjAIhAL80SVSNz6+AkBxzOuhK/7MXjFmPPUT5mTFLvUtZZxqm","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/asyncapi-cable@0.2.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":27240},"type":"module","engines":{"node":">=20"},"exports":{".":{"types":"./src/index.d.mts","default":"./src/index.mjs"}},"gitHead":"d5156a1143d8b7f7236eaaaa0768cad624990882","scripts":{"test":"node --test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:2d79b9a8-3784-46bf-a017-d67c819ab1ec"}},"repository":{"url":"git+https://github.com/101skills-gmbh/asyncapi-cable.git","type":"git"},"_npmVersion":"12.0.2","description":"Generate typed AnyCable channel clients from an AsyncAPI 3.0 document (Vue + React presets).","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@asyncapi/parser":"^3.6.0","@asyncapi/modelina":"^5.10.1"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.1","peerDependencies":{"vue":">=3.4.0","react":">=18.0.0","@anycable/core":">=1.1.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/asyncapi-cable_0.2.0_1785494363849_0.487038775746236","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"asyncapi-cable","version":"0.2.1","keywords":["asyncapi","anycable","actioncable","codegen","websocket","vue","react"],"license":"MIT","_id":"asyncapi-cable@0.2.1","maintainers":[{"name":"martenk","email":"marten@klitzke.xyz"}],"homepage":"https://github.com/101skills-gmbh/asyncapi-cable#readme","bugs":{"url":"https://github.com/101skills-gmbh/asyncapi-cable/issues"},"bin":{"asyncapi-cable":"bin/cli.mjs"},"dist":{"shasum":"3589a3870f068457be9a726d5c91988ff0ea0395","tarball":"https://registry.npmjs.org/asyncapi-cable/-/asyncapi-cable-0.2.1.tgz","fileCount":6,"integrity":"sha512-LSSv4j6RP0qoFEnVL3S798GKnUv5buHTRtT/DGdUBCg12fJBxzGt/FyQipc0PS+3XxOcV47KB6XyZjKVJjM8tQ==","signatures":[{"sig":"MEUCIEhpzueNp343Kot0bQQJ0NgswphjSHpiMlwRU0e4erdRAiEAscr9i9kgxFpvmTQ56+D8/BXIBOaLH02bQZOn2aXUheY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/asyncapi-cable@0.2.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":27240},"type":"module","engines":{"node":">=20"},"exports":{".":{"types":"./src/index.d.mts","default":"./src/index.mjs"}},"gitHead":"ab8d0f243acbf93b09ae26e52b7ae20c68bd6276","scripts":{"test":"node --test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:2d79b9a8-3784-46bf-a017-d67c819ab1ec"}},"repository":{"url":"git+https://github.com/101skills-gmbh/asyncapi-cable.git","type":"git"},"_npmVersion":"12.0.2","description":"Generate typed AnyCable channel clients from an AsyncAPI 3.0 document (Vue + React presets).","directories":{},"_nodeVersion":"24.18.0","dependencies":{"@asyncapi/parser":"^3.6.0","@asyncapi/modelina":"^5.10.1"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.1","peerDependencies":{"vue":">=3.4.0","react":">=18.0.0","@anycable/core":">=1.1.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/asyncapi-cable_0.2.1_1785494918056_0.3046102768216017","host":"s3://npm-registry-packages-npm-production"}},"0.2.3":{"name":"asyncapi-cable","version":"0.2.3","keywords":["asyncapi","anycable","actioncable","codegen","websocket","vue","react"],"license":"MIT","_id":"asyncapi-cable@0.2.3","maintainers":[{"name":"martenk","email":"marten@klitzke.xyz"}],"homepage":"https://github.com/openapi-ruby/asyncapi-cable#readme","bugs":{"url":"https://github.com/openapi-ruby/asyncapi-cable/issues"},"bin":{"asyncapi-cable":"bin/cli.mjs"},"dist":{"shasum":"a1729c5475ca84d102b8af997692fcad7ceea257","tarball":"https://registry.npmjs.org/asyncapi-cable/-/asyncapi-cable-0.2.3.tgz","fileCount":6,"integrity":"sha512-CCJKElF1t12glZAmElNNmmz2TRm/VvLYhw1zhGcynn5qGn/PIxmq6qVhh73zV9RPYNGGjElXb11UThONAz/WhQ==","signatures":[{"sig":"MEUCIQD1Fc7b321us3xKV6aGM/nYAABz3KnQNTKWEmZ3D0T8ggIgcG/Txg8cGNKNy9YAoZTxap0MgY6pEbgHKAicTJ3Mkyw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/asyncapi-cable@0.2.3","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":30771},"type":"module","engines":{"node":">=20"},"exports":{".":{"types":"./src/index.d.mts","default":"./src/index.mjs"}},"gitHead":"597b1a934f6470db76bc830531c3661c151cdfbe","scripts":{"test":"node --test"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:47fa661b-16ca-46c2-979c-5373d57f4693"}},"repository":{"url":"git+https://github.com/openapi-ruby/asyncapi-cable.git","type":"git"},"_npmVersion":"12.0.2","description":"Generate typed AnyCable channel clients from an AsyncAPI 3.0 document (Vue + React presets).","directories":{},"_nodeVersion":"24.19.0","dependencies":{"@asyncapi/parser":"^3.6.0","@asyncapi/modelina":"^5.10.1"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.1","peerDependencies":{"vue":">=3.4.0","react":">=18.0.0","@anycable/core":">=1.1.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"tmp":"tmp/asyncapi-cable_0.2.3_1787751745894_0.12874825013347224","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"_id":"asyncapi-cable@0.3.0","bin":{"asyncapi-cable":"bin/cli.mjs"},"bugs":{"url":"https://github.com/openapi-ruby/asyncapi-cable/issues"},"dist":{"shasum":"16700d7793dd3214a802ab454e8113be151ad8ca","tarball":"https://registry.npmjs.org/asyncapi-cable/-/asyncapi-cable-0.3.0.tgz","fileCount":6,"integrity":"sha512-wB+TBiczhsHTHKzHTfpRivxMeU34KE+EpfwDNRbxdvpsOrwqR6HRIJHHPlpWLTjujnAdW1k1TjYnq8KQUIbAug==","signatures":[{"sig":"MEQCIFm9lv9eKRXHDgigOfEl96T6d/Id/rYEHB7QOo3kPz3qAiA2vZiRBrkl6hFGL0aHdpj49fEBrgAvXRDK7PZ1LUiZlA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDB/CBBaVccueUoGiNcDemzdHK9sOtJf+qaIwMT3PnURgIgUdpr2pE/kdnQ2bJmmTNQAtIKuRKZ6Adz/AASclzwL+Y="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/asyncapi-cable@0.3.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":42760},"name":"asyncapi-cable","type":"module","engines":{"node":">=20"},"exports":{".":{"types":"./src/index.d.mts","default":"./src/index.mjs"}},"gitHead":"10884b3f740f8800df5d6a39c3c4b0bc8e5c2f2d","license":"MIT","scripts":{"test":"node --test"},"version":"0.3.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:47fa661b-16ca-46c2-979c-5373d57f4693"}},"homepage":"https://github.com/openapi-ruby/asyncapi-cable#readme","keywords":["asyncapi","anycable","actioncable","codegen","websocket","vue","react"],"repository":{"url":"git+https://github.com/openapi-ruby/asyncapi-cable.git","type":"git"},"_npmVersion":"12.0.2","description":"Generate typed AnyCable channel clients from an AsyncAPI 3.0 document (Vue + React presets).","directories":{},"maintainers":[{"name":"martenk","email":"marten@klitzke.xyz"}],"_nodeVersion":"24.20.0","dependencies":{"@asyncapi/parser":"^3.6.0","@asyncapi/modelina":"^5.10.1"},"_hasShrinkwrap":false,"packageManager":"pnpm@10.28.1","peerDependencies":{"vue":">=3.4.0","react":">=18.0.0","@anycable/core":">=1.1.0"},"peerDependenciesMeta":{"vue":{"optional":true},"react":{"optional":true}},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/asyncapi-cable_0.3.0_1789388221610_0.15079508820328336"}}},"time":{"created":"2026-07-07T17:11:04.539Z","modified":"2026-09-14T12:17:02.027Z","0.1.0":"2026-07-07T17:11:04.764Z","0.2.0":"2026-07-31T10:39:23.982Z","0.2.1":"2026-07-31T10:48:38.197Z","0.2.3":"2026-08-26T13:42:26.040Z","0.3.0":"2026-09-14T12:17:01.706Z"},"bugs":{"url":"https://github.com/openapi-ruby/asyncapi-cable/issues"},"license":"MIT","homepage":"https://github.com/openapi-ruby/asyncapi-cable#readme","keywords":["asyncapi","anycable","actioncable","codegen","websocket","vue","react"],"repository":{"url":"git+https://github.com/openapi-ruby/asyncapi-cable.git","type":"git"},"description":"Generate typed AnyCable channel clients from an AsyncAPI 3.0 document (Vue + React presets).","maintainers":[{"name":"martenk","email":"marten@klitzke.xyz"}],"readme":"<p align=\"center\">\n  <img src=\"logo.png\" alt=\"asyncapi-cable\" width=\"200\">\n</p>\n\n<h1 align=\"center\">asyncapi-cable</h1>\n\n<p align=\"center\">\n  Generate typed <a href=\"https://docs.anycable.io\">AnyCable</a> channel clients from an\n  <strong>AsyncAPI 3.0</strong> document. Produces platform-agnostic channel classes +\n  message types (usable on web <em>and</em> React Native) plus a thin, framework-specific\n  wrapper (Vue composables or React hooks).\n</p>\n\nThe \"[Orval](https://orval.dev) for cable\" — point it at your AsyncAPI cable\ndocument and get end-to-end typed real-time clients, the same way Orval turns an\nOpenAPI spec into a typed REST client.\n\n## Two packages, one contract\n\nThis repository ships both ends of the cable contract:\n\n| Package | Path | What it does |\n|---------|------|--------------|\n| npm **`asyncapi-cable`** | `/` | Generates typed AnyCable clients *from* an AsyncAPI 3 document |\n| gem **`asyncapi_cable`** | [`ruby/`](ruby) | Generates that document *from* your Rails ActionCable channels, and validates broadcast payloads against it at runtime |\n\nThey are released independently — the gem writes the document, the npm package\nconsumes it — and neither requires the other. The gem pairs with\n[`openapi-ruby`](https://github.com/openapi-ruby/openapi-ruby), sharing its\nschema-component registry so one component can appear in both the OpenAPI and\nthe AsyncAPI document.\n\n## Key Features\n\n- **AsyncAPI 3.0 → typed AnyCable clients** — channel classes + message payload types generated from your cable document\n- **Platform-agnostic core** — the channel classes + models depend only on `@anycable/core`, so they run on web *and* React Native\n- **Vue & React presets** — per-target `preset` emits Vue composables (`onScopeDispose`) or React hooks (`useEffect`); only the runtime + wrapper differ\n- **Typed payloads** — message types generated via [`@asyncapi/modelina`](https://github.com/asyncapi/modelina), preserving snake_case wire keys\n- **Typed payloads behind a JSON string** — a `payload` declared as a string with `contentSchema` gets its decoded model generated plus a `parseXPayload` helper, so the cast lives in one place instead of at every call site\n- **Single cable seam** — only `runtime.ts` imports your AnyCable instance ([Orval-mutator](https://orval.dev/guides/custom-client) style), configurable per target\n- **Multi-target config** — one `cable.config.mjs` (analog of `orval.config.ts`) generates many documents at once\n- **Vendor extensions** — `x-actioncable-channel` maps to the Rails channel identifier; `x-client-supplied: false` marks server-derived params\n\n## Requirements\n\n- Node >= 20\n- An AsyncAPI 3.0 cable document\n- In the consuming app: `@anycable/core`, plus `vue` (vue preset) or `react` (react preset)\n\n## Install\n\n```bash\npnpm add -D asyncapi-cable\n# the generated code imports these in the consuming app:\npnpm add @anycable/core        # + vue (vue preset) or react (react preset)\n```\n\n## Usage\n\nAdd a `cable.config.mjs` (analog of `orval.config.ts`):\n\n```js\nexport default {\n  cableInternalV1: {\n    input: \"asyncapi/cable_internal.yaml\",\n    output: {\n      target: \"src/services/cableInternalV1\",\n      // the \"mutator\": a file exporting your AnyCable instance getter\n      cable: { path: \"../cableClient\", name: \"getCable\" },\n      preset: \"vue\", // or \"react\"\n    },\n  },\n};\n```\n\nThen run:\n\n```bash\npnpm exec asyncapi-cable -c cable.config.mjs\n```\n\nThe config is a map of *target name* → target. Each target:\n\n| Key | Required | Description |\n|-----|----------|-------------|\n| `input` | ✓ | Path to a local AsyncAPI 3.0 document (resolved from the cwd), or an `http(s)` URL to fetch it from (e.g. a backend that serves the contract) |\n| `output.target` | ✓ | Directory for the generated code — **wiped and rebuilt** on each run |\n| `output.cable.path` | | Import path (from `runtime.ts`) to the file exporting your AnyCable getter |\n| `output.cable.name` | | Named export of that getter (defaults to a built-in seam if `cable` is omitted) |\n| `output.preset` | | `\"vue\"` (default) or `\"react\"` |\n| `output.enumType` | | `\"enum\"` (default) or `\"union\"` — see [Enums](#enums) |\n\n## What it emits\n\n```\n<output.target>/\n  models/*.ts        message payload types + enums (via @asyncapi/modelina)\n  channels/*.ts      class XChannel extends Channel<Params, Message>\n                     — depends ONLY on @anycable/core (web + React Native)\n  runtime.ts         the preset's subscribe/lifecycle helper — the ONLY file\n                     importing your cable mutator (output.cable)\n  composables/*.ts   per-channel useXChannel(handlers)  (Vue composable / React hook)\n  index.ts           barrel\n```\n\nThe channel classes and message types are **shared across presets**; only\n`runtime.ts` and the per-channel wrapper differ (`vue` → composable with\n`onScopeDispose`; `react` → hook with `useEffect`).\n\n### Enums\n\nBy default an enum is a TypeScript `enum`. An enum member is *nominal*, though,\nand a cable message is usually the same component a REST schema documents — so\n`StatusEnum.STARTED` from these models is **not** assignable to the literal\nunion an OpenAPI client (Orval, openapi-typescript, …) generates for the very\nsame values, and every payload handed on to code typed by that client needs a\ncast. Set `output.enumType: \"union\"` to emit\n\n```ts\ntype StatusEnum = \"started\" | \"finished\";\n```\n\ninstead, and the two generated worlds share their types. Model files then import\ntheir siblings with `import type`, since nothing they declare is a value.\n\n### The cable mutator\n\n`output.cable` points at a file in your app that exports the AnyCable instance\n(the one seam the generated code imports), e.g.:\n\n```ts\n// src/cableClient.ts\nimport { createCable } from \"@anycable/web\"; // or @anycable/core in React Native\nlet cable;\nexport function getCable() {\n  return (cable ??= createCable(/* url */));\n}\n```\n\n## Document extensions\n\nThe generator reads two vendor extensions from the AsyncAPI document:\n\n- `x-actioncable-channel` on a channel → the Rails channel class name used as\n  the AnyCable `static identifier`.\n- `x-client-supplied: false` on a parameter → server-derived, so it's omitted\n  from the channel's client-supplied params.\n\n## Programmatic API\n\n```js\nimport { generateAll, generateOne } from \"asyncapi-cable\";\nawait generateAll(config, process.cwd());\n```\n\n## Requirements\n\nNode >= 20. AsyncAPI 3.0 input.\n\n## Releasing\n\nReleases are automated with\n[release-please](https://github.com/googleapis/release-please). Land commits on\n`main` using [Conventional Commits](https://www.conventionalcommits.org)\n(`feat:` → minor, `fix:` → patch); release-please opens a \"release\" PR that bumps\nthe version and updates the changelog. Merging that PR tags the release and\npublishes to npm — no stored `NPM_TOKEN`; publishing uses npm\n[Trusted Publishing](https://docs.npmjs.com/trusted-publishers) via GitHub\nActions OIDC.\n\n### Merge queue\n\n`ci.yml` listens on `merge_group` as well as `pull_request`. A queued entry is\ntested against a merge-group ref, so a required check that only runs on\n`pull_request` never reports there and the entry is dropped when the queue's\ncheck timeout expires.\n\n### Component scoping\n\nThe root package covers the npm generator and the `ruby` package covers the\ngem. A package path of `.` matches every commit, so the root entry carries\n`exclude-paths: [\"ruby\"]` — without it, a gem-only change would also cut an npm\nrelease with a changelog full of Ruby entries.\n\n`last-release-sha` marks where the gem was imported. The commits that came in\nwith `git subtree` carry root-level paths from before the import, so the root\npackage would otherwise keep proposing a release for changes that never\ntouched the npm side — and `exclude-paths` cannot filter them, because those\npaths really were at the root when the commits were written.\n\n### Repository settings this depends on\n\nThe `openapi-ruby` organization does not let `GITHUB_TOKEN` open pull requests,\nso release-please authenticates with a **`RELEASE_PLEASE_TOKEN`** repository\nsecret (a PAT with `contents` + `pull-requests` write). Without it the release\njob runs and quietly raises no release PR. Repository settings do **not**\nsurvive a transfer between organizations — after a move, re-check this secret,\nthe branch ruleset, and both trusted publishers.\n\n### npm\n\nTrusted Publishing can only be configured on a package that already exists on\nnpm, so the **first** publish must be done manually:\n\n```bash\nnpm publish --access public\n```\n\nThen, on the package's npm page → **Settings → Publishing access**, add a\nGitHub Actions trusted publisher:\n\n- Organization/user: `openapi-ruby`\n- Repository: `asyncapi-cable`\n- Workflow filename: `release-please.yml`\n- Environment: *(leave blank)*\n\nAfter this, every merged release PR publishes automatically.\n\nIf a publish job was skipped but the release and tag exist, run the **Release**\nworkflow manually and pick the package under `publish` — that republishes the\ntagged version instead of forcing a new one.\n\n### RubyGems\n\nNo manual first push: RubyGems supports a **pending** trusted publisher for a\ngem that does not exist yet. Create it at\n[rubygems.org/profile/oidc/pending_trusted_publishers](https://rubygems.org/profile/oidc/pending_trusted_publishers):\n\n- Gem name: `asyncapi_cable`\n- Repository owner: `openapi-ruby`\n- Repository name: `asyncapi-cable`\n- Workflow filename: `release-please.yml`\n- Environment: `rubygems`\n\nThe first successful push from that workflow creates the gem and converts the\nentry into a normal trusted publisher.\n\nA trusted publisher is bound to one `organization/repository` pair, so\n**transferring the repository invalidates it** on both registries — automated\npublishing fails until each entry is pointed at the new owner.\n\nA trusted publisher is bound to one `organization/repository` pair, so\n**transferring the repository invalidates it** — automated publishing fails\nuntil the entry is pointed at the new owner. Update it on the npm package page\nin the same sitting as the transfer.\n\n## License\n\nMIT\n","readmeFilename":"README.md"}