{"id":16485399,"url":"https://github.com/zaid-ajaj/fable.cloudflareworkers","last_synced_at":"2025-10-07T23:52:35.154Z","repository":{"id":47969979,"uuid":"207681331","full_name":"Zaid-Ajaj/Fable.CloudFlareWorkers","owner":"Zaid-Ajaj","description":"Write CloudFlare Workers in idiomatic, type-safe F# and compile them to JS using Fable","archived":false,"fork":false,"pushed_at":"2023-01-04T12:08:23.000Z","size":238,"stargazers_count":31,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-17T22:37:59.025Z","etag":null,"topics":["cloudflare","fable","fsharp","http","workers"],"latest_commit_sha":null,"homepage":null,"language":"F#","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/Zaid-Ajaj.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}},"created_at":"2019-09-10T23:29:52.000Z","updated_at":"2024-03-08T17:52:34.000Z","dependencies_parsed_at":"2023-02-02T11:45:24.596Z","dependency_job_id":null,"html_url":"https://github.com/Zaid-Ajaj/Fable.CloudFlareWorkers","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/Zaid-Ajaj%2FFable.CloudFlareWorkers","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zaid-Ajaj%2FFable.CloudFlareWorkers/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zaid-Ajaj%2FFable.CloudFlareWorkers/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Zaid-Ajaj%2FFable.CloudFlareWorkers/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Zaid-Ajaj","download_url":"https://codeload.github.com/Zaid-Ajaj/Fable.CloudFlareWorkers/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244757475,"owners_count":20505406,"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":["cloudflare","fable","fsharp","http","workers"],"created_at":"2024-10-11T13:25:47.603Z","updated_at":"2025-10-07T23:52:30.131Z","avatar_url":"https://github.com/Zaid-Ajaj.png","language":"F#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Fable.CloudFlareWorkers\n\nWrite [CloudFlare Workers](https://workers.cloudflare.com/) in idiomatic, type-safe F# and compile them to JS using [Fable](https://github.com/fable-compiler/Fable)\n\n### Install the CloudFlare Worker APIs\n```\ndotnet add package Fable.CloudFlareWorkers\n```\n### Write your worker logic in F#\n```fs\nmodule App\n\nopen CloudFlareWorkers\n\nlet worker (request: IHttpRequest) =\n    async {\n        match request.method, request.path with\n        | HttpMethod.GET, \"/\" -\u003e\n            return Response.create(body=\"Home, sweet home\", status=200)\n\n        | HttpMethod.POST, \"/echo\" -\u003e\n            let! body = request.body()\n            return Response.create(body=body, status=200)\n\n        | otherwise -\u003e\n            let body = \"{ \\\"message\\\": \\\"Not Found\\\" }\"\n            let headers = Map.ofList [ \"content-type\", \"application/json\" ]\n            return Response.create(body, status=404, headers=headers)\n    }\n\nWorker.initialize worker\n```\n\nA \"worker\" is a function of type `IHttpRequest -\u003e Async\u003cIHttpResponse\u003e` which is what `Worker.initialize` expects. However, you could also implement simple synchronous workers of type `IHttpRequest -\u003e IHttpResponse` and give them to `Worker.initialize`:\n```fs\nlet worker (request: IHttpRequest) =\n    match request.method, request.path with\n    | HttpMethod.GET, \"/\" -\u003e\n        Response.create(body=\"Home, sweet home\", status=200)\n\n    | otherwise -\u003e\n        let body = \"{ \\\"message\\\": \\\"Not Found\\\" }\"\n        let headers = [ \"Content-type\", \"application/json\" ]\n        Response.create(body, status=404, headers=headers)\n\nWorker.initialize worker\n```\n\n### Making internal requests from the worker\n\nCloudFlare workers are able to `fetch` resources using requests and receive responses. In order to send a request with `fetch`, you have to inside a [Request Context](https://developers.cloudflare.com/workers/about/tips/request-context/). Using this library, you can access the request context and thus use `fetch` by using the type `IRequestContext` as your input of the worker where\n```fs\ntype IRequestContext =\n    abstract request : IHttpRequest\n    abstract fetch : IHttpRequest -\u003e Async\u003cIHttpResponse\u003e\n```\nNow build your worker where it expects such context:\n```fs\nlet echo (context: IRequestContext) =\n    async {\n        let request = context.request\n        let! response = context.fetch request\n        return response\n    }\n\nWorker.initialize echo\n```\nAs simple as that! Here, `Worker.initialize` is using another overload that has type `IRequestContext -\u003e Async\u003cIHttpResponse\u003e`. You can also create your own requests using the `Request.create` function.\n\n### Compiling the project\n\nUse a combination of `fable-splitter` to compile the project into ES6 syntax, then use [rollup](https://rollupjs.org/guide/en/) to bundle the application as a single script. First of all, assuming the directory structure is as follows:\n```\n{root}\n  |\n  | -- src\n        |\n        | -- App.fs\n        | -- App.fsproj\n  |\n  | -- package.json\n  | -- README.md\n  | -- package-lock.json\n```\nInstall [Fable](https://github.com/fable-compiler/Fable) compiler along with `fable-splitter` and `rollup`:\n```\nnpm install fable-compiler fable-splitter rollup @babel/core --save-dev\n```\nThen have one npm script to compile the application,  another to bundle it and another that does both:\n```json\n{\n    \"compile\": \"fable-splitter ./src -o ./dist\",\n    \"bundle\": \"rollup ./dist/App.js -f iife --name App -o ./dist/bundle.js\",\n    \"build\": \"npm run compile \u0026\u0026 npm run bundle\"\n}\n```\nNotice here that the entry file for `rollup` is `./dist/App.js` that is because `fable-splitter` compiled the entry file `App.fs` as the last file from the F# project which then becomes `App.js`.\n\nNow `rollup` takes this `App.js` entry file and compiles it into a single file as `./dist/bundle.js` this is where your worker script lives.\n\n\u003e As for the  `--name App` flag of rollup, it is used to give the IIFE a name inside the file and it is required but it can be any name you want.\n\n### Testing the worker live\n\nCopy the contents of the file `./dist/bundle.js`, then go to [https://cloudflareworkers.com](https://cloudflareworkers.com) and paste the code to the left, press `CTRL + S` or click the \"Update\" button to update the code running where the page will show you \"Home, sweet home\":\n\n![](assets/home.png)\n\nIf you change the path in the url to something like `/other` then you get the \"Not Found\" message:\n\n![](assets/not-found.png)\n\n### Resources\n\n- [Cloudflare Workers Documentation](https://developers.cloudflare.com/workers/)\n\n- [CloudFlare Workers Tooling](https://developers.cloudflare.com/workers/tooling/)\n\n- [Joerg Beekmann - Cloudflare Workers in FSharp- Part I](https://github.com/jbeeko/cfworker-hello-world)\n\n- [Joerg Beekmann - Cloudflare Workers in FSharp - II](https://github.com/jbeeko/cfworker-web-api)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaid-ajaj%2Ffable.cloudflareworkers","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzaid-ajaj%2Ffable.cloudflareworkers","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzaid-ajaj%2Ffable.cloudflareworkers/lists"}