UNPKG

fastify-rabbitmq

Version:

A Fastify RabbitMQ Plugin Developed in Pure TypeScript.

1 lines 10.1 kB
{"version":3,"file":"index.cjs","names":["RabbitMQConnection"],"sources":["../src/errors.ts","../src/validation.ts","../src/index.ts"],"sourcesContent":["/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport createError from \"@fastify/error\";\n\nexport const errors = {\n /** Error if there is an invalid option used during registration. */\n FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS: createError(\n \"FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS\",\n \"Invalid options: %s\",\n ),\n /** Error if there is an setup error of the plugin itself. */\n FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS: createError(\n \"FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS\",\n \"Setup error: %s\",\n ),\n /** If an invalid usage error was done, this error would pop up. */\n FASTIFY_RABBIT_MQ_ERR_USAGE: createError(\n \"FASTIFY_RABBIT_MQ_ERR_USAGE\",\n \"Usage error: %s\",\n ),\n};\n","/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport { FastifyRabbitMQOptions } from \"./decorate\";\nimport { errors } from \"./errors\";\n\n/**\n * Validate Options\n *\n * The plugin validates only the *shape* of `connection` -- that it is a\n * non-empty connection string or a `ConnectionOptions` object. Parsing the URL\n * and validating the broker options (hosts, TLS, reconnect, etc.) is delegated\n * to `rabbitmq-client`. The shape guard exists because `new Connection(...)`\n * accepts garbage (a number, an array, `null`, `{}`) without throwing and then\n * silently fails to connect at runtime; rejecting it here surfaces a clear\n * registration-time error instead.\n * @since 1.0.0\n * @param options\n */\nexport const validateOpts = async (\n options: FastifyRabbitMQOptions,\n): Promise<void> => {\n const { connection } = options;\n\n // Mandatory\n if (connection === undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection must be defined.\",\n );\n }\n\n if (typeof connection === \"string\") {\n if (connection.length === 0) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection string must not be empty.\",\n );\n }\n return;\n }\n\n const isConnectionOptions =\n typeof connection === \"object\" &&\n connection !== null &&\n !Array.isArray(connection);\n\n if (!isConnectionOptions) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_INVALID_OPTS(\n \"connection must be a connection string or a ConnectionOptions object.\",\n );\n }\n};\n","/*\nMIT License\n\nCopyright (c) 2026 Shane Froebel\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.\n*/\nimport { FastifyInstance } from \"fastify\";\nimport fp from \"fastify-plugin\";\nimport { Connection as RabbitMQConnection } from \"rabbitmq-client\";\n\nimport { FastifyRabbitMQOptions } from \"./decorate\";\nimport { errors } from \"./errors\";\nimport { validateOpts } from \"./validation\";\nexport { type FastifyRabbitMQOptions } from \"./decorate\";\n\n/**\n * How we talk with Fastify\n * @since 1.0.0\n * @param fastify\n * @param options\n * @param connection\n */\nconst decorateFastifyInstance = (\n fastify: FastifyInstance,\n options: FastifyRabbitMQOptions,\n connection: any,\n): void => {\n const { namespace = \"\" } = options;\n\n if (namespace !== undefined && namespace !== \"\") {\n fastify.log.debug(\"[fastify-rabbitmq] Namespace Attempt: %s\", namespace);\n }\n if (namespace !== undefined && namespace !== \"\") {\n if (fastify.rabbitmq === undefined) {\n fastify.decorate(\"rabbitmq\", Object.create(null));\n }\n\n if (fastify.rabbitmq[namespace] !== undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(\n `Already registered with namespace: ${namespace}`,\n );\n }\n\n fastify.log.trace(\n `[fastify-rabbitmq] Decorate Fastify with Namespace: ${namespace}`,\n );\n fastify.rabbitmq[namespace] = connection;\n } else {\n if (fastify.rabbitmq !== undefined) {\n throw new errors.FASTIFY_RABBIT_MQ_ERR_SETUP_ERRORS(\n \"Already registered.\",\n );\n }\n }\n\n if (fastify.rabbitmq === undefined) {\n fastify.log.trace(\"[fastify-rabbitmq] Decorate Fastify\");\n fastify.decorate(\"rabbitmq\", connection);\n }\n};\n\n/**\n * Main Function\n * @since 1.0.0\n * @example\n * This is the basics on how to use this plugin:\n * ```js\n * app.register(fastifyRabbit, {\n * connection: 'amqp://guest:guest@localhost'\n * })\n * ```\n * This will allow you to read from your Fastify \"object\" and\n * use this plugin at the \"rabbitmq\" level. From there you can execute and maintain\n * the RabbitMQ Connection using the 'rabbitmq-client' package, which is wrapping around\n * this plugin to execute functions it provides.\n *\n * @see [https://cody-greene.github.io/node-rabbitmq-client/latest/index.html](https://cody-greene.github.io/node-rabbitmq-client/latest/index.html)\n *\n */\nconst fastifyRabbit = fp<FastifyRabbitMQOptions>(async (fastify, opts) => {\n await validateOpts(opts);\n\n const { connection } = opts;\n\n const c = new RabbitMQConnection(connection);\n\n decorateFastifyInstance(fastify, opts, c);\n});\n\nexport default fastifyRabbit;\n\nexport { decorateFastifyInstance };\n\nexport * from \"./types\";\n\n// Re-export the rabbitmq-client surface so consumers import from this package\n// instead of reaching for the wrapped client. These are the exact types the\n// app.rabbitmq decorator hands back, so they stay correct without owning a\n// parallel definition.\nexport type {\n AsyncMessage,\n Channel,\n Connection,\n ConnectionOptions,\n Consumer,\n ConsumerHandler,\n ConsumerProps,\n Envelope,\n HeaderFields,\n MessageBody,\n Publisher,\n PublisherProps,\n ReturnedMessage,\n RPCClient,\n RPCProps,\n SyncMessage,\n} from \"rabbitmq-client\";\nexport {\n AMQPChannelError,\n AMQPConnectionError,\n AMQPError,\n ConsumerStatus,\n} from \"rabbitmq-client\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAwBA,MAAa,SAAS;;CAEpB,qCAAA,GAAA,eAAA,QAAA,CACE,sCACA,qBACF;;CAEA,qCAAA,GAAA,eAAA,QAAA,CACE,sCACA,iBACF;;CAEA,8BAAA,GAAA,eAAA,QAAA,CACE,+BACA,iBACF;AACF;;;;;;;;;;;;;;;;ACFA,MAAa,eAAe,OAC1B,YACkB;CAClB,MAAM,EAAE,eAAe;CAGvB,IAAI,eAAe,KAAA,GACjB,MAAM,IAAI,OAAO,mCACf,6BACF;CAGF,IAAI,OAAO,eAAe,UAAU;EAClC,IAAI,WAAW,WAAW,GACxB,MAAM,IAAI,OAAO,mCACf,sCACF;EAEF;CACF;CAOA,IAAI,EAJF,OAAO,eAAe,YACtB,eAAe,QACf,CAAC,MAAM,QAAQ,UAAU,IAGzB,MAAM,IAAI,OAAO,mCACf,uEACF;AAEJ;;;;;;;;;;AC/BA,MAAM,2BACJ,SACA,SACA,eACS;CACT,MAAM,EAAE,YAAY,OAAO;CAE3B,IAAI,cAAc,KAAA,KAAa,cAAc,IAC3C,QAAQ,IAAI,MAAM,4CAA4C,SAAS;CAEzE,IAAI,cAAc,KAAA,KAAa,cAAc,IAAI;EAC/C,IAAI,QAAQ,aAAa,KAAA,GACvB,QAAQ,SAAS,YAAY,OAAO,OAAO,IAAI,CAAC;EAGlD,IAAI,QAAQ,SAAS,eAAe,KAAA,GAClC,MAAM,IAAI,OAAO,mCACf,sCAAsC,WACxC;EAGF,QAAQ,IAAI,MACV,uDAAuD,WACzD;EACA,QAAQ,SAAS,aAAa;CAChC,OACE,IAAI,QAAQ,aAAa,KAAA,GACvB,MAAM,IAAI,OAAO,mCACf,qBACF;CAIJ,IAAI,QAAQ,aAAa,KAAA,GAAW;EAClC,QAAQ,IAAI,MAAM,qCAAqC;EACvD,QAAQ,SAAS,YAAY,UAAU;CACzC;AACF;;;;;;;;;;;;;;;;;;;AAoBA,MAAM,iBAAA,GAAA,eAAA,QAAA,CAA2C,OAAO,SAAS,SAAS;CACxE,MAAM,aAAa,IAAI;CAEvB,MAAM,EAAE,eAAe;CAIvB,wBAAwB,SAAS,MAAM,IAFzBA,gBAAAA,WAAmB,UAEM,CAAC;AAC1C,CAAC"}