aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/program/aedifex/repository.lux
blob: 0c8f929930d0a15abc65eaa5b04f32f81f540c9c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
(.module:
  [lux #*
   ["." host (#+ import:)]
   [abstract
    [monad (#+ do)]]
   [control
    ["." io (#+ IO)]
    ["." try (#+ Try)]
    ["." exception (#+ exception:)]
    [concurrency
     ["." promise (#+ Promise)]
     ["." stm]]]
   [data
    [binary (#+ Binary)]
    ["." text
     ["%" format (#+ format)]
     ["." encoding]]]
   [world
    [net (#+ URL)
     ["." uri]]]]
  ["." // #_
   ["#." artifact (#+ Artifact)
    ["#/." extension (#+ Extension)]]])

(type: #export Address
  URL)

(type: #export User
  Text)

(type: #export Password
  Text)

(type: #export Identity
  {#user User
   #password Password})

(signature: #export (Repository !)
  (: (-> Artifact Extension (! (Try Binary)))
     download)
  (: (-> Identity Artifact Extension Binary (! (Try Any)))
     upload))

(def: #export (async repository)
  (-> (Repository IO) (Repository Promise))
  (structure
   (def: (download artifact extension)
     (promise.future (:: repository download artifact extension)))

   (def: (upload identity artifact extension content)
     (promise.future (:: repository upload identity artifact extension content)))
   ))

(signature: #export (Simulation s)
  (: (-> Artifact Extension s
         (Try [s Binary]))
     on-download)
  (: (-> Identity Artifact Extension Binary s
         (Try s))
     on-upload))

(def: #export (mock simulation init)
  (All [s] (-> (Simulation s) s (Repository Promise)))
  (let [state (stm.var init)]
    (structure
     (def: (download artifact extension)
       (stm.commit
        (do {! stm.monad}
          [|state| (stm.read state)]
          (case (:: simulation on-download artifact extension |state|)
            (#try.Success [|state| output])
            (do !
              [_ (stm.write |state| state)]
              (wrap (#try.Success output)))
            
            (#try.Failure error)
            (wrap (#try.Failure error))))))

     (def: (upload identity artifact extension content)
       (stm.commit
        (do {! stm.monad}
          [|state| (stm.read state)]
          (case (:: simulation on-upload identity artifact extension content |state|)
            (#try.Success |state|)
            (do !
              [_ (stm.write |state| state)]
              (wrap (#try.Success [])))
            
            (#try.Failure error)
            (wrap (#try.Failure error))))))
     )))

(import: java/lang/AutoCloseable
  (close [] #io #try void))

(import: java/io/OutputStream
  (flush [] #io #try void)
  (write [[byte]] #io #try void))

(import: java/lang/String)

(import: java/net/URLConnection
  (setDoOutput [boolean] #io #try void)
  (setRequestProperty [java/lang/String java/lang/String] #io #try void)
  (getOutputStream [] #io #try java/io/OutputStream))

(import: java/net/HttpURLConnection
  (setRequestMethod [java/lang/String] #io #try void)
  (getResponseCode [] #io #try int))

(import: java/net/URL
  (new [java/lang/String])
  (openConnection [] #io #try java/net/URLConnection))

(import: java/util/Base64$Encoder
  (encodeToString [[byte]] java/lang/String))

(import: java/util/Base64
  (#static getEncoder [] java/util/Base64$Encoder))

(exception: #export (failure {code Int})
  (exception.report
   ["Code" (%.int code)]))

(def: (basic-auth user password)
  (-> User Password Text)
  (format "Basic " (java/util/Base64$Encoder::encodeToString (encoding.to-utf8 (format user ":" password))
                                                             (java/util/Base64::getEncoder))))

(def: (url address artifact extension)
  (-> Address Artifact Extension URL)
  (format address uri.separator (//artifact.uri artifact) extension))

(structure: #export (default address)
  (All [s] (-> Address (Repository IO)))

  (def: (download artifact extension)
    (io.io (#try.Failure "YOLO")))

  (def: (upload [user password] artifact extension content)
    (do (try.with io.monad)
      [connection (|> (..url address artifact extension)
                      java/net/URL::new
                      java/net/URL::openConnection)
       #let [connection (:coerce java/net/HttpURLConnection connection)]
       _ (java/net/HttpURLConnection::setRequestMethod "PUT" connection)
       _ (java/net/URLConnection::setDoOutput true connection)
       _ (java/net/URLConnection::setRequestProperty "Authorization" (..basic-auth user password) connection)
       stream (java/net/URLConnection::getOutputStream connection)
       _ (java/io/OutputStream::write content stream)
       _ (java/io/OutputStream::flush stream)
       _ (java/lang/AutoCloseable::close stream)
       code (java/net/HttpURLConnection::getResponseCode connection)]
      (case code
        +200 (wrap [])
        _ (:: io.monad wrap (exception.throw ..failure [code])))))
  )