Skip to content

Instantly share code, notes, and snippets.

@wallymathieu
Forked from akhansari/onion-1.fs
Last active September 20, 2022 19:32
Show Gist options
  • Save wallymathieu/68b14bcd3e45c4c5b040b60c558a5318 to your computer and use it in GitHub Desktop.
Save wallymathieu/68b14bcd3e45c4c5b040b60c558a5318 to your computer and use it in GitHub Desktop.

Revisions

  1. wallymathieu revised this gist Sep 20, 2022. 1 changed file with 43 additions and 0 deletions.
    43 changes: 43 additions & 0 deletions onion_1.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,43 @@
    // 1_domain.ts
    // 1. pure, don't think about IO at all

    export function add(x: number, y: number) {
    return x+y;
    }

    // 2_app.ts
    // 2. think about IO but not its implementation
    import * as Domain from './1_domain'

    export async function add( getX: () => Promise<number>, y: number) {
    const x = await getX()
    return Domain.add(x, y);
    }

    // 3_infra.ts
    // 3. IO implementation
    import fetch from 'node-fetch';

    export async function getX(apiUrl:string): Promise<number> {
    const response = await fetch(apiUrl, { method: 'GET'});
    const data = await response.json();
    if (response.ok) {
    return (data as number);
    } else {
    return Promise.reject(`Got an error response ${JSON.stringify(data)}`);
    }
    }

    export function getConfigurationUrl() : string {
    throw new Error('Function not implemented.');
    }

    // 4_index.ts
    import * as App from './2_app'
    import * as Infra from './3_infra'

    // 4. inject dependencies
    export function add (y:number){
    const apiUrl = Infra.getConfigurationUrl();
    return App.add ( ()=> Infra.getX(apiUrl), y);
    }
  2. @akhansari akhansari revised this gist Dec 5, 2020. 2 changed files with 4 additions and 2 deletions.
    3 changes: 2 additions & 1 deletion onion-1.fs
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@ module Domain =

    // 2. think about IO but not its implementation
    module App =
    let add (getX: unit -> int32 Async) y =
    let add (getX: unit -> Async<int32>) y =
    async {
    let! x = getX ()
    return Domain.add x y
    @@ -18,6 +18,7 @@ module Infra =
    module Startup =
    let add = App.add Infra.getX

    // demo
    Startup.add 3
    |> Async.RunSynchronously
    |> printfn "%A" // 10
    3 changes: 2 additions & 1 deletion onion-2.fs
    Original file line number Diff line number Diff line change
    @@ -4,7 +4,7 @@ module Domain =

    // 2. think about IO but not its implementation
    module App =
    let add (getX: unit -> int32 Async) y =
    let add (getX: unit -> Async<int32>) y =
    async {
    let! x = getX ()
    return Domain.add x y
    @@ -24,6 +24,7 @@ module Startup =
    return! App.add (fun () -> Infra.getX conn) y
    }

    // demo
    Startup.add 3
    |> Async.RunSynchronously
    |> printfn "%A" // 10
  3. @akhansari akhansari created this gist Nov 27, 2020.
    23 changes: 23 additions & 0 deletions onion-1.fs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,23 @@
    // 1. pure, don't think about IO at all
    module Domain =
    let add x y = x + y

    // 2. think about IO but not its implementation
    module App =
    let add (getX: unit -> int32 Async) y =
    async {
    let! x = getX ()
    return Domain.add x y
    }

    // 3. IO implementation
    module Infra =
    let getX () = async { return 7 }

    // 4. inject dependencies
    module Startup =
    let add = App.add Infra.getX

    Startup.add 3
    |> Async.RunSynchronously
    |> printfn "%A" // 10
    29 changes: 29 additions & 0 deletions onion-2.fs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    // 1. pure, don't think about IO at all
    module Domain =
    let add x y = x + y

    // 2. think about IO but not its implementation
    module App =
    let add (getX: unit -> int32 Async) y =
    async {
    let! x = getX ()
    return Domain.add x y
    }

    // 3. IO implementation
    module Infra =
    open System.Data.SqlClient
    let newConnection () = new SqlConnection ()
    let getX conn = async { return 7 }

    // 4. inject dependencies
    module Startup =
    let add y =
    async {
    use conn = Infra.newConnection ()
    return! App.add (fun () -> Infra.getX conn) y
    }

    Startup.add 3
    |> Async.RunSynchronously
    |> printfn "%A" // 10