{"id":24355258,"url":"https://github.com/rebolyte/pass-muster","last_synced_at":"2025-03-12T06:44:54.031Z","repository":{"id":90062691,"uuid":"52498316","full_name":"rebolyte/pass-muster","owner":"rebolyte","description":"A simple function emulating an interface so you can validate your argument objects.","archived":false,"fork":false,"pushed_at":"2019-06-17T20:18:22.000Z","size":12,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-01-18T17:36:52.137Z","etag":null,"topics":["design-by-contracts","interfaces","javascript","predicate-functions","schema","signature","types","validation"],"latest_commit_sha":null,"homepage":"","language":"JavaScript","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/rebolyte.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}},"created_at":"2016-02-25T05:05:27.000Z","updated_at":"2023-03-08T03:22:41.000Z","dependencies_parsed_at":null,"dependency_job_id":"12aebc24-defb-4539-a9d1-2028764090f1","html_url":"https://github.com/rebolyte/pass-muster","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rebolyte%2Fpass-muster","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rebolyte%2Fpass-muster/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rebolyte%2Fpass-muster/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rebolyte%2Fpass-muster/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rebolyte","download_url":"https://codeload.github.com/rebolyte/pass-muster/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243172128,"owners_count":20247885,"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":["design-by-contracts","interfaces","javascript","predicate-functions","schema","signature","types","validation"],"created_at":"2025-01-18T17:29:51.743Z","updated_at":"2025-03-12T06:44:54.016Z","avatar_url":"https://github.com/rebolyte.png","language":"JavaScript","readme":"# pass-muster\n\nObjects work well as a single argument to a function. That way you don't have to remember the order of parameters, and your code gets a nice self-documenting look. `passMuster` lets you be a little more sure of those objects that you pass as an argument to functions by validating that the properties you need are there and of the right types. Think of it as a lightweight implementation of interfaces.\n\nOf course, this isn't limited to validating objects passed as arguments. Use it wherever you want to make sure an object has what you need.\n\nThe module is written in good ol' ES5, so it works everywhere.\n\n## Usage\n\n```js\nmyFunction(opts) {\n    passMuster(opts, {\n        id: 'number',\n        username: 'string'\n    });\n    // do something with opts object\n}\n\nmyFunction({\n    id: 007,\n    username: 'jbond'\n})\n// --\u003e no error thrown, myFunction continues\n```\n\nIf `myFunction` is called without a required property, `passMuster` will throw an error:\n\n```js\nmyFunction({\n    id: 007\n})\n// --\u003e \"missing property 'username'\"\n```\n\nIt will also throw an error if the property is not the right type:\n\n```js\nmyFunction({\n    id: 007\n    username: 12345\n})\n// --\u003e \"property 'username' has wrong type\"\n```\n\nAn array of possible types can be supplied:\n\n```js\nlet objToValidate = {\n    prop: 'test'\n}\npassMuster(objToValidate, {\n    prop: ['string', 'number']\n});\n// --\u003e no error\n\npassMuster(objToValidate, {\n    prop: ['array', 'object']\n});\n// --\u003e \"property 'prop' not one of allowed types\"\n```\n\nIf you have further validation you want to do, a predicate function that returns `true` or `false` can be passed in:\n\n```js\nlet objToValidate = {\n    num: 11\n}\npassMuster(objToValidate, {\n    num: p =\u003e (p \u003c 100)\n});\n// --\u003e no error\n\npassMuster(objToValidate, {\n    num: p =\u003e (p % 2 === 0)\n});\n// --\u003e \"property 'num' does not pass predicate function\"\n\nlet alsoValidate = {\n    buf: new Buffer(2)\n}\npassMuster(alsoValidate, {\n    buf: _.isBuffer // \u003c-- using lodash\n});\n// --\u003e no error\n```\n\nPredicate functions are executed in the context of the type object, so you can reference the expected type of other properties:\n\n```js\nlet objToValidate = {\n    otherProp: 'foobar',\n    num: 11\n}\npassMuster(objToValidate, {\n    otherProp: 'string',\n    num: p =\u003e (typeof p !== this.otherProp)\n});\n// --\u003e no error\n```\n\nIf you need to reference the other values passed in, the object being validated is passed as a second argument to predicate functions:\n\n```js\nlet objToValidate = {\n    otherProp: 'foobar',\n    num: 11\n}\npassMuster(objToValidate, {\n    otherProp: 'string',\n    num: (p, objIn) =\u003e is.not.sameType(p, objIn.otherProp) // \u003c-- using @pwn/is, linked below\n});\n// --\u003e no error\n```\n\nNested objects also work:\n\n```js\n myFunction(opts) {\n    passMuster(opts, {\n        id: 'number',\n        address: {\n            street: 'string',\n            city: 'string',\n            state: 'string',\n            zip: 'number'\n        }\n    });\n    // do something with opts object\n}\n\nmyFunction({\n    id: 007,\n    address: {\n        street: '123 anywhere st',\n        city: 'Los Angeles',\n        state: 'CA'\n    }\n})\n// --\u003e \"missing property 'zip'\"\n```\n\nTo mark a property as optional, put it in the special `_optional` block:\n\n```js\nmyFunction(opts) {\n    passMuster(opts, {\n        id: 'number',\n        _optional: {\n            username: 'string'\n        }\n    })\n    // do something with opts object\n}\n\nmyFunction({\n    id: 007\n})\n// --\u003e no error\n\nmyFunction({\n    id: 007,\n    username: 12345\n})\n// --\u003e \"property 'username' has wrong type\"\n```\n\nTo see the function from which you called `passMuster`, just look at the stack trace on the error that gets thrown.\n\n## See also\n\n* [joi](https://github.com/hapijs/joi)\n* [obey](https://github.com/TechnologyAdvice/obey)\n* [is.js](https://github.com/pwnn/is.js) (see `is.conforms`)\n* [rfx](https://github.com/ericelliott/rfx)\n* [validator.js](https://github.com/chriso/validator.js)\n* [io-ts](https://github.com/gcanti/io-ts)\n* [superstruct](https://github.com/ianstormtaylor/superstruct)\n* [yup](https://github.com/jquense/yup)\n\n## License\n\nMIT\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frebolyte%2Fpass-muster","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frebolyte%2Fpass-muster","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frebolyte%2Fpass-muster/lists"}