{"id":22733489,"url":"https://github.com/burdiuz/js-backbone-properties","last_synced_at":"2025-09-10T08:40:33.712Z","repository":{"id":58234217,"uuid":"48587774","full_name":"burdiuz/js-backbone-properties","owner":"burdiuz","description":"Facade for Backbone Model","archived":false,"fork":false,"pushed_at":"2016-03-28T07:55:22.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-30T05:04:43.559Z","etag":null,"topics":["backbone","backbone-model-decorator","backbone-models","decorator","javascript","js","properties"],"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/burdiuz.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":"2015-12-25T17:59:58.000Z","updated_at":"2023-04-11T15:18:27.000Z","dependencies_parsed_at":"2022-08-30T22:31:44.995Z","dependency_job_id":null,"html_url":"https://github.com/burdiuz/js-backbone-properties","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/burdiuz/js-backbone-properties","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burdiuz%2Fjs-backbone-properties","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burdiuz%2Fjs-backbone-properties/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burdiuz%2Fjs-backbone-properties/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burdiuz%2Fjs-backbone-properties/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/burdiuz","download_url":"https://codeload.github.com/burdiuz/js-backbone-properties/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burdiuz%2Fjs-backbone-properties/sbom","scorecard":{"id":258582,"data":{"date":"2025-08-11","repo":{"name":"github.com/burdiuz/js-backbone-properties","commit":"431e9b8649b2fdae08ee59afb2ffac52ba02bc14"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","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":"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":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"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":"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":"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":"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":-1,"reason":"no dependencies found","details":null,"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":"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":"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":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"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":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"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"}}]},"last_synced_at":"2025-08-17T10:14:38.627Z","repository_id":58234217,"created_at":"2025-08-17T10:14:38.627Z","updated_at":"2025-08-17T10:14:38.627Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274433838,"owners_count":25284427,"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-10T02:00:12.551Z","response_time":83,"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":["backbone","backbone-model-decorator","backbone-models","decorator","javascript","js","properties"],"created_at":"2024-12-10T20:14:46.946Z","updated_at":"2025-09-10T08:40:33.662Z","avatar_url":"https://github.com/burdiuz.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Backbone Model Decorator\n\n[![Build Status](https://travis-ci.org/burdiuz/js-backbone-properties.svg?branch=master)](https://travis-ci.org/burdiuz/js-backbone-properties)\n[![Coverage Status](https://coveralls.io/repos/burdiuz/js-backbone-properties/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/burdiuz/js-backbone-properties?branch=master)\n[![Dependencies](https://img.shields.io/david/burdiuz/js-backbone-properties.svg?label=deps)](https://david-dm.org/burdiuz/js-backbone-properties)\n[![Dev Dependencies](https://img.shields.io/david/dev/burdiuz/js-backbone-properties.svg?label=devDeps)](https://david-dm.org/burdiuz/js-backbone-properties#info=devDependencies)\n\nBackbone Model Decorator is a [Backbone.js](http://backbonejs.org/) plugin that decorates `Backbone.Model` with `properties` property that plays role of Model Facade and contains model attributes in form of properties.\n```javascript\nvar DecoratedModel = ModelDecorator.extend({\n  defaults: {\n    email: 'default@email.com',\n    password: ''\n  }\n});\nvar decorated = new DecoratedModel();\n```\nGetting model attribute via such property will return current value of the attribute.\n```javascript\nconsole.log(decorated.properties.email); // default@email.com\ndecorated.set({password: '@!$^\u0026SEvjH#'}); \nconsole.log(decorated.properties.password); // @!$^\u0026SEvjH#\n```\nAnd setting new value to property will immediately change model attribute.\n```javascript\ndecorated.properties.email = 'other@email.com';\nconsole.log(decorated.get('email')); // other@email.com\ndecorated.properties.email = '@!$^\u0026SEvjH#';\nconsole.log(decorated.get('password')); // @!$^\u0026SEvjH#\n```\n\n## Installation\n\nThis package is available via npm \n```\nnpm install backbone-model-decorator --save\n```\n and bower distribution systems\n```\nbower install backbone-model-decorator --save\n```\n Also you can download it as [single file with comments](https://raw.githubusercontent.com/burdiuz/js-backbone-properties/master/dist/backbone-properties.js) or [minified](https://raw.githubusercontent.com/burdiuz/js-backbone-properties/master/dist/backbone-properties.min.js) from this repository. \n\n\n## Usage\n\nTo start using decorator you should extend model from `ModelDecorator` instead of Backbone.Model.\n```javascript\nvar decorated = ModelDecorator.extend({\n  ...\n});\n```\nWith extending from `ModelDecorator`, extended model gains new properties and methods.\n\n * `properties` -- Facade object with all generated properties\n * `propertyOptions` -- Object containing options for model attributes that should be used by default when setting new value via setter function\n * `validateProperties()` -- Method that allows creating bunch of properties on Facade object by going through passed object's property names\n * `property()` -- Method that allows adding or changing single property on Facade object\n\nWorth noting that Model should `know` about possible attributes it might have to properly initialize Facade properties.\nFacade object is populated with properties when model initialization occurs, so it has 3 sources for possible properties:\n 1. Model `attributes` object\n 2. Model `defaults` object\n 3. Model `propertyOptions` object that contains default options applied on property set\nThese objects are checked for property names and each found property will be mirrored on facade object as possible Model attribute.  \n\nThere are two ways to add properties to Facade after model initialization\n * Using `Model.validateProperties()`\n * Using `Model.property()`\nAlso its possible to re-define property via `Model.property()` adding custom getter/setter functions or making read-only properties.\n \n### Model.properties\n\nDefault place where Model Facade object will be stored is `properties` field in Model object. This can be changed in 2 ways.  \n  \nSet `ModelDecorator` to create properties using Model object without creating Facade object. All newly created properties will be available directly from model.\n```javascript\nModelDecorator.facadeType = ModelDecorator.USE_MODEL;\nvar DecoratedModel = ModelDecorator.extend({\n  defaults: {\n    value: 'this is value',\n    name: 'this is name'\n  }\n});\n\nvar decorated = new DecoratedModel();\n\nconsole.log(decorated.properties); // null\nconsole.log(decorated.value); // this is value\nconsole.log(decorated.name); // this is name\n\ndecorated.value = 'new value';\ndecorated.set({name: 'update name'});\n\nconsole.log(decorated.get('value')); // new value\nconsole.log(decorated.name); // update name\n```\n**Note:** *Creating properties on model may cause name collisions with internal Backbone Model instance fields.*  \n  \nOr change Facade property name, by default its `properties`. In this case Facade will be created and stored in field with specified name. All created properties will be stored in Facade object.\n```javascript\nModelDecorator.facadeFieldName = 'props';\n\nvar DecoratedModel = ModelDecorator.extend({\n  defaults: {\n    value: 'this is value',\n    name: 'this is name'\n  }\n});\nvar decorated = new DecoratedModel();\n\nconsole.log(decorated.properties); // null\nconsole.log(decorated.props); // ModelFacade {}\n\nconsole.log(decorated.props.value); // this is value\nconsole.log(decorated.props.name); // this is name\n\ndecorated.props.value = 'new value';\ndecorated.set({name: 'update name'});\n\nconsole.log(decorated.get('value')); // new value\nconsole.log(decorated.props.name); // update name\n```\n**Note:** *Renaming facade property to names used by Backbone Model, like `attributes`, may cause unexpected errors.*\n\n### Model.validateProperties()\n\n`validateProperties()` does lookup for names on passed object and uses this names to create new properties on facade. \nIt will not apply values from passed objects, so new model properties will be created but not initialized.\n```javascript\nvar DecoratedModel = ModelDecorator.extend({});\nvar decorated = new DecoratedModel();\ndecorated.validateProperties({value:'any value here', name: '#$%#$'});\n\nconsole.log(decorated.properties.hasOwnProperty('value')); // true\nconsole.log(decorated.properties.value); // undefined\nconsole.log(decorated.properties.name); // undefined\n\ndecorated.properties.value = 'value1';\ndecorated.properties.name = 'new name';\n\nconsole.log(decorated.attributes); // Object {value: \"value1\", name: \"new name\"}\nconsole.log(decorated.properties.value); // value1\nconsole.log(decorated.properties.name); // new name\n```\n\n### Model.property()\n\nThis method has up to 4 arguments with only first argument required, other are optional.\n 1. `name:String` -- Model attribute name for which property should be created\n 2. `options:Object` -- Object containing options that should be used on every value update\n 3. `setter:Function|Boolean` -- Accepts custom setter function or `true` if property should be read-only\n 4. `getter:Function` -- Custom getter function\n\nWith this method its easy to create computed properties that will not mess with original model\n```javascript\nvar DecoratedModel = ModelDecorator.extend({\n  defaults: {\n    email: 'default@email.com',\n    password: ''\n  }\n});\nvar decorated = new DecoratedModel();\ndecorated.property('emailLink', null, true, (function() {\n  return 'emailTo:'+this.properties.email; \n}).bind(decorated));\nconsole.log(decorated.properties.emailLink); // emailTo:default@email.com\n```\n\nIt always returns property options, if called with name of existing property it will do nothing but return this property options.\n```javascript\nvar DecoratedModel = ModelDecorator.extend({\n  defaults: {\n    value: ''\n  },\n  validate: function(options, opts){\n    return !options.value || options.value.length \u003c opts.minLength;\n  },\n  propertyOptions: {\n    value: {\n      validate: true,\n      minLength: 2\n    }\n  }\n});\nvar decorated = new DecoratedModel();\n\nconsole.log(decorated.property('value').validate); // true\nconsole.log(decorated.property('value').minLength); // 2\n``` \n\n### ModelDecorator.createPropertyGetter/Setter()\n\nModelDecorator has 2 statics methods that called when getter or setter should be generated. These methods can be replaced by custom implementation.\n * `ModelDecorator.createPropertyGetter(model, name)` -- property getter method generator. Generates function that will call model's `.get()` method with `name` and return result of this call.\n * `ModelDecorator.createPropertySetter(model, name)` -- property setter method generator. Generates function that will create object with property for model update and call model's `.set()` method passing created object and property options to it. \n\nThey have identical signature, as parameters model and property name should be passed and both will return function as result.\n```typescript\n ModelDecorator.createPropertyGetter(model:Backbone.Model, name:String):Function\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fburdiuz%2Fjs-backbone-properties","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fburdiuz%2Fjs-backbone-properties","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fburdiuz%2Fjs-backbone-properties/lists"}