Skip to content

Commit

Permalink
docs: add fsdocs initial impl
Browse files Browse the repository at this point in the history
  • Loading branch information
AngelMunoz authored Aug 15, 2024
1 parent a51e45b commit 8ad70b2
Show file tree
Hide file tree
Showing 8 changed files with 157 additions and 5 deletions.
7 changes: 7 additions & 0 deletions .config/dotnet-tools.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@
"fantomas"
],
"rollForward": false
},
"fsdocs-tool": {
"version": "20.0.1",
"commands": [
"fsdocs"
],
"rollForward": false
}
}
}
46 changes: 46 additions & 0 deletions .github/workflows/docs.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
name: Docs

# Trigger this Action when new code is pushed to the main branch
on:
push:
branches:
- main

# We need some permissions to publish to Github Pages
permissions:
contents: write
pages: write
id-token: write

jobs:
build:
runs-on: ubuntu-latest
steps:
# Checkout the source code
- uses: actions/checkout@v4
# Setup dotnet, please use a global.json to ensure the right SDK is used!
- name: Setup .NET
uses: actions/setup-dotnet@v3
# Restore the local tools
- name: Restore tools
run: dotnet tool restore
# Build the code for the API documentation
- name: Build code
run: dotnet build -c Release Threads.Lib/Threads.Lib.fsproj
# Generate the documentation files
- name: Generate the documentation'
run: dotnet fsdocs build --properties Configuration=Release
# Upload the static files
- name: Upload documentation
uses: actions/upload-pages-artifact@v3
with:
path: ./output

# GitHub Actions recommends deploying in a separate job.
deploy:
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -482,3 +482,7 @@ $RECYCLE.BIN/

# Vim temporary swap files
*.swp

output
.fsdocs
tmp
1 change: 0 additions & 1 deletion Sample/Profile.fs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ open Navs.Avalonia

open Threads.Lib
open Threads.Lib.Profiles
open Threads.Lib

module Profile =
open System
Expand Down
3 changes: 2 additions & 1 deletion Sample/Sample.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>false</GenerateDocumentationFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="Extensions.fs" />
Expand All @@ -26,4 +27,4 @@
<ItemGroup>
<ProjectReference Include="..\Threads.Lib\Threads.Lib.fsproj" />
</ItemGroup>
</Project>
</Project>
8 changes: 7 additions & 1 deletion Threads.Lib/Threads.Lib.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,12 @@
<TargetFramework>net8.0</TargetFramework>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>
<PropertyGroup>
<RepositoryUrl>https://github.com/AngelMunoz/Threads.Lib</RepositoryUrl>
<FsDocsLicenseLink>https://github.com/AngelMunoz/Threads.Lib/blob/master/License.md</FsDocsLicenseLink>
<FsDocsReleaseNotesLink>https://github.com/AngelMunoz/Threads.Lib/blob/master/RELEASE_NOTES.md</FsDocsReleaseNotesLink>
<PackageProjectUrl>https://AngelMunoz.github.io/Threads.Lib</PackageProjectUrl>
</PropertyGroup>
<ItemGroup>
<Compile Include="Pagination.fsi" />
<Compile Include="Pagination.fs" />
Expand All @@ -25,4 +31,4 @@
<PackageReference Include="FsToolkit.ErrorHandling.TaskResult" Version="4.16.0" />
<PackageReference Include="Thoth.Json.Net" Version="12.0.0" />
</ItemGroup>
</Project>
</Project>
2 changes: 0 additions & 2 deletions Threads.Lib/Threads.fs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,6 @@ open System.Threading.Tasks
open FsHttp
open System.Runtime.InteropServices

open Threads.Lib

type InsightsService =
abstract FetchMediaInsights:
mediaId: string *
Expand Down
91 changes: 91 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# Threads.Lib

This is a .NET library for the [Threads] API.

## Installation

WIP

## Usage

The library itself is a thin wrapper over the API, so you don't have to craft everything yourself. However we don't provide any authentication dances, so you have to [obtain the access token] required to interact with the API yourself.

Once you have your access token ready to go you can obtain a client instance like this:

```fsharp
open Threads.Lib
open Threads.Lib.Profile
let threads = Threads.Create("access-token")
async {
let! (response: ProfileValue seq) =
threads.Profile.FetchProfile(
profileId = "me",
profileFields = [
ProfileField.Id
ProfileField.Username
ProfileField.ThreadsBiography
ProfileField.ThreadsProfilePictureUrl
]
)
printfn $"%A{response}"
}
```

The Threads API is quite dynamic and you can choose which fields you want to obtain in the response, this is at odds with fsharp's type system which requires types to be statically known at compile time. To work around this we provide a `ProfileValue` type which is a discriminated union of all possible fields you can obtain from the API. This way you can pattern match on the response and extract the fields you need.

An example would be:

```fsharp
// Define a type to represent the user profile
// with all of the fields you're interested in
type UserProfile = {
id: string
username: string
bio: string
}
module UserProfile =
let emptyProfile = {
id = ""
username = ""
bio = ""
}
// In a module or static method, you can define a mapping function to convert
// the ProfileValue seq to a your type instance
let ofValues (values: ProfileValue seq) : UserProfile =
let foldToProfile (current: UserProfile) (nextValue: ProfileValue) =
match nextValue with
| Id id -> { current with id = id }
| Username username -> { current with username = username }
| ThreadsBiography bio -> { current with bio = bio }
| ThreadsProfilePictureUrl profilePicture -> current
Seq.fold foldToProfile emptyProfile values
// somewhere else in your code
async {
let! (response: ProfileValue seq) =
threads.Profile.FetchProfile(
profileId = "me",
profileFields = [
ProfileField.Id
ProfileField.Username
ProfileField.ThreadsBiography
]
)
let profile = UserProfile.ofValues response
printfn $"%A{profile}"
// { id = "1234"; username = "johndoe"; bio = "I'm a bio" }
}
```

While there are too few fields in the profile response. This will come more handy in other responses like the thread posts themselves. Overall the library is meant to be used like this and tries to be as flexible as possible without compromising the type safety of F# or at least that's what we're trying.

[Threads]: https://developers.facebook.com/docs/threads
[obtain the access token]: https://developers.facebook.com/docs/threads/get-started/get-access-tokens-and-permissions

0 comments on commit 8ad70b2

Please sign in to comment.