Merge pull request #163 from tloncorp/hm/renaming-prerelease

meta: renaming prerelease
This commit is contained in:
Hunter Miller 2023-05-08 15:01:03 -05:00 committed by GitHub
commit b0e36cecb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 778 additions and 188 deletions

225
desk/app/settings.hoon Normal file
View File

@ -0,0 +1,225 @@
/- *settings
/+ verb, dbug, default-agent, agentio
|%
+$ card card:agent:gall
+$ versioned-state
$% state-0
state-1
state-2
==
+$ state-0 [%0 settings=settings-0]
+$ state-1 [%1 settings=settings-1]
+$ state-2 [%2 =settings]
--
=| state-2
=* state -
::
%- agent:dbug
%+ verb |
^- agent:gall
=<
|_ =bowl:gall
+* this .
do ~(. +> bowl)
def ~(. (default-agent this %|) bowl)
io ~(. agentio bowl)
::
++ on-init
:: XX: deprecated; migration code
^- (quip card _this)
:_ this
:~ :* %pass
/migrate
%agent
[our dap]:bowl
%poke
noun+!>(%migrate)
== ==
::
++ on-save !>(state)
::
++ on-load
|= =old=vase
^- (quip card _this)
=/ old !<(versioned-state old-vase)
|-
?- -.old
%0 $(old [%1 +.old])
%1 $(old [%2 (~(put by *^settings) %landscape settings.old)])
%2 `this(state old)
==
::
++ on-poke
|= [mar=mark vas=vase]
^- (quip card _this)
?> (team:title our.bowl src.bowl)
=^ cards state
?+ mar (on-poke:def mar vas)
%settings-event
=/ evt=event !<(event vas)
?- -.evt
%put-bucket (put-bucket:do [desk key bucket]:evt)
%del-bucket (del-bucket:do [desk key]:evt)
%put-entry (put-entry:do [desk buc key val]:evt)
%del-entry (del-entry:do [desk buc key]:evt)
==
::
:: XX: deprecated; migration code
%noun
?> ?=(%migrate !<(%migrate vas))
=/ bas /(scot %p our.bowl)/settings-store/(scot %da now.bowl)
:- ~
?. .^(? %gu (weld bas /$))
state
=/ ful .^(data %gx (weld bas /all/noun))
?+ -.ful (on-poke:def mar vas)
%all state(settings +.ful)
==
==
[cards this]
::
++ on-watch
|= pax=path
^- (quip card _this)
?> (team:title our.bowl src.bowl)
?+ pax (on-watch:def pax)
[%all ~]
[~ this]
::
[%desk @ ~]
=* desk i.t.pax
[~ this]
::
[%bucket @ @ ~]
=* desk i.t.pax
=* bucket-key i.t.t.pax
?> (~(has bi settings) desk bucket-key)
[~ this]
::
[%entry @ @ @ ~]
=* desk i.t.pax
=* bucket-key i.t.t.pax
=* entry-key i.t.t.t.pax
=/ bucket (~(got bi settings) desk bucket-key)
?> (~(has by bucket) entry-key)
[~ this]
==
::
++ on-peek
|= pax=path
^- (unit (unit cage))
?+ pax (on-peek:def pax)
[%x %all ~]
``settings-data+!>(`data`all+settings)
::
[%x %desk @ ~]
=* desk i.t.t.pax
=/ desk-settings (~(gut by settings) desk ~)
``settings-data+!>(desk+desk-settings)
::
[%x %bucket @ @ ~]
=* desk i.t.t.pax
=* buc i.t.t.t.pax
=/ bucket=(unit bucket) (~(get bi settings) desk buc)
?~ bucket [~ ~]
``settings-data+!>(`data`bucket+u.bucket)
::
[%x %entry @ @ @ ~]
=* desk i.t.t.pax
=* buc i.t.t.t.pax
=* key i.t.t.t.t.pax
=/ =bucket (~(gut bi settings) desk buc *bucket)
=/ entry=(unit val) (~(get by bucket) key)
?~ entry [~ ~]
``settings-data+!>(`data`entry+u.entry)
::
[%x %has-bucket @ @ ~]
=/ desk i.t.t.pax
=/ buc i.t.t.t.pax
=/ has-bucket=? (~(has bi settings) desk buc)
``noun+!>(`?`has-bucket)
::
[%x %has-entry @ @ @ ~]
=* desk i.t.t.pax
=* buc i.t.t.t.pax
=* key i.t.t.t.t.pax
=/ =bucket (~(gut bi settings) desk buc *bucket)
=/ has-entry=? (~(has by bucket) key)
``noun+!>(`?`has-entry)
==
::
++ on-agent on-agent:def
++ on-leave on-leave:def
++ on-arvo on-arvo:def
++ on-fail on-fail:def
--
::
|_ bol=bowl:gall
::
:: +put-bucket: put a bucket in the top level settings map, overwriting if it
:: already exists
::
++ put-bucket
|= [=desk =key =bucket]
^- (quip card _state)
=/ pas=(list path)
:~ /all
/desk/[desk]
/bucket/[desk]/[key]
==
:- [(give-event pas %put-bucket desk key bucket)]~
state(settings (~(put bi settings) desk key bucket))
::
:: +del-bucket: delete a bucket from the top level settings map
::
++ del-bucket
|= [=desk =key]
^- (quip card _state)
=/ pas=(list path)
:~ /all
/desk/[desk]
/bucket/[key]
==
:- [(give-event pas %del-bucket desk key)]~
state(settings (~(del bi settings) desk key))
::
:: +put-entry: put an entry in a bucket, overwriting if it already exists
:: if bucket does not yet exist, create it
::
++ put-entry
|= [=desk buc=key =key =val]
^- (quip card _state)
=/ pas=(list path)
:~ /all
/desk/[desk]
/bucket/[desk]/[buc]
/entry/[desk]/[buc]/[key]
==
=/ =bucket (~(put by (~(gut bi settings) desk buc *bucket)) key val)
:- [(give-event pas %put-entry desk buc key val)]~
state(settings (~(put bi settings) desk buc bucket))
::
:: +del-entry: delete an entry from a bucket, fail quietly if bucket does not
:: exist
::
++ del-entry
|= [=desk buc=key =key]
^- (quip card _state)
=/ pas=(list path)
:~ /all
/desk/[desk]
/bucket/[desk]/[buc]
/entry/[desk]/[buc]/[key]
==
=/ bucket=(unit bucket) (~(get bi settings) desk buc)
?~ bucket
[~ state]
=. u.bucket (~(del by u.bucket) key)
:- [(give-event pas %del-entry desk buc key)]~
state(settings (~(put bi settings) desk buc u.bucket))
::
++ give-event
|= [pas=(list path) evt=event]
^- card
[%give %fact pas %settings-event !>(evt)]
--

168
desk/app/storage.hoon Normal file
View File

@ -0,0 +1,168 @@
:: storage:
::
:: stores s3 keys for uploading and sharing images and objects
::
/- *storage
/+ storage-json, default-agent, verb, dbug
~% %s3-top ..part ~
|%
+$ card card:agent:gall
+$ versioned-state
$% state-zero
state-one
==
::
+$ state-zero [%0 =credentials:zero:past =configuration:zero:past]
+$ state-one [%1 =credentials =configuration]
--
::
=| state-one
=* state -
::
%- agent:dbug
%+ verb |
^- agent:gall
~% %s3-agent-core ..card ~
|_ =bowl:gall
+* this .
def ~(. (default-agent this %|) bowl)
::
++ on-init
:: XX: deprecated; migration code
^- (quip card _this)
:_ this
:~ :* %pass
/migrate
%agent
[our dap]:bowl
%poke
noun+!>(%migrate)
== ==
++ on-save !>(state)
++ on-load
|= =vase
=/ old !<(versioned-state vase)
|^
?- -.old
%1 `this(state old)
%0 `this(state (state-0-to-1 old))
==
++ state-0-to-1
|= zer=state-zero
^- state-one
:* %1
credentials.zer
(configuration-0-to-1 configuration.zer)
==
++ configuration-0-to-1
|= conf=configuration:zero:past
^- ^configuration
:* buckets.conf
current-bucket.conf
''
==
--
::
++ on-poke
~/ %s3-poke
|= [=mark =vase]
^- (quip card _this)
|^
?> (team:title our.bowl src.bowl)
=^ cards state
?+ mark (on-poke:def mark vase)
%storage-action
(poke-action !<(action vase))
::
:: XX: deprecated; migration code
%noun
?> ?=(%migrate !<(%migrate vase))
=/ bas /(scot %p our.bowl)/s3-store/(scot %da now.bowl)
:- ~
?. .^(? %gu (weld bas /$))
state
=:
credentials
=/ ful .^(update %gx (weld bas /credentials/noun))
?+ -.ful (on-poke:def mark vase)
%credentials +.ful
==
::
configuration
=/ ful .^(update %gx (weld bas /configuration/noun))
?+ -.ful (on-poke:def mark vase)
%configuration +.ful
== ==
state
==
[cards this]
::
++ poke-action
|= act=action
^- (quip card _state)
:- [%give %fact [/all]~ %storage-update !>(act)]~
?- -.act
%set-endpoint
state(endpoint.credentials endpoint.act)
::
%set-access-key-id
state(access-key-id.credentials access-key-id.act)
::
%set-secret-access-key
state(secret-access-key.credentials secret-access-key.act)
::
%set-region
state(region.configuration region.act)
::
%set-current-bucket
%_ state
current-bucket.configuration bucket.act
buckets.configuration (~(put in buckets.configuration) bucket.act)
==
::
%add-bucket
state(buckets.configuration (~(put in buckets.configuration) bucket.act))
::
%remove-bucket
state(buckets.configuration (~(del in buckets.configuration) bucket.act))
==
--
::
++ on-watch
~/ %s3-watch
|= =path
^- (quip card _this)
|^
?> (team:title our.bowl src.bowl)
=/ cards=(list card)
?+ path (on-watch:def path)
[%all ~]
:~ (give %storage-update !>([%credentials credentials]))
(give %storage-update !>([%configuration configuration]))
==
==
[cards this]
::
++ give
|= =cage
^- card
[%give %fact ~ cage]
--
::
++ on-leave on-leave:def
++ on-peek
~/ %s3-peek
|= =path
^- (unit (unit cage))
?. (team:title our.bowl src.bowl) ~
?+ path [~ ~]
[%x %credentials ~]
[~ ~ %storage-update !>(`update`[%credentials credentials])]
::
[%x %configuration ~]
[~ ~ %storage-update !>(`update`[%configuration configuration])]
==
++ on-agent on-agent:def
++ on-arvo on-arvo:def
++ on-fail on-fail:def
--

View File

@ -2,7 +2,9 @@
%treaty
%hark-store
%hark-system-hook
%settings
%settings-store
%storage
%reel
%bait
==

View File

@ -0,0 +1,53 @@
/- *storage
|%
++ json-to-action
|= =json
^- action
=, format
|^ (parse-json json)
++ parse-json
%- of:dejs
:~ [%set-endpoint so:dejs]
[%set-access-key-id so:dejs]
[%set-secret-access-key so:dejs]
[%set-region so:dejs]
[%add-bucket so:dejs]
[%remove-bucket so:dejs]
[%set-current-bucket so:dejs]
==
--
::
++ update-to-json
|= upd=update
^- json
=, format
%+ frond:enjs %s3-update
%- pairs:enjs
:~ ?- -.upd
%set-current-bucket [%'setCurrentBucket' s+bucket.upd]
%add-bucket [%'addBucket' s+bucket.upd]
%set-region [%'setRegion' s+region.upd]
%remove-bucket [%'removeBucket' s+bucket.upd]
%set-endpoint [%'setEndpoint' s+endpoint.upd]
%set-access-key-id [%'setAccessKeyId' s+access-key-id.upd]
%set-secret-access-key
[%'setSecretAccessKey' s+secret-access-key.upd]
::
%credentials
:- %credentials
%- pairs:enjs
:~ [%endpoint s+endpoint.credentials.upd]
[%'accessKeyId' s+access-key-id.credentials.upd]
[%'secretAccessKey' s+secret-access-key.credentials.upd]
==
::
%configuration
:- %configuration
%- pairs:enjs
:~ [%buckets a+(turn ~(tap in buckets.configuration.upd) |=(a=@t s+a))]
[%'currentBucket' s+current-bucket.configuration.upd]
[%'region' s+region.configuration.upd]
==
==
==
--

View File

@ -0,0 +1,13 @@
/+ *storage-json
|_ act=action
++ grad %noun
++ grow
|%
++ noun act
--
++ grab
|%
++ noun action
++ json json-to-action
--
--

View File

@ -0,0 +1,14 @@
/+ *storage-json
|_ upd=update
++ grad %noun
++ grow
|%
++ noun upd
++ json (update-to-json upd)
--
::
++ grab
|%
++ noun update
--
--

27
desk/sur/storage-0.hoon Normal file
View File

@ -0,0 +1,27 @@
|%
+$ credentials
$: endpoint=@t
access-key-id=@t
secret-access-key=@t
==
::
+$ configuration
$: buckets=(set @t)
current-bucket=@t
==
::
+$ action
$% [%set-endpoint endpoint=@t]
[%set-access-key-id access-key-id=@t]
[%set-secret-access-key secret-access-key=@t]
[%add-bucket bucket=@t]
[%remove-bucket bucket=@t]
[%set-current-bucket bucket=@t]
==
::
+$ update
$% [%credentials =credentials]
[%configuration =configuration]
action
==
--

34
desk/sur/storage.hoon Normal file
View File

@ -0,0 +1,34 @@
/- zer=storage-0
|%
++ past
|%
++ zero zer
--
+$ credentials
$: endpoint=@t
access-key-id=@t
secret-access-key=@t
==
::
+$ configuration
$: buckets=(set @t)
current-bucket=@t
region=@t
==
::
+$ action
$% [%set-endpoint endpoint=@t]
[%set-access-key-id access-key-id=@t]
[%set-secret-access-key secret-access-key=@t]
[%add-bucket bucket=@t]
[%remove-bucket bucket=@t]
[%set-current-bucket bucket=@t]
[%set-region region=@t]
==
::
+$ update
$% [%credentials =credentials]
[%configuration =configuration]
action
==
--

View File

@ -2,6 +2,9 @@
"name": "landscape",
"version": "0.0.0",
"private": true,
"engines": {
"node": "^16.0.0"
},
"scripts": {
"dev": "vite",
"mock": "vite --mode mock",

View File

@ -2,21 +2,22 @@
/* tslint:disable */
/**
* Mock Service Worker (1.2.1).
* Mock Service Worker (0.39.2).
* @see https://github.com/mswjs/msw
* - Please do NOT modify this file.
* - Please do NOT serve this file on production.
*/
const INTEGRITY_CHECKSUM = '3d6b9f06410d179a7f7404d4bf4c3c70'
const INTEGRITY_CHECKSUM = '02f4ad4a2797f85668baf196e553d929'
const bypassHeaderName = 'x-msw-bypass'
const activeClientIds = new Set()
self.addEventListener('install', function () {
self.skipWaiting()
return self.skipWaiting()
})
self.addEventListener('activate', function (event) {
event.waitUntil(self.clients.claim())
self.addEventListener('activate', async function (event) {
return self.clients.claim()
})
self.addEventListener('message', async function (event) {
@ -32,9 +33,7 @@ self.addEventListener('message', async function (event) {
return
}
const allClients = await self.clients.matchAll({
type: 'window',
})
const allClients = await self.clients.matchAll()
switch (event.data) {
case 'KEEPALIVE_REQUEST': {
@ -84,6 +83,161 @@ self.addEventListener('message', async function (event) {
}
})
// Resolve the "main" client for the given event.
// Client that issues a request doesn't necessarily equal the client
// that registered the worker. It's with the latter the worker should
// communicate with during the response resolving phase.
async function resolveMainClient(event) {
const client = await self.clients.get(event.clientId)
if (client.frameType === 'top-level') {
return client
}
const allClients = await self.clients.matchAll()
return allClients
.filter((client) => {
// Get only those clients that are currently visible.
return client.visibilityState === 'visible'
})
.find((client) => {
// Find the client ID that's recorded in the
// set of clients that have registered the worker.
return activeClientIds.has(client.id)
})
}
async function handleRequest(event, requestId) {
const client = await resolveMainClient(event)
const response = await getResponse(event, client, requestId)
// Send back the response clone for the "response:*" life-cycle events.
// Ensure MSW is active and ready to handle the message, otherwise
// this message will pend indefinitely.
if (client && activeClientIds.has(client.id)) {
;(async function () {
const clonedResponse = response.clone()
sendToClient(client, {
type: 'RESPONSE',
payload: {
requestId,
type: clonedResponse.type,
ok: clonedResponse.ok,
status: clonedResponse.status,
statusText: clonedResponse.statusText,
body:
clonedResponse.body === null ? null : await clonedResponse.text(),
headers: serializeHeaders(clonedResponse.headers),
redirected: clonedResponse.redirected,
},
})
})()
}
return response
}
async function getResponse(event, client, requestId) {
const { request } = event
const requestClone = request.clone()
const getOriginalResponse = () => fetch(requestClone)
// Bypass mocking when the request client is not active.
if (!client) {
return getOriginalResponse()
}
// Bypass initial page load requests (i.e. static assets).
// The absence of the immediate/parent client in the map of the active clients
// means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
// and is not ready to handle requests.
if (!activeClientIds.has(client.id)) {
return await getOriginalResponse()
}
// Bypass requests with the explicit bypass header
if (requestClone.headers.get(bypassHeaderName) === 'true') {
const cleanRequestHeaders = serializeHeaders(requestClone.headers)
// Remove the bypass header to comply with the CORS preflight check.
delete cleanRequestHeaders[bypassHeaderName]
const originalRequest = new Request(requestClone, {
headers: new Headers(cleanRequestHeaders),
})
return fetch(originalRequest)
}
// Send the request to the client-side MSW.
const reqHeaders = serializeHeaders(request.headers)
const body = await request.text()
const clientMessage = await sendToClient(client, {
type: 'REQUEST',
payload: {
id: requestId,
url: request.url,
method: request.method,
headers: reqHeaders,
cache: request.cache,
mode: request.mode,
credentials: request.credentials,
destination: request.destination,
integrity: request.integrity,
redirect: request.redirect,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
body,
bodyUsed: request.bodyUsed,
keepalive: request.keepalive,
},
})
switch (clientMessage.type) {
case 'MOCK_SUCCESS': {
return delayPromise(
() => respondWithMock(clientMessage),
clientMessage.payload.delay,
)
}
case 'MOCK_NOT_FOUND': {
return getOriginalResponse()
}
case 'NETWORK_ERROR': {
const { name, message } = clientMessage.payload
const networkError = new Error(message)
networkError.name = name
// Rejecting a request Promise emulates a network error.
throw networkError
}
case 'INTERNAL_ERROR': {
const parsedBody = JSON.parse(clientMessage.payload.body)
console.error(
`\
[MSW] Uncaught exception in the request handler for "%s %s":
${parsedBody.location}
This exception has been gracefully handled as a 500 response, however, it's strongly recommended to resolve this error, as it indicates a mistake in your code. If you wish to mock an error response, please see this guide: https://mswjs.io/docs/recipes/mocking-error-responses\
`,
request.method,
request.url,
)
return respondWithMock(clientMessage)
}
}
return getOriginalResponse()
}
self.addEventListener('fetch', function (event) {
const { request } = event
const accept = request.headers.get('accept') || ''
@ -111,10 +265,9 @@ self.addEventListener('fetch', function (event) {
return
}
// Generate unique request ID.
const requestId = Math.random().toString(16).slice(2)
const requestId = uuidv4()
event.respondWith(
return event.respondWith(
handleRequest(event, requestId).catch((error) => {
if (error.name === 'NetworkError') {
console.warn(
@ -137,142 +290,14 @@ self.addEventListener('fetch', function (event) {
)
})
async function handleRequest(event, requestId) {
const client = await resolveMainClient(event)
const response = await getResponse(event, client, requestId)
// Send back the response clone for the "response:*" life-cycle events.
// Ensure MSW is active and ready to handle the message, otherwise
// this message will pend indefinitely.
if (client && activeClientIds.has(client.id)) {
;(async function () {
const clonedResponse = response.clone()
sendToClient(client, {
type: 'RESPONSE',
payload: {
requestId,
type: clonedResponse.type,
ok: clonedResponse.ok,
status: clonedResponse.status,
statusText: clonedResponse.statusText,
body:
clonedResponse.body === null ? null : await clonedResponse.text(),
headers: Object.fromEntries(clonedResponse.headers.entries()),
redirected: clonedResponse.redirected,
},
})
})()
}
return response
}
// Resolve the main client for the given event.
// Client that issues a request doesn't necessarily equal the client
// that registered the worker. It's with the latter the worker should
// communicate with during the response resolving phase.
async function resolveMainClient(event) {
const client = await self.clients.get(event.clientId)
if (client?.frameType === 'top-level') {
return client
}
const allClients = await self.clients.matchAll({
type: 'window',
function serializeHeaders(headers) {
const reqHeaders = {}
headers.forEach((value, name) => {
reqHeaders[name] = reqHeaders[name]
? [].concat(reqHeaders[name]).concat(value)
: value
})
return allClients
.filter((client) => {
// Get only those clients that are currently visible.
return client.visibilityState === 'visible'
})
.find((client) => {
// Find the client ID that's recorded in the
// set of clients that have registered the worker.
return activeClientIds.has(client.id)
})
}
async function getResponse(event, client, requestId) {
const { request } = event
const clonedRequest = request.clone()
function passthrough() {
// Clone the request because it might've been already used
// (i.e. its body has been read and sent to the client).
const headers = Object.fromEntries(clonedRequest.headers.entries())
// Remove MSW-specific request headers so the bypassed requests
// comply with the server's CORS preflight check.
// Operate with the headers as an object because request "Headers"
// are immutable.
delete headers['x-msw-bypass']
return fetch(clonedRequest, { headers })
}
// Bypass mocking when the client is not active.
if (!client) {
return passthrough()
}
// Bypass initial page load requests (i.e. static assets).
// The absence of the immediate/parent client in the map of the active clients
// means that MSW hasn't dispatched the "MOCK_ACTIVATE" event yet
// and is not ready to handle requests.
if (!activeClientIds.has(client.id)) {
return passthrough()
}
// Bypass requests with the explicit bypass header.
// Such requests can be issued by "ctx.fetch()".
if (request.headers.get('x-msw-bypass') === 'true') {
return passthrough()
}
// Notify the client that a request has been intercepted.
const clientMessage = await sendToClient(client, {
type: 'REQUEST',
payload: {
id: requestId,
url: request.url,
method: request.method,
headers: Object.fromEntries(request.headers.entries()),
cache: request.cache,
mode: request.mode,
credentials: request.credentials,
destination: request.destination,
integrity: request.integrity,
redirect: request.redirect,
referrer: request.referrer,
referrerPolicy: request.referrerPolicy,
body: await request.text(),
bodyUsed: request.bodyUsed,
keepalive: request.keepalive,
},
})
switch (clientMessage.type) {
case 'MOCK_RESPONSE': {
return respondWithMock(clientMessage.data)
}
case 'MOCK_NOT_FOUND': {
return passthrough()
}
case 'NETWORK_ERROR': {
const { name, message } = clientMessage.data
const networkError = new Error(message)
networkError.name = name
// Rejecting a "respondWith" promise emulates a network error.
throw networkError
}
}
return passthrough()
return reqHeaders
}
function sendToClient(client, message) {
@ -287,17 +312,27 @@ function sendToClient(client, message) {
resolve(event.data)
}
client.postMessage(message, [channel.port2])
client.postMessage(JSON.stringify(message), [channel.port2])
})
}
function sleep(timeMs) {
function delayPromise(cb, duration) {
return new Promise((resolve) => {
setTimeout(resolve, timeMs)
setTimeout(() => resolve(cb()), duration)
})
}
async function respondWithMock(response) {
await sleep(response.delay)
return new Response(response.body, response)
function respondWithMock(clientMessage) {
return new Response(clientMessage.payload.body, {
...clientMessage.payload,
headers: clientMessage.payload.headers,
})
}
function uuidv4() {
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
const r = (Math.random() * 16) | 0
const v = c == 'x' ? r : (r & 0x3) | 0x8
return v.toString(16)
})
}

View File

@ -1,11 +1,5 @@
import React, { useCallback, useState, FormEvent, useEffect } from 'react';
import api from '../state/api';
import {
setAccessKeyId,
setCurrentBucket,
setEndpoint,
setSecretAccessKey,
} from '@urbit/api';
import { useForm } from 'react-hook-form';
import cn from 'classnames';
import { useAsyncCall } from '../logic/useAsyncCall';
@ -21,6 +15,23 @@ interface CredentialsSubmit {
bucket: string;
}
type S3Update =
| { 'set-region': string }
| { 'set-endpoint': string }
| { 'set-access-key-id': string }
| { 'set-secret-access-key': string }
| { 'set-current-bucket': string }
| { 'add-bucket': string }
| { 'remove-bucket': string };
function storagePoke(data: S3Update | { 'set-region': string }) {
return {
app: 'storage',
mark: 'storage-action',
json: data,
};
}
export const StoragePrefs = () => {
const { s3, loaded, ...storageState } = useStorageState();
@ -35,15 +46,11 @@ export const StoragePrefs = () => {
const { call: addS3Credentials, status } = useAsyncCall(
useCallback(async (data: CredentialsSubmit) => {
api.poke(setEndpoint(data.endpoint));
api.poke(setAccessKeyId(data.accessId));
api.poke(setSecretAccessKey(data.accessSecret));
api.poke(setCurrentBucket(data.bucket));
api.poke({
app: 's3-store',
mark: 's3-action',
json: { 'set-region': data.region },
});
api.poke(storagePoke({ 'set-endpoint': data.endpoint }));
api.poke(storagePoke({ 'set-access-key-id': data.accessId }));
api.poke(storagePoke({ 'set-secret-access-key': data.accessSecret }));
api.poke(storagePoke({ 'set-current-bucket': data.bucket }));
api.poke(storagePoke({ 'set-region': data.region }));
}, [])
);

View File

@ -1,11 +1,5 @@
/* eslint-disable no-param-reassign */
import {
SettingsUpdate,
Value,
putEntry as doPutEntry,
getDeskSettings,
DeskData,
} from '@urbit/api';
import { SettingsUpdate, Value, DeskData } from '@urbit/api';
import _ from 'lodash';
import {
BaseState,
@ -109,12 +103,27 @@ export const useSettingsState = createState<BaseSettingsState>(
},
loaded: false,
putEntry: async (bucket, key, val) => {
const poke = doPutEntry(window.desk, bucket, key, val);
const poke = {
app: 'settings',
mark: 'settings-update',
json: {
'put-entry': {
desk: window.desk,
'bucket-key': bucket,
'entry-key': key,
value: val,
},
},
};
await pokeOptimisticallyN(useSettingsState, poke, reduceUpdate);
},
fetchAll: async () => {
const result = (await api.scry<DeskData>(getDeskSettings(window.desk)))
.desk;
const result = (
await api.scry<DeskData>({
app: 'settings',
path: `/desk/${window.desk}`,
})
).desk;
const newState = {
..._.mergeWith(get(), result, (obj, src) =>
_.isArray(src) ? src : undefined
@ -127,7 +136,7 @@ export const useSettingsState = createState<BaseSettingsState>(
[],
[
(set, get) =>
createSubscription('settings-store', `/desk/${window.desk}`, (e) => {
createSubscription('settings', `/desk/${window.desk}`, (e) => {
const data = _.get(e, 'settings-event', false);
if (data) {
reduceStateN(get(), data, reduceUpdate);

View File

@ -35,7 +35,7 @@ export interface BaseStorageState {
[ref: string]: unknown;
}
export type StorageState = BaseStorageState & BaseState<BaseStorageState>
export type StorageState = BaseStorageState & BaseState<BaseStorageState>;
export const useStorageState = createState<BaseStorageState>(
'Storage',
@ -48,7 +48,7 @@ export const useStorageState = createState<BaseStorageState>(
inputMark: 'noun',
outputMark: 'json',
threadName: 'gcp-is-configured',
body: {}
body: {},
});
},
getToken: async () => {
@ -56,33 +56,33 @@ export const useStorageState = createState<BaseStorageState>(
inputMark: 'noun',
outputMark: 'gcp-token',
threadName: 'gcp-get-token',
body: {}
body: {},
});
get().set((state) => {
state.gcp.token = token;
});
}
},
},
s3: {
configuration: {
buckets: new Set(),
currentBucket: '',
region: 'global'
region: 'global',
},
credentials: null
}
credentials: null,
},
}),
['loaded', 's3', 'gcp'],
[
(set, get) =>
createSubscription('s3-store', '/all', (e) => {
createSubscription('storage', '/all', (e) => {
const d = _.get(e, 's3-update', false);
if (d) {
console.log(d)
console.log(d);
reduceStateN(get(), d, reduce);
set({ loaded: true });
}
})
}),
]
);