{"id":15061214,"url":"https://github.com/phoenix-china/bucklescript-phx","last_synced_at":"2025-04-10T06:37:14.840Z","repository":{"id":57190897,"uuid":"86291528","full_name":"phoenix-china/bucklescript-phx","owner":"phoenix-china","description":"BuckleScript binding for Phoenix Channel/Presence","archived":false,"fork":false,"pushed_at":"2020-03-24T06:52:28.000Z","size":36,"stargazers_count":40,"open_issues_count":2,"forks_count":4,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-24T07:41:02.959Z","etag":null,"topics":["bucklescript","ocaml","phoenix-channels","phoenix-framework"],"latest_commit_sha":null,"homepage":null,"language":"OCaml","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/phoenix-china.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"MIT-LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-03-27T04:33:06.000Z","updated_at":"2025-01-03T08:49:49.000Z","dependencies_parsed_at":"2022-09-15T22:21:12.168Z","dependency_job_id":null,"html_url":"https://github.com/phoenix-china/bucklescript-phx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phoenix-china%2Fbucklescript-phx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phoenix-china%2Fbucklescript-phx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phoenix-china%2Fbucklescript-phx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/phoenix-china%2Fbucklescript-phx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/phoenix-china","download_url":"https://codeload.github.com/phoenix-china/bucklescript-phx/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248171133,"owners_count":21059308,"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":["bucklescript","ocaml","phoenix-channels","phoenix-framework"],"created_at":"2024-09-24T23:11:47.721Z","updated_at":"2025-04-10T06:37:14.807Z","avatar_url":"https://github.com/phoenix-china.png","language":"OCaml","funding_links":[],"categories":[],"sub_categories":[],"readme":"# BuckleScript Phoenix\n[![NPM](https://nodei.co/npm/bucklescript-phx.png?compact=true)](https://nodei.co/npm/bucklescript-phx/)\n\n[![Build Status](https://travis-ci.org/phoenix-china/bucklescript-phx.svg?branch=master)](https://travis-ci.org/phoenix-china/bucklescript-phx)\n#### BuckleScript binding for Phoenix Channel/Presence to Phoenix's official JavaScript client.\n#### This is usable now.\n#### Feel free to create PRs.\n\n- [X] Connect socket\n- [X] Join channel\n- [X] Push event\n- [X] Handle event\n- [X] Presence\n- [ ] Support The Elm Architecture on BuckleScript ([https://github.com/OvermindDL1/bucklescript-tea](BuckleScript-tea))\n- [ ] Fallback support for polling.\n\n#### To install\n```bash\nnpm install -save bucklescript-phx\n```\n\n#### Please update your `bsconfig.json` to make `bsb` aware of this dependency\n```\n\"bs-dependencies\": [\n    \"bucklescript-phx\"\n  ]\n```\n#### Notice:\n\n1. Please add official Phoenix client as your dependency to make sure BuckleScript is able to require Phoenix's js.\n\n2. Meta of Presence and payload of incoming event are decalred as `Js_json.t` which means you need to decode it with your prefered decoder (in TEA it is very convenient with `Json.Decoder.decodeValue`).\n\n3. The bindings are based on [https://github.com/DefinitelyTyped/DefinitelyTyped](DefinitelyTyped). There might be some error on mapping the types. Please help correct them if you find anything wrong. Thank you!\n\n#### Here are the examples:\n\nTo join a channel:\n```ocaml\nopen Phx\n\nlet handleReiceive event any =\n  match event with\n  | \"ok\" -\u003e Js.log (\"handleReiceive:\" ^ event, \"Joined\")\n  | \"error\" -\u003e Js.log (\"handleReiceive:\" ^ event, \"Failed to join channel\")\n  | _ -\u003e Js.log (\"handleReiceive:\" ^ event, any)\n\nlet handleEvent event response =\n  let _ = Js.log (\"handleEvent:\" ^ event, response) in\n  ()\n\n\nlet handleSyncState response =\n  let _ = Js.log (\"handleSyncState\", response) in\n  (*let _ = Js.log (Array.iter (fun key -\u003e Js.log (Js_dict.unsafeGet response key)) (Js_dict.keys response) ) in*)\n  let _presences  =  Presence.syncState (Js.Dict.empty ()) response in\n  ()\n\nlet handleSyncDiff diff =\n  let _ = Js.log (\"handleSyncDiff:diff\", diff) in\n  let presences  =  Presence.syncDiff (Js.Dict.empty ()) diff in\n  let _ = Js.log (\"handleSyncDiff:presences\", presences) in\n  ()\n\nlet _ =\n  let socket = initSocket \"/socket\"\n               |\u003e connectSocket\n               |\u003e putOnClose (fun () -\u003e Js.log \"Socket closed\") in\n  let channel = socket\n                |\u003e initChannel \"user:lobby\" in\n  let _ = channel\n          |\u003e putOn \"from_server\" (handleEvent \"from:server\")\n          |\u003e putOnSyncState handleSyncState\n          |\u003e putOnsyncDiff handleSyncDiff\n          |\u003e joinChannel\n          |\u003e putReceive \"ok\" (handleReiceive \"ok\")\n          |\u003e putReceive \"error\" (handleReiceive \"error\") in\n  push \"new:message\" [%bs.obj { user = \"Hello, Elixir! This is a greeting from BuckleScript!\"} ] channel\n  ```\n  \n  #### Reasonml:\n\nTo join a channel:\n```reason\nopen Phx\n  \n  let handleReiceive = (event, any) =\u003e\n  switch event {\n  | \"ok\" =\u003e Js.log((\"handleReiceive:\" ++ event, \"Joined\"))\n  | \"error\" =\u003e Js.log((\"handleReiceive:\" ++ event, \"Failed to join channel\"))\n  | _ =\u003e Js.log((\"handleReiceive:\" ++ event, any))\n  };\n\nlet handleEvent = (event, response) =\u003e {\n  let _ = Js.log((\"handleEvent:\" ++ event, response));\n  ();\n};\n\nlet handleSyncState = (response) =\u003e {\n  let _ = Js.log((\"handleSyncState\", response));\n  /*let _ = Js.log (Array.iter (fun key -\u003e Js.log (Js_dict.unsafeGet response key)) (Js_dict.keys response) ) in*/\n  let _presences = Presence.syncState(Js.Dict.empty(), response);\n  ();\n};\n\nlet handleSyncDiff = (diff) =\u003e {\n  let _ = Js.log((\"handleSyncDiff:diff\", diff));\n  let presences = Presence.syncDiff(Js.Dict.empty(), diff);\n  let _ = Js.log((\"handleSyncDiff:presences\", presences));\n  ();\n};\n\n{\n  let socket = initSocket(\"/socket\") |\u003e connectSocket |\u003e putOnClose(() =\u003e Js.log(\"Socket closed\"));\n  let channel = socket |\u003e initChannel(\"user:lobby\");\n  let _ =\n    channel\n    |\u003e putOn(\"from_server\", handleEvent(\"from:server\"))\n    |\u003e putOnSyncState(handleSyncState)\n    |\u003e putOnsyncDiff(handleSyncDiff)\n    |\u003e joinChannel\n    |\u003e putReceive(\"ok\", handleReiceive(\"ok\"))\n    |\u003e putReceive(\"error\", handleReiceive(\"error\"));\n  push(\"new:message\", {\"user\": \"Hello, Elixir! This is a greeting from BuckleScript!\"}, channel);\n};\n  \n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphoenix-china%2Fbucklescript-phx","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fphoenix-china%2Fbucklescript-phx","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fphoenix-china%2Fbucklescript-phx/lists"}