on master help sign in
INSTRUCTIONS.mdnew file+60
since splitsnapshots
unifiedsplit
@@ -0,0 +1,60 @@
1+# Installation Instructions
2+
3+1. Create a folder and name it whatever you want.
4+
5+```bash
6+$ mkdir seax-project
7+$ cd seax-project
8+```
9+2. Inside the folder, `clone` the **airlock** library and the **seax** project.
10+
11+```bash
12+$ git clone https://github.com/ilyakooo0/airlock
13+$ git clone https://github.com/ilyakooo0/seax
14+```
15+3. Download the v2.11 pill.
16+
17+```bash
18+$ wget https://bootstrap.urbit.org/urbit-v2.11.pill
19+```
20+4. Start your fake zod using the pill.
21+
22+```bash
23+$ urbit -B urbit-v2.11.pill -F zod
24+```
25+
26+5. Now, inside dojo run the following:
27+```bash
28+dojo> |new-desk %seax
29+dojo> |mount %seax
30+```
31+
32+6. Back in your shell, run:
33+```bash
34+$ rm -r zod/seax
35+$ cp -r seax/zod/seax zod/seax
36+```
37+
38+7. In the dojo install the seax agent and allow cross-site origin requests from localhost.
39+```bash
40+dojo> |commit %seax
41+dojo> |install our %seax
42+dojo> |pass [%e [%approve-origin 'http://localhost:8000']]
43+```
44+
45+8. While your urbit is running in another terminal run:
46+```bash
47+$ ./seax/dev/elm-live.sh
48+```
49+The above command will start the frontend which communicates with your zod ship
50+using the Elm airlock library.
51+
52+Now, you can go to your browser at `http://localhost:8000/`.
53+The seax app should be displaying a search bar. You might need to refresh the page once before using the app.
54+You'll know that everything works if you see the "< ~zod: Opening airlock!" message in your dojo.
55+
56+# Usage Instructions
57+
58+Now, you can fill in the search bar with any term you like.
59+Clicking "search" will iniate collect any relevant results from the configured search sources.
60+In the results page, you can click on any of the sources to filter to only results from that source.
frontend/assets/css/main.css+33−6
@@ -1,11 +1,5 @@
1@import url('https://fonts.googleapis.com/css2?family=Inter:wght@200&family=Roboto+Mono:wght@200&family=Roboto:wght@300&display=swap');
1@import url('https://fonts.googleapis.com/css2?family=Inter:wght@200&family=Roboto+Mono:wght@200&family=Roboto:wght@300&display=swap');
2
2
3−#tilt:hover {
4− /* box-shadow: 0px 0px 30px rgba(0,0,0, 0.6); */
5− /* cursor: pointer; */
6− /* transition: all 0.1s ease-in-out; */
7−}
8−
9.button {
3.button {
10 border: none;
4 border: none;
11 color: white;
5 color: white;
@@ -34,3 +28,36 @@
34.search:hover {
28.search:hover {
35 text-decoration: underline;
29 text-decoration: underline;
36}
30}
31+
32+.wavy {
33+ animation-name: wavy;
34+ animation-duration: 4.2s;
35+ animation-timing-function: ease-in-out;
36+ animation-iteration-count: infinite;
37+ position: relative;
38+ top: 0;
39+ left: 0;
40+}
41+@keyframes wavy {
42+ 0% {
43+ top: 0px;
44+ }
45+ 50% {
46+ top: -15px;
47+ }
48+ 100% {
49+ top: 0px;
50+ }
51+}
52+
53+.result-link {
54+ color: #000;
55+ text-decoration: none;
56+ font-size: 12px !important;
57+}
58+
59+.result-title {
60+ color: #000;
61+ text-decoration: none;
62+ font-size: 16px;
63+}
frontend/elm.json+5
@@ -7,6 +7,7 @@
7 "elm-version": "0.19.1",
7 "elm-version": "0.19.1",
8 "dependencies": {
8 "dependencies": {
9 "direct": {
9 "direct": {
10+ "Evelios/elm-hash": "1.0.0",
10 "TSFoster/elm-bytes-extra": "1.3.0",
11 "TSFoster/elm-bytes-extra": "1.3.0",
11 "avh4/elm-color": "1.0.0",
12 "avh4/elm-color": "1.0.0",
12 "cmditch/elm-bigint": "2.0.1",
13 "cmditch/elm-bigint": "2.0.1",
@@ -32,6 +33,7 @@
32 "ianmackenzie/elm-units": "2.10.0",
33 "ianmackenzie/elm-units": "2.10.0",
33 "jasonliang-dev/elm-heroicons": "2.0.0",
34 "jasonliang-dev/elm-heroicons": "2.0.0",
34 "jxxcarlson/hex": "4.0.0",
35 "jxxcarlson/hex": "4.0.0",
36+ "marcosh/elm-html-to-unicode": "1.0.4",
35 "mdgriffith/elm-animator": "1.1.1",
37 "mdgriffith/elm-animator": "1.1.1",
36 "mdgriffith/elm-ui": "1.1.8",
38 "mdgriffith/elm-ui": "1.1.8",
37 "rtfeldman/elm-css": "18.0.0",
39 "rtfeldman/elm-css": "18.0.0",
@@ -43,6 +45,8 @@
43 "AdrianRibao/elm-derberos-date": "1.2.3",
45 "AdrianRibao/elm-derberos-date": "1.2.3",
44 "NoRedInk/elm-string-conversions": "1.0.1",
46 "NoRedInk/elm-string-conversions": "1.0.1",
45 "bitsoflogic/elm-radixint": "2.0.0",
47 "bitsoflogic/elm-radixint": "2.0.0",
48+ "bonzaico/murmur3": "1.0.0",
49+ "chain-partners/elm-bignum": "1.0.1",
46 "elm/file": "1.0.5",
50 "elm/file": "1.0.5",
47 "elm/parser": "1.1.0",
51 "elm/parser": "1.1.0",
48 "elm/random": "1.0.0",
52 "elm/random": "1.0.0",
@@ -55,6 +59,7 @@
55 "ianmackenzie/elm-interval": "3.1.0",
59 "ianmackenzie/elm-interval": "3.1.0",
56 "ianmackenzie/elm-units-interval": "3.2.0",
60 "ianmackenzie/elm-units-interval": "3.2.0",
57 "ktonon/elm-word": "2.1.2",
61 "ktonon/elm-word": "2.1.2",
62+ "myrho/elm-round": "1.0.5",
58 "robinheghan/murmur3": "1.0.0"
63 "robinheghan/murmur3": "1.0.0"
59 }
64 }
60 },
65 },
frontend/src/Main.elm+108−20
@@ -10,13 +10,19 @@ import Element.Events as Events exposing (onClick)
10import Element.Font as Font
10import Element.Font as Font
11import Element.Input as Input
11import Element.Input as Input
12import Element.Keyed as Keyed
12import Element.Keyed as Keyed
13+import Html exposing (Html, hr)
13import Html.Attributes
14import Html.Attributes
15+import Html.Parser
16+import Html.String
14import Html.String
17import Html.String
15import Html.Styled.Attributes exposing (css)
18import Html.Styled.Attributes exposing (css)
16−import Html exposing (Html, hr)
19+import Html.Styled.Attributes exposing (css)
20+import Html.Events exposing (on)
17import Json.Decode as JD
21import Json.Decode as JD
22+import List
18import List.Extra
23import List.Extra
19import Set exposing (Set)
24import Set exposing (Set)
25+import String.Extra exposing (stripTags)
20import Time exposing (Posix)
26import Time exposing (Posix)
21import Ur
27import Ur
22import Ur.Cmd
28import Ur.Cmd
@@ -25,13 +31,10 @@ import Ur.Jam exposing (isSig)
25import Ur.Run
31import Ur.Run
26import Ur.Sub
32import Ur.Sub
27import Ur.Types exposing (Noun(..))
33import Ur.Types exposing (Noun(..))
28−import Html.String
34+import Url
29−import List
35+import ElmEscapeHtml
30−import Css
36+import Json.Encode
31−import Html.Styled.Attributes exposing (css)
37+import Hash
32−import Html.Parser
33−import String.Extra exposing (stripTags)
34−
35
38
36url : String
39url : String
37url =
40url =
@@ -107,9 +110,16 @@ main =
107 , body =
110 , body =
108 [ view model
111 [ view model
109 |> layout
112 |> layout
110− [ Font.family
113+ [ Font.family
111 [ Font.typeface "monospace"
114 [ Font.typeface "monospace"
112− , Font.typeface "Apple Color Emoji"
115+ , Font.typeface "system-ui"
116+ , Font.typeface "-apple-system"
117+ , Font.typeface "BlinkMacSystemFont"
118+ , Font.typeface "Segoe UI"
119+ , Font.typeface "Roboto"
120+ , Font.typeface "Helvetica"
121+ , Font.typeface "Arial"
122+ , Font.sansSerif
113 ]
123 ]
114 , clipX
124 , clipX
115 ]
125 ]
@@ -154,6 +164,48 @@ logoView attributes =
154 Element.image (List.append [ Html.Attributes.id "tilt" |> htmlAttribute ] attributes)
164 Element.image (List.append [ Html.Attributes.id "tilt" |> htmlAttribute ] attributes)
155 { src = "assets/img/logo.png", description = "%seax logo" }
165 { src = "assets/img/logo.png", description = "%seax logo" }
156
166
167+noSearchResultsView : Element Msg
168+noSearchResultsView = Element.el
169+ [ Html.Attributes.style "padding" "1em" |> htmlAttribute
170+ , width (px 500)
171+ , Font.size 15
172+ , Html.Attributes.class "wavy" |> htmlAttribute
173+ ]
174+ (Element.text """No results found... :)
175+We'll try and find you something.
176+Just come back later.""")
177+
178+subtleLinkView : String -> String -> Element Msg
179+subtleLinkView text href =
180+ Element.el
181+ [ Font.size 15
182+ , pointer
183+ , mouseOver
184+ [ Font.color (rgb 0.1 0.7 0.7)
185+ ]
186+ ]
187+ (Element.html (Html.a [ Html.Attributes.href href ] [ Html.text text ]))
188+
189+aboutView : Element Msg
190+aboutView = row [ centerX, padding 10, spacing 10]
191+ [ subtleLinkView "[About]" "https://vagos.github.io/seax"
192+ , subtleLinkView "[Code]" "https://github.com/ilyakooo0/seax"
193+ ]
194+
195+titleEmoji : String -> String
196+titleEmoji title =
197+ let maxUnicode = 0x1F3F0
198+ minUnicode = 0x1F300
199+ in title |> Hash.fromString
200+ |> Hash.toString
201+ |> String.toInt
202+ |> Maybe.withDefault 0
203+ |> (\x -> ((modBy (maxUnicode - minUnicode) x) + minUnicode))
204+ |> Char.fromCode
205+ |> String.fromChar
206+ |> (\x -> x ++ " ")
207+
208+
157view : Model -> Element Msg
209view : Model -> Element Msg
158view model =
210view model =
159 case model.initiatedSearch of
211 case model.initiatedSearch of
@@ -161,6 +213,7 @@ view model =
161 column [ centerX, centerY, padding 8, spacing 16 ]
213 column [ centerX, centerY, padding 8, spacing 16 ]
162 [ logoView [ centerX, width (px 510), height (px 161) ]
214 [ logoView [ centerX, width (px 510), height (px 161) ]
163 , searchView model
215 , searchView model
216+ , aboutView
164 ]
217 ]
165
218
166 Just _ ->
219 Just _ ->
@@ -214,8 +267,10 @@ view model =
214 ]
267 ]
215 )
268 )
216 ]
269 ]
217− , Element.html (Html.hr [Html.Attributes.style "width" "95%"] [])
270+ , (if List.isEmpty model.searchResults then
271+ noSearchResultsView
272+ else
218− , Keyed.column [ width (minimum 0 fill), padding 8 ]
273+ Keyed.column [ width (minimum 0 fill), padding 8 ]
219 (model.searchResults
274 (model.searchResults
220 |> List.filter
275 |> List.filter
221 (\{ engines } ->
276 (\{ engines } ->
@@ -252,7 +307,7 @@ view model =
252 |> Maybe.map Tuple.first
307 |> Maybe.map Tuple.first
253 |> Maybe.withDefault (Animator.init 0)
308 |> Maybe.withDefault (Animator.init 0)
254 )
309 )
255− (\i -> toFloat i * 47 |> Animator.at)
310+ (\i -> toFloat i * 0 |> Animator.at)
256 |> String.fromFloat
311 |> String.fromFloat
257 )
312 )
258 ++ "px"
313 ++ "px"
@@ -262,27 +317,60 @@ view model =
262 , Html.Attributes.style "padding" "0.5em" |> htmlAttribute
317 , Html.Attributes.style "padding" "0.5em" |> htmlAttribute
263 , Html.Attributes.class "result" |> htmlAttribute
318 , Html.Attributes.class "result" |> htmlAttribute
264 ]
319 ]
265− [ text (stripTags title)
320+ [ (Element.html
266− |> el
321+ (Html.a
267− [ Font.size 16
322+ [ Html.Attributes.href link
323+ , Html.Attributes.class "result-title"
324+ , Html.Attributes.target "_blank"
268 ]
325 ]
326+ [ Html.text
327+ (Maybe.withDefault ""
328+ (Url.percentDecode
329+ (ElmEscapeHtml.unescape
330+ (stripTags
331+ ((titleEmoji title) ++ title)
332+ ))))
333+ ]
334+ )
335+ )
269 , text link
336 , text link
270 |> el
337 |> el
271− [ Font.size 12
272− , Font.color (rgb 0.7 0.7 0.7)
338+ [ Font.color (rgb 0.7 0.7 0.7)
339+ , Html.Attributes.class "result-link" |> htmlAttribute
273 ]
340 ]
274 ]
341 ]
275 )
342 )
276 )
343 )
277− )
344+ ))
278 , Element.html (Html.hr [Html.Attributes.style "width" "95%"] [])
345 , Element.html (Html.hr [Html.Attributes.style "width" "95%"] [])
346+ , aboutView
279 ]
347 ]
280
348
281
349
350+onEnter : msg -> Element.Attribute msg
351+onEnter msg =
352+ Element.htmlAttribute
353+ (Html.Events.on "keyup"
354+ (JD.field "key" JD.string
355+ |> JD.andThen
356+ (\key ->
357+ if key == "Enter" then
358+ JD.succeed msg
359+
360+ else
361+ JD.fail "Not the enter key"
362+ )
363+ )
364+ )
365+
366+
282searchView : { a | search : String } -> Element Msg
367searchView : { a | search : String } -> Element Msg
283searchView model =
368searchView model =
284 row [ spacing 8 ]
369 row [ spacing 8 ]
370+ [ Input.text
285− [ Input.text [ Html.Attributes.class "shadow" |> htmlAttribute, width (px 400)]
371+ [ Html.Attributes.class "shadow" |> htmlAttribute, width (px 400)
372+ , onEnter (Search model.search)
373+ ]
286 { onChange = UpdateSearch
374 { onChange = UpdateSearch
287 , placeholder = Nothing
375 , placeholder = Nothing
288 , text = model.search
376 , text = model.search
zod/seax/app/seax.hoon+10−7
@@ -1,6 +1,6 @@
1/- *seax
1/- *seax
2+/- diary
2−/+ dbug, engines, rank, sink
3+/+ dbug, engines, rank, sink, strandio
3−
4|%
4|%
5+$ query cord
5+$ query cord
6+$ search-state
6+$ search-state
@@ -10,6 +10,7 @@ $:
10==
10==
11+$ state-0
11+$ state-0
12$:
12$:
13+ notes=shelf:diary
13 search-subscriptions=(map query search-state)
14 search-subscriptions=(map query search-state)
14 peers=_(silt ~[~zod ~racfer-hattes])
15 peers=_(silt ~[~zod ~racfer-hattes])
15 alive-peers=(set @p)
16 alive-peers=(set @p)
@@ -17,6 +18,7 @@ $:
17+$ poke
18+$ poke
18 $%
19 $%
19 [%add-peers (set @p)]
20 [%add-peers (set @p)]
21+ [%get-notes ~]
20 ==
22 ==
21++ rank-results
23++ rank-results
22 |= search-results=(map term (unit (list search-result)))
24 |= search-results=(map term (unit (list search-result)))
@@ -88,15 +90,16 @@ $:
88 state state
90 state state
89 ==
91 ==
90++ on-poke
92++ on-poke
91− |= [* * pk=*]
93+ |= [=mark =vase]
92 ^- (quip card:agent:gall _this)
94 ^- (quip card:agent:gall _this)
93− =/ poke (poke pk)
95+ =/ poke !<(poke vase)
94 ~& poke
96 ~& poke
95 ?- -.poke
97 ?- -.poke
96− %add-peers
98+ %add-peers
97− [~ this(peers.state (~(put in (~(uni in peers.state) +.poke)) src.bowl))]
99+ [~ this(peers.state (~(put in (~(uni in peers.state) +.poke)) src.bowl))]
100+ %get-notes
101+ `this(notes.state .^(shelf:diary %gx /(scot %p our.bowl)/diary/(scot %da now.bowl)/shelf/noun))
98 ==
102 ==
99−
100++ on-watch
103++ on-watch
101 |= =path
104 |= =path
102 ?+ path !!
105 ?+ path !!
zod/seax/lib/graph-store.hoonnew file+919
@@ -0,0 +1,919 @@
1+/- sur=graph-store, pos=post, pull-hook, hark=hark-store
2+/+ res=resource, migrate
3+=< [sur .]
4+=< [pos .]
5+=, sur
6+=, pos
7+|%
8+++ hark-content
9+ |= =content
10+ ^- content:hark
11+ ?- -.content
12+ %text content
13+ %mention ship+ship.content
14+ %url text+url.content
15+ %code text+'A code excerpt'
16+ %reference text+'A reference'
17+ ==
18+::
19+++ hark-contents
20+ |= cs=(list content)
21+ (turn cs hark-content)
22+:: NOTE: move these functions to zuse
23+++ nu :: parse number as hex
24+ |= jon=json
25+ ?> ?=([%s *] jon)
26+ (rash p.jon hex)
27+::
28+++ re :: recursive reparsers
29+ |* [gar=* sef=_|.(fist:dejs-soft:format)]
30+ |= jon=json
31+ ^- (unit _gar)
32+ =- ~! gar ~! (need -) -
33+ ((sef) jon)
34+::
35+++ dank :: tank
36+ ^- $-(json (unit tank))
37+ =, ^? dejs-soft:format
38+ %+ re *tank |. ~+
39+ %- of :~
40+ leaf+sa
41+ palm+(ot style+(ot mid+sa cap+sa open+sa close+sa ~) lines+(ar dank) ~)
42+ rose+(ot style+(ot mid+sa open+sa close+sa ~) lines+(ar dank) ~)
43+ ==
44+::
45+++ orm ((on atom node) gth)
46+++ orm-log ((on time logged-update) gth)
47+::
48+++ enjs
49+ =, enjs:format
50+ |%
51+ ::
52+ ++ signatures
53+ |= s=^signatures
54+ ^- json
55+ [%a (turn ~(tap in s) signature)]
56+ ::
57+ ++ signature
58+ |= s=^signature
59+ ^- json
60+ %- pairs
61+ :~ [%signature s+(scot %ux p.s)]
62+ [%ship (ship q.s)]
63+ [%life (numb r.s)]
64+ ==
65+ ::
66+ ++ index
67+ |= ind=^index
68+ ^- json
69+ :- %s
70+ ?: =(~ ind)
71+ '/'
72+ %+ roll ind
73+ |= [cur=@ acc=@t]
74+ ^- @t
75+ =/ num (numb cur)
76+ ?> ?=(%n -.num)
77+ (rap 3 acc '/' p.num ~)
78+ ::
79+ ++ uid
80+ |= u=^uid
81+ ^- json
82+ %- pairs
83+ :~ [%resource (enjs:res resource.u)]
84+ [%index (index index.u)]
85+ ==
86+ ::
87+ ++ content
88+ |= c=^content
89+ ^- json
90+ ?- -.c
91+ %mention (frond %mention (ship ship.c))
92+ %text (frond %text s+text.c)
93+ %url (frond %url s+url.c)
94+ %reference (frond %reference (reference +.c))
95+ %code
96+ %+ frond %code
97+ %- pairs
98+ :- [%expression s+expression.c]
99+ :_ ~
100+ :- %output
101+ :: virtualize output rendering, +tank:enjs:format might crash
102+ ::
103+ =/ result=(each (list json) tang)
104+ (mule |.((turn output.c tank)))
105+ ?- -.result
106+ %& a+p.result
107+ %| a+[a+[%s '[[output rendering error]]']~]~
108+ ==
109+ ==
110+ ::
111+ ++ reference
112+ |= ref=^reference
113+ |^
114+ %+ frond -.ref
115+ ?- -.ref
116+ %graph (graph +.ref)
117+ %group (group +.ref)
118+ %app (app +.ref)
119+ ==
120+ ::
121+ ++ graph
122+ |= [grp=res gra=res idx=^index]
123+ %- pairs
124+ :~ graph+s+(enjs-path:res gra)
125+ group+s+(enjs-path:res grp)
126+ index+(index idx)
127+ ==
128+ ::
129+ ++ group
130+ |= grp=res
131+ s+(enjs-path:res grp)
132+ ::
133+ ++ app
134+ |= [=^ship =desk p=^path]
135+ %- pairs
136+ :~ ship+s+(scot %p ship)
137+ desk+s+desk
138+ path+(path p)
139+ ==
140+ --
141+ ::
142+ ++ maybe-post
143+ |= mp=^maybe-post
144+ ^- json
145+ ?- -.mp
146+ %| s+(scot %ux p.mp)
147+ %& (post p.mp)
148+ ==
149+ ::
150+ ++ post
151+ |= p=^post
152+ ^- json
153+ %- pairs
154+ :~ [%author (ship author.p)]
155+ [%index (index index.p)]
156+ [%time-sent (time time-sent.p)]
157+ [%contents [%a (turn contents.p content)]]
158+ [%hash ?~(hash.p ~ s+(scot %ux u.hash.p))]
159+ [%signatures (signatures signatures.p)]
160+ ==
161+ ::
162+ ++ update
163+ |= upd=^update
164+ ^- json
165+ |^ (frond %graph-update (pairs ~[(encode q.upd)]))
166+ ::
167+ ++ encode
168+ |= upd=action
169+ ^- [cord json]
170+ ?- -.upd
171+ %add-graph
172+ :- %add-graph
173+ %- pairs
174+ :~ [%resource (enjs:res resource.upd)]
175+ [%graph (graph graph.upd)]
176+ [%mark ?~(mark.upd ~ s+u.mark.upd)]
177+ [%overwrite b+overwrite.upd]
178+ ==
179+ ::
180+ %remove-graph
181+ [%remove-graph (enjs:res resource.upd)]
182+ ::
183+ %add-nodes
184+ :- %add-nodes
185+ %- pairs
186+ :~ [%resource (enjs:res resource.upd)]
187+ [%nodes (nodes nodes.upd)]
188+ ==
189+ ::
190+ %remove-posts
191+ :- %remove-posts
192+ %- pairs
193+ :~ [%resource (enjs:res resource.upd)]
194+ [%indices (indices indices.upd)]
195+ ==
196+ ::
197+ %add-signatures
198+ :- %add-signatures
199+ %- pairs
200+ :~ [%uid (uid uid.upd)]
201+ [%signatures (signatures signatures.upd)]
202+ ==
203+ ::
204+ %remove-signatures
205+ :- %remove-signatures
206+ %- pairs
207+ :~ [%uid (uid uid.upd)]
208+ [%signatures (signatures signatures.upd)]
209+ ==
210+ ::
211+ %add-tag
212+ :- %add-tag
213+ %- pairs
214+ :~ [%term s+term.upd]
215+ [%uid (uid uid.upd)]
216+ ==
217+ ::
218+ %remove-tag
219+ :- %remove-tag
220+ %- pairs
221+ :~ [%term s+term.upd]
222+ [%uid (uid uid.upd)]
223+ ==
224+ ::
225+ %archive-graph
226+ [%archive-graph (enjs:res resource.upd)]
227+ ::
228+ %unarchive-graph
229+ [%unarchive-graph (enjs:res resource.upd)]
230+ ::
231+ %keys
232+ [%keys [%a (turn ~(tap in resources.upd) enjs:res)]]
233+ ::
234+ %tags
235+ [%tags [%a (turn ~(tap in tags.upd) |=(=term s+term))]]
236+ ::
237+ %run-updates
238+ [%run-updates ~]
239+ ::
240+ %tag-queries
241+ :- %tag-queries
242+ %- pairs
243+ %+ turn ~(tap by tag-queries.upd)
244+ |= [=term uids=(set ^uid)]
245+ ^- [cord json]
246+ [term [%a (turn ~(tap in uids) uid)]]
247+ ==
248+ ::
249+ ++ graph
250+ |= g=^graph
251+ ^- json
252+ %- pairs
253+ %+ turn
254+ (tap:orm g)
255+ |= [a=atom n=^node]
256+ ^- [@t json]
257+ :_ (node n)
258+ =/ idx (numb a)
259+ ?> ?=(%n -.idx)
260+ p.idx
261+ ::
262+ ++ node
263+ |= n=^node
264+ ^- json
265+ %- pairs
266+ :~ [%post (maybe-post post.n)]
267+ :- %children
268+ ?- -.children.n
269+ %empty ~
270+ %graph (graph +.children.n)
271+ ==
272+ ==
273+ ::
274+ ++ nodes
275+ |= m=(map ^index ^node)
276+ ^- json
277+ %- pairs
278+ %+ turn ~(tap by m)
279+ |= [n=^index o=^node]
280+ ^- [@t json]
281+ :_ (node o)
282+ =/ idx (index n)
283+ ?> ?=(%s -.idx)
284+ p.idx
285+ ::
286+ ++ indices
287+ |= i=(set ^index)
288+ ^- json
289+ [%a (turn ~(tap in i) index)]
290+ ::
291+ --
292+ --
293+::
294+++ dejs
295+ =, dejs:format
296+ |%
297+ ++ update
298+ |= jon=json
299+ ^- ^update
300+ :- *time
301+ ^- action
302+ =< (decode jon)
303+ |%
304+ ++ decode
305+ %- of
306+ :~ [%add-nodes add-nodes]
307+ [%remove-posts remove-posts]
308+ [%add-signatures add-signatures]
309+ [%remove-signatures remove-signatures]
310+ ::
311+ [%add-graph add-graph]
312+ [%remove-graph remove-graph]
313+ ::
314+ [%add-tag add-tag]
315+ [%remove-tag remove-tag]
316+ ::
317+ [%archive-graph archive-graph]
318+ [%unarchive-graph unarchive-graph]
319+ [%run-updates run-updates]
320+ ::
321+ [%keys keys]
322+ [%tags tags]
323+ [%tag-queries tag-queries]
324+ ==
325+ ::
326+ ++ add-graph
327+ %- ot
328+ :~ [%resource dejs:res]
329+ [%graph graph]
330+ [%mark (mu so)]
331+ [%overwrite bo]
332+ ==
333+ ::
334+ ++ graph
335+ |= a=json
336+ ^- ^graph
337+ =/ or-mp ((on atom ^node) gth)
338+ %+ gas:or-mp ~
339+ %+ turn ~(tap by ((om node) a))
340+ |* [b=cord c=*]
341+ ^- [atom ^node]
342+ => .(+< [b c]=+<)
343+ [(rash b dem) c]
344+ ::
345+ ++ remove-graph (ot [%resource dejs:res]~)
346+ ++ archive-graph (ot [%resource dejs:res]~)
347+ ++ unarchive-graph (ot [%resource dejs:res]~)
348+ ::
349+ ++ add-nodes
350+ %- ot
351+ :~ [%resource dejs:res]
352+ [%nodes nodes]
353+ ==
354+ ::
355+ ++ nodes (op ;~(pfix fas (more fas dem)) node)
356+ ::
357+ ++ node
358+ %- ot
359+ :~ [%post maybe-post]
360+ [%children internal-graph]
361+ ==
362+ ::
363+ ++ internal-graph
364+ |= jon=json
365+ ^- ^internal-graph
366+ ?~ jon
367+ [%empty ~]
368+ [%graph (graph jon)]
369+ ::
370+ ++ maybe-post
371+ |= jon=json
372+ ^- ^maybe-post
373+ ?~ jon !!
374+ ?+ -.jon !!
375+ %s [%| (nu jon)]
376+ %o [%& (post jon)]
377+ ==
378+ ::
379+ ++ post
380+ %- ot
381+ :~ [%author (su ;~(pfix sig fed:ag))]
382+ [%index index]
383+ [%time-sent di]
384+ [%contents (ar content)]
385+ [%hash (mu nu)]
386+ [%signatures (as signature)]
387+ ==
388+ ::
389+ ++ content
390+ %- of
391+ :~ [%mention (su ;~(pfix sig fed:ag))]
392+ [%text so]
393+ [%url so]
394+ [%reference reference]
395+ [%code eval]
396+ ==
397+ ::
398+ ++ reference
399+ |^
400+ %- of
401+ :~ graph+graph
402+ group+dejs-path:res
403+ app+app
404+ ==
405+ ::
406+ ++ graph
407+ %- ot
408+ :~ group+dejs-path:res
409+ graph+dejs-path:res
410+ index+index
411+ ==
412+ ::
413+ ++ app
414+ %- ot
415+ :~ ship+(su ;~(pfix sig fed:ag))
416+ desk+so
417+ path+pa
418+ ==
419+ --
420+ ::
421+ ++ tang
422+ |= jon=^json
423+ ^- ^tang
424+ ?> ?=(%a -.jon)
425+ %- zing
426+ %+ turn
427+ p.jon
428+ |= jo=^json
429+ ^- (list tank)
430+ ?> ?=(%a -.jo)
431+ %+ turn
432+ p.jo
433+ |= j=^json
434+ ?> ?=(%s -.j)
435+ ^- tank
436+ leaf+(trip p.j)
437+ ::
438+ ++ eval
439+ %- ot
440+ :~ expression+so
441+ output+tang
442+ ==
443+ ::
444+ ++ remove-posts
445+ %- ot
446+ :~ [%resource dejs:res]
447+ [%indices (as index)]
448+ ==
449+ ::
450+ ++ add-signatures
451+ %- ot
452+ :~ [%uid uid]
453+ [%signatures (as signature)]
454+ ==
455+ ::
456+ ++ remove-signatures
457+ %- ot
458+ :~ [%uid uid]
459+ [%signatures (as signature)]
460+ ==
461+ ::
462+ ++ signature
463+ %- ot
464+ :~ [%hash nu]
465+ [%ship (su ;~(pfix sig fed:ag))]
466+ [%life ni]
467+ ==
468+ ::
469+ ++ uid
470+ %- ot
471+ :~ [%resource dejs:res]
472+ [%index index]
473+ ==
474+ ::
475+ ++ index (su ;~(pfix fas (more fas dem)))
476+ ::
477+ ++ add-tag
478+ %- ot
479+ :~ [%term so]
480+ [%uid uid]
481+ ==
482+ ::
483+ ++ remove-tag
484+ %- ot
485+ :~ [%term so]
486+ [%uid uid]
487+ ==
488+ ::
489+ ++ keys
490+ |= =json
491+ *resources
492+ ::
493+ ++ tags
494+ |= =json
495+ *(set term)
496+ ::
497+ ++ tag-queries
498+ |= =json
499+ *^tag-queries
500+ ::
501+ ++ run-updates
502+ |= a=json
503+ ^- [resource update-log]
504+ [*resource *update-log]
505+ --
506+ ++ pa
507+ |= j=json
508+ ^- path
509+ ?> ?=(%s -.j)
510+ ?: =('/' p.j) /
511+ (stab p.j)
512+ ::
513+ --
514+::
515+++ create
516+ |_ [our=ship now=time]
517+ ++ post
518+ |= [=index contents=(list content)]
519+ ^- ^post
520+ :* our
521+ index
522+ now
523+ contents
524+ ~
525+ *signatures
526+ ==
527+ --
528+::
529+++ upgrade
530+ |%
531+ ::
532+ :: +two
533+ ::
534+ ++ marked-graph-to-two
535+ |= [=graph:one m=(unit mark)]
536+ [(graph-to-two graph) m]
537+ ::
538+ ++ graph-to-two
539+ |= =graph:one
540+ (graph:(upgrade ,post:one ,maybe-post:two) graph post-to-two)
541+ ::
542+ ++ post-to-two
543+ |= p=post:one
544+ ^- maybe-post:two
545+ [%& p]
546+ ::
547+ ::
548+ :: +one
549+ ::
550+ ++ update-log-to-one
551+ |= =update-log:zero
552+ ^- update-log:one
553+ %+ gas:orm-log:one *update-log:one
554+ %+ turn (tap:orm-log:zero update-log)
555+ |= [=time =logged-update:zero]
556+ ^- [^time logged-update:one]
557+ :- time
558+ :- p.logged-update
559+ (logged-update-to-one q.logged-update)
560+ ::
561+ ++ logged-update-to-one
562+ |= upd=logged-update-0:zero
563+ ^- logged-action:one
564+ ?+ -.upd upd
565+ %add-graph upd(graph (graph-to-one graph.upd))
566+ %add-nodes upd(nodes (~(run by nodes.upd) node-to-one))
567+ ==
568+ ::
569+ ++ node-to-one
570+ |= =node:zero
571+ (node:(upgrade ,post:zero ,post:one) node post-to-one)
572+ ::
573+ ++ graph-to-one
574+ |= =graph:zero
575+ (graph:(upgrade ,post:zero ,post:one) graph post-to-one)
576+ ::
577+ ++ marked-graph-to-one
578+ |= [=graph:zero m=(unit mark)]
579+ [(graph-to-one graph) m]
580+ ::
581+ ++ post-to-one
582+ |= p=post:zero
583+ ^- post:one
584+ p(contents (contents-to-one contents.p))
585+ ::
586+ ++ contents-to-one
587+ |= cs=(list content:zero)
588+ ^- (list content:one)
589+ %+ murn cs
590+ |= =content:zero
591+ ^- (unit content:one)
592+ ?: ?=(%reference -.content) ~
593+ `content
594+ ::
595+ ++ upgrade
596+ |* [in-pst=mold out-pst=mold]
597+ =>
598+ |%
599+ ++ in-orm
600+ ((on atom in-node) gth)
601+ +$ in-node
602+ [post=in-pst children=in-internal-graph]
603+ +$ in-graph
604+ ((mop atom in-node) gth)
605+ +$ in-internal-graph
606+ $~ [%empty ~]
607+ $% [%graph p=in-graph]
608+ [%empty ~]
609+ ==
610+ ::
611+ ++ out-orm
612+ ((on atom out-node) gth)
613+ +$ out-node
614+ [post=out-pst children=out-internal-graph]
615+ +$ out-graph
616+ ((mop atom out-node) gth)
617+ +$ out-internal-graph
618+ $~ [%empty ~]
619+ $% [%graph p=out-graph]
620+ [%empty ~]
621+ ==
622+ --
623+ |%
624+ ::
625+ ++ graph
626+ |= $: gra=in-graph
627+ fn=$-(in-pst out-pst)
628+ ==
629+ ^- out-graph
630+ %+ gas:out-orm *out-graph
631+ ^- (list [atom out-node])
632+ %+ turn (tap:in-orm gra)
633+ |= [a=atom n=in-node]
634+ ^- [atom out-node]
635+ [a (node n fn)]
636+ ::
637+ ++ node
638+ |= [nod=in-node fn=$-(in-pst out-pst)]
639+ ^- out-node
640+ :- (fn post.nod)
641+ ^- out-internal-graph
642+ ?: ?=(%empty -.children.nod)
643+ [%empty ~]
644+ [%graph (graph p.children.nod fn)]
645+ --
646+ ::
647+ ++ zero-load
648+ :: =* infinitely recurses
649+ =, store=zero
650+ =, orm=orm:zero
651+ =, orm-log=orm-log:zero
652+ |%
653+ ++ change-revision-graph
654+ |= [=graph:store q=(unit mark)]
655+ ^- [graph:store (unit mark)]
656+ |^
657+ :_ q
658+ ?+ q graph
659+ [~ %graph-validator-link] convert-links
660+ [~ %graph-validator-publish] convert-publish
661+ ==
662+ ::
663+ ++ convert-links
664+ %+ gas:orm *graph:store
665+ %+ turn (tap:orm graph)
666+ |= [=atom =node:store]
667+ ^- [^atom node:store]
668+ :: top-level
669+ ::
670+ :+ atom post.node
671+ ?: ?=(%empty -.children.node)
672+ [%empty ~]
673+ :- %graph
674+ %+ gas:orm *graph:store
675+ %+ turn (tap:orm p.children.node)
676+ |= [=^atom =node:store]
677+ ^- [^^atom node:store]
678+ :: existing comments get turned into containers for revisions
679+ ::
680+ :^ atom
681+ post.node(contents ~, hash ~)
682+ %graph
683+ %+ gas:orm *graph:store
684+ :_ ~ :- %0
685+ :_ [%empty ~]
686+ post.node(index (snoc index.post.node atom), hash ~)
687+ ::
688+ ++ convert-publish
689+ %+ gas:orm *graph:store
690+ %+ turn (tap:orm graph)
691+ |= [=atom =node:store]
692+ ^- [^atom node:store]
693+ :: top-level
694+ ::
695+ :+ atom post.node
696+ ?: ?=(%empty -.children.node)
697+ [%empty ~]
698+ :- %graph
699+ %+ gas:orm *graph:store
700+ %+ turn (tap:orm p.children.node)
701+ |= [=^atom =node:store]
702+ ^- [^^atom node:store]
703+ :: existing container for publish note revisions
704+ ::
705+ ?+ atom !!
706+ %1 [atom node]
707+ %2
708+ :+ atom post.node
709+ ?: ?=(%empty -.children.node)
710+ [%empty ~]
711+ :- %graph
712+ %+ gas:orm *graph:store
713+ %+ turn (tap:orm p.children.node)
714+ |= [=^^atom =node:store]
715+ ^- [^^^atom node:store]
716+ :+ atom post.node(contents ~, hash ~)
717+ :- %graph
718+ %+ gas:orm *graph:store
719+ :_ ~ :- %1
720+ :_ [%empty ~]
721+ post.node(index (snoc index.post.node atom), hash ~)
722+ ==
723+ --
724+ ::
725+ ++ maybe-unix-to-da
726+ |= =atom
727+ ^- @
728+ :: (bex 127) is roughly 226AD
729+ ?. (lte atom (bex 127))
730+ atom
731+ (add ~1970.1.1 (div (mul ~s1 atom) 1.000))
732+ ::
733+ ++ convert-unix-timestamped-node
734+ |= =node:store
735+ ^- node:store
736+ =. index.post.node
737+ (convert-unix-timestamped-index index.post.node)
738+ ?. ?=(%graph -.children.node)
739+ node
740+ :+ post.node
741+ %graph
742+ (convert-unix-timestamped-graph p.children.node)
743+ ::
744+ ++ convert-unix-timestamped-index
745+ |= =index:store
746+ (turn index maybe-unix-to-da)
747+ ::
748+ ++ convert-unix-timestamped-graph
749+ |= =graph:store
750+ %+ gas:orm *graph:store
751+ %+ turn
752+ (tap:orm graph)
753+ |= [=atom =node:store]
754+ ^- [^atom node:store]
755+ :- (maybe-unix-to-da atom)
756+ (convert-unix-timestamped-node node)
757+ --
758+ --
759+++ import
760+ |= [arc=* our=ship]
761+ ^- (quip card:agent:gall [%6 network])
762+ |^
763+ =/ sty [%6 (remake-network ;;(tree-network +.arc))]
764+ :_ sty
765+ %+ turn ~(tap by graphs.sty)
766+ |= [rid=resource =marked-graph]
767+ ^- card:agent:gall
768+ ?: =(our entity.rid)
769+ =/ =cage [%push-hook-action !>([%add rid])]
770+ [%pass / %agent [our %graph-push-hook] %poke cage]
771+ (try-rejoin rid 0)
772+ ::
773+ +$ tree-network
774+ $: graphs=tree-graphs
775+ tag-queries=(tree [term (tree uid)])
776+ update-logs=tree-update-logs
777+ archive=tree-graphs
778+ ~
779+ ==
780+ +$ tree-graphs (tree [resource tree-marked-graph])
781+ +$ tree-marked-graph [p=tree-graph q=(unit ^mark)]
782+ +$ tree-graph (tree [atom tree-node])
783+ +$ tree-node [post=tree-maybe-post children=tree-internal-graph]
784+ +$ tree-internal-graph
785+ $~ [%empty ~]
786+ $% [%graph p=tree-graph]
787+ [%empty ~]
788+ ==
789+ +$ tree-update-logs (tree [resource tree-update-log])
790+ +$ tree-update-log (tree [time tree-logged-update])
791+ +$ tree-logged-update
792+ $: p=time
793+ $= q
794+ $% [%add-graph =resource =tree-graph mark=(unit ^mark) ow=?]
795+ [%add-nodes =resource nodes=(tree [index tree-node])]
796+ [%remove-posts =resource indices=(tree index)]
797+ [%add-signatures =uid signatures=tree-signatures]
798+ [%remove-signatures =uid signatures=tree-signatures]
799+ ==
800+ ==
801+ +$ tree-signatures (tree signature)
802+ +$ tree-maybe-post (each tree-post hash)
803+ +$ tree-post
804+ $: author=ship
805+ =index
806+ time-sent=time
807+ contents=(list content)
808+ hash=(unit hash)
809+ signatures=tree-signatures
810+ ==
811+ ::
812+ ++ remake-network
813+ |= t=tree-network
814+ ^- network
815+ :* (remake-graphs graphs.t)
816+ (remake-jug:migrate tag-queries.t)
817+ (remake-update-logs update-logs.t)
818+ (remake-graphs archive.t)
819+ ~
820+ ==
821+ ::
822+ ++ remake-graphs
823+ |= t=tree-graphs
824+ ^- graphs
825+ %- remake-map:migrate
826+ (~(run by t) remake-marked-graph)
827+ ::
828+ ++ remake-marked-graph
829+ |= t=tree-marked-graph
830+ ^- marked-graph
831+ [(remake-graph p.t) q.t]
832+ ::
833+ ++ remake-graph
834+ |= t=tree-graph
835+ ^- graph
836+ %+ gas:orm *graph
837+ %+ turn ~(tap by t)
838+ |= [a=atom tn=tree-node]
839+ ^- [atom node]
840+ [a (remake-node tn)]
841+ ::
842+ ++ remake-internal-graph
843+ |= t=tree-internal-graph
844+ ^- internal-graph
845+ ?: ?=(%empty -.t)
846+ [%empty ~]
847+ [%graph (remake-graph p.t)]
848+ ::
849+ ++ remake-node
850+ |= t=tree-node
851+ ^- node
852+ :- (remake-post post.t)
853+ (remake-internal-graph children.t)
854+ ::
855+ ++ remake-update-logs
856+ |= t=tree-update-logs
857+ ^- update-logs
858+ %- remake-map:migrate
859+ (~(run by t) remake-update-log)
860+ ::
861+ ++ remake-update-log
862+ |= t=tree-update-log
863+ ^- update-log
864+ =/ ulm ((on time logged-update) gth)
865+ %+ gas:ulm *update-log
866+ %+ turn ~(tap by t)
867+ |= [=time tlu=tree-logged-update]
868+ ^- [^time logged-update]
869+ [time (remake-logged-update tlu)]
870+ ::
871+ ++ remake-logged-update
872+ |= t=tree-logged-update
873+ ^- logged-update
874+ :- p.t
875+ ?- -.q.t
876+ %add-graph
877+ :* %add-graph
878+ resource.q.t
879+ (remake-graph tree-graph.q.t)
880+ mark.q.t
881+ ow.q.t
882+ ==
883+ ::
884+ %add-nodes
885+ :- %add-nodes
886+ :- resource.q.t
887+ %- remake-map:migrate
888+ (~(run by nodes.q.t) remake-node)
889+ ::
890+ %remove-posts
891+ [%remove-posts resource.q.t (remake-set:migrate indices.q.t)]
892+ ::
893+ %add-signatures
894+ [%add-signatures uid.q.t (remake-set:migrate signatures.q.t)]
895+ ::
896+ %remove-signatures
897+ [%remove-signatures uid.q.t (remake-set:migrate signatures.q.t)]
898+ ==
899+ ::
900+ ++ remake-post
901+ |= t=tree-maybe-post
902+ ^- maybe-post
903+ ?- -.t
904+ %| t
905+ %& t(signatures.p (remake-set:migrate signatures.p.t))
906+ ==
907+ ::
908+ ++ try-rejoin
909+ |= [rid=resource nack-count=@]
910+ ^- card:agent:gall
911+ =/ res-path (en-path:res rid)
912+ =/ wire [%try-rejoin (scot %ud nack-count) res-path]
913+ =/ =cage
914+ :- %pull-hook-action
915+ !> ^- action:pull-hook
916+ [%add [entity .]:rid]
917+ [%pass wire %agent [our %graph-pull-hook] %poke cage]
918+ --
919+--
zod/seax/lib/migrate.hoonnew file+19
@@ -0,0 +1,19 @@
1+^? |%
2+++ remake-set
3+ |* s=(tree)
4+ (sy ~(tap in s))
5+::
6+++ remake-map
7+ |* m=(tree)
8+ (my ~(tap by m))
9+::
10+++ remake-jug
11+ |* j=(tree [* (tree)])
12+ %- remake-map
13+ (~(run by j) remake-set)
14+::
15+++ remake-map-of-map
16+ |* mm=(tree [* (tree)])
17+ %- remake-map
18+ (~(run by mm) remake-map)
19+--
zod/seax/lib/resource.hoonnew file+57
@@ -0,0 +1,57 @@
1+/- sur=resource
2+=< resource
3+|%
4++$ resource resource:sur
5+++ en-path
6+ |= =resource
7+ ^- path
8+ ~[%ship (scot %p entity.resource) name.resource]
9+::
10+++ de-path
11+ |= =path
12+ ^- resource
13+ (need (de-path-soft path))
14+::
15+++ de-path-soft
16+ |= =path
17+ ^- (unit resource)
18+ ?. ?=([%ship @ @ *] path)
19+ ~
20+ =/ ship
21+ (slaw %p i.t.path)
22+ ?~ ship
23+ ~
24+ `[u.ship i.t.t.path]
25+::
26+++ enjs
27+ |= =resource
28+ ^- json
29+ =, enjs:format
30+ %- pairs
31+ :~ ship+(ship entity.resource)
32+ name+s+name.resource
33+ ==
34+::
35+++ enjs-path
36+ |= =resource
37+ %- spat
38+ (en-path resource)
39+::
40+++ dejs-path
41+ %- su:dejs:format
42+ ;~ pfix
43+ (jest '/ship/')
44+ ;~((glue fas) ;~(pfix sig fed:ag) urs:ab)
45+ ==
46+::
47+++ dejs
48+ =, dejs:format
49+ ^- $-(json resource)
50+ |= jon=json
51+ ~| dejs+%resource
52+ %. jon
53+ %- ot
54+ :~ ship+(su ;~(pfix sig fed:ag))
55+ name+so
56+ ==
57+--
zod/seax/lib/strand.hoonnew file+1
@@ -0,0 +1 @@
1+rand
zod/seax/lib/strandio.hoonnew file+812
@@ -0,0 +1,812 @@
1+/- spider
2+/+ libstrand=strand
3+=, strand=strand:libstrand
4+=, strand-fail=strand-fail:libstrand
5+|%
6+++ send-raw-cards
7+ |= cards=(list =card:agent:gall)
8+ =/ m (strand ,~)
9+ ^- form:m
10+ |= strand-input:strand
11+ [cards %done ~]
12+::
13+++ send-raw-card
14+ |= =card:agent:gall
15+ =/ m (strand ,~)
16+ ^- form:m
17+ (send-raw-cards card ~)
18+::
19+++ ignore
20+ |= tin=strand-input:strand
21+ `[%fail %ignore ~]
22+::
23+++ get-bowl
24+ =/ m (strand ,bowl:strand)
25+ ^- form:m
26+ |= tin=strand-input:strand
27+ `[%done bowl.tin]
28+::
29+++ get-beak
30+ =/ m (strand ,beak)
31+ ^- form:m
32+ |= tin=strand-input:strand
33+ `[%done [our q.byk da+now]:bowl.tin]
34+::
35+++ get-time
36+ =/ m (strand ,@da)
37+ ^- form:m
38+ |= tin=strand-input:strand
39+ `[%done now.bowl.tin]
40+::
41+++ get-our
42+ =/ m (strand ,ship)
43+ ^- form:m
44+ |= tin=strand-input:strand
45+ `[%done our.bowl.tin]
46+::
47+++ get-entropy
48+ =/ m (strand ,@uvJ)
49+ ^- form:m
50+ |= tin=strand-input:strand
51+ `[%done eny.bowl.tin]
52+::
53+:: Convert skips to %ignore failures.
54+::
55+:: This tells the main loop to try the next handler.
56+::
57+++ handle
58+ |* a=mold
59+ =/ m (strand ,a)
60+ |= =form:m
61+ ^- form:m
62+ |= tin=strand-input:strand
63+ =/ res (form tin)
64+ =? next.res ?=(%skip -.next.res)
65+ [%fail %ignore ~]
66+ res
67+::
68+:: Wait for a poke with a particular mark
69+::
70+++ take-poke
71+ |= =mark
72+ =/ m (strand ,vase)
73+ ^- form:m
74+ |= tin=strand-input:strand
75+ ?+ in.tin `[%skip ~]
76+ ~
77+ `[%wait ~]
78+ ::
79+ [~ %poke @ *]
80+ ?. =(mark p.cage.u.in.tin)
81+ `[%skip ~]
82+ `[%done q.cage.u.in.tin]
83+ ==
84+::
85+++ take-sign-arvo
86+ =/ m (strand ,[wire sign-arvo])
87+ ^- form:m
88+ |= tin=strand-input:strand
89+ ?+ in.tin `[%skip ~]
90+ ~
91+ `[%wait ~]
92+ ::
93+ [~ %sign *]
94+ `[%done [wire sign-arvo]:u.in.tin]
95+ ==
96+::
97+:: Wait for a subscription update on a wire
98+::
99+++ take-fact-prefix
100+ |= =wire
101+ =/ m (strand ,[path cage])
102+ ^- form:m
103+ |= tin=strand-input:strand
104+ ?+ in.tin `[%skip ~]
105+ ~ `[%wait ~]
106+ [~ %agent * %fact *]
107+ ?. =(watch+wire (scag +((lent wire)) wire.u.in.tin))
108+ `[%skip ~]
109+ `[%done (slag (lent wire) wire.u.in.tin) cage.sign.u.in.tin]
110+ ==
111+::
112+:: Wait for a subscription update on a wire
113+::
114+++ take-fact
115+ |= =wire
116+ =/ m (strand ,cage)
117+ ^- form:m
118+ |= tin=strand-input:strand
119+ ?+ in.tin `[%skip ~]
120+ ~ `[%wait ~]
121+ [~ %agent * %fact *]
122+ ?. =(watch+wire wire.u.in.tin)
123+ `[%skip ~]
124+ `[%done cage.sign.u.in.tin]
125+ ==
126+::
127+:: Wait for a subscription close
128+::
129+++ take-kick
130+ |= =wire
131+ =/ m (strand ,~)
132+ ^- form:m
133+ |= tin=strand-input:strand
134+ ?+ in.tin `[%skip ~]
135+ ~ `[%wait ~]
136+ [~ %agent * %kick *]
137+ ?. =(watch+wire wire.u.in.tin)
138+ `[%skip ~]
139+ `[%done ~]
140+ ==
141+::
142+++ echo
143+ =/ m (strand ,~)
144+ ^- form:m
145+ %- (main-loop ,~)
146+ :~ |= ~
147+ ^- form:m
148+ ;< =vase bind:m ((handle ,vase) (take-poke %echo))
149+ =/ message=tape !<(tape vase)
150+ %- (slog leaf+"{message}..." ~)
151+ ;< ~ bind:m (sleep ~s2)
152+ %- (slog leaf+"{message}.." ~)
153+ (pure:m ~)
154+ ::
155+ |= ~
156+ ^- form:m
157+ ;< =vase bind:m ((handle ,vase) (take-poke %over))
158+ %- (slog leaf+"over..." ~)
159+ (pure:m ~)
160+ ==
161+::
162+++ take-watch
163+ =/ m (strand ,path)
164+ |= tin=strand-input:strand
165+ ?+ in.tin `[%skip ~]
166+ ~ `[%wait ~]
167+ [~ %watch *]
168+ `[%done path.u.in.tin]
169+ ==
170+::
171+++ take-wake
172+ |= until=(unit @da)
173+ =/ m (strand ,~)
174+ ^- form:m
175+ |= tin=strand-input:strand
176+ ?+ in.tin `[%skip ~]
177+ ~ `[%wait ~]
178+ [~ %sign [%wait @ ~] %behn %wake *]
179+ ?. |(?=(~ until) =(`u.until (slaw %da i.t.wire.u.in.tin)))
180+ `[%skip ~]
181+ ?~ error.sign-arvo.u.in.tin
182+ `[%done ~]
183+ `[%fail %timer-error u.error.sign-arvo.u.in.tin]
184+ ==
185+::
186+++ take-tune
187+ |= =wire
188+ =/ m (strand ,[spar:ames (unit roar:ames)])
189+ ^- form:m
190+ |= tin=strand-input:strand
191+ ?+ in.tin `[%skip ~]
192+ ~ `[%wait ~]
193+ ::
194+ [~ %sign * %ames %tune ^ *]
195+ ?. =(wire wire.u.in.tin)
196+ `[%skip ~]
197+ `[%done +>.sign-arvo.u.in.tin]
198+ ==
199+::
200+++ take-poke-ack
201+ |= =wire
202+ =/ m (strand ,~)
203+ ^- form:m
204+ |= tin=strand-input:strand
205+ ?+ in.tin `[%skip ~]
206+ ~ `[%wait ~]
207+ [~ %agent * %poke-ack *]
208+ ?. =(wire wire.u.in.tin)
209+ `[%skip ~]
210+ ?~ p.sign.u.in.tin
211+ `[%done ~]
212+ `[%fail %poke-fail u.p.sign.u.in.tin]
213+ ==
214+::
215+++ take-watch-ack
216+ |= =wire
217+ =/ m (strand ,~)
218+ ^- form:m
219+ |= tin=strand-input:strand
220+ ?+ in.tin `[%skip ~]
221+ ~ `[%wait ~]
222+ [~ %agent * %watch-ack *]
223+ ?. =(watch+wire wire.u.in.tin)
224+ `[%skip ~]
225+ ?~ p.sign.u.in.tin
226+ `[%done ~]
227+ `[%fail %watch-ack-fail u.p.sign.u.in.tin]
228+ ==
229+::
230+++ poke
231+ |= [=dock =cage]
232+ =/ m (strand ,~)
233+ ^- form:m
234+ =/ =card:agent:gall [%pass /poke %agent dock %poke cage]
235+ ;< ~ bind:m (send-raw-card card)
236+ (take-poke-ack /poke)
237+::
238+++ raw-poke
239+ |= [=dock =cage]
240+ =/ m (strand ,~)
241+ ^- form:m
242+ =/ =card:agent:gall [%pass /poke %agent dock %poke cage]
243+ ;< ~ bind:m (send-raw-card card)
244+ =/ m (strand ,~)
245+ ^- form:m
246+ |= tin=strand-input:strand
247+ ?+ in.tin `[%skip ~]
248+ ~
249+ `[%wait ~]
250+ ::
251+ [~ %agent * %poke-ack *]
252+ ?. =(/poke wire.u.in.tin)
253+ `[%skip ~]
254+ `[%done ~]
255+ ==
256+::
257+++ raw-poke-our
258+ |= [app=term =cage]
259+ =/ m (strand ,~)
260+ ^- form:m
261+ ;< =bowl:spider bind:m get-bowl
262+ (raw-poke [our.bowl app] cage)
263+::
264+++ poke-our
265+ |= [=term =cage]
266+ =/ m (strand ,~)
267+ ^- form:m
268+ ;< our=@p bind:m get-our
269+ (poke [our term] cage)
270+::
271+++ watch
272+ |= [=wire =dock =path]
273+ =/ m (strand ,~)
274+ ^- form:m
275+ =/ =card:agent:gall [%pass watch+wire %agent dock %watch path]
276+ ;< ~ bind:m (send-raw-card card)
277+ (take-watch-ack wire)
278+::
279+++ watch-one
280+ |= [=wire =dock =path]
281+ =/ m (strand ,cage)
282+ ^- form:m
283+ ;< ~ bind:m (watch wire dock path)
284+ ;< =cage bind:m (take-fact wire)
285+ ;< ~ bind:m (take-kick wire)
286+ (pure:m cage)
287+::
288+++ watch-our
289+ |= [=wire =term =path]
290+ =/ m (strand ,~)
291+ ^- form:m
292+ ;< our=@p bind:m get-our
293+ (watch wire [our term] path)
294+::
295+++ scry
296+ |* [=mold =path]
297+ =/ m (strand ,mold)
298+ ^- form:m
299+ ?> ?=(^ path)
300+ ?> ?=(^ t.path)
301+ ;< =bowl:spider bind:m get-bowl
302+ %- pure:m
303+ .^(mold i.path (scot %p our.bowl) i.t.path (scot %da now.bowl) t.t.path)
304+::
305+++ leave
306+ |= [=wire =dock]
307+ =/ m (strand ,~)
308+ ^- form:m
309+ =/ =card:agent:gall [%pass watch+wire %agent dock %leave ~]
310+ (send-raw-card card)
311+::
312+++ leave-our
313+ |= [=wire =term]
314+ =/ m (strand ,~)
315+ ^- form:m
316+ ;< our=@p bind:m get-our
317+ (leave wire [our term])
318+::
319+++ rewatch
320+ |= [=wire =dock =path]
321+ =/ m (strand ,~)
322+ ;< ~ bind:m ((handle ,~) (take-kick wire))
323+ ;< ~ bind:m (flog-text "rewatching {<dock>} {<path>}")
324+ ;< ~ bind:m (watch wire dock path)
325+ (pure:m ~)
326+::
327+++ wait
328+ |= until=@da
329+ =/ m (strand ,~)
330+ ^- form:m
331+ ;< ~ bind:m (send-wait until)
332+ (take-wake `until)
333+::
334+++ keen
335+ |= [=wire =spar:ames]
336+ =/ m (strand ,~)
337+ ^- form:m
338+ (send-raw-card %pass wire %arvo %a %keen spar)
339+::
340+++ sleep
341+ |= for=@dr
342+ =/ m (strand ,~)
343+ ^- form:m
344+ ;< now=@da bind:m get-time
345+ (wait (add now for))
346+::
347+++ send-wait
348+ |= until=@da
349+ =/ m (strand ,~)
350+ ^- form:m
351+ =/ =card:agent:gall
352+ [%pass /wait/(scot %da until) %arvo %b %wait until]
353+ (send-raw-card card)
354+::
355+++ map-err
356+ |* computation-result=mold
357+ =/ m (strand ,computation-result)
358+ |= [f=$-([term tang] [term tang]) computation=form:m]
359+ ^- form:m
360+ |= tin=strand-input:strand
361+ =* loop $
362+ =/ c-res (computation tin)
363+ ?: ?=(%cont -.next.c-res)
364+ c-res(self.next ..loop(computation self.next.c-res))
365+ ?. ?=(%fail -.next.c-res)
366+ c-res
367+ c-res(err.next (f err.next.c-res))
368+::
369+++ set-timeout
370+ |* computation-result=mold
371+ =/ m (strand ,computation-result)
372+ |= [time=@dr computation=form:m]
373+ ^- form:m
374+ ;< now=@da bind:m get-time
375+ =/ when (add now time)
376+ =/ =card:agent:gall
377+ [%pass /timeout/(scot %da when) %arvo %b %wait when]
378+ ;< ~ bind:m (send-raw-card card)
379+ |= tin=strand-input:strand
380+ =* loop $
381+ ?: ?& ?=([~ %sign [%timeout @ ~] %behn %wake *] in.tin)
382+ =((scot %da when) i.t.wire.u.in.tin)
383+ ==
384+ `[%fail %timeout ~]
385+ =/ c-res (computation tin)
386+ ?: ?=(%cont -.next.c-res)
387+ c-res(self.next ..loop(computation self.next.c-res))
388+ ?: ?=(%done -.next.c-res)
389+ =/ =card:agent:gall
390+ [%pass /timeout/(scot %da when) %arvo %b %rest when]
391+ c-res(cards [card cards.c-res])
392+ c-res
393+::
394+++ send-request
395+ |= =request:http
396+ =/ m (strand ,~)
397+ ^- form:m
398+ (send-raw-card %pass /request %arvo %i %request request *outbound-config:iris)
399+::
400+++ send-cancel-request
401+ =/ m (strand ,~)
402+ ^- form:m
403+ (send-raw-card %pass /request %arvo %i %cancel-request ~)
404+::
405+++ take-client-response
406+ =/ m (strand ,client-response:iris)
407+ ^- form:m
408+ |= tin=strand-input:strand
409+ ?+ in.tin `[%skip ~]
410+ ~ `[%wait ~]
411+ ::
412+ [~ %sign [%request ~] %iris %http-response %cancel *]
413+ ::NOTE iris does not (yet?) retry after cancel, so it means failure
414+ :- ~
415+ :+ %fail
416+ %http-request-cancelled
417+ ['http request was cancelled by the runtime']~
418+ ::
419+ [~ %sign [%request ~] %iris %http-response %finished *]
420+ `[%done client-response.sign-arvo.u.in.tin]
421+ ==
422+::
423+:: Wait until we get an HTTP response or cancelation and unset contract
424+::
425+++ take-maybe-sigh
426+ =/ m (strand ,(unit httr:eyre))
427+ ^- form:m
428+ ;< rep=(unit client-response:iris) bind:m
429+ take-maybe-response
430+ ?~ rep
431+ (pure:m ~)
432+ :: XX s/b impossible
433+ ::
434+ ?. ?=(%finished -.u.rep)
435+ (pure:m ~)
436+ (pure:m (some (to-httr:iris +.u.rep)))
437+::
438+++ take-maybe-response
439+ =/ m (strand ,(unit client-response:iris))
440+ ^- form:m
441+ |= tin=strand-input:strand
442+ ?+ in.tin `[%skip ~]
443+ ~ `[%wait ~]
444+ [~ %sign [%request ~] %iris %http-response %cancel *]
445+ `[%done ~]
446+ [~ %sign [%request ~] %iris %http-response %finished *]
447+ `[%done `client-response.sign-arvo.u.in.tin]
448+ ==
449+::
450+++ extract-body
451+ |= =client-response:iris
452+ =/ m (strand ,cord)
453+ ^- form:m
454+ ?> ?=(%finished -.client-response)
455+ %- pure:m
456+ ?~ full-file.client-response ''
457+ q.data.u.full-file.client-response
458+::
459+++ fetch-cord
460+ |= url=tape
461+ =/ m (strand ,cord)
462+ ^- form:m
463+ =/ =request:http [%'GET' (crip url) ~ ~]
464+ ;< ~ bind:m (send-request request)
465+ ;< =client-response:iris bind:m take-client-response
466+ (extract-body client-response)
467+::
468+++ fetch-json
469+ |= url=tape
470+ =/ m (strand ,json)
471+ ^- form:m
472+ ;< =cord bind:m (fetch-cord url)
473+ =/ json=(unit json) (de:json:html cord)
474+ ?~ json
475+ (strand-fail %json-parse-error ~)
476+ (pure:m u.json)
477+::
478+++ hiss-request
479+ |= =hiss:eyre
480+ =/ m (strand ,(unit httr:eyre))
481+ ^- form:m
482+ ;< ~ bind:m (send-request (hiss-to-request:html hiss))
483+ take-maybe-sigh
484+::
485+:: +build-file: build the source file at the specified $beam
486+::
487+++ build-file
488+ |= [[=ship =desk =case] =spur]
489+ =* arg +<
490+ =/ m (strand ,(unit vase))
491+ ^- form:m
492+ ;< =riot:clay bind:m
493+ (warp ship desk ~ %sing %a case spur)
494+ ?~ riot
495+ (pure:m ~)
496+ ?> =(%vase p.r.u.riot)
497+ (pure:m (some !<(vase q.r.u.riot)))
498+::
499+++ build-file-hard
500+ |= [[=ship =desk =case] =spur]
501+ =* arg +<
502+ =/ m (strand ,vase)
503+ ^- form:m
504+ ;< =riot:clay
505+ bind:m
506+ (warp ship desk ~ %sing %a case spur)
507+ ?> ?=(^ riot)
508+ ?> ?=(%vase p.r.u.riot)
509+ (pure:m !<(vase q.r.u.riot))
510+:: +build-mark: build a mark definition to a $dais
511+::
512+++ build-mark
513+ |= [[=ship =desk =case] mak=mark]
514+ =* arg +<
515+ =/ m (strand ,dais:clay)
516+ ^- form:m
517+ ;< =riot:clay bind:m
518+ (warp ship desk ~ %sing %b case /[mak])
519+ ?~ riot
520+ (strand-fail %build-mark >arg< ~)
521+ ?> =(%dais p.r.u.riot)
522+ (pure:m !<(dais:clay q.r.u.riot))
523+:: +build-tube: build a mark conversion gate ($tube)
524+::
525+++ build-tube
526+ |= [[=ship =desk =case] =mars:clay]
527+ =* arg +<
528+ =/ m (strand ,tube:clay)
529+ ^- form:m
530+ ;< =riot:clay bind:m
531+ (warp ship desk ~ %sing %c case /[a.mars]/[b.mars])
532+ ?~ riot
533+ (strand-fail %build-tube >arg< ~)
534+ ?> =(%tube p.r.u.riot)
535+ (pure:m !<(tube:clay q.r.u.riot))
536+::
537+:: +build-nave: build a mark definition to a $nave
538+::
539+++ build-nave
540+ |= [[=ship =desk =case] mak=mark]
541+ =* arg +<
542+ =/ m (strand ,vase)
543+ ^- form:m
544+ ;< =riot:clay bind:m
545+ (warp ship desk ~ %sing %e case /[mak])
546+ ?~ riot
547+ (strand-fail %build-nave >arg< ~)
548+ ?> =(%nave p.r.u.riot)
549+ (pure:m q.r.u.riot)
550+:: +build-cast: build a mark conversion gate (static)
551+::
552+++ build-cast
553+ |= [[=ship =desk =case] =mars:clay]
554+ =* arg +<
555+ =/ m (strand ,vase)
556+ ^- form:m
557+ ;< =riot:clay bind:m
558+ (warp ship desk ~ %sing %f case /[a.mars]/[b.mars])
559+ ?~ riot
560+ (strand-fail %build-cast >arg< ~)
561+ ?> =(%cast p.r.u.riot)
562+ (pure:m q.r.u.riot)
563+::
564+:: Read from Clay
565+::
566+++ warp
567+ |= [=ship =riff:clay]
568+ =/ m (strand ,riot:clay)
569+ ;< ~ bind:m (send-raw-card %pass /warp %arvo %c %warp ship riff)
570+ (take-writ /warp)
571+::
572+++ read-file
573+ |= [[=ship =desk =case] =spur]
574+ =* arg +<
575+ =/ m (strand ,cage)
576+ ;< =riot:clay bind:m (warp ship desk ~ %sing %x case spur)
577+ ?~ riot
578+ (strand-fail %read-file >arg< ~)
579+ (pure:m r.u.riot)
580+::
581+++ check-for-file
582+ |= [[=ship =desk =case] =spur]
583+ =/ m (strand ,?)
584+ ;< =riot:clay bind:m (warp ship desk ~ %sing %u case spur)
585+ ?> ?=(^ riot)
586+ (pure:m !<(? q.r.u.riot))
587+::
588+++ list-tree
589+ |= [[=ship =desk =case] =spur]
590+ =* arg +<
591+ =/ m (strand ,(list path))
592+ ;< =riot:clay bind:m (warp ship desk ~ %sing %t case spur)
593+ ?~ riot
594+ (strand-fail %list-tree >arg< ~)
595+ (pure:m !<((list path) q.r.u.riot))
596+::
597+:: Take Clay read result
598+::
599+++ take-writ
600+ |= =wire
601+ =/ m (strand ,riot:clay)
602+ ^- form:m
603+ |= tin=strand-input:strand
604+ ?+ in.tin `[%skip ~]
605+ ~ `[%wait ~]
606+ [~ %sign * ?(%behn %clay) %writ *]
607+ ?. =(wire wire.u.in.tin)
608+ `[%skip ~]
609+ `[%done +>.sign-arvo.u.in.tin]
610+ ==
611+:: +check-online: require that peer respond before timeout
612+::
613+++ check-online
614+ |= [who=ship lag=@dr]
615+ =/ m (strand ,~)
616+ ^- form:m
617+ %+ (map-err ,~) |=(* [%offline *tang])
618+ %+ (set-timeout ,~) lag
619+ ;< ~ bind:m
620+ (poke [who %hood] %helm-hi !>(~))
621+ (pure:m ~)
622+::
623+++ eval-hoon
624+ |= [gen=hoon bez=(list beam)]
625+ =/ m (strand ,vase)
626+ ^- form:m
627+ =/ sut=vase !>(..zuse)
628+ |-
629+ ?~ bez
630+ (pure:m (slap sut gen))
631+ ;< vax=vase bind:m (build-file-hard i.bez)
632+ $(bez t.bez, sut (slop vax sut))
633+::
634+++ send-thread
635+ |= [=bear:khan =shed:khan =wire]
636+ =/ m (strand ,~)
637+ ^- form:m
638+ (send-raw-card %pass wire %arvo %k %lard bear shed)
639+::
640+:: Queue on skip, try next on fail %ignore
641+::
642+++ main-loop
643+ |* a=mold
644+ =/ m (strand ,~)
645+ =/ m-a (strand ,a)
646+ =| queue=(qeu (unit input:strand))
647+ =| active=(unit [in=(unit input:strand) =form:m-a forms=(list $-(a form:m-a))])
648+ =| state=a
649+ |= forms=(lest $-(a form:m-a))
650+ ^- form:m
651+ |= tin=strand-input:strand
652+ =* top `form:m`..$
653+ =. queue (~(put to queue) in.tin)
654+ |^ (continue bowl.tin)
655+ ::
656+ ++ continue
657+ |= =bowl:strand
658+ ^- output:m
659+ ?> =(~ active)
660+ ?: =(~ queue)
661+ `[%cont top]
662+ =^ in=(unit input:strand) queue ~(get to queue)
663+ ^- output:m
664+ =. active `[in (i.forms state) t.forms]
665+ ^- output:m
666+ (run bowl in)
667+ ::
668+ ++ run
669+ ^- form:m
670+ |= tin=strand-input:strand
671+ ^- output:m
672+ ?> ?=(^ active)
673+ =/ res (form.u.active tin)
674+ =/ =output:m
675+ ?- -.next.res
676+ %wait `[%wait ~]
677+ %skip `[%cont ..$(queue (~(put to queue) in.tin))]
678+ %cont `[%cont ..$(active `[in.u.active self.next.res forms.u.active])]
679+ %done (continue(active ~, state value.next.res) bowl.tin)
680+ %fail
681+ ?: &(?=(^ forms.u.active) ?=(%ignore p.err.next.res))
682+ %= $
683+ active `[in.u.active (i.forms.u.active state) t.forms.u.active]
684+ in.tin in.u.active
685+ ==
686+ `[%fail err.next.res]
687+ ==
688+ [(weld cards.res cards.output) next.output]
689+ --
690+::
691+++ retry
692+ |* result=mold
693+ |= [crash-after=(unit @ud) computation=_*form:(strand (unit result))]
694+ =/ m (strand ,result)
695+ =| try=@ud
696+ |- ^- form:m
697+ =* loop $
698+ ?: =(crash-after `try)
699+ (strand-fail %retry-too-many ~)
700+ ;< ~ bind:m (backoff try ~m1)
701+ ;< res=(unit result) bind:m computation
702+ ?^ res
703+ (pure:m u.res)
704+ loop(try +(try))
705+::
706+++ backoff
707+ |= [try=@ud limit=@dr]
708+ =/ m (strand ,~)
709+ ^- form:m
710+ ;< eny=@uvJ bind:m get-entropy
711+ %- sleep
712+ %+ min limit
713+ ?: =(0 try) ~s0
714+ %+ add
715+ (mul ~s1 (bex (dec try)))
716+ (mul ~s0..0001 (~(rad og eny) 1.000))
717+::
718+:: ----
719+::
720+:: Output
721+::
722+++ flog
723+ |= =flog:dill
724+ =/ m (strand ,~)
725+ ^- form:m
726+ (send-raw-card %pass / %arvo %d %flog flog)
727+::
728+++ flog-text
729+ |= =tape
730+ =/ m (strand ,~)
731+ ^- form:m
732+ (flog %text tape)
733+::
734+++ flog-tang
735+ |= =tang
736+ =/ m (strand ,~)
737+ ^- form:m
738+ =/ =wall
739+ (zing (turn (flop tang) (cury wash [0 80])))
740+ |- ^- form:m
741+ =* loop $
742+ ?~ wall
743+ (pure:m ~)
744+ ;< ~ bind:m (flog-text i.wall)
745+ loop(wall t.wall)
746+::
747+++ trace
748+ |= =tang
749+ =/ m (strand ,~)
750+ ^- form:m
751+ (pure:m ((slog tang) ~))
752+::
753+++ app-message
754+ |= [app=term =cord =tang]
755+ =/ m (strand ,~)
756+ ^- form:m
757+ =/ msg=tape :(weld (trip app) ": " (trip cord))
758+ ;< ~ bind:m (flog-text msg)
759+ (flog-tang tang)
760+::
761+:: ----
762+::
763+:: Handle domains
764+::
765+++ install-domain
766+ |= =turf
767+ =/ m (strand ,~)
768+ ^- form:m
769+ (send-raw-card %pass / %arvo %e %rule %turf %put turf)
770+::
771+:: ----
772+::
773+:: Threads
774+::
775+++ start-thread
776+ |= file=term
777+ =/ m (strand ,tid:spider)
778+ ;< =bowl:spider bind:m get-bowl
779+ (start-thread-with-args byk.bowl file *vase)
780+::
781+++ start-thread-with-args
782+ |= [=beak file=term args=vase]
783+ =/ m (strand ,tid:spider)
784+ ^- form:m
785+ ;< =bowl:spider bind:m get-bowl
786+ =/ tid
787+ (scot %ta (cat 3 (cat 3 'strand_' file) (scot %uv (sham file eny.bowl))))
788+ =/ poke-vase !>(`start-args:spider`[`tid.bowl `tid beak file args])
789+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
790+ ;< ~ bind:m (sleep ~s0) :: wait for thread to start
791+ (pure:m tid)
792+::
793++$ thread-result
794+ (each vase [term tang])
795+::
796+++ await-thread
797+ |= [file=term args=vase]
798+ =/ m (strand ,thread-result)
799+ ^- form:m
800+ ;< =bowl:spider bind:m get-bowl
801+ =/ tid (scot %ta (cat 3 'strand_' (scot %uv (sham file eny.bowl))))
802+ =/ poke-vase !>(`start-args:spider`[`tid.bowl `tid byk.bowl file args])
803+ ;< ~ bind:m (watch-our /awaiting/[tid] %spider /thread-result/[tid])
804+ ;< ~ bind:m (poke-our %spider %spider-start poke-vase)
805+ ;< ~ bind:m (sleep ~s0) :: wait for thread to start
806+ ;< =cage bind:m (take-fact /awaiting/[tid])
807+ ;< ~ bind:m (take-kick /awaiting/[tid])
808+ ?+ p.cage ~|([%strange-thread-result p.cage file tid] !!)
809+ %thread-done (pure:m %& q.cage)
810+ %thread-fail (pure:m %| ;;([term tang] q.q.cage))
811+ ==
812+--
zod/seax/sur/cite.hoonnew file+57
@@ -0,0 +1,57 @@
1+/- g=groups
2+=< cite
3+|%
4+++ purse
5+ |= =(pole knot)
6+ ^- (unit cite)
7+ ?. =(~.1 -.pole) ~
8+ =. pole +.pole
9+ ?+ pole ~
10+ [%chan agent=@ ship=@ name=@ rest=*]
11+ =/ ship (slaw %p ship.pole)
12+ ?~ ship ~
13+ `[%chan [agent.pole u.ship name.pole] rest.pole]
14+ ::
15+ [%desk ship=@ name=@ rest=*]
16+ =/ ship (slaw %p ship.pole)
17+ ?~ ship ~
18+ `[%desk [u.ship name.pole] rest.pole]
19+ ::
20+ [%group ship=@ name=@ ~]
21+ =/ ship (slaw %p ship.pole)
22+ ?~ ship ~
23+ `[%group u.ship name.pole]
24+ ==
25+++ parse
26+ |= =path
27+ ^- cite
28+ (need (purse path))
29+::
30+++ print
31+ |= c=cite
32+ |^ ^- path
33+ :- (scot %ud 1)
34+ ?- -.c
35+ %chan chan/(welp (nest nest.c) wer.c)
36+ %desk desk/(welp (flag flag.c) wer.c)
37+ %group group/(flag flag.c)
38+ %bait bait/:(welp (flag grp.c) (flag gra.c) wer.c)
39+ ==
40+ ++ flag
41+ |= f=flag:g
42+ ~[(scot %p p.f) q.f]
43+ ++ nest
44+ |= n=nest:g
45+ [p.n (flag q.n)]
46+ --
47+::
48++$ cite
49+ $% [%chan =nest:g wer=path]
50+ [%group =flag:g]
51+ [%desk =flag:g wer=path]
52+ [%bait grp=flag:g gra=flag:g wer=path]
53+ :: scry into groups when you receive a bait for a chat that doesn't exist yet
54+ :: work out what app
55+ ==
56+--
57+
zod/seax/sur/diary-0.hoonnew file+323
@@ -0,0 +1,323 @@
1+/- g=groups, c=cite, graph-store, e=epic
2+/- metadata-store
3+/+ lib-graph=graph-store
4+|%
5+++ okay `epic:e`0
6+++ mar
7+ |%
8+ ++ act `mark`(rap 3 %diary-action '-' (scot %ud okay) ~)
9+ ++ upd `mark`(rap 3 %diary-update '-' (scot %ud okay) ~)
10+ ++ log `mark`(rap 3 %diary-logs '-' (scot %ud okay) ~)
11+ --
12+:: $flag: identifier for a diary channel
13++$ flag (pair ship term)
14+:: $feel: either an emoji identifier like :diff or a URL for custom
15++$ feel @ta
16+:: $view: the persisted display format for a diary
17++$ view ?(%grid %list)
18+:: $sort: the persisted sort type for a diary
19++$ sort ?(%alpha %time %arranged)
20+:: $shelf: my ship's diaries
21++$ shelf (map flag diary)
22+:: $said: used for references
23++$ said (pair flag outline)
24+:: $plan: index into diary state
25+:: p: Note being referred to
26+:: q: Quip being referred to, if any
27+::
28++$ plan
29+ (pair time (unit time))
30+::
31+:: $diary: written longform communication
32+::
33+:: net: an indicator of whether I'm a host or subscriber
34+:: log: the history of all modifications
35+:: perm: holds the diary's permissions
36+:: view: what format to display
37+:: sort: how to order posts
38+:: notes: the actual contents of the diary
39+:: remark: what is the last thing we've read
40+:: banter: comments organized by post
41+::
42++$ diary
43+ $: =net
44+ =log
45+ =perm
46+ =view
47+ =sort
48+ =notes
49+ =remark
50+ ==
51+::
52+:: $notes: a set of time ordered diary posts
53+::
54+++ notes
55+ =< rock
56+ |%
57+ +$ rock
58+ ((mop time note) lte)
59+ ++ on
60+ ((^on time note) lte)
61+ +$ diff
62+ (pair time delta)
63+ +$ delta
64+ $% [%add p=essay]
65+ [%edit p=essay]
66+ [%del ~]
67+ [%quips p=diff:quips]
68+ [%add-feel p=ship q=feel]
69+ [%del-feel p=ship]
70+ ==
71+ --
72+::
73+:: $quips: a set of time ordered note comments
74+::
75+++ quips
76+ =< rock
77+ |%
78+ +$ rock
79+ ((mop time quip) lte)
80+ ++ on
81+ ((^on time quip) lte)
82+ +$ diff
83+ (pair time delta)
84+ +$ delta
85+ $% [%add p=memo]
86+ [%del ~]
87+ [%add-feel p=ship q=feel]
88+ [%del-feel p=ship]
89+ ==
90+ --
91+::
92+:: $outline: abridged $note
93+:: .quips: number of comments
94+::
95++$ outline
96+ [quips=@ud quippers=(set ship) essay]
97+::
98+++ outlines
99+ =< outlines
100+ |%
101+ +$ outlines ((mop time outline) lte)
102+ ++ on ((^on time outline) lte)
103+ --
104+::
105+:: $note: a diary post
106+::
107++$ note [seal essay]
108+:: $quip: a post comment
109+::
110++$ quip [cork memo]
111+::
112+:: $seal: host-side data for a note
113+::
114++$ seal
115+ $: =time
116+ =quips
117+ feels=(map ship feel)
118+ ==
119+::
120+:: $cork: host-side data for a quip
121+::
122++$ cork
123+ $: =time
124+ feels=(map ship feel)
125+ ==
126+:: $essay: the post data itself
127+::
128+:: title: the name of the post
129+:: image: a visual displayed as a header
130+:: content: the body of the post
131+:: author: the ship that wrote the post
132+:: sent: the client-side time the post was made
133+::
134++$ essay
135+ $: title=@t
136+ image=@t
137+ content=(list verse)
138+ author=ship
139+ sent=time
140+ ==
141++$ story (pair (list block) (list inline))
142+:: $memo: the comment data itself
143+::
144+:: content: the body of the comment
145+:: author: the ship that wrote the comment
146+:: sent: the client-side time the comment was made
147+::
148++$ memo
149+ $: content=story
150+ author=ship
151+ sent=time
152+ ==
153+:: $verse: a chunk of post content
154+::
155+:: blocks stand on their own. inlines come in groups and get wrapped
156+:: into a paragraph
157+::
158++$ verse
159+ $% [%block p=block]
160+ [%inline p=(list inline)]
161+ ==
162+:: $listing: recursive type for infinitely nested <ul> or <ol>
163++$ listing
164+ $% [%list p=?(%ordered %unordered) q=(list listing) r=(list inline)]
165+ [%item p=(list inline)]
166+ ==
167+:: $block: post content that sits outside of the normal text
168+::
169+:: %image: a visual, we record dimensions for better rendering
170+:: %cite: an Urbit reference
171+:: %header: a traditional HTML heading, h1-h6
172+:: %listing: a traditional HTML list, ul and ol
173+:: %code: a block of code
174+::
175++$ block
176+ $% [%image src=cord height=@ud width=@ud alt=cord]
177+ [%cite =cite:c]
178+ [%header p=?(%h1 %h2 %h3 %h4 %h5 %h6) q=(list inline)]
179+ [%listing p=listing]
180+ [%rule ~]
181+ [%code code=cord lang=cord]
182+ ==
183+:: $inline: post content that flows within a paragraph
184+::
185+:: @t: plain text
186+:: %italics: italic text
187+:: %bold: bold text
188+:: %strike: strikethrough text
189+:: %inline-code: code formatting for small snippets
190+:: %blockquote: blockquote surrounded content
191+:: %block: link/reference to blocks
192+:: %code: code formatting for large snippets
193+:: %tag: tag gets special signifier
194+:: %link: link to a URL with a face
195+:: %break: line break
196+::
197++$ inline
198+ $@ @t
199+ $% [%italics p=(list inline)]
200+ [%bold p=(list inline)]
201+ [%strike p=(list inline)]
202+ [%blockquote p=(list inline)]
203+ [%inline-code p=cord]
204+ [%ship p=ship]
205+ [%block p=@ud q=cord]
206+ [%code p=cord]
207+ [%tag p=cord]
208+ [%link p=cord q=cord]
209+ [%break ~]
210+ ==
211+:: $log: a time ordered history of modifications to a diary
212+::
213++$ log
214+ ((mop time diff) lte)
215+++ log-on
216+ ((on time diff) lte)
217+::
218+:: $action: the complete set of data required to modify a diary
219+::
220++$ action
221+ (pair flag:g update)
222+::
223+:: $update: a representation in time of a modification to a diary
224+::
225++$ update
226+ (pair time diff)
227+::
228+:: $diff: the full suite of modifications that can be made to a diary
229+::
230++$ diff
231+ $% [%notes p=diff:notes]
232+ ::
233+ [%add-sects p=(set sect:g)]
234+ [%del-sects p=(set sect:g)]
235+ ::
236+ [%create p=perm q=notes]
237+ [%view p=view]
238+ [%sort p=sort]
239+ ::
240+ ==
241+::
242+:: $net: an indicator of whether I'm a host or subscriber
243+::
244+:: %pub: am publisher/host with fresh log
245+:: %sub: subscribed to the ship at saga
246+::
247++$ net
248+ $% [%sub p=ship load=_| =saga:e]
249+ [%pub ~] :: TODO: permissions?
250+ ==
251+::
252+:: $briefs: a map of diary unread information
253+::
254+:: brief: the last time a diary was read, how many posts since,
255+:: and the id of the last read note
256+::
257+++ briefs
258+ =< briefs
259+ |%
260+ +$ briefs
261+ (map flag brief)
262+ +$ brief
263+ [last=time count=@ud read-id=(unit time)]
264+ +$ update
265+ (pair flag brief)
266+ --
267+:: $remark: a marker representing the last note I've read
268+::
269++$ remark
270+ [last-read=time watching=_| ~]
271+::
272++$ remark-action
273+ (pair flag remark-diff)
274+::
275++$ remark-diff
276+ $% [%read ~]
277+ [%read-at p=time]
278+ [?(%watch %unwatch) ~]
279+ ==
280+::
281+:: $perm: represents the permissions for a diary channel and gives a
282+:: pointer back to the group it belongs to.
283+::
284++$ perm
285+ $: writers=(set sect:g)
286+ group=flag:g
287+ ==
288+:: $join: a group + channel flag to join a channel, group required for perms
289+::
290++$ join
291+ $: group=flag:g
292+ chan=flag:g
293+ ==
294+:: $leave: a flag to pass for a channel leave
295+::
296++$ leave flag:g
297+::
298+:: $create: represents a request to create a channel
299+::
300+:: The name will be used as part of the flag which represents the
301+:: channel. $create is consumed by the diary agent first and then
302+:: passed to the groups agent to register the channel with the group.
303+::
304+:: Write permission is stored with the specific agent in the channel,
305+:: read permission is stored with the group's data.
306+::
307++$ create
308+ $: group=flag:g
309+ name=term
310+ title=cord
311+ description=cord
312+ readers=(set sect:g)
313+ writers=(set sect:g)
314+ ==
315++$ import [writers=(set ship) =association:met =update-log:gra =graph:gra]
316+::
317++$ imports (map flag import)
318+::
319+++ gra graph-store
320+++ orm-gra orm:lib-graph
321+++ orm-log-gra orm-log:lib-graph
322+++ met metadata-store
323+--
zod/seax/sur/diary.hoonnew file+335
@@ -0,0 +1,335 @@
1+/- g=groups, c=cite, graph-store, e=epic
2+/- zer=diary-0
3+/- metadata-store
4+/+ lib-graph=graph-store
5+|%
6+++ old
7+ |%
8+ ++ zero zer
9+ --
10+::
11+++ okay `epic:e`2
12+++ mar
13+ |%
14+ ++ act `mark`(rap 3 %diary-action '-' (scot %ud okay) ~)
15+ ++ upd `mark`(rap 3 %diary-update '-' (scot %ud okay) ~)
16+ ++ log `mark`(rap 3 %diary-logs '-' (scot %ud okay) ~)
17+ --
18+:: $flag: identifier for a diary channel
19++$ flag (pair ship term)
20+:: $feel: either an emoji identifier like :diff or a URL for custom
21++$ feel @ta
22+:: $view: the persisted display format for a diary
23++$ view ?(%grid %list)
24+:: $sort: the persisted sort type for a diary
25++$ sort ?(%alpha %time %arranged)
26+:: $arranged-notes: an array of noteIds
27++$ arranged-notes (unit (list time))
28+:: $shelf: my ship's diaries
29++$ shelf (map flag diary)
30+:: $said: used for references
31++$ said (pair flag outline)
32+:: $plan: index into diary state
33+:: p: Note being referred to
34+:: q: Quip being referred to, if any
35+::
36++$ plan
37+ (pair time (unit time))
38+::
39+:: $diary: written longform communication
40+::
41+:: arranged-notes: a list of noteIds, used for manual sorting
42+:: net: an indicator of whether I'm a host or subscriber
43+:: log: the history of all modifications
44+:: perm: holds the diary's permissions
45+:: view: what format to display
46+:: sort: how to order posts
47+:: notes: the actual contents of the diary
48+:: remark: what is the last thing we've read
49+:: banter: comments organized by post
50+::
51++$ diary
52+ $: =arranged-notes
53+ =net
54+ =log
55+ =perm
56+ =view
57+ =sort
58+ =notes
59+ =remark
60+ ==
61+::
62+:: $notes: a set of time ordered diary posts
63+::
64+++ notes
65+ =< rock
66+ |%
67+ +$ rock
68+ ((mop time note) lte)
69+ ++ on
70+ ((^on time note) lte)
71+ +$ diff
72+ (pair time delta)
73+ +$ delta
74+ $% [%add p=essay]
75+ [%edit p=essay]
76+ [%del ~]
77+ [%quips p=diff:quips]
78+ [%add-feel p=ship q=feel]
79+ [%del-feel p=ship]
80+ ==
81+ --
82+::
83+:: $quips: a set of time ordered note comments
84+::
85+++ quips
86+ =< rock
87+ |%
88+ +$ rock
89+ ((mop time quip) lte)
90+ ++ on
91+ ((^on time quip) lte)
92+ +$ diff
93+ (pair time delta)
94+ +$ delta
95+ $% [%add p=memo]
96+ [%del ~]
97+ [%add-feel p=ship q=feel]
98+ [%del-feel p=ship]
99+ ==
100+ --
101+::
102+:: $outline: abridged $note
103+:: .quips: number of comments
104+::
105++$ outline
106+ [quips=@ud quippers=(set ship) essay]
107+::
108+++ outlines
109+ =< outlines
110+ |%
111+ +$ outlines ((mop time outline) lte)
112+ ++ on ((^on time outline) lte)
113+ --
114+::
115+:: $note: a diary post
116+::
117++$ note [seal essay]
118+:: $quip: a post comment
119+::
120++$ quip [cork memo]
121+::
122+:: $seal: host-side data for a note
123+::
124++$ seal
125+ $: =time
126+ =quips
127+ feels=(map ship feel)
128+ ==
129+::
130+:: $cork: host-side data for a quip
131+::
132++$ cork
133+ $: =time
134+ feels=(map ship feel)
135+ ==
136+:: $essay: the post data itself
137+::
138+:: title: the name of the post
139+:: image: a visual displayed as a header
140+:: content: the body of the post
141+:: author: the ship that wrote the post
142+:: sent: the client-side time the post was made
143+::
144++$ essay
145+ $: title=@t
146+ image=@t
147+ content=(list verse)
148+ author=ship
149+ sent=time
150+ ==
151++$ story (pair (list block) (list inline))
152+:: $memo: the comment data itself
153+::
154+:: content: the body of the comment
155+:: author: the ship that wrote the comment
156+:: sent: the client-side time the comment was made
157+::
158++$ memo
159+ $: content=story
160+ author=ship
161+ sent=time
162+ ==
163+:: $verse: a chunk of post content
164+::
165+:: blocks stand on their own. inlines come in groups and get wrapped
166+:: into a paragraph
167+::
168++$ verse
169+ $% [%block p=block]
170+ [%inline p=(list inline)]
171+ ==
172+:: $listing: recursive type for infinitely nested <ul> or <ol>
173++$ listing
174+ $% [%list p=?(%ordered %unordered %tasklist) q=(list listing) r=(list inline)]
175+ [%item p=(list inline)]
176+ ==
177+:: $block: post content that sits outside of the normal text
178+::
179+:: %image: a visual, we record dimensions for better rendering
180+:: %cite: an Urbit reference
181+:: %header: a traditional HTML heading, h1-h6
182+:: %listing: a traditional HTML list, ul and ol
183+:: %code: a block of code
184+::
185++$ block
186+ $% [%image src=cord height=@ud width=@ud alt=cord]
187+ [%cite =cite:c]
188+ [%header p=?(%h1 %h2 %h3 %h4 %h5 %h6) q=(list inline)]
189+ [%listing p=listing]
190+ [%rule ~]
191+ [%code code=cord lang=cord]
192+ ==
193+:: $inline: post content that flows within a paragraph
194+::
195+:: @t: plain text
196+:: %italics: italic text
197+:: %bold: bold text
198+:: %strike: strikethrough text
199+:: %inline-code: code formatting for small snippets
200+:: %blockquote: blockquote surrounded content
201+:: %block: link/reference to blocks
202+:: %code: code formatting for large snippets
203+:: %tag: tag gets special signifier
204+:: %link: link to a URL with a face
205+:: %break: line break
206+::
207++$ inline
208+ $@ @t
209+ $% [%italics p=(list inline)]
210+ [%bold p=(list inline)]
211+ [%strike p=(list inline)]
212+ [%blockquote p=(list inline)]
213+ [%inline-code p=cord]
214+ [%ship p=ship]
215+ [%block p=@ud q=cord]
216+ [%code p=cord]
217+ [%tag p=cord]
218+ [%link p=cord q=cord]
219+ [%task p=?(%.y %.n) q=(list inline)]
220+ [%break ~]
221+ ==
222+:: $log: a time ordered history of modifications to a diary
223+::
224++$ log
225+ ((mop time diff) lte)
226+++ log-on
227+ ((on time diff) lte)
228+::
229+:: $action: the complete set of data required to modify a diary
230+::
231++$ action
232+ (pair flag:g update)
233+::
234+:: $update: a representation in time of a modification to a diary
235+::
236++$ update
237+ (pair time diff)
238+::
239+:: $diff: the full suite of modifications that can be made to a diary
240+::
241++$ diff
242+ $% [%notes p=diff:notes]
243+ ::
244+ [%add-sects p=(set sect:g)]
245+ [%del-sects p=(set sect:g)]
246+ ::
247+ [%create p=perm q=notes]
248+ [%view p=view]
249+ [%sort p=sort]
250+ [%arranged-notes p=arranged-notes]
251+ ::
252+ ==
253+::
254+:: $net: an indicator of whether I'm a host or subscriber
255+::
256+:: %pub: am publisher/host with fresh log
257+:: %sub: subscribed to the ship at saga
258+::
259++$ net
260+ $% [%sub p=ship load=_| =saga:e]
261+ [%pub ~] :: TODO: permissions?
262+ ==
263+::
264+:: $briefs: a map of diary unread information
265+::
266+:: brief: the last time a diary was read, how many posts since,
267+:: and the id of the last read note
268+::
269+++ briefs
270+ =< briefs
271+ |%
272+ +$ briefs
273+ (map flag brief)
274+ +$ brief
275+ [last=time count=@ud read-id=(unit time)]
276+ +$ update
277+ (pair flag brief)
278+ --
279+:: $remark: a marker representing the last note I've read
280+::
281++$ remark
282+ [last-read=time watching=_| ~]
283+::
284++$ remark-action
285+ (pair flag remark-diff)
286+::
287++$ remark-diff
288+ $% [%read ~]
289+ [%read-at p=time]
290+ [?(%watch %unwatch) ~]
291+ ==
292+::
293+:: $perm: represents the permissions for a diary channel and gives a
294+:: pointer back to the group it belongs to.
295+::
296++$ perm
297+ $: writers=(set sect:g)
298+ group=flag:g
299+ ==
300+:: $join: a group + channel flag to join a channel, group required for perms
301+::
302++$ join
303+ $: group=flag:g
304+ chan=flag:g
305+ ==
306+:: $leave: a flag to pass for a channel leave
307+::
308++$ leave flag:g
309+::
310+:: $create: represents a request to create a channel
311+::
312+:: The name will be used as part of the flag which represents the
313+:: channel. $create is consumed by the diary agent first and then
314+:: passed to the groups agent to register the channel with the group.
315+::
316+:: Write permission is stored with the specific agent in the channel,
317+:: read permission is stored with the group's data.
318+::
319++$ create
320+ $: group=flag:g
321+ name=term
322+ title=cord
323+ description=cord
324+ readers=(set sect:g)
325+ writers=(set sect:g)
326+ ==
327++$ import [writers=(set ship) =association:met =update-log:gra =graph:gra]
328+::
329++$ imports (map flag import)
330+::
331+++ gra graph-store
332+++ orm-gra orm:lib-graph
333+++ orm-log-gra orm-log:lib-graph
334+++ met metadata-store
335+--
zod/seax/sur/epic.hoonnew file+15
@@ -0,0 +1,15 @@
1+|%
2+:: $saga: version synchronisation state
3+:: %dex: publisher is ahead
4+:: %lev: we are ahead
5+:: %chi: full sync
6+::
7++$ saga
8+ $% [%dex ver=@ud]
9+ [%lev ~]
10+ [%chi ~]
11+ ==
12+
13++$ epic @ud
14+::
15+--
zod/seax/sur/graph-store.hoonnew file+272
@@ -0,0 +1,272 @@
1+/- *post
2+|%
3++$ graph ((mop atom node) gth)
4++$ marked-graph [p=graph q=(unit mark)]
5+::
6++$ maybe-post (each post hash)
7++$ node [post=maybe-post children=internal-graph]
8++$ graphs (map resource marked-graph)
9+::
10++$ tag-queries (jug term uid)
11+::
12++$ update-log ((mop time logged-update) gth)
13++$ update-logs (map resource update-log)
14+::
15++$ internal-graph
16+ $~ [%empty ~]
17+ $% [%graph p=graph]
18+ [%empty ~]
19+ ==
20+::
21++$ network
22+ $: =graphs
23+ =tag-queries
24+ =update-logs
25+ archive=graphs
26+ ~
27+ ==
28+::
29++$ update [p=time q=action]
30+::
31++$ logged-update [p=time q=logged-action]
32+
33+::
34++$ logged-action
35+ $% [%add-graph =resource =graph mark=(unit mark) overwrite=?]
36+ [%add-nodes =resource nodes=(map index node)]
37+ [%remove-posts =resource indices=(set index)]
38+ [%add-signatures =uid =signatures]
39+ [%remove-signatures =uid =signatures]
40+ ==
41+::
42++$ action
43+ $% logged-action
44+ [%remove-graph =resource]
45+ ::
46+ [%add-tag =term =uid]
47+ [%remove-tag =term =uid]
48+ ::
49+ [%archive-graph =resource]
50+ [%unarchive-graph =resource]
51+ [%run-updates =resource =update-log]
52+ ::
53+ :: NOTE: cannot be sent as pokes
54+ ::
55+ [%keys =resources]
56+ [%tags tags=(set term)]
57+ [%tag-queries =tag-queries]
58+ ==
59+::
60++$ permissions
61+ [admin=permission-level writer=permission-level reader=permission-level]
62+::
63+:: $permission-level: levels of permissions in increasing order
64+::
65+:: %no: May not add/remove node
66+:: %self: May only nodes beneath nodes that were added by
67+:: the same pilot, may remove nodes that the pilot 'owns'
68+:: %yes: May add a node or remove node
69++$ permission-level
70+ ?(%no %self %yes)
71+::
72+:: %graph-store types version 2
73+::
74+++ two
75+ =< [. post-one]
76+ =, post-one
77+ |%
78+ +$ maybe-post (each post hash)
79+ ++ orm ((on atom node) gth)
80+ ++ orm-log ((on time logged-update) gth)
81+ ::
82+ +$ graph ((mop atom node) gth)
83+ +$ marked-graph [p=graph q=(unit mark)]
84+ ::
85+ +$ node [post=maybe-post children=internal-graph]
86+ +$ graphs (map resource marked-graph)
87+ ::
88+ +$ tag-queries (jug term resource)
89+ ::
90+ +$ update-log ((mop time logged-update) gth)
91+ +$ update-logs (map resource update-log)
92+ ::
93+ +$ internal-graph
94+ $~ [%empty ~]
95+ $% [%graph p=graph]
96+ [%empty ~]
97+ ==
98+ ::
99+ +$ network
100+ $: =graphs
101+ =tag-queries
102+ =update-logs
103+ archive=graphs
104+ validators=(set mark)
105+ ==
106+ ::
107+ +$ update [p=time q=action]
108+ ::
109+ +$ logged-update [p=time q=logged-action]
110+ ::
111+ +$ logged-action
112+ $% [%add-graph =resource =graph mark=(unit mark) overwrite=?]
113+ [%add-nodes =resource nodes=(map index node)]
114+ [%remove-nodes =resource indices=(set index)]
115+ [%add-signatures =uid =signatures]
116+ [%remove-signatures =uid =signatures]
117+ ==
118+ ::
119+ +$ action
120+ $% logged-action
121+ [%remove-graph =resource]
122+ ::
123+ [%add-tag =term =resource]
124+ [%remove-tag =term =resource]
125+ ::
126+ [%archive-graph =resource]
127+ [%unarchive-graph =resource]
128+ [%run-updates =resource =update-log]
129+ ::
130+ :: NOTE: cannot be sent as pokes
131+ ::
132+ [%keys =resources]
133+ [%tags tags=(set term)]
134+ [%tag-queries =tag-queries]
135+ ==
136+ --
137+::
138+:: %graph-store types version 1
139+::
140+++ one
141+ =< [. post-one]
142+ =, post-one
143+ |%
144+ ++ orm ((on atom node) gth)
145+ ++ orm-log ((on time logged-update) gth)
146+ ::
147+ +$ graph ((mop atom node) gth)
148+ +$ marked-graph [p=graph q=(unit mark)]
149+ ::
150+ +$ node [=post children=internal-graph]
151+ +$ graphs (map resource marked-graph)
152+ ::
153+ +$ tag-queries (jug term resource)
154+ ::
155+ +$ update-log ((mop time logged-update) gth)
156+ +$ update-logs (map resource update-log)
157+ ::
158+ +$ internal-graph
159+ $~ [%empty ~]
160+ $% [%graph p=graph]
161+ [%empty ~]
162+ ==
163+ ::
164+ +$ network
165+ $: =graphs
166+ =tag-queries
167+ =update-logs
168+ archive=graphs
169+ validators=(set mark)
170+ ==
171+ ::
172+ +$ update [p=time q=action]
173+ ::
174+ +$ logged-update [p=time q=logged-action]
175+ ::
176+ +$ logged-action
177+ $% [%add-graph =resource =graph mark=(unit mark) overwrite=?]
178+ [%add-nodes =resource nodes=(map index node)]
179+ [%remove-nodes =resource indices=(set index)]
180+ [%add-signatures =uid =signatures]
181+ [%remove-signatures =uid =signatures]
182+ ==
183+ ::
184+ +$ action
185+ $% logged-action
186+ [%remove-graph =resource]
187+ ::
188+ [%add-tag =term =resource]
189+ [%remove-tag =term =resource]
190+ ::
191+ [%archive-graph =resource]
192+ [%unarchive-graph =resource]
193+ [%run-updates =resource =update-log]
194+ ::
195+ :: NOTE: cannot be sent as pokes
196+ ::
197+ [%keys =resources]
198+ [%tags tags=(set term)]
199+ [%tag-queries =tag-queries]
200+ ==
201+ --
202+::
203+:: %graph-store types version 0
204+::
205+++ zero
206+ =< [. post-zero]
207+ =, post-zero
208+ |%
209+ ++ orm ((ordered-map atom node) gth)
210+ ++ orm-log ((ordered-map time logged-update) gth)
211+ ::
212+ +$ graph ((mop atom node) gth)
213+ +$ marked-graph [p=graph q=(unit mark)]
214+ ::
215+ +$ node [=post children=internal-graph]
216+ +$ graphs (map resource marked-graph)
217+ ::
218+ +$ tag-queries (jug term resource)
219+ ::
220+ +$ update-log ((mop time logged-update) gth)
221+ +$ update-logs (map resource update-log)
222+ ::
223+ ::
224+ +$ internal-graph
225+ $~ [%empty ~]
226+ $% [%graph p=graph]
227+ [%empty ~]
228+ ==
229+ ::
230+ +$ network
231+ $: =graphs
232+ =tag-queries
233+ =update-logs
234+ archive=graphs
235+ validators=(set mark)
236+ ==
237+ ::
238+ +$ update
239+ $% [%0 p=time q=update-0]
240+ ==
241+ ::
242+ +$ logged-update
243+ $% [%0 p=time q=logged-update-0]
244+ ==
245+ ::
246+ +$ logged-update-0
247+ $% [%add-graph =resource =graph mark=(unit mark) overwrite=?]
248+ [%add-nodes =resource nodes=(map index node)]
249+ [%remove-nodes =resource indices=(set index)]
250+ [%add-signatures =uid =signatures]
251+ [%remove-signatures =uid =signatures]
252+ ==
253+ ::
254+ +$ update-0
255+ $% logged-update-0
256+ [%remove-graph =resource]
257+ ::
258+ [%add-tag =term =resource]
259+ [%remove-tag =term =resource]
260+ ::
261+ [%archive-graph =resource]
262+ [%unarchive-graph =resource]
263+ [%run-updates =resource =update-log]
264+ ::
265+ :: NOTE: cannot be sent as pokes
266+ ::
267+ [%keys =resources]
268+ [%tags tags=(set term)]
269+ [%tag-queries =tag-queries]
270+ ==
271+ --
272+--
zod/seax/sur/group-store.hoonnew file+39
@@ -0,0 +1,39 @@
1+/- *group, *resource
2+^?
3+|%
4+::
5+:: $action: request to change group-store state
6+::
7+:: %add-group: add a group
8+:: %add-members: add members to a group
9+:: %remove-members: remove members from a group
10+:: %add-tag: add a tag to a set of ships
11+:: %remove-tag: remove a tag from a set of ships
12+:: %change-policy: change a group's policy
13+:: %remove-group: remove a group from the store
14+:: %expose: unset .hidden flag
15+::
16++$ action
17+ $% [%add-group =resource =policy hidden=?]
18+ [%add-members =resource ships=(set ship)]
19+ [%remove-members =resource ships=(set ship)]
20+ [%add-tag =resource =tag ships=(set ship)]
21+ [%remove-tag =resource =tag ships=(set ship)]
22+ [%change-policy =resource =diff:policy]
23+ [%remove-group =resource ~]
24+ [%expose =resource ~]
25+ ==
26+:: $update: a description of a processed state change
27+::
28+:: %initial: describe groups upon new subscription
29+::
30++$ update
31+ $% initial
32+ action
33+ ==
34++$ initial
35+ $% [%initial-group =resource =group]
36+ [%initial =groups]
37+ ==
38+--
39+
zod/seax/sur/group.hoonnew file+109
@@ -0,0 +1,109 @@
1+/- *resource
2+::
3+^?
4+|%
5+::
6+++ groups-state-one
7+ |%
8+ +$ groups (map resource group)
9+ ::
10+ +$ tag $@(group-tag [app=term tag=term])
11+ ::
12+ +$ tags (jug tag ship)
13+ ::
14+ +$ group
15+ $: members=(set ship)
16+ =tags
17+ =policy
18+ hidden=?
19+ ==
20+ --
21+:: $groups: a mapping from group-ids to groups
22+::
23++$ groups (map resource group)
24+:: $group-tag: an identifier used by groups
25+::
26+:: These tags should have precise semantics, as they are shared across all
27+:: apps.
28+::
29++$ group-tag ?(role-tag)
30+:: $tag: an identifier used to identify a subset of members
31+::
32+:: Tags may be used and recognised differently across apps.
33+:: for example, you could use tags like `%author`, `%bot`, `%flagged`...
34+::
35++$ tag $@(group-tag [app=term =resource tag=term])
36+:: $role-tag: a kind of $group-tag that identifies a privileged user
37+::
38+:: These roles are
39+:: %admin: Administrator, can do everything except delete the group
40+:: %moderator: Moderator, can add/remove/ban users
41+:: %janitor: Has no special meaning inside group-store,
42+:: but may be given additional privileges in other apps.
43+::
44++$ role-tag
45+ ?(%admin %moderator %janitor)
46+:: $tags: a mapping from a $tag to the members it identifies
47+::
48++$ tags (jug tag ship)
49+:: $group: description of a group of users
50+::
51+:: .members: members of the group
52+:: .tag-queries: a map of tags to subsets of members
53+:: .policy: permissions for the group
54+:: .hidden: is group unmanaged
55++$ group
56+ $: members=(set ship)
57+ =tags
58+ =policy
59+ hidden=?
60+ ==
61+:: $policy: access control for a group
62+::
63+++ policy
64+ =< policy
65+ |%
66+ ::
67+ +$ policy
68+ $% invite
69+ open
70+ ==
71+ :: $diff: change group policy
72+ +$ diff
73+ $% [%invite diff:invite]
74+ [%open diff:open]
75+ [%replace =policy]
76+ ==
77+ :: $invite: allow only invited ships
78+ ++ invite
79+ =< invite-policy
80+ |%
81+ ::
82+ +$ invite-policy
83+ [%invite pending=(set ship)]
84+ :: $diff: add or remove invites
85+ ::
86+ +$ diff
87+ $% [%add-invites invitees=(set ship)]
88+ [%remove-invites invitees=(set ship)]
89+ ==
90+ --
91+ :: $open: allow all unbanned ships of approriate rank
92+ ::
93+ ++ open
94+ =< open-policy
95+ |%
96+ ::
97+ +$ open-policy
98+ [%open ban-ranks=(set rank:title) banned=(set ship)]
99+ :: $diff: ban or allow ranks and ships
100+ ::
101+ +$ diff
102+ $% [%allow-ranks ranks=(set rank:title)]
103+ [%ban-ranks ranks=(set rank:title)]
104+ [%ban-ships ships=(set ship)]
105+ [%allow-ships ships=(set ship)]
106+ ==
107+ --
108+ --
109+--
zod/seax/sur/groups.hoonnew file+364
@@ -0,0 +1,364 @@
1+/- meta, e=epic
2+/- old=group
3+/- grp=group-store
4+/- metadata-store
5+|%
6+++ okay `epic:e`2
7+++ mar
8+ |%
9+ ++ act `mark`(rap 3 %group-action '-' (scot %ud okay) ~)
10+ ++ upd `mark`(rap 3 %group-update '-' (scot %ud okay) ~)
11+ ++ log `mark`(rap 3 %group-log '-' (scot %ud okay) ~)
12+ ++ int `mark`(rap 3 %group-init '-' (scot %ud okay) ~)
13+ --
14+:: $flag: ID for a group
15+::
16++$ flag (pair ship term)
17+::
18+:: $nest: ID for a channel, {app}/{ship}/{name}
19+::
20++$ nest (pair dude:gall flag)
21+::
22+:: $sect: ID for cabal, similar to a role
23+::
24++$ sect term
25+::
26+:: $zone: channel grouping
27+::
28+:: includes its own metadata for display and keeps the order of
29+:: channels within.
30+::
31+:: zone: the term that represents the ID of a zone
32+:: realm: the metadata representing the zone and the order of channels
33+:: delta: the set of actions that can be taken on a zone
34+:: %add: create a zone
35+:: %del: delete the zone
36+:: %edit: modify the zone metadata
37+:: %mov: reorders the zone in the group
38+:: %mov-nest: reorders a channel within the zone
39+::
40+++ zone
41+ =< zone
42+ |%
43+ +$ zone @tas
44+ +$ realm
45+ $: met=data:meta
46+ ord=(list nest)
47+ ==
48+ +$ diff (pair zone delta)
49+ +$ delta
50+ $% [%add meta=data:meta]
51+ [%del ~]
52+ [%edit meta=data:meta]
53+ [%mov idx=@ud]
54+ [%mov-nest =nest idx=@ud]
55+ ==
56+ --
57+::
58+:: $fleet: group members and their associated metadata
59+::
60+:: vessel: a user's set of sects or roles and the time that they joined
61+:: @da default represents an admin added member that has yet to join
62+::
63+++ fleet
64+ =< fleet
65+ |%
66+ +$ fleet (map ship vessel)
67+ +$ vessel
68+ $: sects=(set sect)
69+ joined=time
70+ ==
71+ +$ diff
72+ $% [%add ~]
73+ [%del ~]
74+ [%add-sects sects=(set sect)]
75+ [%del-sects sects=(set sect)]
76+ ==
77+ --
78+::
79+:: $channel: a medium for interaction
80+::
81+++ channel
82+ =< channel
83+ |%
84+ +$ preview
85+ $: =nest
86+ meta=data:meta
87+ group=^preview
88+ ==
89+ ::
90+ +$ channels (map nest channel)
91+ ::
92+ :: $channel: a collection of metadata about a specific agent integration
93+ ::
94+ :: meta: title, description, image, cover
95+ :: added: when the channel was created
96+ :: zone: what zone or section to bucket in
97+ :: join: should the channel be joined by new members
98+ :: readers: what sects can see the channel, empty means anyone
99+ ::
100+ +$ channel
101+ $: meta=data:meta
102+ added=time
103+ =zone
104+ join=?
105+ readers=(set sect)
106+ ==
107+ ::
108+ :: $diff: represents the set of actions you can take on a channel
109+ ::
110+ :: add: create a channel
111+ :: edit: edit a channel
112+ :: del: delete a channel
113+ :: add-sects: add sects to readers
114+ :: del-sects: delete sects from readers
115+ :: zone: change the zone of the channel
116+ :: join: toggle default join
117+ ::
118+ +$ diff
119+ $% [%add =channel]
120+ [%edit =channel]
121+ [%del ~]
122+ ::
123+ [%add-sects sects=(set sect)]
124+ [%del-sects sects=(set sect)]
125+ ::
126+ [%zone =zone]
127+ ::
128+ [%join join=_|]
129+ ==
130+ --
131+::
132+:: $group: collection of people and the pathways in which they interact
133+::
134+:: group holds all data around members, permissions, channel
135+:: organization, and its own metadata to represent the group
136+::
137++$ group
138+ $: =fleet
139+ cabals=(map sect cabal)
140+ zones=(map zone realm:zone)
141+ zone-ord=(list zone)
142+ =bloc
143+ =channels:channel
144+ imported=(set nest)
145+ =cordon
146+ secret=?
147+ meta=data:meta
148+ ==
149+::
150++$ group-ui [group saga=(unit saga:e)]
151+:: $cabal: metadata representing a $sect or role
152+::
153+++ cabal
154+ =< cabal
155+ |%
156+ ::
157+ +$ cabal
158+ [meta=data:meta ~]
159+ ::
160+ +$ diff
161+ $% [%add meta=data:meta]
162+ [%edit meta=data:meta]
163+ [%del ~]
164+ ==
165+ --
166+::
167+:: $cordon: group entry and visibility permissions
168+::
169+++ cordon
170+ =< cordon
171+ |%
172+ ::
173+ :: $open: a group with open entry, only bans are barred entry
174+ ::
175+ ++ open
176+ |%
177+ :: $ban: set of ships and ranks/classes that are not allowed entry
178+ ::
179+ :: bans can either be done at the individual ship level or by the
180+ :: rank level (comet/moon/etc.)
181+ ::
182+ +$ ban [ships=(set ship) ranks=(set rank:title)]
183+ +$ diff
184+ $% [%add-ships p=(set ship)]
185+ [%del-ships p=(set ship)]
186+ ::
187+ [%add-ranks p=(set rank:title)]
188+ [%del-ranks p=(set rank:title)]
189+ ==
190+ --
191+ ::
192+ :: $shut: a group with closed entry, everyone barred entry
193+ ::
194+ :: a shut cordon means that the group is closed, but still visible.
195+ :: people may request entry and either be accepted or denied or
196+ :: they may be invited directly
197+ ::
198+ :: ask: represents those requesting entry
199+ :: pending: represents those who've been invited
200+ ::
201+ ++ shut
202+ |%
203+ +$ state [pend=(set ship) ask=(set ship)]
204+ +$ kind ?(%ask %pending)
205+ +$ diff
206+ $% [%add-ships p=kind q=(set ship)]
207+ [%del-ships p=kind q=(set ship)]
208+ ==
209+ --
210+ ::
211+ :: $cordon: a set of metadata to represent the entry policy for a group
212+ ::
213+ :: open: a group with open entry, only bans barred entry
214+ :: shut: a group with closed entry, everyone barred entry
215+ :: afar: a custom entry policy defined by another agent
216+ ::
217+ +$ cordon
218+ $% [%shut state:shut]
219+ [%afar =flag =path desc=@t]
220+ [%open =ban:open]
221+ ==
222+ ::
223+ :: $diff: the actions you can take on a cordon
224+ ::
225+ +$ diff
226+ $% [%shut p=diff:shut]
227+ [%open p=diff:open]
228+ [%swap p=cordon]
229+ ==
230+ --
231+::
232+:: $bloc: superuser sects
233+::
234+:: sects in the bloc set are allowed to make modifications to the group
235+:: and its various metadata and permissions
236+::
237+++ bloc
238+ =< bloc
239+ |%
240+ +$ bloc (set sect)
241+ +$ diff
242+ $% [%add p=(set sect)]
243+ [%del p=(set sect)]
244+ ==
245+ --
246+::
247+:: $diff: the general set of changes that can be made to a group
248+::
249++$ diff
250+ $% [%fleet p=(set ship) q=diff:fleet]
251+ [%cabal p=sect q=diff:cabal]
252+ [%channel p=nest q=diff:channel]
253+ [%bloc p=diff:bloc]
254+ [%cordon p=diff:cordon]
255+ [%zone p=diff:zone]
256+ [%meta p=data:meta]
257+ [%secret p=?]
258+ [%create p=group]
259+ [%del ~]
260+ ==
261+::
262+:: $action: the complete set of data required to edit a group
263+::
264++$ action
265+ (pair flag update)
266+::
267+:: $update: a representation in time of a modification of a group
268+::
269++$ update
270+ (pair time diff)
271+::
272+:: $create: a request to make a group
273+::
274++$ create
275+ $: name=term
276+ title=cord
277+ description=cord
278+ image=cord
279+ cover=cord
280+ =cordon
281+ members=(jug ship sect)
282+ secret=?
283+ ==
284+::
285++$ init [=time =group]
286+::
287+:: $groups-ui: map for frontend to display groups
288++$ groups-ui
289+ (map flag group-ui)
290++$ groups
291+ (map flag group)
292++$ net-groups
293+ (map flag [net group])
294+::
295+:: $log: a time ordered map of all modifications to groups
296+::
297++$ log
298+ ((mop time diff) lte)
299+::
300+++ log-on
301+ ((on time diff) lte)
302+::
303+:: $net: an indicator of whether I'm a host or subscriber
304+::
305++$ net
306+ $~ [%pub ~]
307+ $% [%pub p=log]
308+ [%sub p=time load=_| =saga:e]
309+ ==
310+::
311+:: $join: a join request, can elect to join all channels
312+::
313++$ join
314+ $: =flag
315+ join-all=?
316+ ==
317+::
318+:: $knock: a request to enter a closed group
319+::
320++$ knock flag
321+::
322+:: $progress: the state of a group join
323+::
324++$ progress
325+ ?(%knocking %adding %watching %done %error)
326+::
327+:: $claim: a mark for gangs to represent a join in progress
328+::
329++$ claim
330+ $: join-all=?
331+ =progress
332+ ==
333+::
334+:: $preview: the metadata and entry policy for a group
335+::
336++$ preview
337+ $: =flag
338+ meta=data:meta
339+ =cordon
340+ =time
341+ secret=?
342+ ==
343+::
344++$ previews (map flag preview)
345+::
346+:: $invite: a marker to show you've been invited to a group
347+::
348++$ invite (pair flag ship)
349+::
350+:: $gang: view of foreign group
351+::
352++$ gang
353+ $: cam=(unit claim)
354+ pev=(unit preview)
355+ vit=(unit invite)
356+ ==
357+::
358++$ gangs (map flag gang)
359+++ met metadata-store
360+::
361++$ import [self=association:met chan=(map flag =association:met) roles=(set flag) =group:old]
362+::
363++$ imports (map flag import)
364+--
zod/seax/sur/hark-store.hoonnew file+159
@@ -0,0 +1,159 @@
1+^?
2+::
3+:: %hark-store: Notification, unreads store
4+::
5+:: Timeboxing & binning:
6+::
7+:: Unread notifications accumulate in $unreads. They are grouped by
8+:: their $bin. A notification may become read by either:
9+:: a) being read by a %read-count or %read-each or %read-note
10+:: b) being read by a %seen
11+::
12+:: If a) then we insert the corresponding bin into $reads at the
13+:: current timestamp
14+:: If b) then we empty $unreads and move all bins to $reads at the
15+:: current timestamp
16+::
17+:: Unread tracking:
18+:: Unread tracking has two 'modes' which may be used concurrently,
19+:: if necessary.
20+::
21+:: count:
22+:: This stores the unreads as a simple atom, describing the number
23+:: of unread items. May be increased with %unread-count and
24+:: set to zero with %read-count. Ideal for high-frequency linear
25+:: datastructures, e.g. chat
26+:: each:
27+:: This stores the unreads as a set of paths, describing the set of
28+:: unread items. Unreads may be added to the set with %unread-each
29+:: and removed with %read-each. Ideal for non-linear, low-frequency
30+:: datastructures, e.g. blogs
31+::
32+|%
33+:: $place: A location, under which landscape stores stats
34+::
35+:: .desk must match q.byk.bowl
36+:: Examples:
37+:: A chat:
38+:: [%landscape /~dopzod/urbit-help]
39+:: A note in a notebook:
40+:: [%landscape /~darrux-landes/feature-requests/12374893234232]
41+:: A group:
42+:: [%hark-group-hook /~bitbet-bolbel/urbit-community]
43+:: Comments on a link
44+:: [%landscape /~dabben-larbet/urbit-in-the-news/17014118450499614194868/2]
45+::
46++$ place [=desk =path]
47+::
48+:: $bin: Identifier for grouping notifications
49+::
50+:: Examples
51+:: A mention in a chat:
52+:: [/mention %landscape /~dopzod/urbit-help]
53+:: New messages in a chat
54+:: [/message %landscape /~dopzod/urbit-help]
55+:: A new comment in a notebook:
56+:: [/comment %landscape /~darrux-landes/feature-requests/12374893234232/2]
57+::
58++$ bin [=path =place]
59+::
60+:: $lid: Reference to a timebox
61+::
62++$ lid
63+ $% [%archive =time]
64+ [%seen ~]
65+ [%unseen ~]
66+ ==
67+:: $content: Notification content
68++$ content
69+ $% [%ship =ship]
70+ [%text =cord]
71+ ==
72+::
73+:: $body: A notification body
74+::
75++$ body
76+ $: title=(list content)
77+ content=(list content)
78+ =time
79+ binned=path
80+ link=path
81+ ==
82+::
83++$ notification
84+ [date=@da =bin body=(list body)]
85+:: $timebox: Group of notificatons
86++$ timebox
87+ (map bin notification)
88+:: $archive: Archived notifications, ordered by time
89++$ archive
90+ ((mop @da timebox) gth)
91+::
92++$ action
93+ $% :: hook actions
94+ ::
95+ :: %add-note: add a notification
96+ [%add-note =bin =body]
97+ ::
98+ :: %del-place: Underlying resource disappeared, remove all
99+ :: associated notifications
100+ [%del-place =place]
101+ :: %unread-count: Change unread count by .count
102+ [%unread-count =place inc=? count=@ud]
103+ :: %unread-each: Add .path to list of unreads for .place
104+ [%unread-each =place =path]
105+ :: %saw-place: Update last-updated for .place to now.bowl
106+ [%saw-place =place time=(unit time)]
107+ :: store actions
108+ ::
109+ :: %archive: archive single notification
110+ :: if .time is ~, then archiving unread notification
111+ :: else, archiving read notification
112+ [%archive =lid =bin]
113+ :: %read-count: set unread count to zero
114+ [%read-count =place]
115+ :: %read-each: remove path from unreads for .place
116+ [%read-each =place =path]
117+ :: %read-note: Read note at .bin
118+ [%read-note =bin]
119+ :: %archive-all: Archive all notifications
120+ [%archive-all ~]
121+ :: %opened: User opened notifications, reset timeboxing logic.
122+ ::
123+ [%opened ~]
124+ ::
125+ :: XX: previously in hark-store, now deprecated
126+ :: the hooks responsible for creating notifications may offer pokes
127+ :: similar to this
128+ :: [%read-graph =resource]
129+ :: [%read-group =resource]
130+ :: [%remove-graph =resource]
131+ ::
132+ ==
133+:: .stats: Statistics for a .place
134+::
135++$ stats
136+ $: count=@ud
137+ each=(set path)
138+ last=@da
139+ timebox=(unit @da)
140+ ==
141+::
142++$ update
143+ $% action
144+ :: %more: more updates
145+ [%archived =time =lid =notification]
146+ [%more more=(list update)]
147+ :: %note-read: note has been read with timestamp
148+ [%note-read =time =bin]
149+ [%added =notification]
150+ :: %timebox: description of timebox.
151+ ::
152+ [%timebox =lid =(list notification)]
153+ :: %place-stats: description of .stats for a .place
154+ [%place-stats =place =stats]
155+ :: %place-stats: stats for all .places
156+ [%all-stats places=(map place stats)]
157+ ==
158+--
159+
zod/seax/sur/meta.hoonnew file+21
@@ -0,0 +1,21 @@
1+|%
2+:: $data: generic metadata for various entities
3+::
4+:: title: the pretty text representing what something is called
5+:: description: a longer text entry giving a detailed summary
6+:: image: an image URL or color string used as an icon/avatar
7+:: cover: an image URL or color string, used as a header
8+::
9++$ data
10+ $: title=cord
11+ description=cord
12+ image=cord
13+ cover=cord
14+ ==
15++$ diff
16+ $% [%title =cord]
17+ [%description =cord]
18+ [%image =cord]
19+ [%cover =cord]
20+ ==
21+--
zod/seax/sur/metadata-store.hoonnew file+138
@@ -0,0 +1,138 @@
1+/- *resource
2+^?
3+|%
4+::
5++$ app-name term
6++$ md-resource [=app-name =resource]
7++$ association [group=resource =metadatum]
8++$ associations (map md-resource association)
9++$ group-preview
10+ $: group=resource
11+ channels=associations
12+ members=@ud
13+ channel-count=@ud
14+ =metadatum
15+ ==
16+::
17++$ color @ux
18++$ url @t
19+::
20+:: $vip-metadata: variation in permissions
21+::
22+:: This will be passed to the graph-permissions mark
23+:: conversion to allow for custom permissions.
24+::
25+:: %reader-comments: Allow readers to comment, regardless
26+:: of whether they can write. (notebook, collections)
27+:: %member-metadata: Allow members to add channels (groups)
28+:: %host-feed: Only host can post to group feed
29+:: %admin-feed: Only admins and host can post to group feed
30+:: %$: No variation
31+::
32++$ vip-metadata
33+ $? %reader-comments
34+ %member-metadata
35+ %host-feed
36+ %admin-feed
37+ %$
38+ ==
39+::
40++$ md-config
41+ $~ [%empty ~]
42+ $% [%group feed=(unit (unit md-resource))]
43+ [%graph module=term]
44+ [%empty ~]
45+ ==
46+::
47++$ edit-field
48+ $% [%title title=cord]
49+ [%description description=cord]
50+ [%color color=@ux]
51+ [%picture =url]
52+ [%preview preview=?]
53+ [%hidden hidden=?]
54+ [%vip vip=vip-metadata]
55+ ==
56+::
57++$ metadatum
58+ $: title=cord
59+ description=cord
60+ =color
61+ date-created=time
62+ creator=ship
63+ config=md-config
64+ picture=url
65+ preview=?
66+ hidden=?
67+ vip=vip-metadata
68+ ==
69+::
70++$ action
71+ $% [%add group=resource resource=md-resource =metadatum]
72+ [%remove group=resource resource=md-resource]
73+ [%edit group=resource resource=md-resource =edit-field]
74+ [%initial-group group=resource =associations]
75+ ==
76+::
77++$ hook-update
78+ $% [%req-preview group=resource]
79+ [%preview group-preview]
80+ ==
81+::
82++$ update
83+ $% action
84+ [%associations =associations]
85+ $: %updated-metadata
86+ group=resource
87+ resource=md-resource
88+ before=metadatum
89+ =metadatum
90+ ==
91+ ==
92+:: historical
93+++ one
94+ |%
95+ ::
96+ +$ action
97+ $~ [%remove *resource *md-resource]
98+ $< %edit ^action
99+ ::
100+ +$ update
101+ $~ [%remove *resource *md-resource]
102+ $< %edit ^update
103+ ::
104+ --
105+++ zero
106+ |%
107+ ::
108+ +$ association [group=resource =metadatum]
109+ ::
110+ +$ associations (map md-resource association)
111+ ::
112+ +$ metadatum
113+ $: title=cord
114+ description=cord
115+ =color
116+ date-created=time
117+ creator=ship
118+ module=term
119+ picture=url
120+ preview=?
121+ vip=vip-metadata
122+ ==
123+ ::
124+ +$ update
125+ $% [%add group=resource resource=md-resource =metadatum]
126+ [%remove group=resource resource=md-resource]
127+ [%initial-group group=resource =associations]
128+ [%associations =associations]
129+ $: %updated-metadata
130+ group=resource
131+ resource=md-resource
132+ before=metadatum
133+ =metadatum
134+ ==
135+ ==
136+ ::
137+ --
138+--
zod/seax/sur/notes.hoonnew file+74
@@ -0,0 +1,74 @@
1+|%
2++$ diary
3+ $: *
4+ *
5+ *
6+ *
7+ *
8+ =notes
9+ *
10+ ==
11++$ seal
12+ $: =time
13+ * :: =quips
14+ * :: feels=(map ship feel)
15+ ==
16++$ note [seal essay]
17++$ verse
18+ $% [%block p=block]
19+ [%inline p=(list inline)]
20+ ==
21++$ listing
22+ $% [%list p=?(%ordered %unordered) q=(list listing) r=(list inline)]
23+ [%item p=(list inline)]
24+ ==
25++$ block
26+ $% [%image src=cord height=@ud width=@ud alt=cord]
27+ [%cite *] :: =cite:c]
28+ [%header p=?(%h1 %h2 %h3 %h4 %h5 %h6) q=(list inline)]
29+ [%listing p=listing]
30+ [%rule ~]
31+ [%code code=cord lang=cord]
32+ ==
33++$ inline
34+ $@ @t
35+ $% [%italics p=(list inline)]
36+ [%bold p=(list inline)]
37+ [%strike p=(list inline)]
38+ [%blockquote p=(list inline)]
39+ [%inline-code p=cord]
40+ [%ship p=ship]
41+ [%block p=@ud q=cord]
42+ [%code p=cord]
43+ [%tag p=cord]
44+ [%link p=cord q=cord]
45+ [%break ~]
46+ ==
47++$ essay
48+ $: title=@t
49+ image=@t
50+ content=(list verse)
51+ author=ship
52+ sent=time
53+ ==
54+++ notes
55+ =< rock
56+ |%
57+ +$ rock
58+ ((mop time note) lte)
59+ ++ on
60+ ((^on time note) lte)
61+ +$ diff
62+ (pair time delta)
63+ +$ delta
64+ $% [%add p=essay]
65+ [%edit p=essay]
66+ [%del ~]
67+ [%quips *] :: p=diff:quips]
68+ [%add-feel p=ship *] :: q=feel]
69+ [%del-feel p=ship]
70+ ==
71+ --
72++$ shelf (map flag diary)
73++$ flag (pair ship term)
74+--
zod/seax/sur/post.hoonnew file+91
@@ -0,0 +1,91 @@
1+/- *resource
2+|%
3++$ index (list atom)
4++$ uid [=resource =index]
5+::
6+:: +sham (half sha-256) hash of +validated-portion
7++$ hash @ux
8+::
9++$ signature [p=@ux q=ship r=life]
10++$ signatures (set signature)
11++$ post
12+ $: author=ship
13+ =index
14+ time-sent=time
15+ contents=(list content)
16+ hash=(unit hash)
17+ =signatures
18+ ==
19+::
20++$ indexed-post [a=atom p=post]
21+::
22++$ validated-portion
23+ $: parent-hash=(unit hash)
24+ author=ship
25+ time-sent=time
26+ contents=(list content)
27+ ==
28+::
29++$ reference
30+ $% [%graph group=resource =uid]
31+ [%group group=resource]
32+ [%app =ship =desk =path]
33+ ==
34+::
35++$ content
36+ $% [%text text=cord]
37+ [%mention =ship]
38+ [%url url=cord]
39+ [%code expression=cord output=(list tank)]
40+ [%reference =reference]
41+ ==
42+::
43+++ post-one
44+ |%
45+ ::
46+ +$ indexed-post [a=atom p=post]
47+ ::
48+ +$ post
49+ $: author=ship
50+ =index
51+ time-sent=time
52+ contents=(list content)
53+ hash=(unit hash)
54+ =signatures
55+ ==
56+ ::
57+ +$ content
58+ $% [%text text=cord]
59+ [%mention =ship]
60+ [%url url=cord]
61+ [%code expression=cord output=(list tank)]
62+ [%reference =reference]
63+ ==
64+ ::
65+ +$ reference
66+ $% [%graph group=resource =uid]
67+ [%group group=resource]
68+ ==
69+ --
70+::
71+++ post-zero
72+ |%
73+ ::
74+ +$ content
75+ $% [%text text=cord]
76+ [%mention =ship]
77+ [%url url=cord]
78+ [%code expression=cord output=(list tank)]
79+ [%reference =uid]
80+ ==
81+ ::
82+ +$ post
83+ $: author=ship
84+ =index
85+ time-sent=time
86+ contents=(list content)
87+ hash=(unit hash)
88+ =signatures
89+ ==
90+ --
91+--
zod/seax/sur/pull-hook.hoonnew file+11
@@ -0,0 +1,11 @@
1+/- *resource
2+|%
3++$ action
4+ $% [%add =ship =resource]
5+ [%remove =resource]
6+ ==
7+::
8++$ update
9+ $% [%tracking tracking=(map resource ship)]
10+ ==
11+--
zod/seax/sur/resource.hoonnew file+10
@@ -0,0 +1,10 @@
1+^?
2+|%
3++$ resource [=entity name=term]
4++$ resources (set resource)
5+::
6++$ entity
7+ $@ ship
8+ $% !!
9+ ==
10+--
zod/seax/sur/spider.hoonnew file+27
@@ -0,0 +1,27 @@
1+/+ libstrand=strand
2+=, strand=strand:libstrand
3+|%
4++$ thread $-(vase shed:khan)
5++$ input [=tid =cage]
6++$ tid tid:strand
7++$ bowl bowl:strand
8++$ http-error
9+ $? %bad-request :: 400
10+ %forbidden :: 403
11+ %nonexistent :: 404
12+ %offline :: 504
13+ ==
14++$ start-args
15+ $: parent=(unit tid)
16+ use=(unit tid)
17+ =beak
18+ file=term
19+ =vase
20+ ==
21++$ inline-args
22+ $: parent=(unit tid)
23+ use=(unit tid)
24+ =beak
25+ =shed:khan
26+ ==
27+--