{"id":43252176,"url":"https://github.com/thoughtsunificator/domodel","last_synced_at":"2026-02-01T13:12:49.394Z","repository":{"id":45135501,"uuid":"372201054","full_name":"thoughtsunificator/domodel","owner":"thoughtsunificator","description":"ES6 Modules based front-end library","archived":false,"fork":false,"pushed_at":"2025-09-13T04:08:41.000Z","size":1601,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-12T19:10:42.205Z","etag":null,"topics":["domodel","front-end","javascript","library"],"latest_commit_sha":null,"homepage":"http://domodel.unificator.me","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/thoughtsunificator.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-05-30T11:50:55.000Z","updated_at":"2025-09-12T08:29:04.000Z","dependencies_parsed_at":"2024-11-10T12:30:14.187Z","dependency_job_id":null,"html_url":"https://github.com/thoughtsunificator/domodel","commit_stats":{"total_commits":123,"total_committers":3,"mean_commits":41.0,"dds":0.2682926829268293,"last_synced_commit":"ef07093d38bee7f53ad9e85d4bcef7a2e943ce35"},"previous_names":[],"tags_count":88,"template":false,"template_full_name":null,"purl":"pkg:github/thoughtsunificator/domodel","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtsunificator%2Fdomodel","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtsunificator%2Fdomodel/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtsunificator%2Fdomodel/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtsunificator%2Fdomodel/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/thoughtsunificator","download_url":"https://codeload.github.com/thoughtsunificator/domodel/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/thoughtsunificator%2Fdomodel/sbom","scorecard":{"id":883134,"data":{"date":"2025-08-11","repo":{"name":"github.com/thoughtsunificator/domodel","commit":"602a58f33ee77ff168ad98f93a2bdbfb137ae387"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.6,"checks":[{"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":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","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/10 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":"Maintained","score":5,"reason":"7 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 5","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"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":"Pinned-Dependencies","score":4,"reason":"dependency not pinned by hash detected -- score normalized to 4","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/release.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/thoughtsunificator/domodel/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:27: update your workflow using https://app.stepsecurity.io/secureworkflow/thoughtsunificator/domodel/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:45: update your workflow using https://app.stepsecurity.io/secureworkflow/thoughtsunificator/domodel/release.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/release.yml:53: update your workflow using https://app.stepsecurity.io/secureworkflow/thoughtsunificator/domodel/release.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/test.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/thoughtsunificator/domodel/test.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   3 third-party GitHubAction dependencies pinned","Info:   2 out of   2 npmCommand dependencies pinned"],"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/release.yml:1","Warn: no topLevel permission defined: .github/workflows/test.yml:1","Info: no jobLevel write permissions found"],"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":"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":"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":"Branch-Protection","score":-1,"reason":"internal error: error during branchesHandler.setup: internal error: githubv4.Query: Resource not accessible by integration","details":null,"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"}},{"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":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 29 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":0,"reason":"19 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-6chw-6frg-f759","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-fjxv-7rqg-78g4","Warn: Project is vulnerable to: GHSA-896r-f27r-55mw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-6vfc-qv3f-vr6c","Warn: Project is vulnerable to: GHSA-5v2h-r2cx-5xgj","Warn: Project is vulnerable to: GHSA-rrrm-qjm4-v8hf","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp","Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6","Warn: Project is vulnerable to: GHSA-mxhp-79qh-mcx6","Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3","Warn: Project is vulnerable to: GHSA-cf4h-3jhx-xvhq","Warn: Project is vulnerable to: GHSA-6fc8-4gx4-v693","Warn: Project is vulnerable to: GHSA-3h5v-q93c-6h6q"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-24T08:59:27.739Z","repository_id":45135501,"created_at":"2025-08-24T08:59:27.740Z","updated_at":"2025-08-24T08:59:27.740Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28978967,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-01T12:13:08.691Z","status":"ssl_error","status_checked_at":"2026-02-01T12:13:08.356Z","response_time":56,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["domodel","front-end","javascript","library"],"created_at":"2026-02-01T13:12:46.493Z","updated_at":"2026-02-01T13:12:49.382Z","avatar_url":"https://github.com/thoughtsunificator.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# domodel\n\ndomodel is front-end library that organizes the user interface into models (look) and bindings (behavior) it follows the principle of separation of concerns, it also introduce elements of the observable pattern for the communication between the different parts of the user interface.\n\n## Getting started\n\n### Installing\n\n#### Setup a new project\n\n``npx create-domodel-app [name]``\n\n#### Setup as a dependency to an existing project\n\n``npm install domodel``\n\n### Model\n\nA model is a JSON representation of a DOM [Element](https://html.spec.whatwg.org/multipage/dom.html#htmlelement).\n\nA model can also be used to refer to both the [Model](https://domodel.unificator.me/global.html#Model) and its [Binding](https://domodel.unificator.me/domodel/Binding.html) as a whole, that is a component (a search bar model for example). \n\nLet's take this [Model](https://domodel.unificator.me/global.html#Model) for example:\n\n```javascript\nexport default {\n  tagName: \"button\"\n}\n```\n\nThat would the equivalent of:\n\n```javascript\nconst button = document.createElement(\"button\")\n```\n\nNext, a [Model](https://domodel.unificator.me/global.html#Model) with children:\n\n```javascript\nexport default {\n  tagName: \"div\",\n  children: [\n    {\n      tagName: \"h2\",\n      identifier: \"headline\",\n      textContent: \"Unveil a new world\"\n    }\n  ]\n}\n```\n\nNotice the ``textContent`` property. You can set any [Element](https://html.spec.whatwg.org/multipage/dom.html#htmlelement) properties in this fashion. \n\n\u003e If you want to set an ``attribute`` use the attributes object property.\n\nThe ``identifier`` allows your binding to track a model and manipulate it in within the available hooks.\n\n#### Properties\n\u003ca href=\"#model-properties\"\u003e\u003c/a\u003e\n\nMost properties listed in your model comes from the [Element](https://html.spec.whatwg.org/multipage/dom.html#htmlelement) class.\n\nIt also includes:\n\n- ``tagName`` - ``string`` - Which is passed to ``createElement``\n- ``children`` - ``Array`` - To add children to an Element\n- ``identifier`` - ``string`` - To save and retrieve a Node\n- ``childModel`` - [ChildModel](https://domodel.unificator.me/global.html#ChildModel) - [For model nesting](#nesting-models)\n\n\n### Core\n\n#### Adding models to the DOM and managing them\n\nTo add a [Model](https://domodel.unificator.me/global.html#Model) to the DOM we use the [Core.run](http://domodel.unificator.me/Core.html#.run) method provided by the [Core module](http://domodel.unificator.me/Core.html).\n\nCreate a ``main.js`` in ``src/``, it is the entry point module that is defined in your ``index.html`` :\n\n``src/main.js``\n```javascript\nimport { Core } from \"domodel\" // first we're importing DOModel\n\n// It is preferred to use camel case and suffix model names with \"Model\" and binding names with \"Binding\" such as: RectangleModel and RectangleBinding.\nimport Model from \"./model/model.js\" // the model we defined earlier, it is our super model\nimport ModelBinding from \".model/model.binding.js\" // the binding we will be defining .bindinglater\n\nwindow.addEventListener(\"DOMContentLoaded\", function() {\n  Core.run(Model, {\n    method: Core.METHOD.APPEND_CHILD, // This is the default method and will append the children to the given target.\n    binding: new ModelBinding({ myProp: \"hello :)\" }), // we're creating an instance of our binding (which extends the Binding class provided by DOModel) and passing it to the run method.\n    target: document.body // the node we want to target in this case it is the node where we want to append the child node using appendChild.\n  })\n})\n\n```\n\nCreate the associated [Binding](http://domodel.unificator.me/Binding.html):\n\n``src/model/model.binding.js``\n```javascript\nimport { Core } from \"domodel\" // you could import the library again and run yet another model inside this model\n\nclass ModelBinding extends Binding {\n\n  onCreated() {\n\n    // access your model root element through the root property: this.root\n\n    // access identifier with the identifier property:\n\n    this.elements.headline.textContent = \"The new world was effectively unveiled before my very eyes\"\n\n    // you might even run another model inside this model\n  }\n\n}\n\nexport default ModelBinding \n```\n\n#### Methods\n\n- ``APPEND_CHILD`` Append your model to ``target``\n\n- ``INSERT_BEFORE`` Insert your model before ``target``\n\n- ``INSERT_AFTER`` Insert your model after ``target``\n\n- ``REPLACE_NODE`` Replace ``target`` with your model\n\n- ``WRAP_NODE`` Wrap ``target`` inside your model\n\n- ``PREPEND`` Insert your model before the first child of ``target``\n\nThese are available through [Core.METHOD](https://domodel.unificator.me/global.html#Method).\n\n### Binding\n\nWhile a [Model](https://domodel.unificator.me/global.html#Model) defines the look of a component, a [Binding](http://domodel.unificator.me/Binding.html) defines its behavior.\n\n#### Hooks\n\nThe following are hooks that your binding can implement to add specific behaviors to your models.\n\n#### onCreated\n\nThis method will be called before your model is added to the DOM.\n\n#### onConnected\n\nThis method will be called immediately after your model is added to the DOM.\n\n#### Properties\n\u003ca href=\"#binding-properties\"\u003e\u003c/a\u003e\n\nThe following properties are made available from within the the instance of a [Binding](http://domodel.unificator.me/Binding.html):\n\n- ``root`` Root [Element](https://html.spec.whatwg.org/multipage/dom.html#htmlelement) of your model.\n- ``identifier`` Hosts individual [Element](https://html.spec.whatwg.org/multipage/dom.html#htmlelement) previously tagged in the definition of the model (see [Model properties](#model-properties)).\n\n### Methods\n\n#### listen\n\nListen to a given observable event. See [Binding.listen](https://domodel.unificator.me/Binding.html#listen).\n\n\u003e This is the preferred method for listening to events as any listener will be cleaned up when your binding is removed using [Binding.remove](https://domodel.unificator.me/Binding.html#remove).\n\n#### run\n\nSynonym of [Core.run](https://domodel.unificator.me/Core.html#.run), with the differences being :\n\n- ```target``` property is set to the current binding root element.\n- A hierarchy of models is created using Binding._children. Making it easier to remove them using [Binding.remove](https://domodel.unificator.me/Binding.html#remove).\n\n#### remove\n\nRemove the model from the DOM. See [Binding.remove](https://domodel.unificator.me/Binding.html#remove).\n\n### Observable\n\nAn [Observable](http://domodel.unificator.me/observable.Observable.html) is a way for your models to communicate with each other and store their states.\n\n``src/object/observable-example.js``\n```javascript\nimport { Observable } from \"domodel\"\n\nclass ExampleObservable extends Observable {\n\n  // you can have a constructor\n\n  // getter setter...\n\n  // or even better, you could have methods.\n\n}\n\nexport default ExampleObservable \n```\n\n#### Listening to events\n\n##### EventListener\n\nHere we associate the EventListener with our current binding and give it ``observable`` as the observable to register the events to.\n\n``src/model/model.binding.js``\n```javascript\nimport { Observable, Binding } from \"domodel\"\n\nimport ModelEventListener from \"/model/model.event.js\"\n\nclass ModelBinding extends Binding {\n\n  constructor(observable) {\n    super(new ModelEventListener(observable))\n  }\n\n}\n\nexport default ModelBinding \n```\n\nAny method inside an ``EventListener`` is automatically registered as a listener to the given observable.\n\n``src/model/model.event.js``\n```javascript\nimport { EventListener } from \"domodel\"\n\nclass ModelEventListener extends EventListener {\n\n  message(data) {\n    console.log(data)\n  } \n\n}\n\nexport default ModelEventListener \n```\n\n##### observable.listen\n\nUseful when you want to listen to other parts your UI.\n\n``src/model/model.binding.js``\n```javascript\nimport { Observable, Binding } from \"domodel\"\n\nclass ModelBinding extends Binding {\n\n  onCreated() {\n\n    const observable = new Observable()\n\n    observable.listen(\"message\", data =\u003e {\n      console.log(data)\n    })\n\n  }\n\n}\n\nexport default ModelBinding \n```\n\n\u003e [Binding.listen](https://domodel.unificator.me/Binding.html#listen) also works on non-Observable targets.\n\n#### Emitting events\n\n``src/model/model.binding.js``\n```javascript\nimport { Observable } from \"domodel\"\n\nclass ModelBinding extends Binding {\n\n  onCreated() {\n\n    const observable = new Observable()\n\n    observable.emit(\"message\", { /* data go here */ })\n\n  }\n\n}\n\nexport default ModelBinding \n```\n\n\u003e You can also emit to a non-Observable target using [Binding.emit](https://domodel.unificator.me/Binding.html#emit).\n\nRunning your model:\n\n```javascript\nimport { Core, Observable } from \"domodel\"\n\nimport Model from \"/model/model.js\"\nimport ModelBinding from \"/model/model.binding.js\"\n\nconst observable = new Observable()\n\nCore.run(Model, { target: document.body, binding: new ModelBinding({ observable }) })\n\n```\n\n### Advanced\n\n#### Nesting models\n\n##### Method 1 - Import\n\n``src/model/application.js``\n```javascript\nimport Model from \"./model.js\"\n\nexport default {\n  tagName: \"div\",\n  children: [\n    Model\n  ]\n}\n```\n\n##### Method 2 - Binding\n\n``src/model/application.binding.js``\n```javascript\nimport { Core } from \"domodel\"\n\nimport Model from \"./model.js\"\nimport ModelBinding from \"./model.binding.js\"\n\nclass extends Binding {\n\n  onCreated() {\n    Core.run(Model, { target: this.root, binding: new ModelBinding() })\n  }\n\n}\n\nexport default class \n```\n\n##### Method 3 - \"childModel\" property\n\n``src/model/application.js``\n```javascript\nimport Model from \"./model.js\"\nimport ModelBinding from \"./model.binding.js\"\n\nexport default {\n  tagName: \"div\",\n  children: [\n    {\n      childModel: {\n        model: Model,\n        binding: ModelBinding // optionnal\n        arguments: [] // optionnal\n        identifier: \"model\" // optionnal\n        // Any other property is ignored.\n      }\n    }\n  ]\n}\n```\n\n##### Referencing to nested models\n\nIn some cases, you might want to reference to a nested model.\n\nYou can use the ``identifier``, it will reference to an instance of the [Binding](http://domodel.unificator.me/Binding.html) you specified, in this case it would be an instance of ``ModelBinding``.\n\nAccessing the reference:\n\n``src/model/model.binding.js``\n\n```javascript\nimport { Binding } from \"domodel\" // you could import the library again and run yet another model inside this model\n\nclass extends Binding {\n\n  onCreated() {\n\n    console.log(this.identifiers.model) // returns an Identifier\n    // and much more...\n\n  }\n\n}\n\nexport default class \n```\n\n#### Model chain\n\nYou can alter an existing model using the `ModelChain` API:\n\n```javascript\nconst MyModel = {\n  tagName: \"div\",\n  children: [\n    {\n      tagName: \"div\",\n      identifier: \"title\"\n    }\n  ]\n}\n\nconst MyModelChain = new ModelChain(MyModel).after(\"title\", {\n  tagName: \"div\",\n  textContent: \"A description\"\n})\n\nCore.run(MyModelChain.definition, { target: document.body })\n```\n\nAvailable methods: \n\n* `ModelChain.prepend`\n* `ModelChain.append`\n* `ModelChain.replace`\n* `ModelChain.before`\n* `ModelChain.after`\n\n\n### API\n\nSee [http://domodel.unificator.me](http://domodel.unificator.me).\n\n## Extensions\n\nSee [https://github.com/topics/domodel-extension](https://github.com/topics/domodel-extension).\n\n## Demos\n\nSee [https://github.com/topics/domodel-demo](https://github.com/topics/domodel-demo).\n\n## Testing\n\n- ``npm install``\n- ``npm test``\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtsunificator%2Fdomodel","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fthoughtsunificator%2Fdomodel","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fthoughtsunificator%2Fdomodel/lists"}