<commit_before>port module PouchDB exposing (..)

import Ext.Random as Random
import Json.Decode as D exposing (Decoder)
import Json.Decode.Pipeline as D
import Json.Encode as E
import Port exposing (Tracker)
import Random.Pcg as Random exposing (Seed)
import List.Extra as List
import Time exposing (Time)
import Toolkit.Helpers exposing (..)
import Toolkit.Operators exposing (..)
import Ext.Function exposing (..)
import Ext.Function.Infix exposing (..)
import Tuple2


--port onPouchDBBulkDocksResponse : (D.Value -> msg) -> Sub msg
-- COMMANDS
--port pouchDBBulkDocks : ( String, List D.Value ) -> Cmd msg


port pouchDBUpsert : ( String, String, D.Value ) -> Cmd msg


upsert : String -> (Document x -> E.Value) -> Document x -> Cmd msg
upsert dbName encoder doc =
    pouchDBUpsert ( dbName, doc.id, encoder doc )


type alias Id =
    String


type alias Revision =
    String


defaultRevision =
    ""


type alias Document moreFields =
    { moreFields | id : Id, rev : Revision, dirty : Bool }


type alias HasTimeStamps otherFields =
    { otherFields | createdAt : Time, modifiedAt : Time }


documentFieldsDecoder : Decoder (Id -> Revision -> otherFields) -> Decoder otherFields
documentFieldsDecoder =
    D.required "_id" D.string
        >> D.required "_rev" D.string


timeStampFieldsDecoder : Decoder (Time -> Time -> otherFields) -> Decoder otherFields
timeStampFieldsDecoder =
    D.optional "createdAt" (D.float) 0
        >> D.optional "modifiedAt" (D.float) 0


type alias Store x =
    { seed : Seed
    , list : List (Document x)
    , encoder : Document x -> E.Value
    , name : String
    }


init name encoder list seed =
    { seed = seed
    , list = list
    , name = name
    , encoder = encoder
    }


prepend : Document x -> Store x -> Store x
prepend model =
    updateList (asList >> (::) model)


map fn =
    asList >> List.map fn


findBy predicate =
    asList >> List.find predicate


findById id =
    findBy (.id >> (==) id)


addFromTuple : ( Document x, Store x ) -> ( Document x, Store x )
addFromTuple =
    apply2 ( Tuple.first, uncurry prepend )


insert : (Id -> Document x) -> Store x -> Store x
insert constructor s=
    Random.mapWithIdGenerator constructor

            |> generate # s

            |>  (\( d, s ) -> prepend { d | dirty = True } s)


update : Document x -> Store x -> Store x
update doc s =
    let
        newDoc =
            { doc | dirty = True }
    in
        List.replaceIf (\d2 -> d2.id == doc.id) (newDoc) s.list
            |> (setList # s)


generate : Random.Generator (Document x) -> Store x -> ( Document x, Store x )<commit_msg>Refactoring: centralize id generation code<commit_after>port module PouchDB exposing (..)

import Ext.Random as Random
import Json.Decode as D exposing (Decoder)
import Json.Decode.Pipeline as D
import Json.Encode as E
import Port exposing (Tracker)
import Random.Pcg as Random exposing (Seed)
import List.Extra as List
import Time exposing (Time)
import Toolkit.Helpers exposing (..)
import Toolkit.Operators exposing (..)
import Ext.Function exposing (..)
import Ext.Function.Infix exposing (..)
import Tuple2


--port onPouchDBBulkDocksResponse : (D.Value -> msg) -> Sub msg
-- COMMANDS
--port pouchDBBulkDocks : ( String, List D.Value ) -> Cmd msg


port pouchDBUpsert : ( String, String, D.Value ) -> Cmd msg


upsert : String -> (Document x -> E.Value) -> Document x -> Cmd msg
upsert dbName encoder doc =
    pouchDBUpsert ( dbName, doc.id, encoder doc )


type alias Id =
    String


type alias Revision =
    String


defaultRevision =
    ""


type alias Document moreFields =
    { moreFields | id : Id, rev : Revision, dirty : Bool }


type alias HasTimeStamps otherFields =
    { otherFields | createdAt : Time, modifiedAt : Time }


documentFieldsDecoder : Decoder (Id -> Revision -> otherFields) -> Decoder otherFields
documentFieldsDecoder =
    D.required "_id" D.string
        >> D.required "_rev" D.string


timeStampFieldsDecoder : Decoder (Time -> Time -> otherFields) -> Decoder otherFields
timeStampFieldsDecoder =
    D.optional "createdAt" (D.float) 0
        >> D.optional "modifiedAt" (D.float) 0


type alias Store x =
    { seed : Seed
    , list : List (Document x)
    , encoder : Document x -> E.Value
    , name : String
    }


init name encoder list seed =
    { seed = seed
    , list = list
    , name = name
    , encoder = encoder
    }


prepend : Document x -> Store x -> Store x
prepend model =
    updateList (asList >> (::) model)


map fn =
    asList >> List.map fn


findBy predicate =
    asList >> List.find predicate


findById id =
    findBy (.id >> (==) id)


addFromTuple : ( Document x, Store x ) -> ( Document x, Store x )
addFromTuple =
    apply2 ( Tuple.first, uncurry prepend )


insert : (Id -> Document x) -> Store x -> Store x
insert constructor s =
    Random.mapWithIdGenerator constructor
        |> (generate # s)
        |> (\( d, s ) -> prepend { d | dirty = True } s)


update : Document x -> Store x -> Store x
update doc s =
    let
        newDoc =
            { doc | dirty = True }
    in
        List.replaceIf (\d2 -> d2.id == doc.id) (newDoc) s.list
            |> (setList # s)


generate : Random.Generator (Document x) -> Store x -> ( Document x, Store x )
{'fraction_non_alphanumeric': 0.11242153319383678, 'fraction_numerical': 0.002282670724747955, 'mean_word_length': 2.689824561403509, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 87, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '191638', 'n_tokens_mistral': 1700, 'n_tokens_neox': 1603, 'n_words': 560}