{"_id":"apostrophe-external-notifications","_rev":"27-0e81bb3d53d1f2553723680296c8c4c3","name":"apostrophe-external-notifications","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"apostrophe-external-notifications","version":"1.0.0","keywords":["apostrophecms","content management system","external-notifications","apostrophe"],"author":{"name":"P'unk Avenue LLC"},"license":"MIT","_id":"apostrophe-external-notifications@1.0.0","maintainers":[{"name":"boutell","email":"tom@punkave.com"}],"homepage":"https://github.com/apostrophecms/apostrophe-external-notifications#readme","bugs":{"url":"https://github.com/apostrophecms/apostrophe-external-notifications/issues"},"dist":{"shasum":"f226d6a881e990bb8bd7234911683d0da79be7d8","tarball":"https://registry.npmjs.org/apostrophe-external-notifications/-/apostrophe-external-notifications-1.0.0.tgz","fileCount":8,"integrity":"sha512-vwol2Jgpx0Gs/JsvGUJVFykurLzCthOHmRS4f6B0JSO7l+y61XDzurjvF1pmihXvjFv3KUmCP13ru4kjRnaeQw==","signatures":[{"sig":"MEUCIQCdyZaJE0Tn8ecddWNp6m1thSnByCDzE2TjkRjOFpAepgIgM1GymYCwGpJctQ6m0peNCnYFIvbBAHBkMNJ9ygz8Ieo=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":24268,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdJhCoCRA9TVsSAnZWagAALTcP/0oJL6y0BHd8L/M3fcA3\npvki414yauESlb/5ptwhajzZlF/ysKfBK0TSp1xPlL5ya+vmVjyruIQusatS\nJ25rHIpys+WL4rJrUwc8Z89t6oE3QGGtQqR0BMTgLozlGZXqqjdIT+uLFAqy\nrOJ6NjsLPjHrfjd6pAFJ7dGiw8/bKHvHkeprNvnRiqAD1WORKPZYWw2S219X\nRQw4UUCcYwJQm3EhLviomXPPyM7/o6MQojmLAmFujTRH7+ZSrO6u6ZtitU1n\nOZEBtWKSItEl4gGuZekf2vkmMN6F0b1hJcCtpnPD2nv8hRn+lWBwpTvo6W/j\njBGQxCTS80aBNLqZtMwiXFNXx4QgkAgO6r3znuvhoraEfg9haD1LXRAkr5DB\n4uSFUHT807tEj6obbZO0iXvTyswAHWJ9WjIFvpPmw/LRYuzKCQruIHhk2BYV\nSYP25sNIdJhZr1bEXxACVZnE3Xx/cfX0lco3cJwVJGoQMyOgTrepV9vy/VOu\nyaKkR3q4azfRQFkdQEr7+kRlTbtV4jWPKCh3vVfJ73JCNEf5UXSVqT0KAgXF\nAdYQtDuOcEB7sBpONUurFii9enV6hOIcHo0iIkhi8tqpouCpQeAirezvJr2G\naUS1YRSIj8JGDDg+ukDJGUJHUpxaHdiUsIIfOQrDgY16SoylMLeIFtF02Ac6\ntPgW\r\n=ujpg\r\n-----END PGP SIGNATURE-----\r\n"},"main":"index.js","engines":{"node":">=8.0.0"},"gitHead":"4356871388949cafbf15f18485f5404a505164dc","scripts":{"test":"eslint . && mocha"},"_npmUser":{"name":"boutell","email":"tom@punkave.com"},"repository":{"url":"git+https://github.com/apostrophecms/apostrophe-external-notifications.git","type":"git"},"_npmVersion":"6.4.1","description":"Send notifications to Slack when various events occur in ApostropheCMS","directories":{},"_nodeVersion":"8.16.0","dependencies":{"request":"^2.88.0","request-promise":"^4.2.4"},"_hasShrinkwrap":false,"devDependencies":{"mocha":"^6.1.4","eslint":"^5.16.0","apostrophe":"^2.92.0","eslint-plugin-node":"^6.0.1","apostrophe-workflow":"^2.21.2","eslint-plugin-import":"^2.17.2","eslint-plugin-promise":"^3.8.0","eslint-config-standard":"^11.0.0","eslint-plugin-standard":"^3.1.0","eslint-config-apostrophe":"^2.0.2"},"_npmOperationalInternal":{"tmp":"tmp/apostrophe-external-notifications_1.0.0_1562775719842_0.4367883009912725","host":"s3://npm-registry-packages"}}},"time":{"created":"2019-07-10T16:21:59.842Z","modified":"2026-01-26T19:10:19.761Z","1.0.0":"2019-07-10T16:21:59.954Z"},"bugs":{"url":"https://github.com/apostrophecms/apostrophe-external-notifications/issues"},"author":{"name":"P'unk Avenue LLC"},"license":"MIT","homepage":"https://github.com/apostrophecms/apostrophe-external-notifications#readme","keywords":["apostrophecms","content management system","external-notifications","apostrophe"],"repository":{"url":"git+https://github.com/apostrophecms/apostrophe-external-notifications.git","type":"git"},"description":"Send notifications to Slack when various events occur in ApostropheCMS","maintainers":[{"email":"alex@apostrophecms.com","name":"alexgilbert"},{"email":"tom@apostrophecms.com","name":"boutell"},{"email":"stuart+npm@apostrophecms.com","name":"romanek"},{"email":"robert.means1969+apostrophecms@gmail.com","name":"bodonkey"}],"readme":"# apostrophe-external-notifications\n\nA simple way to get notifications via Slack and other external systems when various events occur in [ApostropheCMS](https://apostrophecms.org).\n\n## Installation\n\n```\n# In the root dir of your existing apostrophe project\nnpm install apostrophe-external-notifications\n```\n\n## Configuration\n\n```javascript\n  // in app.js\n  modules: {\n    'apostrophe-external-notifications': {\n      // OPTIONAL: an alias to make it easier to send your own notifications,\n      // see example below\n      alias: 'external',\n      platforms: {\n        slack: {\n          // See below for a more nuanced way to do this\n          channel: [ '#apostrophe-edits' ],\n          webhooks: {\n            '#apostrophe-edits': 'https://hooks.slack.com/services/GO/GET-YOUR-OWN'\n          }\n        }\n      }\n    }\n  }\n```\n\n> To set this up in Slack, you need to [register a Slack \"app\" here](https://api.slack.com/apps?new_app=1). After copying that information, click \"Incoming Webhooks,\" then be sure to turn them on. Now click \"Add New Webhook to Workspace\" and select the desired channel. Repeat for each channel you wish to notify. Finally, copy and paste the resulting webhook URLs into the `webhooks` configuration as shown above.\n\n### Sending different events to different channels\n\nThe simple configuration above sends everything to the `#apostrophe-edits` channel in Slack. You can also break down which events go to which channels:\n\n```javascript\n  modules: {\n    'apostrophe-external-notifications': {\n      alias: 'external',\n      platforms: {\n        slack: {\n          events: {\n            'apostrophe-workflow:afterCommit': '#apostrophe-commits',\n            'apostrophe-workflow:afterExport': '#apostrophe-exports',\n            'apostrophe-workflow:afterForceExport': '#apostrophe-exports'\n          },\n          webhooks: {\n            '#apostrophe-commits': 'https://hooks.slack.com/services/GO/GET-YOUR-OWN-1',\n            '#apostrophe-exports': 'https://hooks.slack.com/services/GO/GET-YOUR-OWN-2'\n          }\n        }\n      }\n    }\n  }\n```\n\nIf you do not configure the shared `channel` option, then **only the events you individually configure are sent to Slack at all.** You may also do it both ways.\n\n> Anywhere you see channels configured above, you can specify **either an array of channels or a single channel**.\n> \n> If you configure more than one channel, you must also create and paste in the \"webhook\" URLs for each of them.\n\n## Limitations\n\nThere must be an Apostrophe promise event associated with what you want notifications for, and an external notification handler must be registered for that event. `apostrophe-external-notifications` has handlers for some popular cases, but not all.\n\n## Built-in event listeners: what you can get without writing any code\n\nCurrently the following event handlers have listeners built into this module:\n\n```\napostrophe-workflow:afterCommit\napostrophe-workflow:afterExport\napostrophe-workflow:afterForceExport\n```\n\nMore event handlers are coming. In the meantime, you can add support for more events yourself, as shown below. We suggest doing so as a PR on the module in question so that the community benefits and you are aware when we add a handler that would otherwise duplicate yours.\n\n## Adding support for more events\n\nHere's how you might add support for the `afterCommit` event, if we didn't already have it. **This code assumes you gave the module an alias in your project,** as seen above.\n\n```\nself.apos.external.notifyOn('apostrophe-workflow:afterCommit', (req, commit) => \n  [ '{user} committed the {type} {title} which has these tags: {string}.', commit.from, commit.from, commit.from.tags ]\n);\n```\n\n\"What's going on in this code?\" `apostrophe-workflow:afterCommit` is the event we want to listen for. `(req, commit)` are the arguments that the `afterCommit` event provides. We then return an array containing a template string, and arguments to replace parts of the template string. The template string can contain the following optional placeholders:\n\n* `{user}` displays the current user's name, or falls back gracefully if there is no user. Powered by the `req` argument from the event, so we do not need to pass anything else. Not all events have `req`. If `req` is not present or contains no username `Anonymous` is sent.\n* `{type}` displays the type of a document in a user-friendly way, or falls back to the `type` property. Expects a matching `doc` argument as shown above. (The `commit` object emitted by `afterCommit` has a `from` property containing the doc that was committed.)\n* `{title}` displays the `title` a document in a user-friendly way, or falls back to the `slug` property. Expects a matching `doc` argument. (The `commit` object emitted by `afterCommit` has a `from` property containing the doc that was committed.)\n* `{string}` simply expects and sends a string argument. If it receives an array argument, it will send it as a comma-separted string, with spaces.\n\n> While you could do everything with `{string}`, the other placeholders save time and prevent frequent causes of crashing bugs due to missing sanity checks.\n\n## Adding support for your own events in a published npm module\n\nThanks for doing that! Follow the above technique. However, **in a public npm module, you MUST NOT assume** that `apostrophe-external-notifications` has a handy alias (do NOT write `apos.external`). You also should NOT assume that the module is present at all. Instead, write:\n\n```javascript\nconst external = self.apos.modules['apostrophe-external-notifications'];\nif (external) {\n  external.notifyOn(/* ... as seen above */);\n}\n```\n\n## Adding support for more platforms\n\nSupport for Slack ships with this module by default. You can add handlers for other platforms.\n\nHere is a simplified Slack platform handler:\n\n```\nconst rp = require('request-promise');\nself.apos.externals.addPlatform('slack', async (req, options, channels, message) => {\n  for (const channel of channels) {\n    await rp({\n      method: 'POST',\n      uri: options.webhooks[channel],\n      form: {\n        text: message.formatted\n      }\n    });\n  }\n});\n```\n\n> The above example assumes you gave the module the alias `externals`. If you want to ship support for a platform as an npm module, refer to our module as `self.apos.modules['apostrophe-externals']` to be safe.\n\nNote that `req` **may be undefined** in cases where an event is global and not concerned with an individual request. `req` is provided in case you want to handle the message differently depending on the sender's identity. Here we do not.\n\n`channels` contains the array of channel names the event should be sent to. **It may be empty and you should do nothing if it is empty**, unless channels are not a relevant concept for your platform. If you don't care about channels, you may wish to look at `message.event`, which contains the original ApostropheCMS promise event name.\n\n`message.formatted` contains the message to be sent, as a string. Placeholders have already been resolved, the message is complete and ready to send.\n\n> Although our platform handler function is `async` and `await`s each channel's message delivery to Slack, for the sake of performance `apostrophe-external-notifications` will not wait for the handler to finish before allowing the original Apostrophe event handler to return. However, for the sake of consistency the module does guarantee that notifications sent for a specific `req` will be delivered in order relative to their peers. Those with no `req` are also sent in order.\n","readmeFilename":"README.md"}