{"id":15866166,"url":"https://github.com/kanitsharma/elvish","last_synced_at":"2025-10-09T07:38:29.283Z","repository":{"id":57222735,"uuid":"156950782","full_name":"kanitsharma/elvish","owner":"kanitsharma","description":"A functional, reactive and some what type safe javascript library to build UIs, inspired by Elm","archived":false,"fork":false,"pushed_at":"2019-10-31T11:27:57.000Z","size":10837,"stargazers_count":4,"open_issues_count":5,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-09-24T14:57:49.390Z","etag":null,"topics":["elm","elm-architecture","functional-programming","inferno","javascript","union-types"],"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/kanitsharma.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-11-10T05:30:25.000Z","updated_at":"2025-05-04T05:11:42.000Z","dependencies_parsed_at":"2022-08-28T23:23:20.568Z","dependency_job_id":null,"html_url":"https://github.com/kanitsharma/elvish","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/kanitsharma/elvish","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanitsharma%2Felvish","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanitsharma%2Felvish/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanitsharma%2Felvish/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanitsharma%2Felvish/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kanitsharma","download_url":"https://codeload.github.com/kanitsharma/elvish/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kanitsharma%2Felvish/sbom","scorecard":{"id":549323,"data":{"date":"2025-08-11","repo":{"name":"github.com/kanitsharma/elvish","commit":"fc4c7c47cbb87a1b501c3f50a0e422ee1064d6ed"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":1.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":"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":"Code-Review","score":0,"reason":"Found 1/25 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":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":"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":0,"reason":"license file not detected","details":["Warn: project does not have a license file"],"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"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 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":"32 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-968p-4wvh-cqc8","Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92","Warn: Project is vulnerable to: GHSA-6chw-6frg-f759","Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw","Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw","Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-cwfw-4gq5-mrqx","Warn: Project is vulnerable to: GHSA-g95f-p29q-9xw4","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-w8qv-6jwh-64r5","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c","Warn: Project is vulnerable to: GHSA-3gx7-xhv7-5mx3","Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj","Warn: Project is vulnerable to: GHSA-8j8c-7jfh-h6hx","Warn: Project is vulnerable to: GHSA-9c47-m6qq-7p4h","Warn: Project is vulnerable to: GHSA-6c8f-qphg-qjgp","Warn: Project is vulnerable to: GHSA-jf85-cpcp-j695","Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw","Warn: Project is vulnerable to: GHSA-29mw-wpgm-hmr9","Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3","Warn: Project is vulnerable to: GHSA-vh95-rmgr-6w4m","Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h","Warn: Project is vulnerable to: GHSA-r683-j2x4-v87g","Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9","Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm","Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw","Warn: Project is vulnerable to: GHSA-h9rv-jmmf-4pgx","Warn: Project is vulnerable to: GHSA-hxcc-f52p-wc94","Warn: Project is vulnerable to: GHSA-52f5-9888-hmc6"],"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-20T10:22:09.009Z","repository_id":57222735,"created_at":"2025-08-20T10:22:09.010Z","updated_at":"2025-08-20T10:22:09.010Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":279000961,"owners_count":26082973,"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-10-09T02:00:07.460Z","response_time":59,"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":["elm","elm-architecture","functional-programming","inferno","javascript","union-types"],"created_at":"2024-10-05T23:04:48.788Z","updated_at":"2025-10-09T07:38:29.267Z","avatar_url":"https://github.com/kanitsharma.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src='logo.png' /\u003e\n\n A functional, reactive and some what type safe javascript library to build UIs \n\nElvish is heavily inspired from elm-architecture, it is an effort to implement the type safe and functional architecture that elm provides in a non typed language like javascript.\n\n## Getting Started\n\nThe logic of every Elvish program will break up into three cleanly separated parts:\n\n- Model — the state of your application\n- Update — a way to update your state\n- View — a way to view your state as HTML\n\n### Counter Example\n\nHere is a [Code Sandbox](https://codesandbox.io/s/km6jzkwk0r)\n\n```javascript\nimport run from 'elvish';\nimport { onClick, Text, div, button, span } from \"elvish\";\nimport { Union, Record } from 'elvish'\n\nconst Model = Record({\n  counter: Number\n})\n\n// init :: Model\nconst Init = Model.create(0)\n\n// Msg = Increment | Decrement\nconst Msg = Union({\n  Increment: [],\n  Decrement: []\n});\n\n// update :: Model -\u003e Msg -\u003e Model\nconst Update = model =\u003e Msg.case({\n  Increment: () =\u003e ({ ...model, counter: model.counter + 1 }),\n  Decrement: () =\u003e ({ ...model, counter: model.counter - 1 }),\n  _: () =\u003e model\n})\n\n// view :: Model -\u003e Html Msg\nconst View = ({ counter }) =\u003e\n  div([], [\n    button([ onClick(Msg.Increment) ], [\"+\"]),\n    span([], [ Text(counter) ]),\n    button([ onClick(Msg.Decrement) ], [\"-\"])\n  ])\n\n// Run\nconst Root = document.getElementById(\"root\");\n\nrun({\n  View,\n  Update,\n  Init,\n  Root\n});\n```\n\n### Side Effect example\n\nHere is a [Code Sandbox](https://codesandbox.io/s/309960pr2p)\n\n```javascript\nimport run from \"elvish\";\nimport { div, button, h3, onClick, Text } from 'elvish'\nimport { Union, Record, Effect } from 'elvish'\n\nconst Model = Record({\n  userId: Number,\n  title: String,\n  fetched: Boolean,\n  url: String\n})\n\n// init :: Model\nconst Init = Model.create(0)('')(false)('https://jsonplaceholder.typicode.com/todos/1')\n\n// Msg :: FetchData | FetchedData | FetchError\nconst Msg = Union({\n  FetchData: [],\n  FetchedData: [Number, String],\n  FetchError: [String]\n});\n\n// getJson :: String -\u003e Effect err { number, string }\nconst getJson = url =\u003e Effect((reject, resolve) =\u003e\n  fetch(url)\n    .then(x =\u003e !x.ok ? reject('Error') : x.json())\n    .then(resolve)\n)\n\n// fetchUserData :: String -\u003e Effect FetchError FetchedData\nconst fetchUserData = url =\u003e\n  Effect.of(url)\n    .chain(getJson)\n    .bimap(err =\u003e Msg.FetchError(err), ({ userId, title }) =\u003e Msg.FetchedData(userId, title))\n\n// update :: Model -\u003e Msg -\u003e Model | (Model, Effect)\nconst Update = model =\u003e Msg.case({\n  FetchData: () =\u003e [model, fetchUserData(model.url)],\n  FetchedData: (userId, title) =\u003e ({ ...model, userId, title, fetched: true }),\n  FetchError: err =\u003e ({ ...model, title: err, fetched: true }),\n  _: _ =\u003e model\n})\n\n// view :: Model -\u003e Html Msg\nconst View = ({ userId, title, fetched }) =\u003e\n  div([],\n    [\n      button([onClick(Msg.FetchData)], [Text('Fetch Data')]),\n      fetched \u0026\u0026 div([], [\n        h3([], [Text(userId)]),\n        h3([], [Text(title)])\n      ])\n    ]\n  );\n\n\n// Run\nconst Root = document.getElementById(\"root\");\n\nrun({\n  View,\n  Update,\n  Init,\n  Root\n});\n```\n\n## Performance\n\nElvish uses [Inferno](https://github.com/infernojs/inferno) as its Vdom which makes it insanely fast, even faster than React and Elm itself.\n\nHere is the jS-benchmark\n\n\u003cimg src=\"docs/benchmark.png\" height=\"500\" width=\"350\" /\u003e\n\n## Types\n\n### Record\n\n- Example\n```javascript\n  const Model = Record({\n    counter: Number,\n    text: String\n  }) // Returns a type constructor Model(counter, text)\n\n  const model = Model.create(0, 'hello world') // create new Model\n\n  console.log(model.counter) // 0\n  console.log(model.text) // hello world\n```\n\n- Type safe\n\n```javascript\n  const Model = Record({\n    counter: Number\n  })\n\n  const model = Model.create('0') // wrong type passed to record\n```\n\n### Union Type\n\nUnion types are an important part of an elvish application. \n\n- Example\n\n```javascript\n  const Bool = Union({\n    True: [],\n    False: []\n  })\n```\n\n- Adding instance methods to union types.\n\n```javascript\n  const T = () =\u003e true\n\n  const Maybe = Union({\n    Just: [T],\n    Nothing: []\n  })\n  \n  Maybe.map = function(fn) {\n    return Maybe.case({\n      Nothing: () =\u003e Maybe.Nothing,\n      Just: (v) =\u003e Maybe.Just(fn(v))\n    }, this);\n  };\n\n  const just = Maybe.Just(1)\n  const nothing = Maybe.Nothing\n  nothing.map(add(1)); // =\u003e Nothing\n  just.map(add(1)); // =\u003e Just(2)\n```\n\n- Pattern Matching\n\n```javascript\n  const Action = Union({\n    ShowNumber: [Number],\n    HideNumber: []\n  })\n\n  const initState = {\n    number: 0,\n    showNumber: false\n  }\n\n  const reducer = (initState, action) =\u003e\n    Action.case({\n      ShowNumber: number =\u003e ({ showNumber: true, number }),\n      HideNumber: _ =\u003e ({ showNumber: false, number: 0 })\n      _: () =\u003e initState,\n    }, action)\n```\n\n### Effect type\n\nEffect types are used to run side effects in an elvish application. Effects is a structure for time-dependent values.\n\nBasically the idea is to abstract the side effects from your pure code and running them separately, so your code stays pure even when you are doing side effects.\n\nYou can think of an elvish application as pure and functional code running in an imperative shell.\n\n- Example\n\n```javascript\n  const executeEffect = number =\u003e\n    Effect.of(number)\n      .map(x =\u003e x + 10)\n```\nOnly way to run Effects in an elvish application is to return a tuple from the update function containing [ Model, Effect ].\n\n```javascript\n  ExecuteEffect: () =\u003e [model, executeEffect(model.number)],\n```\n\n#### Instances\n\n```javascript\n\n  // Constructing\n  Effect.of(value)\n  //  b -\u003e Effect(a, b)\n  // Constructs a new Effect containing the given successful value.\n\n  Effect.rejected(value)\n  // a -\u003e Effect(a, b)\n  // Constructs a new Effect containing the given failure value.\n\n  Effect.empty()\n  // () -\u003e Effect(a, b)\n  // Constructs a Effect that will never resolve.\n\n  // Transforming\n  Effect.map(transformation)\n  // Effect(a, b) =\u003e (b -\u003e c) -\u003e Effect(a, c)\n  // Transforms the successful value of the Effect using a regular unary function.\n\n  Effect.chain(transformation)\n  // Effect(a, b) =\u003e (b -\u003e Effect(a, c)) -\u003e Effect(a, c)\n  // Transforms the succesful value of the Effect using a function over monads.\n\n  Effect.orElse(transformation)\n  // Effect(a, b) =\u003e (a -\u003e Effect(c, b)) -\u003e Effect(c, b)\n  // Transforms the failure value of the Effect into a new Effect.\n\n  Effect.fold(onRejection, onSucecss)\n  // Effect(a, b) =\u003e (a -\u003e c), (b -\u003e c) -\u003e Effect(d, c)\n  // Applies a function to each side of the Effect.\n\n  Effect.cata(pattern)\n  // Effect(a, b) =\u003e { Rejected: a -\u003e c, Resolved: b -\u003e c } → Effect(d, c)\n  // Applies a function to each side of the Effect.\n\n  Effect.bimap(onRejection, onSuccess)\n  // Effect(a, b) =\u003e (a -\u003e c), (b -\u003e d) -\u003e Effect(c, d)\n  // Maps both sides of the Effect.\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkanitsharma%2Felvish","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkanitsharma%2Felvish","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkanitsharma%2Felvish/lists"}