{"id":50805820,"url":"https://github.com/pactflow/example-bi-directional-provider-asyncapi","last_synced_at":"2026-06-13T01:04:39.038Z","repository":{"id":360838241,"uuid":"1251863823","full_name":"pactflow/example-bi-directional-provider-asyncapi","owner":"pactflow","description":"Example AsyncAPI project","archived":false,"fork":false,"pushed_at":"2026-05-28T03:42:58.000Z","size":73,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-28T05:12:23.704Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/pactflow.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-28T01:26:38.000Z","updated_at":"2026-05-28T03:23:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/pactflow/example-bi-directional-provider-asyncapi","commit_stats":null,"previous_names":["pactflow/example-bi-directional-provider-asyncapi"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/pactflow/example-bi-directional-provider-asyncapi","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fexample-bi-directional-provider-asyncapi","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fexample-bi-directional-provider-asyncapi/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fexample-bi-directional-provider-asyncapi/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fexample-bi-directional-provider-asyncapi/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pactflow","download_url":"https://codeload.github.com/pactflow/example-bi-directional-provider-asyncapi/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pactflow%2Fexample-bi-directional-provider-asyncapi/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34268195,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-12T02:00:06.859Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-13T01:04:38.375Z","updated_at":"2026-06-13T01:04:39.014Z","avatar_url":"https://github.com/pactflow.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Example: Bi-Directional Contract Testing with AsyncAPI\n\n\u003e **Early access demo** — PactFlow's AsyncAPI support for bi-directional contract\n\u003e testing is not yet publicly available. This demo shows how it works.\n\n## What is this?\n\nThis repository demonstrates how to write **Pact consumer tests for a\nmessage-based service** and verify the provider contract using **PactFlow's\nAsyncAPI bi-directional contract testing (BDCT)** feature.\n\nInstead of running the provider application, BDCT compares the generated Pact\nfile against the provider's **AsyncAPI document**.\n\n### Two messaging patterns are demonstrated\n\n| Pattern | AsyncAPI action | Pact interaction type |\n|---|---|---|\n| **Fire-and-forget** | `receive` | `Asynchronous/Messages` |\n| **Request/Reply** | `send` + `reply` | `Synchronous/Messages` |\n\n---\n\n## Project layout\n\n```\n.\n├── src/\n│   ├── consumer.ts          # User Service event handlers (consumer code)\n│   └── consumer.test.ts     # Pact V4 consumer tests\n├── provider/\n│   └── asyncapi.yaml        # AsyncAPI 3.1.0 document (provider contract)\n├── scripts/\n│   └── verify-provider.mjs  # Runs the comparator against pacts + AsyncAPI doc\n├── pacts/                   # Generated Pact files (git-ignored)\n├── package.json\n└── vitest.config.ts\n```\n\n---\n\n## Quick start\n\n\u003e **Pre-release dependency** — AsyncAPI support in `@pactflow/openapi-pact-comparator`\n\u003e is not yet published to npm. `package.json` references the GitHub main branch.\n\n```bash\n# Install dependencies (includes the pre-release comparator from GitHub)\nnpm install\n\n# Step 1 — run consumer tests → generates ./pacts/UserServiceConsumer-UserService.json\nnpm run test:consumer\n\n# Step 2 — verify the Pact file against the AsyncAPI document\nnpm run verify:provider\n\n# OR, run both sequentially with...\n# npm t\n```\n\n---\n\n## How it works\n\n### Consumer side\n\nThe consumer tests (`src/consumer.test.ts`) use **Pact V4** (`@pact-foundation/pact`)\nto describe the messages the consumer expects.  Each interaction is linked to\nthe relevant **AsyncAPI operation** via the `.reference()` call:\n\n```ts\npact\n  .addAsynchronousInteraction()\n  .reference('AsyncAPI', 'operationId', 'receiveUserEvents')\n  .expectsToReceive('a user-created event', (builder) =\u003e {\n    builder.withJSONContent({ userId: string('u-abc-123'), email: string('...') });\n  })\n  .executeTest(v4SynchronousBodyHandler(handleUserCreated));\n```\n\nRunning the tests writes a Pact file to `./pacts/` with a `comments.references`\nblock that the comparator uses to look up the correct AsyncAPI operation:\n\n```json\n{\n  \"comments\": {\n    \"references\": {\n      \"AsyncAPI\": {\n        \"operationId\": \"receiveUserEvents\",\n      }\n    }\n  }\n}\n```\n\n### Provider side\n\nThe provider only needs to publish its **AsyncAPI document**\n(`provider/asyncapi.yaml`).  No code runs.  The comparator checks that every\ninteraction in the Pact file is compatible with the schema defined in the spec.\n\n```bash\nnpm run verify:provider\n```\n\nThis calls `@pactflow/openapi-pact-comparator` programmatically against:\n- `provider/asyncapi.yaml` — the provider's AsyncAPI spec\n- `pacts/UserServiceConsumer-UserService.json` — the generated consumer contract\n\n---\n\n## AsyncAPI document overview\n\n```mermaid\nflowchart LR\n  consumer[\"UserServiceConsumer\"]\n  provider[\"UserService\"]\n\n  subgraph broker[\"Message broker / logical channels\"]\n    direction TB\n    events([\"user-events\"])\n    requests([\"user-get-requests\"])\n    responses([\"user-get-responses\"])\n  end\n\n  provider -- \"publish lifecycle events\" --\u003e events\n  events -- \"deliver events\" --\u003e consumer\n\n  consumer -- \"send getUserRequest\u003cbr/\u003epayload: userId\" --\u003e requests\n  requests -- \"route request\" --\u003e provider\n\n  provider -- \"send getUserResponse\u003cbr/\u003epayload: userId, name, email\" --\u003e responses\n  responses -- \"deliver reply\" --\u003e consumer\n\n  classDef app fill:#e0f2fe,stroke:#0284c7,stroke-width:2px,color:#0f172a;\n  classDef service fill:#eef2ff,stroke:#6366f1,stroke-width:2px,color:#0f172a;\n  classDef eventStream fill:#fef3c7,stroke:#f59e0b,stroke-width:2px,color:#0f172a;\n  classDef request fill:#e0f2fe,stroke:#06b6d4,stroke-width:2px,color:#0f172a;\n  classDef response fill:#d1fae5,stroke:#10b981,stroke-width:2px,color:#0f172a;\n\n  class consumer app;\n  class provider service;\n  class events eventStream;\n  class requests request;\n  class responses response;\n```\n\nThe `provider/asyncapi.yaml` defines:\n\n- **`userEvents` channel** (`user-events`) — carries `userCreated` and\n  `userDeleted` events consumed by downstream services.\n- **`getUserRequests` / `getUserResponses` channels** — used for synchronous\n  user lookup via request/reply (AsyncAPI 3.x `reply` block).\n\n### Operations\n\n```\nreceiveUserEvents   action: receive   → fire-and-forget events\ngetUser             action: send      → request/reply lookup\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpactflow%2Fexample-bi-directional-provider-asyncapi","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpactflow%2Fexample-bi-directional-provider-asyncapi","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpactflow%2Fexample-bi-directional-provider-asyncapi/lists"}