{"id":16694491,"url":"https://github.com/foxfriends/svelte-io","last_synced_at":"2026-04-21T10:02:49.936Z","repository":{"id":42617717,"uuid":"409022182","full_name":"foxfriends/svelte-io","owner":"foxfriends","description":"IO monad for Svelte","archived":false,"fork":false,"pushed_at":"2024-08-30T17:21:45.000Z","size":746,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-13T23:43:22.194Z","etag":null,"topics":["fantasy-land","functional-programming","monad","svelte"],"latest_commit_sha":null,"homepage":"","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/foxfriends.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-09-22T01:07:01.000Z","updated_at":"2024-08-30T17:21:48.000Z","dependencies_parsed_at":"2024-06-17T15:09:28.638Z","dependency_job_id":null,"html_url":"https://github.com/foxfriends/svelte-io","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/foxfriends/svelte-io","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxfriends%2Fsvelte-io","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxfriends%2Fsvelte-io/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxfriends%2Fsvelte-io/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxfriends%2Fsvelte-io/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/foxfriends","download_url":"https://codeload.github.com/foxfriends/svelte-io/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/foxfriends%2Fsvelte-io/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":263799994,"owners_count":23513430,"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":["fantasy-land","functional-programming","monad","svelte"],"created_at":"2024-10-12T16:46:10.086Z","updated_at":"2026-04-21T10:02:44.875Z","avatar_url":"https://github.com/foxfriends.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SvelteIO\n\n[![NodeJS CI](https://github.com/foxfriends/svelte-io/actions/workflows/nodejs.yml/badge.svg)](https://github.com/foxfriends/svelte-io/actions/workflows/nodejs.yml)\n\n[Basic Usage][] | [API Reference][]\n\nAn IO [monad][] for [Svelte][]. [Fantasy Land][] compatible.\n\n[Fantasy Land]: https://github.com/fantasyland/fantasy-land\n[monad]: https://github.com/fantasyland/fantasy-land#monad\n[Svelte]: https://svelte.dev/\n[Basic Usage]: #Usage\n[API Reference]: ./API.md\n\n\u003e Disclaimer: This package, as written, has not been actually used in any practical way.\n\u003e It very well may not work the way you see it today. The documentation below also\n\u003e may very well not work as written. If this concept is interesting to you, but you\n\u003e find that the package is not working, please reach out and we'll get something\n\u003e sorted out!\n\n## Installation\n\nNot currently published to NPM, so install from Github:\n\n```sh\nnpm i -S github:foxfriends/svelte-io\n```\n\nFor obvious reasons, `svelte ^3.39` is also a (peer) dependency.\n\n## Usage\n\nFor a significant number of cases, usage of this package should come quite naturally.\nSuch usage will be covered first.\n\n```svelte\n\u003c!-- Hello.svelte --\u003e\n\u003cscript\u003e\n  export let name;\n\u003c/script\u003e\n\nHello {name}!\n```\n\n```svelte\n\u003c!-- App.svelte --\u003e\n\u003cscript\u003e\n  import { onMount } from 'svelte';\n  import Driver, { render } from 'svelte-io';\n  import Hello from './Hello.svelte';\n\n  let driver;\n\n  onMount(() =\u003e {\n    driver.run(render(Hello, { name: 'World' }));\n  });\n\u003c/script\u003e\n\n\u003cDriver bind:this={driver} /\u003e\n```\n\nThis example shows the most fundamental parts of this package:\n1.  The `Driver` represents where in the Svelte component hierarchy each `SvelteIO` will be run.\n2.  Pass a `SvelteIO` to `driver.run()`, and it will be run by that driver.\n3.  `render(Component, props)` is a built-in `SvelteIO` constructor that renders a component from the position of the `Driver`.\n\n\u003e   For those who want TypeScript types, and are finding they are missing from the package, here they are:\n\u003e   *   `render(Component: SvelteComponent, props?: Record\u003cstring, any\u003e): SvelteIO`\n\u003e   *   `driver.run(io: SvelteIO\u003cT\u003e) -\u003e Promise\u003cT\u003e`\n\nOf course, the ability to render a single component is not all that exciting. What *is* exciting about\n`SvelteIO` is that these `SvelteIO` values are *composable*.\n\n```svelte\n\u003c!-- App.svelte --\u003e\n\u003cscript\u003e\n  import { onMount } from 'svelte';\n  import Driver, { doIO, render } from 'svelte-io';\n  import Hello from './Hello.svelte';\n  import GetName from './GetName.svelte';\n\n  let driver;\n\n  onMount(() =\u003e {\n    const main = doIO(async function* () {\n      const name = yield render(GetName);\n      yield render(Hello, { name });\n    })\n    driver.run(main);\n  });\n\u003c/script\u003e\n\n\u003cDriver bind:this={driver} /\u003e\n```\n\nIn this example, `doIO(generator: AsyncGenerator): SvelteIO\u003cT\u003e` is used to construct a more\ncomplex `SvelteIO` by transforming a generator that itself yields other `SvelteIO`s.\nHere, `main` is a `SvelteIO` that first renders the `GetName` component then, using the\n*output value* of `GetName`, renders the `Hello` as before.\n\nDifferent than in regular Svelte, `SvelteIO` components are generally expected to be displayed,\ninteracted with, and then be removed when its job is done, outputting some final value. Let's\ntake a look at how `GetName` is implemented:\n\n```svelte\n\u003c!-- GetName.svelte --\u003e\n\u003cscript\u003e\n  import { useSvelteIO } from 'svelte-io';\n\n  const { next } = useSvelteIO();\n\n  let name = '';\n\u003c/script\u003e\n\n\u003cinput bind:value={name} /\u003e\n\n\u003cbutton on:click={() =\u003e next(name)}\u003e\n  Submit\n\u003c/button\u003e\n```\n\n`SvelteIO` components call `useSvelteIO()` to get access to a function `next(value: T)`.\nThis `next(value)` function is the one that causes the generator from which the component\nwas `yield`ed to continue, very much like you called the `.next()` function on that\ngenerator. Similarly, the value passed to this `next(value)` is the one that gets returned\nfrom the `yield` statement!\n\nThere are a bunch more things you can do from SvelteIO: pretty much anything that you can do with\na regular Svelte component, including accessing context (`getContext(key: any): SvelteIO\u003cT\u003e`),\naccessing the props passed to the `\u003cDriver\u003e` (`getProp(prop: string): SvelteIO\u003cT\u003e`), and\ndispatching events from the `\u003cDriver\u003e` (`dispatch(event: string, detail?: any): SvelteIO\u003cvoid\u003e`).\nCheck out all the details in the [API reference][].\n\n## Advanced Usage\n\nAs mentioned in the header, `SvelteIO` is actually implemented as a [monad][] (as defined\nby [Fantasy Land][]). For those versed in Haskell, `doIO` is the closest thing we can get to\n`do`-notation for Javascript, providing the intuitive interface seen above.\n\nGiven this knowledge, it should become apparent that all the usual things you can do to monads\napply to `SvelteIO`s. The example of `main` from above could have equivalently been written\nusing monad operators as follows:\n\n```javascript\nimport { chain } from 'fantasy-land';\nconst main = render(GetName)[chain]((name) =\u003e render(Hello, { name }));\n```\n\nOr, since [Ramda][] is also Fantasy Land compatible:\n\n[Ramda]: https://ramdajs.com/\n\n```javascript\nimport { chain } from 'ramda';\nconst main = chain((name) =\u003e render(Hello, { name }), render(GetName));\n```\n\nOf course, this example does not show a great reason to use this syntax over that of `doIO`,\nbut if you are using this library in situations advanced enough that you need this level of\npower, you likely know what you need anyway.\n\nSomething I have not tried, but would like to believe works, is using this Monad as the base\nmonad of other monad transforms (such as those from [Akh][]) to further add to their flexibility.\n\n[Akh]: https://github.com/mattbierner/akh\n\n## Contributing\n\nSuggestions and improvements are welcome. Feel free to create issues, pull requests, or just\nmessage me somewhere to discuss anything.\n\n## Related Works\n\nFor those of us still stuck working with React, a similar package [Monadic React][] exists.\nThough it takes a different philosophy to the features it provides, it is built on the same concept.\n\nAnother (React world) package which can be used to achieve similar separation of concerns of\ndata flow from component rendering is [Redux-Saga][].\n\n[Monadic React]: https://github.com/hoppinger/MonadicReact\n[Redux-Saga]: https://redux-saga.js.org/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoxfriends%2Fsvelte-io","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffoxfriends%2Fsvelte-io","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffoxfriends%2Fsvelte-io/lists"}