{"id":25644511,"url":"https://github.com/ttab/amqp-as-promised","last_synced_at":"2025-09-11T11:34:41.305Z","repository":{"id":462438,"uuid":"14896083","full_name":"ttab/amqp-as-promised","owner":"ttab","description":null,"archived":false,"fork":false,"pushed_at":"2025-01-20T12:35:24.000Z","size":429,"stargazers_count":20,"open_issues_count":9,"forks_count":3,"subscribers_count":24,"default_branch":"master","last_synced_at":"2025-08-14T05:49:19.984Z","etag":null,"topics":["backend","coffee","library","mocha"],"latest_commit_sha":null,"homepage":"","language":"CoffeeScript","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/ttab.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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}},"created_at":"2013-12-03T14:34:43.000Z","updated_at":"2025-01-20T12:35:26.000Z","dependencies_parsed_at":"2024-06-18T22:53:38.773Z","dependency_job_id":"dafd3f48-3132-48cc-a4b0-cc7c04c25775","html_url":"https://github.com/ttab/amqp-as-promised","commit_stats":{"total_commits":295,"total_committers":8,"mean_commits":36.875,"dds":0.4,"last_synced_commit":"74eada64b6099aea99668a704859b18982475f24"},"previous_names":[],"tags_count":59,"template":false,"template_full_name":null,"purl":"pkg:github/ttab/amqp-as-promised","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttab%2Famqp-as-promised","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttab%2Famqp-as-promised/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttab%2Famqp-as-promised/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttab%2Famqp-as-promised/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ttab","download_url":"https://codeload.github.com/ttab/amqp-as-promised/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ttab%2Famqp-as-promised/sbom","scorecard":{"id":901347,"data":{"date":"2025-08-11","repo":{"name":"github.com/ttab/amqp-as-promised","commit":"64196f4cece7fcdd951b4f93342ee635ccc94188"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:12: update your workflow using https://app.stepsecurity.io/secureworkflow/ttab/amqp-as-promised/test.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:13: update your workflow using https://app.stepsecurity.io/secureworkflow/ttab/amqp-as-promised/test.yml/master?enable=pin","Warn: npmCommand not pinned by hash: .github/workflows/test.yml:17","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   1 npmCommand dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-mwcw-c2x4-8c55","Warn: Project is vulnerable to: GHSA-9wv6-86v2-598j","Warn: Project is vulnerable to: GHSA-76p7-773f-r4q5"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-24T15:41:16.895Z","repository_id":462438,"created_at":"2025-08-24T15:41:16.896Z","updated_at":"2025-08-24T15:41:16.896Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274625394,"owners_count":25319880,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-11T02:00:13.660Z","response_time":74,"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":["backend","coffee","library","mocha"],"created_at":"2025-02-23T08:18:08.330Z","updated_at":"2025-09-11T11:34:41.282Z","avatar_url":"https://github.com/ttab.png","language":"CoffeeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"AMQP as Promised\n================\n\n![Version](http://img.shields.io/npm/v/amqp-as-promised.svg) \u0026nbsp;\n![License](http://img.shields.io/npm/l/amqp-as-promised.svg) \u0026nbsp;\n![Monthly downloads](http://img.shields.io/npm/dm/amqp-as-promised.svg) \u0026nbsp;\n![Build Status](https://ci2.tt.se/buildStatus/icon\\?job\\=ttab/amqp-as-promised/master)\n\nA high-level [promise-based](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises) API built on\n[`amqplib`](https://www.npmjs.com/package/amqplib)\nextended with functions for AMQP-based RPC.\n\n* [`amqplib` API docs][amqplib-api-docs]\n* Old versions of this package were based on [node-amqp][npm-node-amqp].\n\n  [amqplib-api-docs]: http://www.squaremobius.net/amqp.node/channel_api.html\n  [npm-node-amqp]: https://github.com/postwait/node-amqp\n\n## Table of contents\n\n * [Configuration](#configuration)\n * [Examples](#examples)\n * [API](#api)\n   * [The amqpc object](#the-amqpc-object)\n   * [The exchange object](#the-exchange-object)\n   * [The queue object](#the-queue-object)\n   * [RPC functions](#rpc-functions)\n * [Changelog](CHANGELOG.md)\n\n## Version Notes\n\n#### 5.0\n\nSyntax to access the library has been changed in 5.0 to improve\nconnection management. See the [Running](#running)-section for\ninstructions.\n\n#### 3.0\n\nThe underlying amqp library was changed from\n`node-amqp` to `amqplib`. Efforts have been made to keep everything as\nbackwards compatible as possible, but some things have changed:\n\n * Local mode is no longer supported.\n * `queue.shift()` is no longer supported.\n * `Q` has been dropped in favor of native promises. As a result,\n   support for promise progress notifications over RPC is no longer\n   supported.\n\n## Installing\n\n`npm install amqp-as-promised`\n\n## Running\n\n5.0+\n```coffee\n    conf = require './myconf.json' # see example conf below\n    ((require 'amqp-as-promised') conf.amqp).then (amqpc) -\u003e\n```\n\nEarlier versions\n```coffee\n    conf = require './myconf.json' # see example conf below\n    amqpc = (require 'amqp-as-promised') conf.amqp\n```\n\n## Configuration\n\nAs of version 0.1.0, the following config parameters are accepted,\nalthough we also try to keep backwards compatibility with the older\nformat.\n\n### `connection`\n\nConnection settings accepted by\n[node-amqp](https://github.com/postwait/node-amqp#connection-options-and-url). You\nneed to at minimum specify either\n* `host`\n* `vhost`\n* `login`\n* `password`\n\nor\n* `url`.\n\n### `rpc`\n\n* `timeout`: timeout in ms for rpc calls. Default: 1000ms\n\n\n### `publisherConfirm`\n\n*Since 5.7.0*\n\n * `publisherConfirm`: boolean that enables or disables the RabbitMQ\n    [Publisher Confirms](https://www.rabbitmq.com/docs/confirms) extension.\n    Default: false.\n\n### `logLevel`\n\n* `logLevel`: sets the log level. Defaults to `INFO`. Possible levels\n  are `DEBUG`, `INFO`, `WARN`, `ERROR`\n\n### `errorHandler`\n\n*Since 2.0.0* connection errors are rethrown to crash process. \n\n* `errorHandler`: sets a handler function to receive the error instead\nof throwing to process. This option is deprecated, as a better way to\ndo this is to attach an `error` event handler.\n\n### `waitForConnection`\n\n*Since 4.1.0*\n\n* `waitForConnection`: on startup, keeps retrying to connect until\n  successful. Will not attempt reconnect after established connection.\n\n## Example config\n\n    {\n        \"connection\": {\n            \"host\": \"192.168.0.10\",\n            \"vhost\": \"test\",\n            \"login\": \"test\",\n            \"password\": \"supersecret\"\n        },\n        \"publisherConfirm\": true,\n        \"logLevel\": \"warn\",\n        \"rpc\": {\n            \"timeout\": 2000\n        }\n    }\n\nOr with url:\n\n\n    {\n        \"connection\": {\n            \"url\": \"amqp://myuser:supersecret@192.168.0.10/test\"\n        },\n        \"logLevel\": \"warn\"\n    }\n\n\nEvents\n=======\n\nAmqp-as-promised emits `error` events on unexpected network errors,\nfor example then the connection to the server has been lost. It is up\nto the client to handle these errors, as amqp-as-promised doesn't\nreconnect automatically. Keep in mind that error recovery can be\ntricky, and the best option might be to just crash and restart the\napplication on error.\n\nThis is a simple but effective error handler:\n\n```coffee\namqpc.on 'error', (err) -\u003e\n    console.log err\n    process.exit 1\n```\n\n## Unhandled errors\n\nIf there are no error handlers attached (either using `amqp.on()` or\nsetting the `errorHandler` in the configuration), amqp-as-promised\nwill as a last resort throw the error. This will most likely result in\nan application crash unless there is an uncaught exception handler set\non the `process`.\n\nExamples\n==========\n\n## Using `amqpc` to publish\n\n```coffee\namqpc.exchange('myexchange').then (ex) -\u003e\n    msg = {}\n    msg.domain = domain\n    ex.publish('mytopic.foo', msg).then -\u003e\n        console.log 'published message!'\n```\n\n## Using `amqpc` to bind\n\nThis is shorthand for binding and subscribing.\n\n```coffee\namqpc.bind 'myexchange', 'myqueue', 'mytopic.#', (msg, headers, del) -\u003e\n    console.log 'received message', msg\n```\n\nTo bind an anonymous queue.\n\n    amqpc.bind 'myexchange', '', 'mytopic.#', (msg, headers, del) -\u003e\n        console.log 'received message', msg\n\nOr even shorter\n\n```coffee\namqpc.bind 'myexchange', 'mytopic.#', (msg, headers, del) -\u003e\n    console.log 'received message', msg\n```\n\nTo bind the queue to the exchange without subscribing to it, skip the\nlast parameter (the subscription callback). This is essentially the\nsame as `queue.bind myexchange, 'mytopic'`, except the exchange and\nqueue are specified by their names:\n\n```coffee\namqpc.bind 'myexchange', 'myqueue', 'mytopic.#'\n```\n\n## Using `amqpc` to get an anomymous queue\n\nTo create an anomymous queue.\n\n```coffee\namqpc.queue().then (q) -\u003e console.log 'my queue', q\n```\n\n## Using `amqpc` to do RPC-style calls\n\nto send a message to a service that honors the replyTo/correlationId contract:\n\n\n```coffee\namqpc.rpc('myexchange', 'routing.key', msg, [headers], [options]).then (response) -\u003e\n    console.log 'received message', response\n```\n\n * `headers` is an optional parameter holding any custom headers to be\n   passed on the RPC service.\n * `options` supports the following settings\n   - `timeout` - the timeout in ms for this call\n\n\n\n*Note!* In earlier versions the response was an array that included\n the response headers. As of version 0.1.0, this is no longer the case.\n\n## Using `amqpc` to serve RPC-style calls\n\nTo set up a message consumer that automatically honors the\nreplyTo/correlationId contract:\n\n```coffee\namqpc.serve 'myexchange', 'mytopic.#', (msg, headers, del) -\u003e\n    return { result: 'ok' }\n```\n\nThe value returned from the handler will be sent back on the queue\nspecified by the `replyTo` header, with the `correlationId` set.\n\nIf an exception is thrown by the handler, it will be propagated back\nto the client as an object:\n```\n{\n  \"error\": {\n    \"message\": \u003cexception.message\u003e,\n    [ \"code\": \u003cexception.code\u003e, ]\n    [ \"errno\": \u003cexception.errno\u003e ]\n  }\n}\n```\n\n### Serve with prefetchCount/ack\n\nTo rate limit the rpc calls to 5 concurrent, we use an options object\nto set `{ack:true, prefetchCount:5}`.\n\nNotice that the message acking is handled by the rpc backend wrapper.\n\n```coffee\namqpc.serve 'myexchange', 'mytopic.#', {ack:true, prefetchCount:5}, (msg, headers, del) -\u003e\n    return { result: 'ok' }\n```\n\n## Shutting down\n\n```coffee\ngraceful = (opts) -\u003e\n    log.info 'Shutting down'\n    amqpc.shutdown().then -\u003e\n        process.exit 0\n\nprocess.on 'SIGINT', graceful\nprocess.on 'SIGTERM', graceful\n```\n\nAPI\n===\n\n## The `amqpc` object\n\n### `amqpc.on(event, handler)`\n\nAttach an event handler. Currently only `error` events are supported.\n\n### `amqpc.exchange(name, opts)`\n\nA promise for an exchange. If `opts` is omitted, then `passive:true`\nis assumed.\n\n### `amqpc.queue(qname, opts)`\n\nA promise for a queue. If `qname` is omitted, `\"\"` is used. If opts is\nomitted, then `exclusive:true` is assumed if the name is empty, or\n`passive:true` if not.\n\nThus, `amqpc.queue()` will create a new exclusive, anonymous, queue\nthat is automatically deleted on disconnect, while\n`amqpc.queue('my-queue')` will try to passively declare the existing\nqueue `my-queue`.\n\nSee [`queue.*`](#the-queue-object) below.\n\n### `amqpc.bind(exchange, queue, topic[, callback])`\n\nShorthand for\n\n1. If `exchange` is a string, then look up the existing exchange with\n   that name.\n2. If `queue` is a string, then look up the existing queue with that name.\n3. Bind queue to `exchange/topic`.\n4. Subscribe `callback` to queue (optional).\n\n#### Parameters\n\n * `exchange` - an exchange object or a string with the name of an\n   exchange\n * `queue` - a queue object or a string with the name of a queue\n * `topic` - a string with the topic name.\n * `callback` - see `queue.subscribe` below.\n\n\n### `amqpc.shutdown()`\n\nWill unbind all queues and unsubscribe all callbacks then gracefully\nshut down the socket connection.\n\n## The `exchange` object\n\n### `exchange.publish(routingKey, msg, options)`\n\nPublishes a message, returning a promise.\n\n## The `queue` object\n\n### `queue.bind(exchange, topic)`\n\nBinds the queue to the given exchange (object, or string). Will unbind\nif queue was already bound.\n\n### `queue.unbind()`\n\nUnbinds the queue (if currently bound).\n\n### `queue.subscribe(opts, callback)`\n\nSubscribes the callback to this queue. Will unsubscribe any previous\ncallback. If opts is omitted, defaults to `ack: false, prefetchCount: 1`\n\nThe callback will be called with arguments `(msg, headers, deliveryinfo,\nactions)`, where `actions` is an object that holds these methods:\n\n  * `acknowledge()`: returns a Promise to acknowledge the message. This is\n    only relevant if `opts.ack` is false (which is the default).\n\n### `queue.unsubscribe()`\n\nUnsubscribes current callback (if any).\n\n### `queue.name`\n\nRead only property with the queue name.\n\n## RPC functions\n\n### `amqpc.rpc(exchange, routingKey, msg, [headers], [options])`\n\nPerform an AMQP-based remote procedure call, and returns a promise for\nthe return value:\n\n 1. Creates an exlusive, anonymous, return queue if doesn't already\n    exist.\n 2. Publishes an RPC-style message on the given `exchange`, with the\n    specified `routingkey`, `headers` and `options`. The `replyTo` and\n    `correlationId` headers are set automatically.\n 3. Waits for a reply on the return queue, and resolves the promise\n    with the contents of the reply. If no reply is received before the\n    timeout, the promise is instead rejected. Replies that are JSON\n    objects that have an `error` property set are assumed to be remote\n    errors, and will result in a rejected promise.\n\n#### Parameters\n\n * `exchange` - the name of an exchange, or an exchange object\n * `routingkey`\n * `headers` - AMQP headers to be sent with the message. See [exchange.publish()](#exchangepublishroutingkey-msg-options).\n * `options` - valid options are:\n   + `timeout` - timeout in milliseconds. If none is specified, the\n     default value specified when creating the client is used.\n   + `compress` - set to `true` to use [payload compression](#compression)\n\n### Compression\n\n*Since 0.4.0*\n\nThe RPC mechanism has a transparent payload gzip compression of JSON\nobjects Buffer. When activated both request and response are\ncompressed. To activate, the rpc client must ask for compression by setting\nthe `compress` option.\n\nExample\n\n```coffee\namqpc.rpc('myexchange', 'routing.key', msg, [headers], {compress:true}).then (response) -\u003e\n    console.log 'received message', response\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttab%2Famqp-as-promised","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fttab%2Famqp-as-promised","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fttab%2Famqp-as-promised/lists"}