{"id":28398405,"url":"https://github.com/primus/fortress-maximus","last_synced_at":"2025-06-28T14:31:14.982Z","repository":{"id":17962829,"uuid":"20953160","full_name":"primus/fortress-maximus","owner":"primus","description":"Despite his great power, size, and rank, Fortress Maximus is a weary and reluctant warrior. Fighting is against his pacifist nature and now spends his time validating.","archived":false,"fork":false,"pushed_at":"2022-12-31T19:42:04.000Z","size":478,"stargazers_count":8,"open_issues_count":1,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-06-09T11:11:22.546Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/primus.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-06-18T07:24:30.000Z","updated_at":"2022-12-31T19:42:07.000Z","dependencies_parsed_at":"2023-01-13T19:35:52.486Z","dependency_job_id":null,"html_url":"https://github.com/primus/fortress-maximus","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/primus/fortress-maximus","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primus%2Ffortress-maximus","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primus%2Ffortress-maximus/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primus%2Ffortress-maximus/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primus%2Ffortress-maximus/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/primus","download_url":"https://codeload.github.com/primus/fortress-maximus/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/primus%2Ffortress-maximus/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":261676597,"owners_count":23192817,"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","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":"2025-06-01T04:38:41.334Z","updated_at":"2025-06-28T14:31:14.976Z","avatar_url":"https://github.com/primus.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# fortress maximus\n\n[![Version npm](https://img.shields.io/npm/v/fortress-maximus.svg?style=flat-square)](https://www.npmjs.com/package/fortress-maximus)[![CI](https://img.shields.io/github/actions/workflow/status/primus/fortress-maximus/ci.yml?branch=master\u0026label=CI\u0026style=flat-square)](https://github.com/primus/fortress-maximus/actions?query=workflow%3ACI+branch%3Amaster)[![Coverage Status](https://img.shields.io/coveralls/primus/fortress-maximus/master.svg?style=flat-square)](https://coveralls.io/r/primus/fortress-maximus?branch=master)\n\nDespite his great power, size, and rank, Fortress Maximus is a weary and\nreluctant warrior. Fighting is against his pacifist nature and now spends his\ntime validating.\n\n\u003e Whether I am a hero or a coward is not the issue! I am weary! My joints creak\n\u003e from the corrosion of war without end! I... cannot break this ring of hate that\n\u003e surrounds us all -- but I can remove myself from it. No matter what you\n\u003e decide... I am leaving and joining Primus to innovate real-time.\n\nFortress Maximus validates every incoming message on your Primus server as all\nuser input should be seen as a potential security risk.\n\n## Installation\n\nThis is a plugin for the Primus framework and can be installed using `npm`:\n\n```\nnpm install --save fortress-maximus\n```\n\nThe `--save` tells `npm` to automatically add the installed version to your\npackage.json.\n\n## Dependencies\n\nIn order to work with emitted events we assume that you're using the\n`primus-emit` module as emit plugin. Any other plugin will simply be seen and\nvalidated as `data` event. See https://github.com/primus/emit for more\ninformation about this supported plugin.\n\n## Usage\n\nAs this is a plugin for Primus we need to add it. This plugin only has a server\ncomponent so it doesn't require you to re-compile your client. To add this\nplugin to your Primus server simply call the `.plugin` method on your Primus\ninstance:\n\n```js\nprimus.plugin('fortress maximus', require('fortress-maximus'));\n```\n\nIf you want every single message to be validated make sure that you've added\n`fortress-maximus` as the first plugin you use:\n\n```js\nprimus.plugin('fortress maximus', require('fortress-maximus'))\n      .plugin('emit', require('primus-emit'));\n```\n\nIn the example code above we can successfully intercept emit messages and\nvalidate them before they are processed by the `primus-emit` plugin and emitted\non the spark instance. The `primus-emit` module has two different modes which\nconfigure where the events are emitted. On the spark or on the server. We need\nto know where so we can correctly validate that there are events registered\nfor it. That's why it's possible to configure the `fortress-maximus` module\ndirectly through the Primus server constructor. The following options are\navailable:\n\n- `fortress`: Where the events are emitted. Either `spark` or `primus`.\n  Defaults to `spark`.\n\nJust as a quick reminder, this is how you supply the options to your Primus\nserver:\n\n```js\nvar primus = new Primus(httpsserver, {\n  fortress: 'spark'\n});\n```\n\n## Validating\n\nAfter you've added the plugin you can use the newly introduced `primus.validate`\nmethod to add validators for any given event that is emitted on the spark. The\nvalidate method accepts 2 arguments:\n\n1. The name of the event you want to validate. If you are not using custom\n   events this would only be the `data` event.\n2. The function that does the actual validation. The function should accept the\n   same amount of arguments as the event listener + one extra callback function\n\n```js\nprimus.on('connection', function (spark) {\n  spark.on('data', function (msg) {\n    // msg will always be string here\n  });\n});\n\nprimus.validate('data', function (msg, next) {\n  if ('string' !=== typeof msg) return next(new Error('Invalid'));\n\n  return next();\n})\n```\n\nWhen we receive a new message on the server we first run some standard\nvalidation checks to:\n\n1. Prevent reserved events from being emitted.\n2. Only allow events to be emitted when there are listeners.\n3. Only allow events which are validated.\n4. Make sure the correct amount of arguments are received.\n\nIf all these checks pass we will call the supplied validator function with\narguments.\n\n```js\nprimus.validate('custom event', function validate(foo, bar, next) {\n  if (foo !== 'bar') return next(new Error('Foo should be bar'));\n  if (bar !== 'foo') return next(new Error('Bar should be foo'));\n\n  next();\n});\n```\n\nThe context of your validator function will be set to the `spark` so you could\ndo some additional validation based on that:\n\n```js\nprimus.validate('admin', function validate(notification, next) {\n  isUserAdministrator(this.headers.cookie, function (err, admin) {\n    if (err) return next(err);\n    if (!admin) return next(new Error('Received admin event by non-admin'));\n\n    next();\n  }):\n});\n```\n\nIf you are too lazy to create `new Error()` objects for every single validation\nyou can also call the callback function with a boolean (`true` or `false`) to\nindicate if the event is valid.\n\n```js\nprimus.validate('custom event', function validate(foo, bar, next) {\n  next(foo !== 'bar' \u0026\u0026 bar !== 'foo');\n});\n```\n\n## Invalid\n\nWhen validation fails an `invalid` event is emitted on your Primus server\ninstance. This `invalid` event receives 2 arguments:\n\n1. `err` An error instance explaining why the given message was invalid.\n2. `args` The arguments that we attempted to validate.\n\n```js\nprimus.on('invalid', function invalid(err, args) {\n  // log things\n});\n```\n\nTo figure out which was the event that did not pass validation you can check\nthe supplied error object. We add an `event` property to it with the name of\nthe event.\n\n```js\nprimus.on('invalid', function invalid(err, args) {\n  console.log(err.event);\n});\n```\n\n## Debug\n\nIn addition to the `invalid` event, we also log the error with the `diagnostics`\nmodule. These debug messages can be seen by setting the environment variable\n`DEBUG`:\n\n```\nDEBUG=primus:fortress node \u003cyour app.js\u003e\n```\n\n## License\n\n[MIT](LICENSE)\n\n![Fortress Maximus](https://raw.githubusercontent.com/primus/fortress-maximus/master/logo.jpg)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprimus%2Ffortress-maximus","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprimus%2Ffortress-maximus","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprimus%2Ffortress-maximus/lists"}