{"id":19226992,"url":"https://github.com/dvtng/cosmos","last_synced_at":"2025-04-10T23:03:55.092Z","repository":{"id":245199628,"uuid":"817529744","full_name":"dvtng/cosmos","owner":"dvtng","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-09T18:06:40.000Z","size":169,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-04-10T23:03:49.106Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","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/dvtng.png","metadata":{"files":{"readme":null,"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":"2024-06-19T23:22:01.000Z","updated_at":"2025-03-09T18:06:43.000Z","dependencies_parsed_at":"2024-08-02T20:43:31.565Z","dependency_job_id":"312305c5-3f85-4a86-a046-5d042c377277","html_url":"https://github.com/dvtng/cosmos","commit_stats":null,"previous_names":["dvtng/cosmos"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvtng%2Fcosmos","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvtng%2Fcosmos/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvtng%2Fcosmos/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/dvtng%2Fcosmos/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/dvtng","download_url":"https://codeload.github.com/dvtng/cosmos/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248312142,"owners_count":21082638,"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":[],"created_at":"2024-11-09T15:21:15.345Z","updated_at":"2025-04-10T23:03:55.083Z","avatar_url":"https://github.com/dvtng.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# cosmos\n\nProof of concept for a flexible data-fetching framework for React.\n\n## Core concepts\n\nData sources are described using models:\n\n```ts\nconst Weather = model({\n  type: \"Weather\",\n  refresh: { minutes: 5 },\n  get({ latitude, longitude }) {\n    return fetch(`https://weather.example.com/${latitude}/${latitude}`).then(\n      (resp) =\u003e resp.json()\n    );\n  },\n});\n```\n\nModels can then be queried inside components:\n\n```tsx\nfunction WeatherIcon({ latitude, longitude }) {\n  const [weather] = useModel(Weather({ latitude, longitude }));\n\n  return \u003cimg src={weather ? weather.iconUrl : placeholderIconUrl} /\u003e;\n}\n```\n\nWe can use suspense if preferred using `waitFor`:\n\n```tsx\nfunction WeatherIcon({ latitude, longitude }) {\n  const [weather] = waitFor(useModel(Weather({ latitude, longitude })));\n\n  return \u003cimg src={weather.iconUrl} /\u003e;\n}\n```\n\nModels can also represent data sources that continuously emit data, such as\nwebsockets or event listeners:\n\n```ts\nconst MyLocation = model({\n  type: \"MyLocation\",\n  emitter(emit) {\n    const id = navigator.geolocation.watchPosition((position) =\u003e {\n      emit(position.coords);\n    });\n    // Stop watching when this model is no longer used\n    return () =\u003e {\n      clearWatch(id);\n    };\n  },\n});\n```\n\nIf we frequently need to get the weather at the current location, we can combine\nthese two models into one:\n\n```ts\nconst MyWeather = model({\n  type: \"MyWeather\",\n  derive(getModel) {\n    const [coords] = waitFor(getModel(MyLocation()));\n    return getModel(Weather(coords));\n  },\n});\n\nfunction MyWeatherIcon() {\n  const [myWeather] = waitFor(useModel(MyWeather()));\n\n  return \u003cimg src={myWeather.iconUrl} /\u003e;\n}\n```\n\nCosmos automatically tracks the dependencies of MyWeather so that it updates\nwhenever either MyLocation or Weather updates.\n\nIt also tracks usages of each model so that they are initialized once when used\nby a component, and then cleaned up when no longer needed.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvtng%2Fcosmos","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdvtng%2Fcosmos","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdvtng%2Fcosmos/lists"}