Merge branch 'develop' into i/6303/eyre-verbose

This commit is contained in:
tadad 2023-03-16 09:36:27 -06:00 committed by GitHub
commit 328a3d687d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
112 changed files with 2941 additions and 35747 deletions

View File

@ -1,3 +0,0 @@
module.exports = {
ignorePatterns: ["**/*"]
};

34
.github/workflows/develop.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Push to develop
on:
push:
branches:
- 'develop'
paths:
- '.github/workflows/feature.yml'
- '.github/workflows/develop.yml'
- '.github/workflows/release.yml'
- '.github/workflows/master.yml'
- '.github/workflows/vere.yml'
- 'pkg/arvo/**'
- 'pkg/docker-image/**'
- 'pkg/ent/**'
- 'pkg/ge-additions/**'
- 'pkg/libaes_siv/**'
- 'pkg/urbit/**'
- 'pkg/urcrypt/**'
- 'tests/**'
- 'bin/**'
- 'nix/**'
- 'default.nix'
jobs:
call-vere:
uses: ./.github/workflows/vere.yml
with:
pace: 'edge'
upload: >-
${{
(github.ref_name == 'next/vere' && github.ref_type == 'branch')
}}
secrets: inherit

View File

@ -1,25 +1,12 @@
name: build
name: Feature pull request
on:
push:
paths:
- '.github/workflows/build.yml'
- '.github/workflows/vere.yml'
- 'pkg/arvo/**'
- 'pkg/docker-image/**'
- 'pkg/ent/**'
- 'pkg/ge-additions/**'
- 'pkg/libaes_siv/**'
- 'pkg/urbit/**'
- 'pkg/urcrypt/**'
- 'tests/**'
- 'bin/**'
- 'nix/**'
- 'default.nix'
- 'vere-version'
pull_request:
paths:
- '.github/workflows/build.yml'
- '.github/workflows/feature.yml'
- '.github/workflows/develop.yml'
- '.github/workflows/release.yml'
- '.github/workflows/master.yml'
- '.github/workflows/vere.yml'
- 'pkg/arvo/**'
- 'pkg/docker-image/**'
@ -32,13 +19,12 @@ on:
- 'bin/**'
- 'nix/**'
- 'default.nix'
- 'vere-version'
jobs:
call-vere:
uses: ./.github/workflows/vere.yml
with:
pace: 'edge' # XX s/b once?
pace: 'edge'
upload: >-
${{
(github.ref_name == 'next/vere' && github.ref_type == 'branch')

34
.github/workflows/master.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Push to master
on:
push:
branches:
- 'master'
paths:
- '.github/workflows/feature.yml'
- '.github/workflows/develop.yml'
- '.github/workflows/release.yml'
- '.github/workflows/master.yml'
- '.github/workflows/vere.yml'
- 'pkg/arvo/**'
- 'pkg/docker-image/**'
- 'pkg/ent/**'
- 'pkg/ge-additions/**'
- 'pkg/libaes_siv/**'
- 'pkg/urbit/**'
- 'pkg/urcrypt/**'
- 'tests/**'
- 'bin/**'
- 'nix/**'
- 'default.nix'
jobs:
call-vere:
uses: ./.github/workflows/vere.yml
with:
pace: 'live'
upload: >-
${{
(github.ref_name == 'next/vere' && github.ref_type == 'branch')
}}
secrets: inherit

View File

@ -1,62 +0,0 @@
name: publish-npm-packages
on:
push:
branches:
- 'master'
paths:
- 'pkg/npm/**'
jobs:
publish-api:
runs-on: ubuntu-latest
name: "Publish '@urbit/api' if a new version is available"
steps:
- uses: actions/checkout@v2
with:
lfs: true
- uses: actions/setup-node@v2
with:
node-version: '14'
- run: 'npm install'
working-directory: 'pkg/npm/api'
- uses: JS-DevTools/npm-publish@v1
with:
check-version: true
package: './pkg/npm/api/package.json'
token: ${{ secrets.NPM_TOKEN }}
publish-http-api:
runs-on: ubuntu-latest
name: "Publish '@urbit/http-api' if a new version is available"
steps:
- uses: actions/checkout@v2
with:
lfs: true
- uses: actions/setup-node@v2
with:
node-version: '14'
- run: 'npm install'
working-directory: 'pkg/npm/http-api'
- uses: JS-DevTools/npm-publish@v1
with:
check-version: true
package: './pkg/npm/http-api/package.json'
token: ${{ secrets.NPM_TOKEN }}
publish-eslint-config:
runs-on: ubuntu-latest
name: "Publish '@urbit/eslint-config' if a new version is available"
steps:
- uses: actions/checkout@v2
with:
lfs: true
- uses: actions/setup-node@v2
with:
node-version: '14'
- run: 'npm install'
working-directory: 'pkg/npm/eslint-config'
- uses: JS-DevTools/npm-publish@v1
with:
check-version: true
package: './pkg/npm/eslint-config/package.json'
token: ${{ secrets.NPM_TOKEN }}

34
.github/workflows/release.yml vendored Normal file
View File

@ -0,0 +1,34 @@
name: Push to release branch
on:
push:
branches:
- 'release/*'
paths:
- '.github/workflows/feature.yml'
- '.github/workflows/develop.yml'
- '.github/workflows/release.yml'
- '.github/workflows/master.yml'
- '.github/workflows/vere.yml'
- 'pkg/arvo/**'
- 'pkg/docker-image/**'
- 'pkg/ent/**'
- 'pkg/ge-additions/**'
- 'pkg/libaes_siv/**'
- 'pkg/urbit/**'
- 'pkg/urcrypt/**'
- 'tests/**'
- 'bin/**'
- 'nix/**'
- 'default.nix'
jobs:
call-vere:
uses: ./.github/workflows/vere.yml
with:
pace: 'soon'
upload: >-
${{
(github.ref_name == 'next/vere' && github.ref_type == 'branch')
}}
secrets: inherit

View File

@ -39,11 +39,6 @@ on:
- soon
- live
env:
UPLOAD_BASE: bootstrap.urbit.org/vere
VERE_PACE: ${{ inputs.pace }}
VERSION_TYPE: ${{ (inputs.pace == 'soon' || inputs.pace == 'live') && 'real' || 'hash' }}
jobs:
urbit:
strategy:
@ -61,12 +56,12 @@ jobs:
# for the docker build. We don't want in on Mac, where it isn't but
# it breaks the nix install. The two `if` clauses should be mutually
# exclusive
- uses: cachix/install-nix-action@v16
- uses: cachix/install-nix-action@v20
with:
extra_nix_config: |
system-features = nixos-test benchmark big-parallel kvm
if: ${{ matrix.type == 'linux' }}
- uses: cachix/install-nix-action@v16
- uses: cachix/install-nix-action@v20
if: ${{ matrix.os != 'ubuntu-latest' }}
- uses: cachix/cachix-action@v10
@ -78,8 +73,10 @@ jobs:
name: run urbit-tests
run: |
cp -RL tests pkg/arvo/tests
vere="$(cat ./vere-version | sed -e 's/\([^ ]*\) \([^ ]*\)/\1\/\2\/vere-\2/g' | tr -d '\n')"
url="$(echo https://bootstrap.urbit.org/vere/${vere}-linux-x86_64)"
vere=$(curl https://bootstrap.urbit.org/vere/${{ inputs.pace }}/last)
echo $vere
url="$(echo https://bootstrap.urbit.org/vere/${{ inputs.pace }}/v${vere}/vere-v${vere}-linux-x86_64)"
echo $url
# put in .jam so it doesn't crash when it gets -A'd in
curl -Lo pkg/arvo/vere.jam "$url"
chmod +x pkg/arvo/vere.jam

1
.nvmrc
View File

@ -1 +0,0 @@
16.14.0

View File

@ -1,16 +0,0 @@
bin
doc
extras
nix
pkg/arvo
pkg/base-dev
pkg/docker-image
pkg/ent
pkg/garden
pkg/garden-dev
pkg/ge-additions
pkg/herb
pkg/hs
pkg/libaes_siv
pkg/urbit
sh

View File

@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4066cd90ac7d33b3d96b1b4d611d846d941de6e538c8355047c7cafcadce0851
size 6017832
oid sha256:9d0ff563027d47436d12f00b7500352ec844a1db7d336b0e5b9cfd5c4c49c66c
size 6017943

View File

@ -1,9 +0,0 @@
{
"packages": [
"pkg/npm/*",
"pkg/btc-wallet",
"pkg/interface",
"pkg/grid"
],
"version": "independent"
}

View File

@ -17,7 +17,7 @@ in stdenvNoCC.mkDerivation {
buildPhase = ''
set -xeuo pipefail
${arvo}/vere.jam ${lib.concatStringsSep " " args} ./pier
${arvo}/vere.jam ${lib.concatStringsSep " " args} -c ./pier
cleanup () {
if [ -f ./pier/.vere.lock ]; then

15716
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -1,21 +0,0 @@
{
"name": "root",
"private": true,
"engines": {
"node": "16.14.0"
},
"devDependencies": {
"eslint": "^7.29.0",
"husky": "^6.0.0",
"lerna": "^4.0.0",
"lint-staged": "^11.1.2",
"prettier": "^2.3.2"
},
"scripts": {
"watch-libs": "lerna run watch --no-private --parallel",
"build-libs": "lerna run build --no-private",
"test": "lerna run test",
"bootstrap": "lerna bootstrap",
"build:prod": "lerna run build:prod"
}
}

View File

@ -801,8 +801,8 @@
=/ heads=(list [tako desk])
%+ turn ~(tap in desks)
|= =desk
=+ .^(=dome %cv /(scot %p our.bowl)/[desk]/(scot %da now.bowl))
=/ =tako (~(got by hit.dome) let.dome)
=+ .^(=domo %cv /(scot %p our.bowl)/[desk]/(scot %da now.bowl))
=/ =tako (~(got by hit.domo) let.domo)
[tako desk]
=/ yakis=(set yaki)
%- silt

View File

@ -2,8 +2,8 @@
/+ drum=hood-drum, helm=hood-helm, kiln=hood-kiln
|%
+$ state
$~ [%25 *state:drum *state:helm *state:kiln]
$>(%25 any-state)
$~ [%26 *state:drum *state:helm *state:kiln]
$>(%26 any-state)
::
+$ any-state
$% [ver=?(%1 %2 %3 %4 %5 %6) lac=(map @tas fin-any-state)]
@ -26,6 +26,7 @@
[%23 drum=state-4:drum helm=state-2:helm kiln=state-9:kiln]
[%24 drum=state-4:drum helm=state-2:helm kiln=state-10:kiln]
[%25 drum=state-5:drum helm=state-2:helm kiln=state-10:kiln]
[%26 drum=state-6:drum helm=state-2:helm kiln=state-10:kiln]
==
+$ any-state-tuple
$: drum=any-state:drum
@ -124,6 +125,7 @@
|= [=wire syn=sign-arvo]
^- step:agent:gall
?+ wire ~|([%hood-bad-wire wire] !!)
[%drum *] =^(c drum.state (take-arvo:drum-core t.wire syn) [c this])
[%helm *] =^(c helm.state (take-arvo:helm-core t.wire syn) [c this])
[%kiln *] =^(c kiln.state (take-arvo:kiln-core t.wire syn) [c this])
==

View File

@ -0,0 +1,6 @@
:: Helm: Adjust Ames congestion control constants
::
:- %say
|= [^ [msg=@ud mem=@ud ~] ~]
:- %helm-ames-cong
msg^mem

View File

@ -1,4 +1,4 @@
:: Helm: Adjust vane error verbosity knob
:: Drum: Adjust vane error verbosity knob
::
/? 310
::
@ -6,5 +6,5 @@
::
:- %say
|= [^ [error-tag=@tas level=?(%hush %soft %loud) ~] ~]
:- %helm-knob
:- %drum-knob
[error-tag level]

View File

@ -16,6 +16,6 @@
?> ((sane %tas) +<.arg)
[-.arg +<.arg]
=+ .^(=cone:clay %cx /(scot %p p.bec)//(scot %da now)/domes)
=/ =foam:clay (~(gut by cone) [p.bec des] *foam:clay)
=+ ((slog ?:(=(%live liv.foam) ~ ['kiln: desk not live' ~])) ~)
[%kiln-rein des (~(put by ren.foam) dap &)]
=/ =dome:clay (~(gut by cone) [p.bec des] *dome:clay)
=+ ((slog ?:(=(%live liv.dome) ~ ['kiln: desk not live' ~])) ~)
[%kiln-rein des (~(put by ren.dome) dap &)]

View File

@ -13,7 +13,7 @@
=/ =lobe u.fil.arch
=+ .^(=rang %cx /(scot %p p.bec)//(scot %da now)/rang)
=+ .^(=cone %cx /(scot %p p.bec)//(scot %da now)/domes)
=/ domes=(list [[=ship =desk] foam]) ~(tap by cone)
=/ domes=(list [[=ship =desk] dome]) ~(tap by cone)
=/ norms
|^
|- ^- (set [ship desk tako norm path])
@ -30,7 +30,7 @@
(~(uni in paths) $(aeon +(aeon)))
::
++ draw-tako
|= [=ship =desk foam =tako]
|= [=ship =desk dome =tako]
^- (set [^ship ^desk ^tako norm path])
~+
=/ =yaki (~(got by hut.rang) tako)

View File

@ -8,7 +8,7 @@
%- flop ^- tang
%- zing
%+ turn ~(tap by cone)
|= [[=ship =desk] foam]
|= [[=ship =desk] dome]
:- leaf+"{<ship>}/{<desk>}:"
%+ turn ~(tap of nor)
|= [=path keep=?]

View File

@ -1,21 +1,28 @@
/- *sole
/+ sole
|%
+$ state state-5
+$ state state-6
+$ any-state
$~ *state
$% state-5
$% state-6
state-5
state-4
state-3
state-2
==
+$ state-6 [%6 pith-6]
+$ state-5 [%5 pith-5]
+$ state-4 [%4 pith-4]
+$ state-3 [%3 pith-3]
+$ state-2 [%2 pith-2]
::
+$ pith-5
+$ pith-6
$: bin=(map @ source) :: terminals
nob=(map @tas ?(%hush %soft %loud))
==
::
+$ pith-5
$: bin=(map @ source)
==
::
+$ pith-4
@ -130,7 +137,9 @@
++ klr klr:format
+$ state ^state :: proxy
+$ any-state ^any-state :: proxy
++ on-init (poke-link %$ our.hid %dojo)
++ on-init
=+ out=(poke-link %$ our.hid %dojo)
out(- [hear-logs -.out])
::
++ prep
|= s=@tas
@ -191,11 +200,16 @@
=^ txt +> ?@(arg [arg +>] [+.arg (prep -.arg)])
se-abet:(se-blit-sys [%sav pax txt]) ::
::
++ poke-knob
|= [tag=@tas lev=?(%hush %soft %loud)]
se-abet(nob (~(put by nob) tag lev))
::
++ poke
|= [=mark =vase]
?> =(our src):hid
?+ mark ~|([%poke-drum-bad-mark mark] !!)
%dill-poke =;(f (f !<(_+<.f vase)) poke-dill)
%drum-knob =;(f (f !<(_+<.f vase)) poke-knob)
%drum-exit =;(f (f !<(_+<.f vase)) poke-exit)
%drum-link =;(f (f !<(_+<.f vase)) poke-link)
%drum-put =;(f (f !<(_+<.f vase)) poke-put)
@ -229,7 +243,9 @@
[%mod -.b p.b]
--
::
?> ?=(%5 -.old)
=? moz ?=(%5 -.old) [hear-logs moz]
=? old ?=(%5 -.old) [%6 bin.old ~]
?> ?=(%6 -.old)
=. sat old
=. dev (~(gut by bin) ses *source)
this
@ -276,6 +292,15 @@
=^ gyl this (open way)
~& [%drum-quit src.hid gyl]
(se-drop %| gyl)
::
++ hear-logs
`card:agent:gall`[%pass /drum/dill/logs %arvo %d %logs [~ ~]]
::
++ take-arvo
|= [way=wire syn=sign-arvo]
?> =(/dill/logs way)
?> ?=(%logs +<.syn)
se-abet:(se-told:(prep %$) told.syn)
:: :: ::
:::: :: ::
:: :: ::
@ -363,6 +388,19 @@
~| [inx=inx wag=wag fug=fug eel=eel]
`(snag inx `(list gill:gall)`wag)
::
++ se-told :: render system output
|= =told:dill
^+ +>
?- -.told
%crud =/ lev (~(gut by nob) p.told %loud)
=? +>.$ !=(%hush lev)
(se-text "crud: %{(trip p.told)} event failed")
?. =(%loud lev) +>.$
(se-dump q.told)
%talk (se-dump (flop p.told)) ::NOTE +se-dump flops internally
%text (se-text p.told)
==
::
++ se-belt :: handle input
|= bet=dill-belt:dill
^+ +>
@ -438,7 +476,7 @@
(se-blit %mor [%hop 0] [%wyp ~] lin [%nel ~] ~)
::
++ se-dump :: print tanks
|= tac=(list tank)
|= tac=tang
^+ +>
=/ wol=wall
(zing (turn (flop tac) |=(a=tank (~(win re a) [0 edg]))))

View File

@ -249,9 +249,9 @@
|= dry=? =< abet
(emit %pass /helm %arvo %a %kroc dry)
::
++ poke-knob
|= [error-tag=@tas level=?(%hush %soft %loud)] =< abet
(emit %pass /helm %arvo %d %knob error-tag level)
++ poke-ames-cong
|= cong=[msg=@ud mem=@ud] =< abet
(emit %pass /helm %arvo %a %cong cong)
::
++ poke-serve
|= [=binding:eyre =generator:eyre] =< abet
@ -285,6 +285,7 @@
%helm-ames-verb =;(f (f !<(_+<.f vase)) poke-ames-verb)
%helm-ames-wake =;(f (f !<(_+<.f vase)) poke-ames-wake)
%helm-ames-kroc =;(f (f !<(_+<.f vase)) poke-ames-kroc)
%helm-ames-cong =;(f (f !<(_+<.f vase)) poke-ames-cong)
%helm-atom =;(f (f !<(_+<.f vase)) poke-atom)
%helm-automass =;(f (f !<(_+<.f vase)) poke-automass)
%helm-cancel-automass =;(f (f !<(_+<.f vase)) poke-cancel-automass)
@ -295,7 +296,6 @@
%helm-gall-sift =;(f (f !<(_+<.f vase)) poke-gall-sift)
%helm-gall-verb =;(f (f !<(_+<.f vase)) poke-gall-verb)
%helm-hi =;(f (f !<(_+<.f vase)) poke-hi)
%helm-knob =;(f (f !<(_+<.f vase)) poke-knob)
%helm-pans =;(f (f !<(_+<.f vase)) poke-pans)
%helm-mass =;(f (f !<(_+<.f vase)) poke-mass)
%helm-meld =;(f (f !<(_+<.f vase)) poke-meld)

View File

@ -807,10 +807,16 @@
::
++ poke-uninstall
|= loc=desk
?~ got=(~(get by sources) loc)
=+ .^(=rock:tire %cx /(scot %p our)//(scot %da now)/tire)
?~ got=(~(get by rock) loc)
abet:(spam leaf+"desk does not exist: {<loc>}" ~)
?: =(+<:got %dead)
abet:(spam leaf+"desk not installed: {<loc>}" ~)
~> %slog.(fmt "uninstalling {<loc>}")
=. ..on-init (emit %pass /kiln/uninstall %arvo %c %zest loc %dead)
(poke-unsync loc u.got)
?~ sync=(~(get by sources) loc)
abet
(poke-unsync loc u.sync)
::
++ poke-unmount
|= mon=kiln-unmount

View File

@ -0,0 +1,10 @@
/- eval=ted-eval
|_ put=inpt:eval
++ grab |%
++ noun inpt:eval
--
++ grow |%
++ noun put
--
++ grad %noun
--

View File

@ -0,0 +1,5 @@
^?
|%
+$ deps (list path)
+$ inpt $@(cord (pair cord deps))
--

View File

@ -1 +1 @@
[%zuse 415]
[%zuse 414]

View File

@ -50,12 +50,7 @@
|: [a=`@`1 b=`@`1]
:: quotient
^- @
~_ leaf+"divide-by-zero"
?< =(0 b)
=+ c=0
|-
?: (lth a b) c
$(a (sub a b), c +(c))
-:(dvr a b)
::
++ dvr
~/ %dvr
@ -63,11 +58,16 @@
::
:: a: dividend
:: b: divisor
|= [a=@ b=@]
|: [a=`@`1 b=`@`1]
:: p: quotient
:: q: remainder
^- [p=@ q=@]
[(div a b) (mod a b)]
~_ leaf+"divide-by-zero"
?< =(0 b)
=+ c=0
|-
?: (lth a b) [c a]
$(a (sub a b), c +(c))
::
++ gte
~/ %gte
@ -150,8 +150,7 @@
|: [a=`@`1 b=`@`1]
:: the remainder
^- @
?< =(0 b)
(sub a (mul b (div a b)))
+:(dvr a b)
::
++ mul
~/ %mul
@ -4218,12 +4217,19 @@
$(inx +(inx))
==
|- ^- ?
?: =(0 b) &
=+ cur=(end 3 b)
?: =(inx len) &
=+ cur=(cut 3 [inx 1] b)
?: &((lth cur 32) !=(10 cur)) |
=+ len=(teff cur)
?& |(=(1 len) =+(i=1 |-(|(=(i len) &((gte (cut 3 [i 1] b) 128) $(i +(i)))))))
$(b (rsh [3 len] b))
=+ tef=(teff cur)
?& ?| =(1 tef)
=+ i=1
|- ^- ?
?|
=(i tef)
?& (gte (cut 3 [(add i inx) 1] b) 128)
$(i +(i))
== == ==
$(inx +(inx))
==
::
++ ruth :: biblical sanity
@ -5313,7 +5319,7 @@
--
++ ag
|%
++ ape |*(fel=rule ;~(pose (cold 0 (just '0')) fel))
++ ape |*(fel=rule ;~(pose (cold `@`0 (just '0')) fel))
++ bay (ape (bass 16 ;~(plug qeb:ab (star ;~(pfix dog qib:ab)))))
++ bip =+ tod=(ape qex:ab)
(bass 0x1.0000 ;~(plug tod (stun [7 7] ;~(pfix dog tod))))

View File

@ -3,7 +3,7 @@
!:
=> ..part
|%
++ lull %326
++ lull %325
:: :: ::
:::: :: :: (1) models
:: :: ::
@ -834,17 +834,34 @@
[%worn =ship =desk =tako =norm] :: set commit norm
[%seek =ship =desk =cash] :: fetch source blobs
== ::
+$ cone (map [ship desk] foam) :: domes
+$ foam ::
$: dome ::
tom=(map tako norm) ::
nor=norm ::
liv=zest ::
ren=(map dude:gall ?) ::
+$ cone (map [ship desk] dome) :: domes
::
:: Desk state.
::
:: Includes a checked-out ankh with current content, most recent version, map
:: of all version numbers to commit hashes (commits are in hut.rang), and map
:: of labels to version numbers.
::
:: `mim` is a cache of the content in the directories that are mounted
:: to unix. Often, we convert to/from mime without anything really
:: having changed; this lets us short-circuit that in some cases.
:: Whenever you give an `%ergo`, you must update this.
::
+$ dome
$: let=aeon :: top id
hit=(map aeon tako) :: versions by id
lab=(map @tas aeon) :: labels
tom=(map tako norm) :: tomb policies
nor=norm :: default policy
mim=(map path mime) :: mime cache
fod=flue :: ford cache
wic=(map weft yoki) :: commit-in-waiting
liv=zest :: running agents
ren=rein :: force agents on/off
== ::
+$ crew (set ship) :: permissions group
+$ dict [src=path rul=real] :: effective permission
+$ dome :: project state
+$ domo :: project state
$: let=@ud :: top id
hit=(map @ud tako) :: changes by id
lab=(map @tas @ud) :: labels
@ -1107,6 +1124,30 @@
::
+$ flow (map leak [refs=@ud =soak])
::
:: Per-desk ford cache
::
:: Spill is the set of "roots" we have into the global ford cache.
:: We add a root for everything referenced directly or indirectly on
:: a desk, then invalidate them on commit only if their dependencies
:: change.
::
:: Sprig is a fast-lookup index over the global ford cache. The only
:: goal is to make cache hits fast.
::
+$ flue [spill=(set leak) sprig=(map mist [=leak =soak])]
::
:: Ford build without content.
::
+$ mist
$% [%file =path]
[%nave =mark]
[%dais =mark]
[%cast =mars]
[%tube =mars]
[%vale =path]
[%arch =path]
==
::
:: $pile: preprocessed hoon source file
::
:: /- sur-file :: surface imports from /sur
@ -1215,26 +1256,26 @@
[%meld ~] :: unify memory
[%pack ~] :: compact memory
[%trim p=@ud] :: trim kernel state
[%logs =told] :: system output
== ::
+$ task :: in request ->$
$~ [%vega ~] ::
$% [%boot lit=? p=*] :: weird %dill boot
[%crop p=@ud] :: trim kernel state
[%crud p=@tas q=(list tank)] :: print error
[%flog p=flog] :: wrapped error
[%heft ~] :: memory report
$>(%init vane-task) :: after gall ready
[%logs p=(unit ~)] :: watch system output
[%meld ~] :: unify memory
[%pack ~] :: compact memory
[%seat =desk] :: install desk
[%shot ses=@tas task=session-task] :: task for session
[%talk p=(list tank)] :: print tanks
[%text p=tape] :: print tape
$>(%trim vane-task) :: trim state
$>(%vega vane-task) :: report upgrade
[%verb ~] :: verbose mode
[%knob tag=term level=?(%hush %soft %loud)] :: error verbosity
[%knob tag=term level=?(%hush %soft %loud)] :: deprecated removeme
session-task :: for default session
told :: system output
== ::
:: ::
+$ session-task :: session request
@ -1246,6 +1287,12 @@
[%shut ~] :: close session
[%view ~] :: watch session blits
== ::
:: ::
+$ told :: system output
$% [%crud p=@tas q=tang] :: error
[%talk p=(list tank)] :: tanks (in order)
[%text p=tape] :: tape
== ::
::
:::: :: (1d2)
::
@ -1279,7 +1326,7 @@
== ::
+$ dill-belt :: arvo input
$% belt :: client input
[%cru p=@tas q=(list tank)] :: echo error
[%cru p=@tas q=(list tank)] :: errmsg (deprecated)
[%hey ~] :: refresh
[%rez p=@ud q=@ud] :: resize, cols, rows
[%yow p=gill:gall] :: connect to app
@ -1290,11 +1337,11 @@
== ::
+$ flog :: sent to %dill
$% [%crop p=@ud] :: trim kernel state
[%crud p=@tas q=(list tank)] ::
$>(%crud told) ::
[%heft ~] ::
[%meld ~] :: unify memory
[%pack ~] :: compact memory
[%text p=tape] ::
$>(%text told) ::
[%verb ~] :: verbose mode
== ::
:: ::
@ -1561,9 +1608,8 @@
::
[%scry ~]
:: respond with the @p the requester is authenticated as
:: TODO: put this back in when we burn the next kelvin
::
:: [%name ~]
[%name ~]
:: respond with the default file not found page
::
[%four-oh-four ~]

File diff suppressed because it is too large Load Diff

View File

@ -138,7 +138,7 @@
:: `sto` stores the data needed to merge, and `bas` is the base
:: beak for the merge.
::
+$ melt [bas=beak con=(list [beak germ]) sto=(map beak (unit dome:clay))]
+$ melt [bas=beak con=(list [beak germ]) sto=(map beak (unit domo))]
::
:: Domestic desk state.
::
@ -153,30 +153,6 @@
fiz=melt :: state for mega merges
==
::
:: Desk state.
::
:: Includes a checked-out ankh with current content, most recent version, map
:: of all version numbers to commit hashes (commits are in hut.rang), and map
:: of labels to version numbers.
::
:: `mim` is a cache of the content in the directories that are mounted
:: to unix. Often, we convert to/from mime without anything really
:: having changed; this lets us short-circuit that in some cases.
:: Whenever you give an `%ergo`, you must update this.
::
+$ dome
$: let=aeon :: top id
hit=(map aeon tako) :: versions by id
lab=(map @tas aeon) :: labels
tom=(map tako norm) :: tomb policies
nor=norm :: default policy
mim=(map path mime) :: mime cache
fod=flue :: ford cache
wic=(map weft yoki) :: commit-in-waiting
liv=zest :: running agents
ren=rein :: force agents on/off
== ::
::
:: Over-the-wire backfill request/response
::
+$ fill
@ -191,30 +167,6 @@
[%1 peg=(unit page)]
==
::
:: Per-desk ford cache
::
:: Spill is the set of "roots" we have into the global ford cache.
:: We add a root for everything referenced directly or indirectly on
:: a desk, then invalidate them on commit only if their dependencies
:: change.
::
:: Sprig is a fast-lookup index over the global ford cache. The only
:: goal is to make cache hits fast.
::
+$ flue [spill=(set leak) sprig=(map mist [=leak =soak])]
::
:: Ford build without content.
::
+$ mist
$% [%file =path]
[%nave =mark]
[%dais =mark]
[%cast =mars]
[%tube =mars]
[%vale =path]
[%arch =path]
==
::
:: New desk data.
::
:: Sent to other ships to update them about a particular desk.
@ -2289,9 +2241,9 @@
|= [bas=beak con=(list [beak germ])]
^- melt
:+ bas con
%- ~(gas by *(map beak (unit dome:clay)))
:- [bas *(unit dome:clay)]
(turn con |=(a=[beak germ] [-.a *(unit dome:clay)]))
%- ~(gas by *(map beak (unit domo)))
:- [bas *(unit domo)]
(turn con |=(a=[beak germ] [-.a *(unit domo)]))
::
++ start-fuse
|= [bas=beak con=(list [beak germ])]
@ -2314,7 +2266,7 @@
=/ discarded=tang
%+ turn
~(tap in sto.fiz)
|= [k=beak v=(unit dome:clay)]
|= [k=beak v=(unit domo)]
^- tank
=/ received=tape ?~(v "missing" "received")
leaf+"{<(en-beam k ~)>} {received}"
@ -2341,17 +2293,17 @@
((slog [leaf+"clay: got strange fuse response {<msg>}"]~) ..take-fuse)
=. fiz
:+ bas.fiz con.fiz
(~(put by sto.fiz) bec `!<(dome:clay q.r.u.riot))
(~(put by sto.fiz) bec `!<(domo q.r.u.riot))
=/ all-done=flag
%- ~(all by sto.fiz)
|= res=(unit dome:clay)
|= res=(unit domo)
^- flag
!=(res ~)
?. all-done
..take-fuse
=| rag=rang
=/ clean-state ..take-fuse
=/ initial-dome=dome:clay (need (~(got by sto.fiz) bas.fiz))
=/ initial-dome=domo (need (~(got by sto.fiz) bas.fiz))
=/ next-yaki=yaki
(~(got by hut.ran) (~(got by hit.initial-dome) let.initial-dome))
=/ parents=(list tako) ~[(~(got by hit.initial-dome) let.initial-dome)]
@ -2362,7 +2314,7 @@
=. ..take-fuse (done-fuse clean-state %& ~)
(park | & [%| next-yaki(p (flop parents))] rag)
=/ [bec=beak g=germ] i.merges
=/ ali-dom=dome:clay (need (~(got by sto.fiz) bec))
=/ ali-dom=domo (need (~(got by sto.fiz) bec))
=/ result (merge-helper p.bec q.bec g ali-dom `next-yaki)
?- -.result
%|
@ -2428,10 +2380,10 @@
^+ ..merge
?~ riot
(done %| %ali-unavailable ~[>[ali-ship ali-desk germ]<])
=/ ali-dome=dome:clay
=/ ali-dome=domo
?: &(?=(@ -.q.q.r.u.riot) !=(~ -.q.q.r.u.riot))
!<(dome:clay q.r.u.riot)
+:!<([* dome:clay] q.r.u.riot)
!<(domo q.r.u.riot)
+:!<([* domo] q.r.u.riot)
=/ result=(each (unit merge-result) (pair term tang))
(merge-helper ali-ship ali-desk germ ali-dome ~)
?- -.result
@ -2447,7 +2399,7 @@
+$ merge-result [conflicts=(set path) new=yoki lat=(map lobe page)]
::
++ merge-helper
|= [=ali=ship =ali=desk =germ ali-dome=dome:clay next-yaki=(unit yaki)]
|= [=ali=ship =ali=desk =germ ali-dome=domo next-yaki=(unit yaki)]
^- (each (unit merge-result) [term tang])
|^
^- (each (unit merge-result) [term tang])
@ -4324,17 +4276,17 @@
::
++ read-v
|= [yon=aeon pax=path]
^- (unit (unit [%dome (hypo dome:clay)]))
^- (unit (unit [%dome (hypo domo)]))
?: (lth yon let.dom)
:* ~ ~ %dome -:!>(*dome:clay)
^- dome:clay
:* ~ ~ %dome -:!>(*domo)
^- domo
:* let=yon
hit=(molt (skim ~(tap by hit.dom) |=([p=@ud *] (lte p yon))))
lab=(molt (skim ~(tap by lab.dom) |=([* p=@ud] (lte p yon))))
== ==
?: (gth yon let.dom)
~
``[%dome -:!>(*dome:clay) [let hit lab]:dom]
``[%dome -:!>(*domo) [let hit lab]:dom]
::
:: Gets all cases refering to the same revision as the given case.
::
@ -5654,19 +5606,19 @@
%- ~(gas by *cone)
%+ turn ~(tap by dos.rom.ruf)
|= [=desk =dojo]
[[our desk] [[let hit lab] tom nor liv ren]:dom.dojo]
[[our desk] dom.dojo]
=. domes
%- ~(uni by domes)
%- ~(gas by *cone)
^- (list [[ship desk] foam])
^- (list [[ship desk] dome])
%- zing
^- (list (list [[ship desk] foam]))
^- (list (list [[ship desk] dome]))
%+ turn ~(tap by hoy.ruf)
|= [=ship =rung]
^- (list [[^ship desk] foam])
^- (list [[^ship desk] dome])
%+ turn ~(tap by rus.rung)
|= [=desk =rede]
[[ship desk] [[let hit lab] tom nor liv ren]:dom.rede]
[[ship desk] dom.rede]
``[%domes !>(`cone`domes)]
::
++ cult

View File

@ -8,14 +8,12 @@
-- ::
=> |% :: console protocol
+$ axle ::
$: %6 ::
$: %7 ::
hey=(unit duct) :: default duct
dug=(map @tas axon) :: conversations
eye=(jug @tas duct) :: outside listeners
eye=(jug @tas duct) :: outside observers
ear=(set duct) :: syslog listeners
lit=? :: boot in lite mode
$= veb :: vane verbosities
$~ (~(put by *(map @tas log-level)) %hole %soft) :: quiet packet crashes
(map @tas log-level) ::
egg=_| :: see +take, removeme
== ::
+$ axon :: dill session
@ -97,10 +95,6 @@
?+ -.kyz ~& [%strange-kiss -.kyz] +>
%hail (send %hey ~)
%belt (send `dill-belt`p.kyz)
%talk (talk p.kyz)
%text (fore (tuba p.kyz) ~)
%crud :: (send `dill-belt`[%cru p.kyz q.kyz])
(crud p.kyz q.kyz)
%blew (send(wid p.p.kyz) %rez p.p.kyz q.p.kyz)
%heft (pass /whey %$ whey/~)
%meld (dump kyz)
@ -115,25 +109,11 @@
==
::
++ crud
|= [err=@tas tac=(list tank)]
:: unknown errors default to %loud
::
=/ lev=log-level (~(gut by veb.all) err %loud)
:: apply log level for this error tag
::
?- lev
%hush +>.$
%soft (fore (tuba "crud: %{(trip err)} event failed") ~)
%loud (talk leaf+"crud: %{(trip err)} event failed" (flop tac))
==
::
++ talk
|= tac=(list tank)
%- fore
%- zing
%+ turn tac
|= a=tank
(turn (~(win re a) [0 wid]) tuba)
|= [err=@tas tac=tang]
=- +>.$(moz (weld - moz))
%+ turn
~(tap in ear.all)
(late %give %logs %crud err tac)
::
++ dump :: pass down to hey
|= git=gift
@ -155,30 +135,6 @@
|= [=wire =note]
+>(moz :_(moz [hen %pass wire note]))
::
++ fore :: send dill output
::NOTE there are still implicit assumptions
:: about the underlying console app's
:: semantics here. specifically, trailing
:: newlines are important to not getting
:: overwritten by the drum prompt, and a
:: bottom-of-screen cursor position gives
:: nicest results. a more agnostic solution
:: will need to replace this arm, someday.
:: perhaps +send this to .ram instead?
::
|= liz=(list (list @c))
~? !=(%$ ses) [%d %foreing-in-session ses]
^+ +>
=. +>
=| biz=(list blit)
|- ^+ +>.^$
?~ liz (done %blit [%hop 0] [%wyp ~] biz)
$(liz t.liz, biz (welp biz [%put i.liz] [%nel ~] ~))
:: since dill is acting on its own accord,
:: we %hey the term app so it may clean up.
::
(send %hey ~)
::
++ from :: receive blit
|= bit=dill-blit
^+ +>
@ -349,10 +305,13 @@
::
?: ?=(?(%trim %vega) -.task)
[~ ..^$]
:: %knob sets a verbosity level for an error tag
:: %knob used to set a verbosity level for an error tag,
:: but dill no longer prints errors itself, so implementing %knob
:: has become a recommendation to error printers (like drum).
:: remove this when %knob gets removed from lull, next™ kelvin release.
::
?: ?=(%knob -.task)
=. veb.all (~(put by veb.all) tag.task level.task)
~& [%dill %knob-deprecated]
[~ ..^$]
:: %open opens a new dill session
::
@ -400,6 +359,18 @@
?: ?=(%flee -.task)
:- ~
..^$(eye.all (~(del ju eye.all) ses hen))
:: %logs opens or closes a subscription to system output
::
?: ?=(%logs -.task)
=. ear.all
?~ p.task (~(del in ear.all) hen)
(~(put in ear.all) hen)
[~ ..^$]
:: if we were $told something, give %logs to all interested parties
::
?: ?=(?(%crud %talk %text) -.task)
:_ ..^$
(turn ~(tap in ear.all) (late %give %logs task))
::
=/ nus
(ax hen ses)
@ -408,8 +379,7 @@
:: could be before %boot (or %boot failed)
::
~& [%dill-call-no-session ses hen -.task]
=/ tan ?:(?=(%crud -.task) q.task ~)
[((slog (flop tan)) ~) ..^$]
[~ ..^$]
::
=^ moz all abet:(call:u.nus task)
[moz ..^$]
@ -417,12 +387,28 @@
++ load :: import old state
=< |= old=any-axle
?- -.old
%6 ..^$(all old)
%7 ..^$(all old)
%6 $(old (axle-6-to-7 old))
%5 $(old (axle-5-to-6 old))
%4 $(old (axle-4-to-5 old))
==
|%
+$ any-axle $%(axle axle-5 axle-4)
+$ any-axle $%(axle axle-6 axle-5 axle-4)
::
+$ axle-6
$: %6
hey=(unit duct)
dug=(map @tas axon)
eye=(jug @tas duct)
lit=?
veb=(map @tas log-level)
egg=_|
==
::
++ axle-6-to-7
|= a=axle-6
^- axle
[%7 hey dug eye ~ lit egg]:a
::
+$ axle-5
$: %5
@ -435,7 +421,7 @@
::
++ axle-5-to-6
|= a=axle-5
^- axle
^- axle-6
:: [%6 hey `(map @tas axon)`dug eye lit veb |]
a(- %6, veb [veb.a &])
::

View File

@ -71,32 +71,6 @@
$: %~2023.2.17
=server-state
==
::
:: +outstanding-connection-new: intermediate type to enable
:: /~/name endpoint without
:: breaking type change in lull
::
+$ outstanding-connection-new
$: :: action: the action that had matched
::
action=action-new
:: inbound-request: the original request which caused this connection
::
=inbound-request
:: response-header: set when we get our first %start
::
response-header=(unit response-header:http)
:: bytes-sent: the total bytes sent in response
::
bytes-sent=@ud
==
:: +action-new: intermediate type to enable /~/name endpoint
:: without breaking type change in lull
::
+$ action-new
$% action
[%name ~]
==
:: +server-state: state relating to open inbound HTTP connections
::
+$ server-state
@ -109,13 +83,13 @@
:: TODO: It would be nice if we had a path trie. We could decompose
:: the :binding into a (map (unit @t) (trie knot =action)).
::
bindings=(list [=binding =duct action=action-new])
bindings=(list [=binding =duct =action])
:: cors-registry: state used and managed by the +cors core
::
=cors-registry
:: connections: open http connections not fully complete
::
connections=(map duct outstanding-connection-new)
connections=(map duct outstanding-connection)
:: authentication-state: state managed by the +authentication core
::
=authentication-state
@ -605,7 +579,7 @@
::
=/ act [%app app=%lens]
::
=/ connection=outstanding-connection-new
=/ connection=outstanding-connection
[act [& secure address request] ~ 0]
::
=. connections.state
@ -630,13 +604,13 @@
(fall (forwarded-for u.forwards) address)
::
=/ host (get-header:http 'host' headers)
=/ [action=action-new suburl=@t]
=/ [=action suburl=@t]
(get-action-for-binding host url.request)
::
=/ authenticated (request-is-logged-in:authentication request)
:: record that we started an asynchronous response
::
=/ connection=outstanding-connection-new
=/ connection=outstanding-connection
[action [authenticated secure address request] ~ 0]
=. connections.state
:: XX pretty sure this is superfluous - done in +handle-response
@ -1969,7 +1943,7 @@
(session-cookie-string u.session-id &)
headers.response-header.http-event
::
=/ connection=outstanding-connection-new
=/ connection=outstanding-connection
(~(got by connections.state) duct)
:: if the request was a simple cors request from an approved origin
:: append the necessary cors headers to the response
@ -2007,7 +1981,7 @@
=. connections.state
%- (trace 2 |.("{<duct>} continuing "))
%+ ~(jab by connections.state) duct
|= connection=outstanding-connection-new
|= connection=outstanding-connection
=+ size=?~(data.http-event 0 p.u.data.http-event)
connection(bytes-sent (add bytes-sent.connection size))
::
@ -2063,7 +2037,7 @@
:: Adds =binding =action if there is no conflicting bindings.
::
++ add-binding
|= [=binding action=action-new]
|= [=binding =action]
^- [(list move) server-state]
=^ success bindings.state
:: prevent binding in reserved namespaces
@ -2084,7 +2058,7 @@
%_ state
bindings
%+ skip bindings.state
|= [item-binding=^binding item-duct=^duct action=action-new]
|= [item-binding=^binding item-duct=^duct =action]
^- ?
&(=(item-binding binding) =(item-duct duct))
==
@ -2092,7 +2066,7 @@
::
++ get-action-for-binding
|= [raw-host=(unit @t) url=@t]
^- [action=action-new suburl=@t]
^- [=action suburl=@t]
:: process :raw-host
::
:: If we are missing a 'Host:' header, if that header is a raw IP
@ -2210,8 +2184,8 @@
:: +insert-binding: add a new binding, replacing any existing at its path
::
++ insert-binding
|= $: new=[=binding =duct action=action-new]
bindings=(list [=binding =duct action=action-new])
|= $: new=[=binding =duct =action]
bindings=(list [=binding =duct =action])
==
^+ bindings
?~ bindings [new]~
@ -2274,7 +2248,7 @@
::
=. bindings.server-state.ax
=- (roll - insert-binding)
^- (list [binding ^duct action-new])
^- (list [binding ^duct action])
:~ [[~ /~/login] duct [%authentication ~]]
[[~ /~/logout] duct [%logout ~]]
[[~ /~/channel] duct [%channel ~]]
@ -2657,31 +2631,6 @@
--
::
++ http-server-gate ..$
:: +bindings-old: filter /~/name endpoint from bindings
::
++ bindings-old
|= new=(list [b=binding d=duct a=action-new])
=| old=(list [binding duct action])
|- ^+ old
?~ new old
=/ l
?: ?=([%name ~] a.i.new)
old
(snoc old [b.i.new d.i.new a.i.new])
$(new t.new, old l)
:: +connections-old: filter /~/name endpoint from connections
::
++ connections-old
|= new=(map duct outstanding-connection-new)
=| old=(map duct outstanding-connection)
=/ l=(list [d=duct o=outstanding-connection-new]) ~(tap by new)
|- ^+ old
?~ l old
=/ x
?: ?=([%name ~] -.o.i.l)
old
(~(put by old) d.i.l o.i.l)
$(l t.l, old x)
:: +load: migrate old state to new state (called on vane reload)
::
++ load
@ -2770,9 +2719,9 @@
=* who p.why
?: =(tyl /whey)
=/ maz=(list mass)
:~ bindings+&+(bindings-old bindings.server-state.ax)
:~ bindings+&+bindings.server-state.ax
auth+&+authentication-state.server-state.ax
connections+&+(connections-old connections.server-state.ax)
connections+&+connections.server-state.ax
channels+&+channel-state.server-state.ax
axle+&+ax
==
@ -2812,8 +2761,8 @@
?. ?=(%$ ren)
[~ ~]
?+ syd [~ ~]
%bindings ``noun+!>((bindings-old bindings.server-state.ax))
%connections ``noun+!>((connections-old connections.server-state.ax))
%bindings ``noun+!>(bindings.server-state.ax)
%connections ``noun+!>(connections.server-state.ax)
%authentication-state ``noun+!>(authentication-state.server-state.ax)
%channel-state ``noun+!>(channel-state.server-state.ax)
::

View File

@ -4,7 +4,7 @@
=> ..lull
~% %zuse ..part ~
|%
++ zuse %415
++ zuse %414
:: :: ::
:::: :: :: (2) engines
:: :: ::

View File

@ -14,8 +14,8 @@
=/ [b-path=path shallow=flag] ?:(?=([^ *] b) b [`path`b |])
=/ a-beam (need (de-beam a-path))
=/ b-beam (need (de-beam b-path))
;< a-dome=dome bind:m (get-from-clay a-beam dome %v)
;< b-dome=dome bind:m (get-from-clay b-beam dome %v)
;< a-domo=domo bind:m (get-from-clay a-beam domo %v)
;< b-domo=domo bind:m (get-from-clay b-beam domo %v)
;< diffs=(list diff-type) bind:m (diff-beams a-beam b-beam)
%- pure:m
!> ^- tang

View File

@ -1,16 +1,11 @@
/- spider
/- spider, eval=ted-eval
/+ strandio
=, strand=strand:spider
=>
|%
+$ deps (list path)
+$ inpt $@(cord (pair cord deps))
--
^- thread:spider
|= raw=vase
=/ m (strand ,vase)
^- form:m
=+ !<(arg=(unit inpt) raw)
=+ !<(arg=(unit inpt:eval) raw)
?~ arg
(strand-fail:strand %no-input ~)
?@ u.arg

View File

@ -1,16 +1,11 @@
/- spider
/- spider, eval=ted-eval
/+ strandio
=, strand=strand:spider
=>
|%
+$ deps (list path)
+$ inpt $@(cord (pair cord deps))
--
^- thread:spider
|= raw=vase
=/ m (strand ,vase)
^- form:m
=+ !<(arg=(unit inpt) raw)
=+ !<(arg=(unit inpt:eval) raw)
?~ arg
(strand-fail:strand %no-input ~)
=/ com

View File

@ -733,7 +733,7 @@
::
%eth-get-block-by-number
:- 'eth_getBlockByNumber'
:~ (tape (num-to-hex bon.req))
:~ (tape (num-to-hex-minimal bon.req))
b+txs.req
==
::
@ -942,6 +942,12 @@
%- render-hex-bytes
(as-octs:mimes:html n)
::
++ num-to-hex-minimal
|= n=@
^- tape
%- prefix-hex
((x-co:co 1) n)
::
++ address-to-hex
|= a=address
^- tape

View File

@ -73,9 +73,9 @@
?~ sink [hash]~
(mergebase-hashes our syd now her.u.sink sud.u.sink)
=/ dek (~(got by tyr) syd)
=/ =foam (~(got by cone) our syd)
=/ =dome (~(got by cone) our syd)
=/ [on=(list [@tas ?]) of=(list [@tas ?])]
(skid ~(tap by ren.foam) |=([* ?] +<+))
(skid ~(tap by ren.dome) |=([* ?] +<+))
=/ sat
?- zest.dek
%live "running"
@ -130,7 +130,7 @@
=/ syd (scot %tas desk)
=/ yon (scot %ud aeon)
::
=/ dom .^(dome cv/~[her syd yon])
=/ dom .^(domo cv/~[her syd yon])
=/ tak ~| aeons=~(key by hit.dom)
(scot %uv (~(got by hit.dom) aeon))
=/ yak .^(yaki cs/~[her syd yon %yaki tak])

View File

@ -1 +0,0 @@
Each one of the folders in this directory is published at `@urbit/{folder name}`

View File

@ -1,12 +0,0 @@
{
"presets": [
[
"@babel/preset-env",
{
"targets": "> 1%",
"useBuiltIns": "usage",
"corejs": "3.19.1"
}
]
]
}

View File

@ -1,3 +0,0 @@
module.exports = {
extends: '@urbit'
};

View File

@ -1 +0,0 @@
tmp

View File

@ -1,41 +0,0 @@
# Urbit API in JavaScript
This package simplifies the process of working with Urbit's APIs into fluent, typed functions organized by app. Pairs well with `@urbit/http-api`. Compare:
Without:
```ts
import UrbitInterface from '@urbit/http-api';
const api: UrbitInterface = useApi();
api.poke({
app: 'settings-store',
mark: 'settings-event',
json: {
'put-entry': {
'bucket-key': bucket,
'entry-key': key,
'value': value
}
}
});
```
With:
```ts
import UrbitInterface from '@urbit/http-api';
import { settings } from '@urbit/api';
const api: UrbitInterface = useApi();
api.poke(settings.putEntry(bucket, key, value));
```
You may import single functions
```ts
import { putEntry } from '@urbit/api';
```
or whole apps:
```ts
import { settings } from '@urbit/api';
```
This package also provides types and utilities for working with Urbit's internal data structures, such as Nouns, Das, Tas, and so forth.
This package was originally developed as part of Tlon's Landscape client and therefore the best reference material exists [there](https://github.com/urbit/urbit/tree/master/pkg/interface/src).

View File

@ -1,2 +0,0 @@
export * from './types';
export * from './lib';

View File

@ -1,109 +0,0 @@
import { Patp, Poke, Scry } from '../lib';
import {
Contact,
ContactUpdateAdd,
ContactUpdateEdit,
ContactUpdateRemove,
ContactEditField,
ContactShare,
ContactUpdate,
ContactUpdateAllowShips,
ContactUpdateAllowGroup,
ContactUpdateSetPublic
} from './types';
export const CONTACT_UPDATE_VERSION = 0;
const storeAction = <T extends ContactUpdate>(data: T, version: number = CONTACT_UPDATE_VERSION): Poke<T> => ({
app: 'contact-store',
mark: `contact-update-${version}`,
json: data
});
export { storeAction as contactStoreAction };
export const addContact = (ship: Patp, contact: Contact): Poke<ContactUpdateAdd> => {
contact['last-updated'] = Date.now();
return storeAction({
add: { ship, contact }
});
};
export const removeContact = (ship: Patp): Poke<ContactUpdateRemove> =>
storeAction({
remove: { ship }
});
export const share = (recipient: Patp, version: number = CONTACT_UPDATE_VERSION): Poke<ContactShare> => ({
app: 'contact-push-hook',
mark: 'contact-share',
json: { share: recipient }
});
export const editContact = (
ship: Patp,
editField: ContactEditField
): Poke<ContactUpdateEdit> =>
storeAction({
edit: {
ship,
'edit-field': editField,
timestamp: Date.now()
}
});
export const allowShips = (
ships: Patp[]
): Poke<ContactUpdateAllowShips> => storeAction({
allow: {
ships
}
});
export const allowGroup = (
ship: string,
name: string
): Poke<ContactUpdateAllowGroup> => storeAction({
allow: {
group: { ship, name }
}
});
export const setPublic = (
setPublic: any
): Poke<ContactUpdateSetPublic> => {
return storeAction({
'set-public': setPublic
});
};
export const retrieve = (
ship: string
) => {
const resource = { ship, name: '' };
return {
app: 'contact-pull-hook',
mark: 'pull-hook-action',
json: {
add: {
resource,
ship
}
}
};
};
export const fetchIsAllowed = (
entity: string,
name: string,
ship: string,
personal: boolean
): Scry => {
const isPersonal = personal ? 'true' : 'false';
return {
app: 'contact-store',
path: `/is-allowed/${entity}/${name}/${ship}/${isPersonal}`
};
};

View File

@ -1,82 +0,0 @@
import { Path, Patp } from '../lib';
import { Resource } from '../groups';
export type ContactUpdate =
| ContactUpdateAdd
| ContactUpdateRemove
| ContactUpdateEdit
| ContactUpdateInitial
| ContactUpdateAllowGroup
| ContactUpdateAllowShips
| ContactUpdateSetPublic;
export interface ContactUpdateAdd {
add: {
ship: Patp;
contact: Contact;
};
}
export interface ContactUpdateRemove {
remove: {
ship: Patp;
};
}
export interface ContactUpdateEdit {
edit: {
ship: Patp;
'edit-field': ContactEditField;
timestamp: number;
};
}
export interface ContactUpdateAllowShips {
allow: {
ships: Patp[];
}
}
export interface ContactUpdateAllowGroup {
allow: {
group: Resource;
}
}
export interface ContactUpdateSetPublic {
'set-public': boolean;
}
export interface ContactShare {
share: Patp;
}
export interface ContactUpdateInitial {
initial: Rolodex;
}
export type Rolodex = {
[p in Patp]: Contact;
};
export type Contacts = Rolodex;
export interface Contact {
nickname: string;
bio: string;
status: string;
color: string;
avatar: string | null;
cover: string | null;
groups: Path[];
'last-updated': number;
}
type ContactKeys = keyof Contact;
export type ContactEditFieldPrim = Exclude<ContactKeys, 'groups' | 'last-updated'>;
export type ContactEditField = Partial<Pick<Contact, ContactEditFieldPrim>> & {
'add-group'?: Resource;
'remove-group'?: Resource;
};

View File

@ -1,8 +0,0 @@
declare module 'urbit-ob' {
/**
* Convert a @p-encoded string to a decimal-encoded string.
*/
function patp2dec(name: string): string
}

View File

@ -1,2 +0,0 @@
export * from './lib';
export * from './types';

View File

@ -1,65 +0,0 @@
import { Poke, Scry } from '../lib';
import { Chad } from './types';
export function chadIsRunning(chad: Chad) {
return 'glob' in chad || 'site' in chad;
}
export const scryCharges: Scry = {
app: 'docket',
path: '/charges'
};
export const scryDockets: Scry = {
app: 'docket',
path: '/dockets'
};
export const scryTreaties: Scry = {
app: 'treaty',
path: '/treaties'
};
export const scryDefaultAlly: Scry = {
app: 'treaty',
path: '/default-ally'
};
export const scryAllies: Scry = {
app: 'treaty',
path: '/allies'
};
export const scryAllyTreaties = (ship: string): Scry => ({
app: 'treaty',
path: `/treaties/${ship}`
});
/**
* Uninstall a desk, and remove docket
*/
export function docketUninstall(desk: string): Poke<string> {
return {
app: 'docket',
mark: 'docket-uninstall',
json: desk
};
}
export function docketInstall(ship: string, desk: string): Poke<any> {
return {
app: 'docket',
mark: 'docket-install',
json: `${ship}/${desk}`
};
}
export function allyShip(ship: string): Poke<any> {
return {
app: 'treaty',
mark: 'ally-update-0',
json: {
add: ship
}
};
}

View File

@ -1,135 +0,0 @@
import { Cass } from '../hood';
export type DeskStatus = 'active' | 'suspended';
export type DocketHref = DocketHrefSite | DocketHrefGlob;
export interface DocketHrefGlob {
glob: {
base: string;
}
}
export interface DocketHrefSite {
site: string;
}
export interface Docket {
title: string;
info?: string;
color: string;
href: DocketHref;
website: string;
license: string;
version: string;
image?: string;
}
export interface Charge extends Docket {
chad: Chad;
}
export type Chad = HungChad | GlobChad | SiteChad | InstallChad | SuspendChad;
export interface HungChad {
hung: string;
}
export interface GlobChad {
glob: null;
}
export interface SiteChad {
site: null;
}
export interface InstallChad {
install: null;
}
export interface SuspendChad {
suspend: null;
}
export interface Treaty extends Docket {
ship: string;
desk: string;
cass: Cass;
hash: string;
}
export interface Charges {
[desk: string]: Charge;
}
export interface Treaties {
[ref: string]: Treaty;
}
export type Charter = string[];
export interface Allies {
[ship: string]: Charter;
}
export interface Provider {
shipName: string;
nickname?: string;
status?: string;
}
export type ChargeUpdate = ChargeUpdateInitial | ChargeUpdateAdd | ChargeUpdateDel;
export interface ChargeUpdateInitial {
initial: {
[desk: string]: Charge;
}
}
export interface ChargeUpdateAdd {
'add-charge': {
desk: string;
charge: Charge;
}
}
export interface ChargeUpdateDel {
'del-charge': string;
}
export type AllyUpdate = AllyUpdateIni | AllyUpdateAdd | AllyUpdateDel | AllyUpdateNew;
export interface AllyUpdateIni {
ini: {
[ship: string]: string[];
}
}
export interface AllyUpdateAdd {
add: string;
}
export interface AllyUpdateDel {
del: string;
}
export interface AllyUpdateNew {
new: {
ship: string;
alliance: string[];
}
}
export type TreatyUpdate = TreatyUpdateIni | TreatyUpdateAdd | TreatyUpdateDel;
export interface TreatyUpdateIni {
ini: {
[foreignDesk: string]: Treaty;
}
}
export interface TreatyUpdateAdd {
add: Treaty;
}
export interface TreatyUpdateDel {
del: string;
}

View File

@ -1,2 +0,0 @@
export * from './lib';
export * from './types';

View File

@ -1,534 +0,0 @@
import { GroupPolicy, makeResource, Resource, resourceFromPath } from '../groups';
import { decToUd, deSig, unixToDa, Scry } from '../lib';
import { Enc, Path, Patp, PatpNoSig, Poke, Thread } from '../lib/types';
import { Content, GraphChildrenPoke, GraphNode, GraphNodePoke, Post } from './types';
import { patp2dec } from 'urbit-ob';
export const GRAPH_UPDATE_VERSION = 3;
export const createBlankNodeWithChildPost = (
ship: PatpNoSig,
parentIndex = '',
childIndex = '',
contents: Content[]
): GraphNodePoke => {
const date = unixToDa(Date.now()).toString();
const nodeIndex = parentIndex + '/' + date;
const childGraph: GraphChildrenPoke = {};
childGraph[childIndex] = {
post: {
author: `~${ship}`,
index: nodeIndex + '/' + childIndex,
'time-sent': Date.now(),
contents,
hash: null,
signatures: []
},
children: null
};
return {
post: {
author: `~${ship}`,
index: nodeIndex,
'time-sent': Date.now(),
contents: [],
hash: null,
signatures: []
},
children: childGraph
};
};
export const markPending = (nodes: any): any => {
Object.keys(nodes).forEach((key) => {
nodes[key].post.author = deSig(nodes[key].post.author);
nodes[key].post.pending = true;
if (nodes[key].children) {
nodes[key].children = markPending(nodes[key].children);
}
});
return nodes;
};
export const createPost = (
ship: PatpNoSig,
contents: Content[],
parentIndex = '',
childIndex = 'DATE_PLACEHOLDER'
): Post => {
if (childIndex === 'DATE_PLACEHOLDER') {
childIndex = unixToDa(Date.now()).toString();
}
return {
author: `~${ship}`,
index: parentIndex + '/' + childIndex,
'time-sent': Date.now(),
contents,
hash: null,
signatures: []
};
};
function moduleToMark(mod: string): string | undefined {
if(mod === 'link') {
return 'graph-validator-link';
}
if(mod === 'publish') {
return 'graph-validator-publish';
}
if(mod === 'chat') {
return 'graph-validator-chat';
}
return undefined;
}
const storeAction = <T>(data: T, version: number = GRAPH_UPDATE_VERSION): Poke<T> => ({
app: 'graph-store',
mark: `graph-update-${version}`,
json: data
});
export { storeAction as graphStoreAction };
const viewAction = <T>(threadName: string, action: T): Thread<T> => ({
inputMark: 'graph-view-action',
outputMark: 'json',
threadName,
body: action
});
export { viewAction as graphViewAction };
const hookAction = <T>(data: T, version: number = GRAPH_UPDATE_VERSION): Poke<T> => ({
app: 'graph-push-hook',
mark: `graph-update-${version}`,
json: data
});
const dmAction = <T>(data: T): Poke<T> => ({
app: 'dm-hook',
mark: 'dm-hook-action',
json: data
});
export { hookAction as graphHookAction };
export const createManagedGraph = (
ship: PatpNoSig,
name: string,
title: string,
description: string,
group: Path,
mod: string
): Thread<any> => {
const associated = { group: resourceFromPath(group) };
const resource = makeResource(`~${ship}`, name);
return viewAction('graph-create', {
create: {
resource,
title,
description,
associated,
module: mod,
mark: moduleToMark(mod)
}
});
};
export const createUnmanagedGraph = (
ship: PatpNoSig,
name: string,
title: string,
description: string,
policy: Enc<GroupPolicy>,
mod: string
): Thread<any> => viewAction('graph-create', {
create: {
resource: makeResource(`~${ship}`, name),
title,
description,
associated: { policy },
module: mod,
mark: moduleToMark(mod)
}
});
export const joinGraph = (
ship: Patp,
name: string
): Thread<any> => viewAction('graph-join', {
join: {
resource: makeResource(ship, name),
ship
}
});
export const deleteGraph = (
ship: PatpNoSig,
name: string
): Thread<any> => viewAction('graph-delete', {
'delete': {
resource: makeResource(`~${ship}`, name)
}
});
export const leaveGraph = (
ship: Patp,
name: string
): Thread<any> => viewAction('graph-leave', {
'leave': {
resource: makeResource(ship, name)
}
});
export const groupifyGraph = (
ship: Patp,
name: string,
toPath?: string
): Thread<any> => {
const resource = makeResource(ship, name);
const to = toPath && resourceFromPath(toPath);
return viewAction('graph-groupify', {
groupify: {
resource,
to
}
});
};
export const evalCord = (
cord: string
): Thread<any> => {
return ({
inputMark: 'graph-view-action',
outputMark: 'tang',
threadName: 'graph-eval',
body: {
eval: cord
}
});
};
export const addGraph = (
ship: Patp,
name: string,
graph: any,
mark: any
): Poke<any> => {
return storeAction({
'add-graph': {
resource: { ship, name },
graph,
mark
}
});
};
export const addNodes = (
ship: Patp,
name: string,
nodes: Object
): Thread<any> => ({
inputMark: `graph-update-${GRAPH_UPDATE_VERSION}`,
outputMark: 'graph-view-action',
threadName: 'graph-add-nodes',
body: {
'add-nodes': {
resource: { ship, name },
nodes
}
}
});
export const addPost = (
ship: Patp,
name: string,
post: Post
): Thread<any> => {
const nodes: Record<string, GraphNode> = {};
nodes[post.index] = {
post,
children: null
};
return addNodes(ship, name, nodes);
};
export const addNode = (
ship: Patp,
name: string,
node: GraphNodePoke
): Thread<any> => {
const nodes: Record<string, GraphNodePoke> = {};
nodes[node.post.index] = node;
return addNodes(ship, name, nodes);
};
export const createGroupFeed = (
group: Resource,
vip: any = ''
): Thread<any> => ({
inputMark: 'graph-view-action',
outputMark: 'resource',
threadName: 'graph-create-group-feed',
body: {
'create-group-feed': {
resource: group,
vip
}
}
});
export const disableGroupFeed = (
group: Resource
): Thread<any> => ({
inputMark: 'graph-view-action',
outputMark: 'json',
threadName: 'graph-disable-group-feed',
body: {
'disable-group-feed': {
resource: group
}
}
});
/**
* Set dm-hook to screen new DMs or not
*
*/
export const setScreen = (screen: boolean): Poke<any> => dmAction({ screen });
/**
* Accept a pending DM request
*
* @param ship the ship to accept
*/
export const acceptDm = (ship: string) => dmAction({
accept: ship
});
/**
* Decline a pending DM request
*
* @param ship the ship to accept
*/
export const declineDm = (ship: string) => dmAction({
decline: ship
});
/**
* Remove posts from a set of indices
*
*/
export const removePosts = (
ship: Patp,
name: string,
indices: string[]
): Poke<any> => hookAction({
'remove-posts': {
resource: { ship, name },
indices
}
});
/**
* Remove a DM message from our inbox
*
* @remarks
* This does not remove the message from the recipients inbox
*/
export const removeDmMessage = (
our: Patp,
index: string
): Poke<any> => ({
app: 'graph-store',
mark: `graph-update-${GRAPH_UPDATE_VERSION}`,
json: {
'remove-posts': {
resource: { ship: our, name: 'dm-inbox' },
indices: [index]
}
}
});
/**
* Send a DM to a ship
*
* @param our sender
* @param ship recipient
* @param contents contents of message
*/
export const addDmMessage = (our: PatpNoSig, ship: Patp, contents: Content[]): Poke<any> => {
const post = createPost(our, contents, `/${patp2dec(ship)}`);
const node: GraphNode = {
post,
children: null
};
return {
app: 'dm-hook',
mark: `graph-update-${GRAPH_UPDATE_VERSION}`,
json: {
'add-nodes': {
resource: { ship: `~${our}`, name: 'dm-inbox' },
nodes: {
[post.index]: node
}
}
}
};
};
const encodeIndex = (idx: string) => idx.split('/').map(decToUd).join('/');
/**
* Fetch all graph keys
*/
export const getKeys = (): Scry => ({
app: 'graph-store',
path: '/keys'
});
/**
* Fetch newest (larger keys) nodes in a graph under some index
*
* @param ship ship of graph
* @param name name of graph
* @param count number of nodes to load
* @param index index to query
*/
export const getNewest = (
ship: string,
name: string,
count: number,
index = ''
): Scry => ({
app: 'graph-store',
path: `/graph/${ship}/${name}/node/siblings` +
`/newest/lone/${count}${encodeIndex(index)}`
});
/**
* Fetch nodes in a graph that are older (key is smaller) and direct
* siblings of some index
*
* @param ship ship of graph
* @param name name of graph
* @param count number of nodes to load
* @param index index to query
*/
export const getOlderSiblings = (
ship: string,
name: string,
count: number,
index: string
): Scry => ({
app: 'graph-store',
path: `/graph/${ship}/${name}/node/siblings/older/lone/${count}${encodeIndex(index)}`
});
/**
* Fetch nodes in a graph that are younger (key is larger) and direct
* siblings of some index
*
* @param ship ship of graph
* @param name name of graph
* @param count number of nodes to load
* @param index index to query
*/
export const getYoungerSiblings = (
ship: string,
name: string,
count: number,
index: string
): Scry => ({
app: 'graph-store',
path: `/graph/${ship}/${name}/node/siblings/newer/lone/${count}${encodeIndex(index)}`
});
/**
* Fetch all nodes in a graph under some index, without loading children
*
* @param ship ship of graph
* @param name name of graph
* @param index index to query
*/
export const getShallowChildren = (ship: string, name: string, index = '') => ({
app: 'graph-store',
path: `/graph/${ship}/${name}/node/children/lone/~/~${encodeIndex(index)}`
});
/**
* Fetch newest nodes in a graph as a flat map, including children,
* optionally starting at a specified key
*
* @param ship ship of graph
* @param name name of graph
* @param count number of nodes to load
* @param start key to start at
*
*/
export const getDeepOlderThan = (
ship: string,
name: string,
count: number,
start = ''
) => ({
app: 'graph-store',
path: `/graph/${ship}/${name}/node/siblings` +
`/${start.length > 0 ? 'older' : 'newest'}` +
`/kith/${count}${encodeIndex(start)}`
});
/**
* Fetch a flat map of a nodes ancestors and firstborn children
*
* @param ship ship of graph
* @param name name of graph
* @param index index to query
*
*/
export const getFirstborn = (
ship: string,
name: string,
index: string
): Scry => ({
app: 'graph-store',
path: `/graph/${ship}/${name}/node/firstborn${encodeIndex(index)}`
});
/**
* Fetch a single node, and all it's children
*
* @param ship ship of graph
* @param name name of graph
* @param index index to query
*
*/
export const getNode = (
ship: string,
name: string,
index: string
): Scry => ({
app: 'graph-store',
path: `/graph/${ship}/${name}/node/index/kith${encodeIndex(index)}`
});
/**
* Fetch entire graph
*
* @param ship ship of graph
* @param name name of graph
*
*/
export const getGraph = (
ship: string,
name: string
): Scry => ({
app: 'graph-store',
path: `/graph/${ship}/${name}`
});

View File

@ -1,94 +0,0 @@
import { Patp } from '../lib';
import { BigIntOrderedMap } from '../lib/BigIntOrderedMap';
import { BigIntArrayOrderedMap } from '../lib/BigIntArrayOrderedMap';
export interface TextContent {
text: string;
}
export interface UrlContent {
url: string;
}
export interface CodeContent {
code: {
expression: string;
output: string[] | undefined;
}
}
export interface ReferenceContent {
reference: AppReference | GraphReference | GroupReference;
}
export interface GraphReference {
graph: {
graph: string;
group: string;
index: string;
}
}
export interface GroupReference {
group: string;
}
export interface AppReference {
app: {
ship: string;
desk: string;
path: string;
}
}
export interface MentionContent {
mention: string;
emphasis?: 'bold' | 'italic';
}
export type Content =
| TextContent
| UrlContent
| CodeContent
| ReferenceContent
| MentionContent;
export interface Post {
author: Patp;
contents: Content[];
hash: string | null;
index: string;
pending?: boolean;
signatures: string[];
'time-sent': number;
}
export interface GraphNodePoke {
post: Post;
children: GraphChildrenPoke | null;
}
export interface GraphChildrenPoke {
[k: string]: GraphNodePoke;
}
export interface GraphNode {
children: Graph | null;
post: Post;
}
export interface FlatGraphNode {
children: null;
post: Post;
}
export type Graph = BigIntOrderedMap<GraphNode>;
export type Graphs = { [rid: string]: Graph };
export type FlatGraph = BigIntArrayOrderedMap<FlatGraphNode>;
export type FlatGraphs = { [rid: string]: FlatGraph };
export type ThreadGraphs = {
[rid: string]: {
[index: string]: FlatGraph;
}
};

View File

@ -1,2 +0,0 @@
export * from './types';
export * from './lib';

View File

@ -1,226 +0,0 @@
import { deSig } from '../index';
import { Enc, Path, Patp, PatpNoSig, Poke, Thread } from '../lib/types';
import { Group, GroupPolicy, GroupPolicyDiff, GroupUpdateAddMembers, GroupUpdateAddTag, GroupUpdateChangePolicy, GroupUpdateRemoveGroup, GroupUpdateRemoveMembers, GroupUpdateRemoveTag, Resource, RoleTags, Tag } from './types';
import { GroupUpdate } from './update';
export const GROUP_UPDATE_VERSION = 0;
export const proxyAction = <T>(data: T, version: number = GROUP_UPDATE_VERSION): Poke<T> => ({
app: 'group-push-hook',
mark: `group-update-${version}`,
json: data
});
const storeAction = <T extends GroupUpdate>(data: T, version: number = GROUP_UPDATE_VERSION): Poke<T> => ({
app: 'group-store',
mark: `group-update-${version}`,
json: data
});
export { storeAction as groupStoreAction };
const viewAction = <T>(data: T): Poke<T> => ({
app: 'group-view',
mark: 'group-view-action',
json: data
});
export { viewAction as groupViewAction };
export const viewThread = <T>(thread: string, action: T): Thread<T> => ({
inputMark: 'group-view-action',
outputMark: 'json',
threadName: thread,
body: action
});
export const removeMembers = (
resource: Resource,
ships: PatpNoSig[]
): Poke<GroupUpdateRemoveMembers> => proxyAction({
removeMembers: {
resource,
ships
}
});
export const addTag = (
resource: Resource,
tag: Tag,
ships: Patp[]
): Poke<GroupUpdateAddTag> => proxyAction({
addTag: {
resource,
tag,
ships
}
});
export const removeTag = (
tag: Tag,
resource: Resource,
ships: PatpNoSig[]
): Poke<GroupUpdateRemoveTag> => proxyAction({
removeTag: {
tag,
resource,
ships
}
});
export const addMembers = (
resource: Resource,
ships: PatpNoSig[]
): Poke<GroupUpdateAddMembers> => proxyAction({
addMembers: {
resource,
ships
}
});
export const removeGroup = (
resource: Resource
): Poke<GroupUpdateRemoveGroup> => storeAction({
removeGroup: {
resource
}
});
export const changePolicy = (
resource: Resource,
diff: Enc<GroupPolicyDiff>
): Poke<Enc<GroupUpdateChangePolicy>> => proxyAction({
changePolicy: {
resource,
diff
}
});
export const join = (
ship: string,
name: string,
app: "groups" | "graph",
autojoin: boolean,
share: boolean
): Poke<any> => viewAction({
join: {
resource: makeResource(ship, name),
ship,
shareContact: share || false,
app,
autojoin
}
});
export const createGroup = (
name: string,
policy: Enc<GroupPolicy>,
title: string,
description: string
): Thread<any> => viewThread('group-create', {
create: {
name,
policy,
title,
description
}
});
export const deleteGroup = (
ship: string,
name: string
): Thread<any> => viewThread('group-delete', {
remove: makeResource(ship, name)
});
export const leaveGroup = (
ship: string,
name: string
): Thread<any> => viewThread('group-leave', {
leave: makeResource(ship, name)
});
export const invite = (
ship: string,
name: string,
ships: Patp[],
description: string
): Thread<any> => viewThread('group-invite', {
invite: {
resource: makeResource(ship, name),
ships,
description
}
});
export const abortJoin = (
resource: string
): Poke<any> => viewAction({
abort: resource
});
export const roleTags = ['janitor', 'moderator', 'admin'];
// TODO make this type better?
export const groupBunts = {
group: (): Group => ({ members: [], tags: { role: {} }, hidden: false, policy: groupBunts.policy() }),
policy: (): GroupPolicy => ({ open: { banned: [], banRanks: [] } })
};
export const joinError = ['no-perms', 'strange', 'abort'] as const;
export const joinResult = ['done', ...joinError] as const;
export const joinLoad = ['start', 'added', 'metadata'] as const;
export const joinProgress = [...joinLoad, ...joinResult] as const;
export function roleForShip(
group: Group,
ship: PatpNoSig
): RoleTags | undefined {
return roleTags.reduce((currRole, role) => {
const roleShips = group?.tags?.role?.[role];
return roleShips && roleShips.includes(ship) ? role : currRole;
}, undefined as RoleTags | undefined);
};
export function resourceFromPath(path: Path): Resource {
const [, , ship, name] = path.split('/');
return { ship, name };
}
export function makeResource(ship: string, name: string) {
return { ship, name };
}
export const isWriter = (group: Group, resource: string, ship: string) => {
const graph = group?.tags?.graph;
const writers: string[] | undefined = graph && (graph[resource] as any)?.writers;
const admins = group?.tags?.role?.admin ?? [];
if (typeof writers === 'undefined') {
return true;
} else {
return [...writers].includes(ship) || admins.includes(ship);
}
};
export function isChannelAdmin(
group: Group,
resource: string,
ship: string
): boolean {
const role = roleForShip(group, deSig(ship));
return (
isHost(resource, ship) ||
role === 'admin' ||
role === 'moderator'
);
}
export function isHost(
resource: string,
ship: string
): boolean {
const [, , host] = resource.split('/');
return ship === host;
}

View File

@ -1,2 +0,0 @@
export * from './update';
export * from './view';

View File

@ -1,175 +0,0 @@
import { PatpNoSig, Path, ShipRank, Enc } from '../lib';
import { roleTags } from './index';
export type RoleTags = typeof roleTags[number];
interface RoleTag {
tag: 'admin' | 'moderator' | 'janitor';
}
interface AppTag {
app: string;
resource: string;
tag: string;
}
export type Tag = AppTag | RoleTag;
export interface InvitePolicy {
invite: {
pending: PatpNoSig[];
};
}
export interface OpenPolicy {
open: {
banned: PatpNoSig[];
banRanks: ShipRank[];
};
}
export interface Resource {
name: string;
ship: PatpNoSig;
}
export type OpenPolicyDiff =
| AllowRanksDiff
| BanRanksDiff
| AllowShipsDiff
| BanShipsDiff;
export interface AllowRanksDiff {
allowRanks: ShipRank[];
}
export interface BanRanksDiff {
banRanks: ShipRank[];
}
export interface AllowShipsDiff {
allowShips: PatpNoSig[];
}
export interface BanShipsDiff {
banShips: PatpNoSig[];
}
export type InvitePolicyDiff = AddInvitesDiff | RemoveInvitesDiff;
export interface AddInvitesDiff {
addInvites: PatpNoSig[];
}
export interface RemoveInvitesDiff {
removeInvites: PatpNoSig[];
}
export interface ReplacePolicyDiff {
replace: GroupPolicy;
}
export type GroupPolicyDiff =
| { open: OpenPolicyDiff }
| { invite: InvitePolicyDiff }
| ReplacePolicyDiff;
export type GroupPolicy = OpenPolicy | InvitePolicy;
export interface TaggedShips {
[tag: string]: PatpNoSig[];
}
export interface Tags {
role: TaggedShips;
[app: string]: TaggedShips;
}
export interface Group {
members: PatpNoSig[];
tags: Tags;
policy: GroupPolicy;
hidden: boolean;
}
export type Groups = {
[p in Path]: Group;
};
export interface GroupUpdateInitial {
initial: Enc<Groups>;
}
export interface GroupUpdateAddGroup {
addGroup: {
resource: Resource;
policy: Enc<GroupPolicy>;
hidden: boolean;
};
}
export interface GroupUpdateAddMembers {
addMembers: {
ships: PatpNoSig[];
resource: Resource;
};
}
export interface GroupUpdateRemoveMembers {
removeMembers: {
ships: PatpNoSig[];
resource: Resource;
};
}
export interface GroupUpdateAddTag {
addTag: {
tag: Tag;
resource: Resource;
ships: PatpNoSig[];
};
}
export interface GroupUpdateRemoveTag {
removeTag: {
tag: Tag;
resource: Resource;
ships: PatpNoSig[];
};
}
export interface GroupUpdateChangePolicy {
changePolicy: { resource: Resource; diff: GroupPolicyDiff };
}
export interface GroupUpdateRemoveGroup {
removeGroup: {
resource: Resource;
};
}
export interface GroupUpdateExpose {
expose: {
resource: Resource;
};
}
export interface GroupUpdateInitialGroup {
initialGroup: {
resource: Resource;
group: Enc<Group>;
};
}
export type GroupUpdate =
| GroupUpdateInitial
| GroupUpdateAddGroup
| GroupUpdateAddMembers
| GroupUpdateRemoveMembers
| GroupUpdateAddTag
| GroupUpdateRemoveTag
| GroupUpdateChangePolicy
| GroupUpdateRemoveGroup
| GroupUpdateExpose
| GroupUpdateInitialGroup;
export type GroupAction = Omit<GroupUpdate, 'initialGroup' | 'initial'>;

View File

@ -1,30 +0,0 @@
import { joinError, joinProgress, joinResult } from ".";
import {Patp} from "../lib";
export type JoinError = typeof joinError[number];
export type JoinResult = typeof joinResult[number];
export type JoinProgress = typeof joinProgress[number];
export interface JoinRequest {
/**
* Whether to display the join request or not
*/
hidden: boolean;
/**
* Timestamp of when the request started
*/
started: number;
ship: Patp;
progress: JoinProgress;
shareContact: boolean;
autojoin: boolean;
app: 'graph' | 'groups';
invite: string[];
}
export interface JoinRequests {
[rid: string]: JoinRequest;
}

View File

@ -1,2 +0,0 @@
export * from './types';
export * from './lib';

View File

@ -1,163 +0,0 @@
import { BigInteger } from 'big-integer';
import { Poke } from '../lib/types';
import {
HarkBin,
HarkBinId,
HarkBody,
HarkLid,
HarkPlace
} from './types';
import { decToUd } from '../lib';
export const harkAction = <T>(data: T): Poke<T> => ({
app: 'hark-store',
mark: 'hark-action',
json: data
});
const graphHookAction = <T>(data: T): Poke<T> => ({
app: 'hark-graph-hook',
mark: 'hark-graph-hook-action',
json: data
});
export { graphHookAction as harkGraphHookAction };
const groupHookAction = <T>(data: T): Poke<T> => ({
app: 'hark-group-hook',
mark: 'hark-group-hook-action',
json: data
});
export { groupHookAction as harkGroupHookAction };
export const actOnNotification = (
frond: string,
intTime: BigInteger,
bin: HarkBin
): Poke<unknown> =>
harkAction({
[frond]: {
time: decToUd(intTime.toString()),
bin
}
});
export const setMentions = (mentions: boolean): Poke<unknown> =>
graphHookAction({
'set-mentions': mentions
});
export const setWatchOnSelf = (watchSelf: boolean): Poke<unknown> =>
graphHookAction({
'set-watch-on-self': watchSelf
});
export const setDoNotDisturb = (dnd: boolean): Poke<unknown> =>
harkAction({
'set-dnd': dnd
});
export const addNote = (bin: HarkBin, body: HarkBody) =>
harkAction({
'add-note': {
bin,
body
}
});
export const archive = (bin: HarkBin, lid: HarkLid): Poke<unknown> =>
harkAction({
archive: {
lid,
bin
}
});
export const opened = harkAction({
opened: null
});
export const markCountAsRead = (place: HarkPlace): Poke<unknown> =>
harkAction({
'read-count': place
});
export const markEachAsRead = (
place: HarkPlace,
path: string
): Poke<unknown> =>
harkAction({
'read-each': {
place,
path
}
});
export const seen = () => harkAction({ seen: null });
export const readAll = harkAction({ 'read-all': null });
export const archiveAll = harkAction({ 'archive-all': null });
export const ignoreGroup = (group: string): Poke<unknown> =>
groupHookAction({
ignore: group
});
export const ignoreGraph = (graph: string, index: string): Poke<unknown> =>
graphHookAction({
ignore: {
graph,
index
}
});
export const listenGroup = (group: string): Poke<unknown> =>
groupHookAction({
listen: group
});
export const listenGraph = (graph: string, index: string): Poke<unknown> =>
graphHookAction({
listen: {
graph,
index
}
});
/**
* Read all graphs belonging to a particular group
*/
export const readGroup = (group: string) =>
harkAction({
'read-group': group
});
/**
* Read all unreads in a graph
*/
export const readGraph = (graph: string) =>
harkAction({
'read-graph': graph
});
export function harkBinToId(bin: HarkBin): HarkBinId {
const { place, path } = bin;
return `${place.desk}${place.path}${path}`;
}
export function harkBinEq(a: HarkBin, b: HarkBin): boolean {
return (
a.place.path === b.place.path &&
a.place.desk === b.place.desk &&
a.path === b.path
);
}
export function harkLidToId(lid: HarkLid): string {
if('time' in lid) {
return `archive-${lid.time}`;
}
return Object.keys(lid)[0];
}

View File

@ -1,58 +0,0 @@
export interface HarkStats {
count: number;
each: string[];
last: number;
}
export interface Timebox {
[binId: string]: Notification;
}
export type HarkContent = { ship: string; } | { text: string; };
export interface HarkBody {
title: HarkContent[];
time: number;
content: HarkContent[];
link: string;
binned: string;
}
export interface HarkPlace {
desk: string;
path: string;
}
export interface HarkBin {
path: string;
place: HarkPlace;
}
export type HarkLid =
{ unseen: null; }
| { seen: null; }
| { time: string; };
export type HarkBinId = string;
export interface Notification {
bin: HarkBin;
time: number;
body: HarkBody[];
}
export interface NotificationGraphConfig {
watchOnSelf: boolean;
mentions: boolean;
watching: WatchedIndex[]
}
export interface Unreads {
[path: string]: HarkStats;
}
interface WatchedIndex {
graph: string;
index: string;
}
export type GroupNotificationsConfig = string[];

View File

@ -1,2 +0,0 @@
export * from './lib';
export * from './types';

View File

@ -1,127 +0,0 @@
import { Poke, Scry } from '../lib';
import { Pike } from './types';
export const getPikes: Scry = {
app: 'hood',
path: '/kiln/pikes'
};
/**
* Install a foreign desk
*/
export function kilnInstall(
ship: string,
desk: string,
local?: string
): Poke<any> {
return {
app: 'hood',
mark: 'kiln-install',
json: {
ship,
desk,
local: local || desk
}
};
}
/**
* Sync with a foreign desk
*/
export function kilnSync(
ship: string,
desk: string,
local?: string
): Poke<any> {
return {
app: 'hood',
mark: 'kiln-sync',
json: {
ship,
desk,
local: local || desk
}
};
}
/**
* Unsync with a foreign desk
*/
export function kilnUnsync(
ship: string,
desk: string,
local?: string
): Poke<any> {
return {
app: 'hood',
mark: 'kiln-unsync',
json: {
ship,
desk,
local: local || desk
}
};
}
/**
* Uninstall a desk
*/
export function kilnUninstall(
desk: string
): Poke<any> {
return {
app: 'hood',
mark: 'kiln-uninstall',
json: desk
};
}
export function kilnSuspend(
desk: string
): Poke<any> {
return {
app: 'hood',
mark: 'kiln-suspend',
json: desk
};
}
export function kilnRevive(
desk: string
): Poke<any> {
return {
app: 'hood',
mark: 'kiln-revive',
json: desk
};
}
export function kilnBump(): Poke<any> {
return {
app: 'hood',
mark: 'kiln-bump',
json: null,
};
}
export function kilnPause(desk: string) {
return {
app: 'hood',
mark: 'kiln-pause',
json: desk
};
}
export function kilnResume(desk: string) {
return {
app: 'hood',
mark: 'kiln-resume',
json: desk
};
}
export const scryLag: Scry = ({ app: 'hood', path: '/kiln/lag' });
export function getPikePublisher(pike: Pike) {
return pike.sync?.ship;
}

View File

@ -1,208 +0,0 @@
/**
* A pending commit, awaiting a future kelvin version
*/
interface Woof {
aeon: number;
weft: Weft;
}
interface Rein {
/**
* Agents not in manifest that should be running
*/
add: string[];
/**
* Agents in manifest that should not be running
*/
sub: string[];
}
export interface Rail {
/**
* Original publisher of desk, if available
*/
publisher: string | null;
/**
* Ship of foreign vat
*/
ship: string;
/**
* Desk of foreign vat
*/
desk: string;
/**
* Aeon (version number) that we currently have synced
*/
aeon: number;
next: Woof[];
paused: boolean;
}
/**
* A tracker of a foreign {@link Vat}
*
*/
export interface Arak {
rein: Rein;
rail: Rail | null;
}
/**
* A component's kelvin version
*/
export interface Weft {
/**
* Name of the component
*
* @remarks
* Usually %zuse, %hoon, or %lull
*/
name: string;
/**
* Kelvin version
*
*/
kelvin: number;
}
export interface KilnDiffBlock {
block: {
desk: string;
arak: Arak;
weft: Weft;
blockers: string[];
};
}
export interface KilnDiffReset {
reset: {
desk: string;
arak: Arak;
};
}
export interface KilnDiffMerge {
merge: {
desk: string;
arak: Arak;
};
}
export interface KilnDiffMergeSunk {
'merge-sunk': {
desk: string;
arak: Arak;
tang: string;
};
}
export interface KilnDiffMergeFail {
'merge-fail': {
desk: string;
arak: Arak;
tang: string;
};
}
export type KilnDiff =
| KilnDiffBlock
| KilnDiffReset
| KilnDiffMerge
| KilnDiffMergeSunk
| KilnDiffMergeFail;
/**
* Cases for revision
*
*/
export interface Cass {
/**
* Revision number
*/
ud: number;
/**
* Timestamp of revision, as stringifed `@da`
*
* @remarks
* If \@da is outside valid positive unix timestamp, value will be zero
*/
da: string;
}
/**
* A local desk installation
*/
export interface Vat {
/**
* Desk that this Vat describes
*/
desk: string;
/**
* Hash of the desk, rendered as `@uv`
*
* @remarks
* Equivalent to
* ```hoon
* .^(@uv %cz /=desk=)
* ```
*/
hash: string;
/**
* Current revision
*/
cass: Cass;
/**
* Foreign sync
*/
arak: Arak;
}
export interface Vats {
[desk: string]: Vat;
}
/**
* TODO: crisp one-liner describing a Pike
*/
export interface Pike {
/**
* Hash of the desk, rendered as `@uv`
*
* @remarks
* Equivalent to
* ```hoon
* .^(@uv %cz /=desk=)
* ```
*/
hash: string;
sync: {
/**
* Source desk for this Pike
*/
desk: string;
/**
* Source ship for this Pike
*/
ship: string;
} | null;
/**
* {@link Weft}s associated with this Pike
*/
wefts: Weft[];
/**
* how live is this pike?
*
* live - app is running
* held - app is not running, but is trying to run. this state can be entered
* in two main ways:
* - when installing an app but it hasn't finished downloading (or it did
* but failed to install for some reason)
* - when user forced a kelvin upgrade by suspending desks.
* dead - app is not running
*/
zest: "live" | "dead" | "held";
}
export interface Pikes {
[desk: string]: Pike;
}

View File

@ -1,26 +0,0 @@
export * from './contacts';
export * as contacts from './contacts';
export * from './graph';
export * as graph from './graph';
export * from './groups';
export * as groups from './groups';
export * from './hark';
export * as hark from './hark';
export * from './invite';
// this conflicts with /groups/lib invite
// export * as invite from './invite';
export * from './metadata';
export * as metadata from './metadata';
export * from './settings';
export * as settings from './settings';
export * from './s3';
export * as s3 from './s3';
export * from './lib';
export * from './lib/BigIntOrderedMap';
export * from './lib/BigIntArrayOrderedMap';
export * as hood from './hood';
export * from './hood';
export * as docket from './docket';
export * from './docket';
export * as term from './term';
export * from './term';

View File

@ -1,2 +0,0 @@
export * from './types';
export * from './lib';

View File

@ -1,28 +0,0 @@
import { Poke, Serial } from "../lib";
import { InviteUpdate, InviteUpdateAccept, InviteUpdateDecline } from "./types";
export const inviteAction = <T extends InviteUpdate>(data: T): Poke<T> => ({
app: 'invite-store',
mark: 'invite-action',
json: data
});
export const accept = (
app: string,
uid: Serial
): Poke<InviteUpdateAccept> => inviteAction({
accept: {
term: app,
uid
}
});
export const decline = (
app: string,
uid: Serial
): Poke<InviteUpdateDecline> => inviteAction({
decline: {
term: app,
uid
}
});

View File

@ -1,75 +0,0 @@
import { Serial, PatpNoSig, Path } from '../lib';
import { Resource } from "../groups";
export type InviteUpdate =
InviteUpdateInitial
| InviteUpdateCreate
| InviteUpdateDelete
| InviteUpdateInvite
| InviteUpdateAccept
| InviteUpdateAccepted
| InviteUpdateDecline;
export interface InviteUpdateAccept {
accept: {
term: string;
uid: Serial;
}
}
export interface InviteUpdateInitial {
initial: Invites;
}
export interface InviteUpdateCreate {
create: {
term: string;
};
}
export interface InviteUpdateDelete {
delete: {
term: string;
};
}
export interface InviteUpdateInvite {
invite: {
term: string;
uid: Serial;
invite: Invite;
};
}
export interface InviteUpdateAccepted {
accepted: {
term: string;
uid: Serial;
};
}
export interface InviteUpdateDecline {
decline: {
term: string;
uid: Serial;
};
}
// actual datastructures
export type Invites = {
[p in Path]: AppInvites;
};
export type AppInvites = {
[s in Serial]: Invite;
};
export interface Invite {
app: string;
recipient: PatpNoSig;
resource: Resource;
ship: PatpNoSig;
text: string;
}

View File

@ -1,152 +0,0 @@
import produce, { immerable, castDraft, setAutoFreeze, enablePatches } from 'immer';
import bigInt, { BigInteger } from 'big-integer';
setAutoFreeze(false);
enablePatches();
export function stringToArr(str: string) {
return str.split('/').slice(1).map((ind) => {
return bigInt(ind);
});
}
export function arrToString(arr: BigInteger[]) {
let string = '';
arr.forEach((key) => {
string = string + `/${key.toString()}`;
});
return string;
}
function sorted(a: BigInteger[], b: BigInteger[], reversed = false) {
const getSort = sortBigIntArr(a, b);
if (reversed) {
return getSort * -1;
} else {
return getSort;
}
}
export function sortBigIntArr(a: BigInteger[], b: BigInteger[]) {
const aLen = a.length;
const bLen = b.length;
const aCop = a.slice(0);
const bCop = b.slice(0);
aCop.reverse();
bCop.reverse();
let i = 0;
while (i < aLen && i < bLen) {
if (aCop[i].lt(bCop[i])) {
return 1;
} else if (aCop[i].gt(bCop[i])) {
return -1;
} else {
i++;
}
}
return bLen - aLen;
}
export class BigIntArrayOrderedMap<V> implements Iterable<[BigInteger[], V]> {
root: Record<string, V> = {}
cachedIter: [BigInteger[], V][] | null = null;
[immerable] = true;
reversed = false;
constructor(items: [BigInteger[], V][] = [], reversed = false) {
items.forEach(([key, val]) => {
this.set(key, val);
});
this.reversed = reversed;
}
get size() {
return Object.keys(this.root).length;
}
get(key: BigInteger[]) {
return this.root[arrToString(key)] ?? null;
}
gas(items: [BigInteger[], V][]) {
return produce(this, (draft) => {
items.forEach(([key, value]) => {
draft.root[arrToString(key)] = castDraft(value);
});
draft.generateCachedIter();
},
(patches) => {
// console.log(`gassed with ${JSON.stringify(patches, null, 2)}`);
});
}
set(key: BigInteger[], value: V) {
return produce(this, (draft) => {
draft.root[arrToString(key)] = castDraft(value);
draft.cachedIter = null;
});
}
clear() {
return produce(this, (draft) => {
draft.cachedIter = [];
draft.root = {};
});
}
has(key: BigInteger[]) {
return arrToString(key) in this.root;
}
delete(key: BigInteger[]) {
const result = produce(this, (draft) => {
delete draft.root[arrToString(key)];
draft.cachedIter = null;
});
return result;
}
[Symbol.iterator](): IterableIterator<[BigInteger[], V]> {
let idx = 0;
const result = this.generateCachedIter();
return {
[Symbol.iterator]: this[Symbol.iterator],
next: (): IteratorResult<[BigInteger[], V]> => {
if (idx < result.length) {
return { value: result[idx++], done: false };
}
return { done: true, value: null };
}
};
}
peekLargest() {
const sorted = Array.from(this);
return sorted[0] as [BigInteger[], V] | null;
}
peekSmallest() {
const sorted = Array.from(this);
return sorted[sorted.length - 1] as [BigInteger[], V] | null;
}
keys() {
return Array.from(this).map(([k,v]) => k);
}
generateCachedIter() {
if(this.cachedIter) {
return [...this.cachedIter];
}
const result = Object.keys(this.root).map((key) => {
return [stringToArr(key), this.root[key]] as [BigInteger[], V];
}).sort(([a], [b]) => sorted(a, b, this.reversed));
this.cachedIter = result;
return [...result];
}
}

View File

@ -1,117 +0,0 @@
import produce, { immerable, castDraft, setAutoFreeze, enablePatches } from 'immer';
import bigInt, { BigInteger } from 'big-integer';
setAutoFreeze(false);
enablePatches();
function sortBigInt(a: BigInteger, b: BigInteger) {
if (a.lt(b)) {
return 1;
} else if (a.eq(b)) {
return 0;
} else {
return -1;
}
}
export class BigIntOrderedMap<V> implements Iterable<[BigInteger, V]> {
root: Record<string, V> = {}
cachedIter: [BigInteger, V][] | null = null;
[immerable] = true;
constructor(items: [BigInteger, V][] = []) {
items.forEach(([key, val]) => {
this.set(key, val);
});
}
get size() {
if(this.cachedIter) {
return this.cachedIter.length;
}
return this.generateCachedIter().length;
}
get(key: BigInteger) {
return this.root[key.toString()] ?? null;
}
gas(items: [BigInteger, V][]) {
return produce(this, (draft) => {
items.forEach(([key, value]) => {
draft.root[key.toString()] = castDraft(value);
});
draft.cachedIter = null;
},
(patches) => {
// console.log(`gassed with ${JSON.stringify(patches, null, 2)}`);
});
}
set(key: BigInteger, value: V) {
return produce(this, (draft) => {
draft.root[key.toString()] = castDraft(value);
draft.cachedIter = null;
});
}
clear() {
return produce(this, (draft) => {
draft.cachedIter = [];
draft.root = {};
});
}
has(key: BigInteger) {
return key.toString() in this.root;
}
delete(key: BigInteger) {
const result = produce(this, (draft) => {
delete draft.root[key.toString()];
draft.cachedIter = null;
});
return result;
}
[Symbol.iterator](): IterableIterator<[BigInteger, V]> {
let idx = 0;
const result = this.generateCachedIter();
return {
[Symbol.iterator]: this[Symbol.iterator],
next: (): IteratorResult<[BigInteger, V]> => {
if (idx < result.length) {
return { value: result[idx++], done: false };
}
return { done: true, value: null };
}
};
}
peekLargest() {
const sorted = Array.from(this);
return sorted[0] as [BigInteger, V] | null;
}
peekSmallest() {
const sorted = Array.from(this);
return sorted[sorted.length - 1] as [BigInteger, V] | null;
}
keys() {
return Array.from(this).map(([k,v]) => k);
}
generateCachedIter() {
if(this.cachedIter) {
return [...this.cachedIter];
}
const result = Object.keys(this.root).map((key) => {
const num = bigInt(key);
return [num, this.root[key]] as [BigInteger, V];
}).sort(([a], [b]) => sortBigInt(a,b));
this.cachedIter = result;
return [...result];
}
}

View File

@ -1,2 +0,0 @@
export * from './lib';
export * from './types';

View File

@ -1,259 +0,0 @@
import bigInt, { BigInteger } from "big-integer";
import { Resource } from "../groups/types";
import { Post, GraphNode } from "../graph/types";
const DA_UNIX_EPOCH = bigInt("170141184475152167957503069145530368000"); // `@ud` ~1970.1.1
const DA_SECOND = bigInt("18446744073709551616"); // `@ud` ~s1
function chunk<T>(arr: T[], size: number): T[][] {
let chunk: T[] = [];
let newArray = [chunk];
for (let i = 0;i < arr.length;i++) {
if (chunk.length < size) {
chunk.push(arr[i])
} else {
chunk = [arr[i]]
newArray.push(chunk)
}
}
return newArray;
}
function dropWhile<T>(arr: T[], pred: (x: T) => boolean): T[] {
const newArray = arr.slice();
for (const item of arr) {
if (pred(item)) {
newArray.shift();
} else {
return newArray;
}
}
return newArray;
}
/**
* Given a bigint representing an urbit date, returns a unix timestamp.
*
* @param {BigInteger} da The urbit date
*
* @return {number} The unix timestamp
*/
export function daToUnix(da: BigInteger): number {
// ported from +time:enjs:format in hoon.hoon
const offset = DA_SECOND.divide(bigInt(2000));
const epochAdjusted = offset.add(da.subtract(DA_UNIX_EPOCH));
return Math.round(
epochAdjusted.multiply(bigInt(1000)).divide(DA_SECOND).toJSNumber()
);
}
/**
* Given a unix timestamp, returns a bigint representing an urbit date
*
* @param {number} unix The unix timestamp
*
* @return {BigInteger} The urbit date
*/
export function unixToDa(unix: number): BigInteger {
const timeSinceEpoch = bigInt(unix).multiply(DA_SECOND).divide(bigInt(1000));
return DA_UNIX_EPOCH.add(timeSinceEpoch);
}
export function makePatDa(patda: string): BigInteger {
return bigInt(udToDec(patda));
}
export function udToDec(ud: string): string {
return ud.replace(/\./g, "");
}
export function decToUd(str: string): string {
const transform = chunk(str.split('').reverse(), 3)
.map(group => group.reverse().join(''))
.reverse()
.join('.')
return transform.replace(/^[0\.]+/g, '');
}
export function resourceAsPath(resource: Resource): string {
const { name, ship } = resource;
return `/ship/~${ship}/${name}`;
}
export function uuid(): string {
let str = "0v";
str += Math.ceil(Math.random() * 8) + ".";
for (let i = 0; i < 5; i++) {
let _str = Math.ceil(Math.random() * 10000000).toString(32);
_str = ("00000" + _str).substr(-5, 5);
str += _str + ".";
}
return str.slice(0, -1);
}
/*
Goes from:
~2018.7.17..23.15.09..5be5 // urbit @da
To:
(javascript Date object)
*/
export function daToDate(st: string): Date {
const dub = function (n: string) {
return parseInt(n) < 10 ? "0" + parseInt(n) : n.toString();
};
const da = st.split("..");
const bigEnd = da[0].split(".");
const lilEnd = da[1].split(".");
const ds = `${bigEnd[0].slice(1)}-${dub(bigEnd[1])}-${dub(bigEnd[2])}T${dub(
lilEnd[0]
)}:${dub(lilEnd[1])}:${dub(lilEnd[2])}Z`;
return new Date(ds);
}
/*
Goes from:
(javascript Date object)
To:
~2018.7.17..23.15.09..5be5 // urbit @da
*/
export function dateToDa(d: Date, mil: boolean = false): string {
const fil = function (n: number) {
return n >= 10 ? n : "0" + n;
};
return (
`~${d.getUTCFullYear()}.` +
`${d.getUTCMonth() + 1}.` +
`${fil(d.getUTCDate())}..` +
`${fil(d.getUTCHours())}.` +
`${fil(d.getUTCMinutes())}.` +
`${fil(d.getUTCSeconds())}` +
`${mil ? "..0000" : ""}`
);
}
export function preSig(ship: string): string {
if (!ship) {
return '';
}
if (ship.trim().startsWith('~')) {
return ship.trim();
}
return '~'.concat(ship.trim());
}
export function deSig(ship: string): string | null {
if (!ship) {
return null;
}
return ship.replace("~", "");
}
// trim patps to match dojo, chat-cli
export function cite(ship: string) {
let patp = ship,
shortened = '';
if (patp === null || patp === '') {
return null;
}
if (patp.startsWith('~')) {
patp = patp.substr(1);
}
// comet
if (patp.length === 56) {
shortened = '~' + patp.slice(0, 6) + '_' + patp.slice(50, 56);
return shortened;
}
// moon
if (patp.length === 27) {
shortened = '~' + patp.slice(14, 20) + '^' + patp.slice(21, 27);
return shortened;
}
return `~${patp}`;
}
export function uxToHex(ux: string) {
if (ux.length > 2 && ux.substr(0, 2) === '0x') {
const value = ux.substr(2).replace('.', '').padStart(6, '0');
return value;
}
const value = ux.replace('.', '').padStart(6, '0');
return value;
}
export const hexToUx = (hex: string): string => {
const nonZeroChars = dropWhile(hex.split(''), y => y === '0');
const ux = chunk(nonZeroChars.reverse(), 4).map(x => {
return x.reverse().join('');
}).reverse().join('.') || '0';
return `0x${ux}`;
};
// encode the string into @ta-safe format, using logic from +wood.
// for example, 'some Chars!' becomes '~.some.~43.hars~21.'
//
export function stringToTa(str: string): string {
let out = "";
for (let i = 0; i < str.length; i++) {
const char = str[i];
let add = "";
switch (char) {
case " ":
add = ".";
break;
case ".":
add = "~.";
break;
case "~":
add = "~~";
break;
default:
const charCode = str.charCodeAt(i);
if (
(charCode >= 97 && charCode <= 122) || // a-z
(charCode >= 48 && charCode <= 57) || // 0-9
char === "-"
) {
add = char;
} else {
// TODO behavior for unicode doesn't match +wood's,
// but we can probably get away with that for now.
add = "~" + charCode.toString(16) + ".";
}
}
out = out + add;
}
return "~." + out;
}
export const buntPost = (): Post => ({
author: '',
contents: [],
hash: null,
index: '',
signatures: [],
'time-sent': 0
});
export function makeNodeMap(posts: Post[]): Record<string, GraphNode> {
const nodes: Record<string, GraphNode> = {};
posts.forEach((p: Post) => {
nodes[String(p.index)] = { children: null, post: p };
});
return nodes;
}

View File

@ -1,67 +0,0 @@
/**
* Martian embassy
*/
import { BigIntOrderedMap } from "./BigIntOrderedMap";
// an urbit style path rendered as string
export type Path = string;
// patp including leading sig
export type Patp = string;
// patp excluding leading sig
export type PatpNoSig = string;
// @uvH encoded string
export type Serial = string;
// jug from hoon
export type Jug<K,V> = Map<K,Set<V>>;
// name of app
export type AppName = 'chat' | 'link' | 'contacts' | 'publish' | 'graph' | 'groups';
export type ShipRank = 'czar' | 'king' | 'duke' | 'earl' | 'pawn';
export type Action = 'poke' | 'subscribe' | 'ack' | 'unsubscribe' | 'delete';
export type SetElement<S> = S extends Set<(infer T)> ? T : never;
export type MapKey<M> = M extends Map<(infer K), any> ? K : never;
export type MapValue<M> = M extends Map<any, (infer V)> ? V : never;
/**
* Turns sets into arrays and maps into objects so we can send them over the wire
*/
export type Enc<S> =
S extends Set<any> ?
Enc<SetElement<S>>[] :
S extends Map<string, any> ?
{ [s: string]: Enc<MapValue<S>> } :
S extends object ?
{ [K in keyof S]: Enc<S[K]> } :
S extends BigIntOrderedMap<infer T> ?
{ [index: string]: T } :
S;
export type Mark = string;
export interface Poke<Action> {
ship?: string; // This should be handled by the http library, but is part of the spec
app: string;
mark: Mark;
json: Action;
}
export interface Scry {
app: string;
path: string;
}
export interface Thread<Action> {
inputMark: string;
outputMark: string;
threadName: string;
body: Action;
}

View File

@ -1,2 +0,0 @@
export * from './types';
export * from './lib';

View File

@ -1,99 +0,0 @@
import { Path, Poke, uxToHex, PatpNoSig } from '../lib';
import { MdAppName, Association, Metadata, MetadataUpdate, MetadataUpdateAdd, MetadataUpdateRemove, MetadataEditField, MetadataUpdateEdit } from './types';
export const METADATA_UPDATE_VERSION = 2;
export const metadataAction = <T extends MetadataUpdate>(data: T, version: number = METADATA_UPDATE_VERSION): Poke<T> => ({
app: 'metadata-push-hook',
mark: `metadata-update-${version}`,
json: data
});
export const add = (
ship: PatpNoSig,
appName: MdAppName,
resource: Path,
group: Path,
title: string,
description: string,
dateCreated: string,
color: string,
moduleName: string
): Poke<MetadataUpdateAdd> => metadataAction({
add: {
group,
resource: {
resource,
'app-name': appName
},
metadata: {
title,
description,
color,
'date-created': dateCreated,
creator: `~${ship}`,
config: { graph: moduleName },
picture: '',
hidden: false,
preview: false,
vip: ''
}
}
});
export { add as metadataAdd };
export const remove = (
appName: MdAppName,
resource: string,
group: string
): Poke<MetadataUpdateRemove> => metadataAction<MetadataUpdateRemove>({
remove: {
group,
resource: {
resource,
'app-name': appName
}
}
});
export { remove as metadataRemove };
export const edit = (
association: Association,
edit: MetadataEditField
): Poke<MetadataUpdateEdit> => metadataAction<MetadataUpdateEdit>({
edit: {
group: association.group,
resource: {
resource: association.resource,
'app-name': association['app-name']
},
edit
}
});
export { edit as metadataEdit };
/**
* @deprecated use {@link edit} instead
*/
export const update = (
association: Association,
newMetadata: Partial<Metadata>
): Poke<MetadataUpdateAdd> => {
const metadata = { ...association.metadata, ...newMetadata };
metadata.color = uxToHex(metadata.color);
return metadataAction<MetadataUpdateAdd>({
add: {
group: association.group,
resource: {
resource: association.resource,
'app-name': association['app-name']
},
metadata
}
});
};
export { update as metadataUpdate };

View File

@ -1,101 +0,0 @@
import { Path, Patp } from '../lib';
export type MdAppName = 'groups' | 'graph';
export type MetadataUpdate =
MetadataUpdateInitial
| MetadataUpdateAdd
| MetadataUpdateUpdate
| MetadataUpdateRemove
| MetadataUpdateEdit;
export interface MetadataUpdateInitial {
associations: ResourceAssociations;
}
export type ResourceAssociations = {
[p in Path]: Association;
}
export type MetadataUpdateAdd = {
add: AssociationPoke;
}
export type MetadataUpdateUpdate = {
update: AssociationPoke;
}
export interface MetadataUpdateEdit {
edit: {
resource: MdResource;
group: string;
edit: MetadataEditField;
}
}
export type MetadataEditField = Partial<Omit<Metadata, 'config' | 'creator' | 'date-created'>>;
export type MetadataUpdateRemove = {
remove: {
resource: MdResource;
group: string;
}
}
export interface MdResource {
resource: string;
'app-name': MdAppName;
}
export interface MetadataUpdatePreview {
group: string;
channels: Associations;
'channel-count': number;
members: number;
metadata: Metadata;
}
export type Associations = {
groups: AppAssociations<GroupConfig>
graph: AppAssociations<GraphConfig>;
}
export type AppAssociations<C = MetadataConfig> = {
[p in Path]: Association<C>;
}
export type Association<C = MetadataConfig> = MdResource & {
group: Path;
metadata: Metadata<C>;
};
export interface AssociationPoke {
group: Path;
resource: MdResource;
metadata: Metadata;
}
export interface Metadata<C = MetadataConfig> {
color: string;
creator: Patp;
'date-created': string;
description: string;
title: string;
config: C;
hidden: boolean;
picture: string;
preview: boolean;
vip: PermVariation;
}
export type MetadataConfig = GroupConfig | GraphConfig;
export interface GraphConfig {
graph: string;
}
export interface GroupConfig {
group: undefined | {} | MdResource;
}
export type PermVariation = '' | ' ' | 'reader-comments' | 'member-metadata' | 'host-feed' | 'admin-feed';

File diff suppressed because it is too large Load Diff

View File

@ -1,56 +0,0 @@
{
"name": "@urbit/api",
"version": "2.2.0",
"description": "A library that provides bindings and types for Urbit's various userspace desks",
"repository": {
"type": "git",
"url": "ssh://git@github.com/urbit/urbit.git",
"directory": "pkg/npm/api"
},
"type": "module",
"main": "dist/cjs/index.cjs",
"module": "dist/esm/index.js",
"exports": {
"require": "./dist/cjs/index.cjs",
"import": "./dist/esm/index.js"
},
"jsdelivr": "dist/urbit-api.min.js",
"unpkg": "dist/urbit-api.min.js",
"types": "dist/index.d.ts",
"files": [
"dist/**"
],
"scripts": {
"test": "echo \"No test specified\" && exit 0",
"build": "npm run clean && rollup -c && npx tsc -p tsconfig.json",
"prepare": "npm run build",
"watch": "rollup -c -w",
"clean": "rm -rf dist/* types/*"
},
"author": "",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.16.0",
"big-integer": "^1.6.48",
"core-js": "^3.19.1",
"immer": "^9.0.1",
"urbit-ob": "^5.0.1"
},
"devDependencies": {
"@babel/core": "^7.16.0",
"@rollup/plugin-babel": "^5.3.0",
"@rollup/plugin-commonjs": "^21.0.1",
"@rollup/plugin-node-resolve": "^13.0.6",
"@types/node": "^15.12.5",
"@typescript-eslint/eslint-plugin": "^4.28.2",
"@typescript-eslint/parser": "^4.28.2",
"@urbit/eslint-config": "^1.0.3",
"babel-eslint": "^10.1.0",
"eslint-plugin-react": "^7.24.0",
"rollup": "^2.59.0",
"rollup-plugin-analyzer": "^4.0.0",
"rollup-plugin-terser": "^7.0.2",
"rollup-plugin-typescript2": "^0.30.0",
"typescript": "^4.3.2"
}
}

View File

@ -1,76 +0,0 @@
import { nodeResolve } from '@rollup/plugin-node-resolve';
import commonJS from '@rollup/plugin-commonjs';
import { terser } from 'rollup-plugin-terser';
import babel from '@rollup/plugin-babel';
import typescript from 'rollup-plugin-typescript2';
import analyze from 'rollup-plugin-analyzer'
const input = ['./index.ts'];
// Skip certain warnings
function onwarn(warning) {
if (warning.code === 'THIS_IS_UNDEFINED') {
return;
}
console.warn(warning.message);
}
export default [
{
input,
onwarn,
plugins: [
nodeResolve({
extensions: ['.js', '.jsx', '.ts', '.tsx']
}),
commonJS(),
typescript(),
babel({
babelHelpers: 'bundled',
exclude: ['node_modules/**']
}),
terser({
ecma: 2017,
compress: true,
mangle: true
})
],
output: {
file: 'dist/urbit-api.min.js',
format: 'umd',
name: 'UrbitAPI', // this is the name of the global object
esModule: false,
exports: 'named',
sourcemap: true
}
},
{
input,
onwarn,
plugins: [
nodeResolve({
extensions: ['.js', '.jsx', '.ts', '.tsx']
}),
commonJS(),
typescript(),
analyze({
limit: 10
})
],
output: [
{
file: 'dist/esm/index.js',
format: 'esm',
exports: 'named',
sourcemap: true,
},
{
file: 'dist/cjs/index.cjs',
format: 'cjs',
exports: 'named',
sourcemap: true
}
]
}
];

View File

@ -1,2 +0,0 @@
export * from './lib';
export * from './types';

View File

@ -1,47 +0,0 @@
import { Poke } from '../lib/types';
import { S3Update, S3UpdateAccessKeyId, S3UpdateAddBucket, S3UpdateCurrentBucket, S3UpdateEndpoint, S3UpdateRemoveBucket, S3UpdateSecretAccessKey } from './types';
const s3Action = <T extends S3Update>(
data: any
): Poke<T> => ({
app: 's3-store',
mark: 's3-action',
json: data
});
export const setCurrentBucket = (
bucket: string
): Poke<S3UpdateCurrentBucket> => s3Action({
'set-current-bucket': bucket
});
export const addBucket = (
bucket: string
): Poke<S3UpdateAddBucket> => s3Action({
'add-bucket': bucket
});
export const removeBucket = (
bucket: string
): Poke<S3UpdateRemoveBucket> => s3Action({
'remove-bucket': bucket
});
export const setEndpoint = (
endpoint: string
): Poke<S3UpdateEndpoint> => s3Action({
'set-endpoint': endpoint
});
export const setAccessKeyId = (
accessKeyId: string
): Poke<S3UpdateAccessKeyId> => s3Action({
'set-access-key-id': accessKeyId
});
export const setSecretAccessKey = (
secretAccessKey: string
): Poke<S3UpdateSecretAccessKey> => s3Action({
'set-secret-access-key': secretAccessKey
});

View File

@ -1,60 +0,0 @@
export interface S3Credentials {
endpoint: string;
accessKeyId: string;
secretAccessKey: string;
}
export interface S3Configuration {
buckets: Set<string>;
currentBucket: string;
}
export interface S3State {
configuration: S3Configuration;
credentials: S3Credentials | null;
}
export interface S3UpdateCredentials {
credentials: S3Credentials;
}
export interface S3UpdateConfiguration {
configuration: {
buckets: string[];
currentBucket: string;
}
}
export interface S3UpdateCurrentBucket {
setCurrentBucket: string;
}
export interface S3UpdateAddBucket {
addBucket: string;
}
export interface S3UpdateRemoveBucket {
removeBucket: string;
}
export interface S3UpdateEndpoint {
setEndpoint: string;
}
export interface S3UpdateAccessKeyId {
setAccessKeyId: string;
}
export interface S3UpdateSecretAccessKey {
setSecretAccessKey: string;
}
export type S3Update =
S3UpdateCredentials
| S3UpdateConfiguration
| S3UpdateCurrentBucket
| S3UpdateAddBucket
| S3UpdateRemoveBucket
| S3UpdateEndpoint
| S3UpdateAccessKeyId
| S3UpdateSecretAccessKey;

View File

@ -1,2 +0,0 @@
export * from './types';
export * from './lib';

View File

@ -1,78 +0,0 @@
import { Poke, Scry } from '../lib';
import { PutBucket, Key, Bucket, DelBucket, Value, PutEntry, DelEntry, SettingsUpdate } from './types';
export const action = <T extends SettingsUpdate>(data: T): Poke<T> => ({
app: 'settings-store',
mark: 'settings-event',
json: data
});
export const putBucket = (
desk: string,
key: Key,
bucket: Bucket
): Poke<PutBucket> => action({
'put-bucket': {
desk,
'bucket-key': key,
'bucket': bucket
}
});
export const delBucket = (
desk: string,
key: Key
): Poke<DelBucket> => action({
'del-bucket': {
desk,
'bucket-key': key
}
});
export const putEntry = (
desk: string,
bucket: Key,
key: Key,
value: Value
): Poke<PutEntry> => action({
'put-entry': {
desk,
'bucket-key': bucket,
'entry-key': key,
value: value
}
});
export const delEntry = (
desk: string,
bucket: Key,
key: Key
): Poke<DelEntry> => action({
'del-entry': {
desk,
'bucket-key': bucket,
'entry-key': key
}
});
export const getAll: Scry = {
app: 'settings-store',
path: '/all'
};
export const getBucket = (desk: string, bucket: string) => ({
app: 'settings-store',
path: `/bucket/${bucket}`
});
export const getEntry = (desk: string, bucket: string, entry: string) => ({
app: 'settings-store',
path: `/entry/${desk}/${bucket}/${entry}`
});
export const getDeskSettings = (desk: string) => ({
app: 'settings-store',
path: `/desk/${desk}`
});
export * from './types';

View File

@ -1,64 +0,0 @@
export type Key = string;
export type Value = string | string[] | boolean | number;
export type Bucket = { [key: string]: Value; };
export type DeskSettings = { [bucket: string]: Bucket; };
export type Settings = { [desk: string]: Settings; }
export interface PutBucket {
'put-bucket': {
desk: string;
'bucket-key': Key;
'bucket': Bucket;
};
}
export interface DelBucket {
'del-bucket': {
desk: string;
'bucket-key': Key;
};
}
export interface PutEntry {
'put-entry': {
'bucket-key': Key;
'entry-key': Key;
'value'?: Value;
};
}
export interface DelEntry {
'del-entry': {
desk: string;
'bucket-key': Key;
'entry-key': Key;
};
}
export interface AllData {
'all': Settings;
}
export interface DeskData {
desk: DeskSettings;
}
export interface BucketData {
'bucket': Bucket;
}
export interface EntryData {
'entry': Value;
}
export type SettingsUpdate =
| PutBucket
| DelBucket
| PutEntry
| DelEntry;
export type SettingsData =
| AllData
| BucketData
| EntryData
| DeskData;

View File

@ -1,2 +0,0 @@
export * from './types';
export * from './lib';

View File

@ -1,20 +0,0 @@
import { Scry } from '../../http-api/src'
import { Poke } from '../../http-api/src/types';
import { Belt, Task, SessionTask } from './types';
export const pokeTask = (session: string, task: Task): Poke<SessionTask> => ({
app: 'herm',
mark: 'herm-task',
json: { session, ...task }
});
export const pokeBelt = (
session: string,
belt: Belt
): Poke<SessionTask> => pokeTask(session, { belt });
//NOTE scry will return string[]
export const scrySessions = (): Scry => ({
app: 'herm',
path: `/sessions`
});

View File

@ -1,61 +0,0 @@
// outputs
//
export type TermUpdate =
| Blit;
export type Tint =
| null
| 'r' | 'g' | 'b' | 'c' | 'm' | 'y' | 'k' | 'w'
| { r: number, g: number, b: number };
export type Deco = null | 'br' | 'un' | 'bl';
export type Stye = {
deco: Deco[],
back: Tint,
fore: Tint
};
export type Stub = {
stye: Stye,
text: string[]
}
export type Blit =
| { bel: null } // make a noise
| { clr: null } // clear the screen
| { hop: number | { x: number, y: number } } // set cursor col/pos
| { klr: Stub[] } // put styled
| { mor: Blit[] } // multiple blits
| { nel: null } // newline
| { put: string[] } // put text at cursor
| { sag: { path: string, file: string } } // save to jamfile
| { sav: { path: string, file: string } } // save to file
| { url: string } // activate url
| { wyp: null } // wipe cursor line
// inputs
//
export type Bolt =
| string
| { aro: 'd' | 'l' | 'r' | 'u' }
| { bac: null }
| { del: null }
| { hit: { x: number, y: number } }
| { ret: null }
export type Belt =
| Bolt
| { mod: { mod: 'ctl' | 'met' | 'hyp', key: Bolt } }
| { txt: Array<string> }
export type Task =
| { belt: Belt }
| { blew: { w: number, h: number } }
| { hail: null }
| { open: { term: string, apps: Array<{ who: string, app: string }> } }
| { shut: null }
export type SessionTask = { session: string } & Task

View File

@ -1,24 +0,0 @@
{
"compilerOptions": {
"baseUrl": ".",
"outDir": "./tmp",
"module": "ESNext",
"noImplicitAny": true,
"target": "ESNext",
"pretty": true,
"moduleResolution": "node",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"declaration": true,
"sourceMap": true,
"strict": false,
"noErrorTruncation": true
},
"exclude": [
"node_modules",
"./dist/**/*",
"./tmp/**/*",
"rollup.config.ts"
],
"include": ["./*.ts"]
}

View File

@ -1,204 +0,0 @@
const env = {
"browser": true,
"es6": true,
"node": true
};
const rules = {
"array-bracket-spacing": ["error", "never"],
"arrow-parens": [
"error",
"as-needed",
{
"requireForBlockBody": true
}
],
"arrow-spacing": "error",
"@typescript-eslint/ban-ts-comment": [2,
{
'ts-expect-error': 'allow-with-description',
'ts-ignore': 'allow-with-description',
'ts-nocheck': 'allow-with-description',
'ts-check': 'allow-with-description',
minimumDescriptionLength: 3,
}],
"@typescript-eslint/ban-types": "off",
"block-spacing": ["error", "always"],
"brace-style": ["error", "1tbs"],
"camelcase": [
"error",
{
"properties": "never"
}
],
"comma-dangle": ["error", "never"],
"eol-last": ["error", "always"],
"@typescript-eslint/explicit-module-boundary-types": "off",
"func-name-matching": "error",
"indent": [
"off",
2,
{
"ArrayExpression": "off",
"SwitchCase": 1,
"CallExpression": {
"arguments": "off"
},
"FunctionDeclaration": {
"parameters": "off"
},
"FunctionExpression": {
"parameters": "off"
},
"MemberExpression": "off",
"ObjectExpression": "off",
"ImportDeclaration": "off"
}
],
"handle-callback-err": "off",
"linebreak-style": ["error", "unix"],
"max-lines": [
"warn",
{
"max": 300,
"skipBlankLines": true,
"skipComments": true
}
],
"max-lines-per-function": [
"warn",
{
"skipBlankLines": true,
"skipComments": true
}
],
"max-statements-per-line": [
"error",
{
"max": 1
}
],
"new-cap": [
"error",
{
"newIsCap": true,
"capIsNew": false
}
],
"new-parens": "error",
"no-buffer-constructor": "error",
"no-console": "off",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-empty-function": "off",
"no-extra-semi": "off",
"no-fallthrough": "off",
"no-func-assign": "off",
"no-implicit-coercion": "error",
"no-multi-assign": "error",
"no-multiple-empty-lines": [
"error",
{
"max": 1
}
],
"no-nested-ternary": "warn",
"no-param-reassign": "off",
"no-return-assign": "error",
"no-return-await": "off",
"no-shadow-restricted-names": "error",
"no-tabs": "error",
"no-trailing-spaces": "error",
"no-unused-vars": "off",
"@typescript-eslint/no-unused-vars": [
"error",
{
"vars": "all",
"args": "none",
"ignoreRestSiblings": false
}
],
"no-use-before-define": "off",
"@typescript-eslint/no-use-before-define": [
"error",
{
"functions": false,
"classes": false
}
],
"no-useless-escape": "off",
"no-var": "error",
"nonblock-statement-body-position": ["error", "below"],
"object-curly-spacing": ["error", "always"],
"padded-blocks": ["error", "never"],
"prefer-arrow-callback": "error",
"prefer-const": [
"error",
{
"destructuring": "all",
"ignoreReadBeforeAssign": true
}
],
"prefer-template": "off",
"quotes": ["error", "single"],
"react/display-name": "off",
"semi": ["error", "always"],
"spaced-comment": [
"error",
"always",
{
"exceptions": ["!"]
}
],
"space-before-blocks": "error",
"unicode-bom": ["error", "never"],
"valid-jsdoc": "error",
"wrap-iife": ["error", "inside"],
"react/jsx-closing-bracket-location": 1,
"react/jsx-tag-spacing": 1,
"react/jsx-max-props-per-line": ["error", { "maximum": 2, "when": "multiline" }],
"react/prop-types": 0
};
module.exports = {
"env": env,
"extends": [
"plugin:react/recommended",
"eslint:recommended",
],
"settings": {
"react": {
"version": "^16.5.2"
}
},
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 10,
"requireConfigFile": false,
"sourceType": "module"
},
"root": true,
"rules": rules,
"overrides": [
{
"files": ["**/*.ts", "**/*.tsx"],
"env": env,
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaFeatures": { "jsx": true },
"ecmaVersion": 10,
"requireConfigFile": false,
"sourceType": "module"
},
"plugins": ["@typescript-eslint"],
"rules": {
...rules,
"valid-jsdoc": "off"
}
}
]
};

File diff suppressed because it is too large Load Diff

View File

@ -1,22 +0,0 @@
{
"name": "@urbit/eslint-config",
"version": "1.0.3",
"description": "",
"repository": {
"type": "git",
"url": "ssh://git@github.com/urbit/urbit.git",
"directory": "pkg/npm/eslint-config"
},
"main": "index.js",
"scripts": {},
"author": "",
"license": "MIT",
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^4.15.0",
"@typescript-eslint/parser": "^4.15.0",
"babel-eslint": "^10.1.0",
"eslint": "^7.26.0",
"eslint-plugin-react": "^7.22.0",
"typescript": "^4.1.5"
}
}

View File

@ -1,13 +0,0 @@
{
"presets": [
"@babel/preset-typescript", //needed for .ts jest tests
[
"@babel/preset-env",
{
"targets": "> 1%",
"useBuiltIns": "usage",
"corejs": "3.19.1"
}
]
]
}

View File

@ -1,4 +0,0 @@
dist
node_modules
coverage
tmp

View File

@ -1,21 +0,0 @@
# Urbit Connector
This project allows you to connect to an [Urbit](https://urbit.org) ship via a JavaScript application.
## Example
Check out the `example` directory for examples of how to use this code.
1. Open `example/index.html` in your browser and follow the instructions there, or
2. With a ship running in the same fashion as indicated in the file above, run `node example/index.js`
The code for either of these can be found in `src/example/browser.js` or `src/example/node.js`, depending on your context.
## Design
This library is designed to be useful for node applications that communicate with an urbit running either on the local computer or on a remote one.
The majority of its methods are asynchronous and return Promises. This is due to the non-blocking nature of JavaScript. If used in a React app, response handlers should be bound with `this` to `setState` after a message is received.
## NOTE
You must enable CORS requests on your urbit for this library to work in browser context. Use `+cors-registry` to see domains which have made requests to your urbit, and then approve the needed one, e.g. `|cors-approve http://zod.arvo.network`.

View File

@ -1,3 +0,0 @@
// import Urbit from '../../dist/browser';
// window.Urbit = Urbit;

View File

@ -1,122 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Demo</title>
<script src="../dist/urbit-http-api.min.js"></script>
<style>
@import url('https://rsms.me/inter/inter.css');
@font-face {
font-family: 'Source Code Pro';
src: url('https://storage.googleapis.com/media.urbit.org/fonts/scp-regular.woff');
font-weight: 400;
}
body {
margin: 0 auto;
max-width: 70ch;
padding: 2ch;
font-family: 'Inter', sans-serif;
}
#mylog {
white-space: pre-wrap;
padding: 2ch;
background: black;
color: white;
font-family: 'Source Code Pro', monospace;
}
#mylog div {
margin-bottom: 1rem;
}
.chunk {
border-bottom: 1px dashed currentColor;
}
</style>
</head>
<body>
<details>
<summary>Show instructions</summary>
<p>Assuming you are running a fakezod on port 8080, run</p>
<code id="instructions">|cors-approve '{window.location.origin}'</code>
<p>in its dojo.</p>
<p>
Press the button to run the code below. Output will be logged. You
should see <code>&lt; ~zod: opening airlock</code> in your dojo. Create
a chat and send a message to see the events logged.
</p>
<pre>
window.airlock = await UrbitHttpApi.Urbit.authenticate({
ship: 'zod',
url: 'localhost:8080',
code: 'lidlut-tabwed-pillex-ridrup',
verbose: true
});
window.airlock.subscribe({
app: 'graph-store',
path: '/updates',
event: console.log
});</pre
>
</details>
<button id="blastoff" onclick="blastOff()">Blast Off</button>
<pre id="mylog"></pre>
</body>
<script>
var baseLogFunction = console.log;
console.log = function () {
baseLogFunction.apply(console, arguments);
var chunk = document.createElement('div');
chunk.className = 'chunk';
var args = Array.prototype.slice.call(arguments);
for (var i = 0; i < args.length; i++) {
const val =
typeof args[i] === 'string' ? args[i] : JSON.stringify(args[i]);
var node = createLogNode(val);
chunk.appendChild(node);
}
document
.querySelector('#mylog')
.insertBefore(chunk, document.querySelector('#mylog').firstChild);
};
function createLogNode(message) {
var node = document.createElement('div');
node.className = 'message';
var textNode = document.createTextNode(message);
node.appendChild(textNode);
return node;
}
window.onerror = function (message, url, linenumber) {
console.log(
'JavaScript error: ' +
message +
' on line ' +
linenumber +
' for ' +
url
);
};
const instructions = document.getElementById('instructions');
instructions.innerText = instructions.innerText.replace(
'{window.location.origin}',
window.location.origin
);
async function blastOff() {
window.airlock = await UrbitHttpApi.Urbit.authenticate({
ship: 'zod',
url: 'localhost',
code: 'lidlut-tabwed-pillex-ridrup',
verbose: true,
});
window.airlock.subscribe({
app: 'graph-store',
path: '/updates',
event: console.log,
});
document.body.removeChild(document.getElementById('blastoff'));
}
</script>
</html>

View File

@ -1,14 +0,0 @@
// import Urbit from '../../dist/index';
// async function blastOff() {
// const airlock = await Urbit.authenticate({
// ship: 'zod',
// url: 'localhost:8080',
// code: 'lidlut-tabwed-pillex-ridrup',
// verbose: true
// });
// airlock.subscribe('chat-view', '/primary');
// }
// blastOff();

View File

@ -1,194 +0,0 @@
/*
* For a detailed explanation regarding each configuration property and type check, visit:
* https://jestjs.io/docs/configuration
*/
module.exports = {
// All imported modules in your tests should be mocked automatically
automock: false,
// Stop running tests after `n` failures
// bail: 0,
// The directory where Jest should store its cached dependency information
// cacheDirectory: "/private/var/folders/7w/hvrpvq7978bbb9kwkbhsn6rr0000gn/T/jest_dx",
// Automatically clear mock calls and instances between every test
clearMocks: true,
// Indicates whether the coverage information should be collected while executing the test
collectCoverage: true,
// An array of glob patterns indicating a set of files for which coverage information should be collected
// collectCoverageFrom: undefined,
// The directory where Jest should output its coverage files
coverageDirectory: 'coverage',
// An array of regexp pattern strings used to skip coverage collection
// coveragePathIgnorePatterns: [
// "/node_modules/"
// ],
// Indicates which provider should be used to instrument code for coverage
// coverageProvider: "babel",
// A list of reporter names that Jest uses when writing coverage reports
// coverageReporters: [
// "json",
// "text",
// "lcov",
// "clover"
// ],
// An object that configures minimum threshold enforcement for coverage results
// coverageThreshold: undefined,
// A path to a custom dependency extractor
// dependencyExtractor: undefined,
// Make calling deprecated APIs throw helpful error messages
// errorOnDeprecated: false,
// Force coverage collection from ignored files using an array of glob patterns
// forceCoverageMatch: [],
// A path to a module which exports an async function that is triggered once before all test suites
// globalSetup: undefined,
// A path to a module which exports an async function that is triggered once after all test suites
// globalTeardown: undefined,
// A set of global variables that need to be available in all test environments
// globals: {},
// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
maxWorkers: 1,
// An array of directory names to be searched recursively up from the requiring module's location
// moduleDirectories: [
// "node_modules"
// ],
// An array of file extensions your modules use
// moduleFileExtensions: [
// "js",
// "jsx",
// "ts",
// "tsx",
// "json",
// "node"
// ],
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
// moduleNameMapper: {},
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
// modulePathIgnorePatterns: [],
// Activates notifications for test results
// notify: false,
// An enum that specifies notification mode. Requires { notify: true }
// notifyMode: "failure-change",
// A preset that is used as a base for Jest's configuration
// preset: undefined,
// Run tests from one or more projects
// projects: undefined,
// Use this configuration option to add custom reporters to Jest
// reporters: undefined,
// Automatically reset mock state between every test
// resetMocks: false,
// Reset the module registry before running each individual test
// resetModules: false,
// A path to a custom resolver
// resolver: undefined,
// Automatically restore mock state between every test
// restoreMocks: false,
// The root directory that Jest should scan for tests and modules within
// rootDir: undefined,
// A list of paths to directories that Jest should use to search for files in
// roots: [
// "<rootDir>"
// ],
// Allows you to use a custom runner instead of Jest's default test runner
// runner: "jest-runner",
// The paths to modules that run some code to configure or set up the testing environment before each test
setupFiles: ['./setupEnv.js'],
// A list of paths to modules that run some code to configure or set up the testing framework before each test
// setupFilesAfterEnv: [],
// The number of seconds after which a test is considered as slow and reported as such in the results.
// slowTestThreshold: 5,
// A list of paths to snapshot serializer modules Jest should use for snapshot testing
// snapshotSerializers: [],
// The test environment that will be used for testing
testEnvironment: 'jsdom',
// Options that will be passed to the testEnvironment
// testEnvironmentOptions: {},
// Adds a location field to test results
// testLocationInResults: false,
// The glob patterns Jest uses to detect test files
// testMatch: [
// "**/__tests__/**/*.[jt]s?(x)",
// "**/?(*.)+(spec|test).[tj]s?(x)"
// ],
// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
// testPathIgnorePatterns: [
// "/node_modules/"
// ],
// The regexp pattern or array of patterns that Jest uses to detect test files
// testRegex: [],
// This option allows the use of a custom results processor
// testResultsProcessor: undefined,
// This option allows use of a custom test runner
// testRunner: "jest-circus/runner",
// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
testURL: 'http://localhost',
// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
// timers: "real",
// A map from regular expressions to paths to transformers
// transform: undefined,
// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
// transformIgnorePatterns: [
// "/node_modules/",
// "\\.pnp\\.[^\\/]+$"
// ],
// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
// unmockedModulePathPatterns: undefined,
// Indicates whether each individual test should be reported during the run
// verbose: undefined,
// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
// watchPathIgnorePatterns: [],
// Whether to use watchman for file crawling
// watchman: true,
};

Some files were not shown because too many files have changed in this diff Show More