urbit/api: bring inline with current userspace

This commit is contained in:
Liam Fitzgerald 2021-02-17 12:23:49 +10:00
parent 9d8be26fea
commit ad035b54f1
No known key found for this signature in database
GPG Key ID: D390E12C61D1CFFB
14 changed files with 147 additions and 181 deletions

View File

@ -1,25 +1,14 @@
import { Path, Patp } from ".."; import { Path, Patp } from "..";
import {Resource} from "groups/update";
export type ContactUpdate = export type ContactUpdate =
| ContactUpdateCreate
| ContactUpdateDelete
| ContactUpdateAdd | ContactUpdateAdd
| ContactUpdateRemove | ContactUpdateRemove
| ContactUpdateEdit | ContactUpdateEdit
| ContactUpdateInitial | ContactUpdateInitial
| ContactUpdateContacts;
interface ContactUpdateCreate {
create: Path;
}
interface ContactUpdateDelete {
delete: Path;
}
interface ContactUpdateAdd { interface ContactUpdateAdd {
add: { add: {
path: Path;
ship: Patp; ship: Patp;
contact: Contact; contact: Contact;
}; };
@ -27,7 +16,6 @@ interface ContactUpdateAdd {
interface ContactUpdateRemove { interface ContactUpdateRemove {
remove: { remove: {
path: Path;
ship: Patp; ship: Patp;
}; };
} }
@ -36,50 +24,55 @@ interface ContactUpdateEdit {
edit: { edit: {
path: Path; path: Path;
ship: Patp; ship: Patp;
"edit-field": ContactEdit; "edit-field": ContactEditField;
timestamp: number;
}; };
} }
interface ContactUpdateAllowShips {
allow: {
ships: Patp[];
}
}
interface ContactUpdateAllowGroup {
allow: {
group: Path;
}
}
interface ContactUpdateSetPublic {
'set-public': boolean;
}
export interface ContactShare {
share: Patp;
}
interface ContactUpdateInitial { interface ContactUpdateInitial {
initial: Rolodex; initial: Rolodex;
} }
interface ContactUpdateContacts {
contacts: {
path: Path;
contacts: Contacts;
};
}
//
type ContactAvatar = ContactAvatarUrl | ContactAvatarOcts;
export type Rolodex = { export type Rolodex = {
[p in Path]: Contacts;
};
export type Contacts = {
[p in Patp]: Contact; [p in Patp]: Contact;
}; };
interface ContactAvatarUrl {
url: string;
}
interface ContactAvatarOcts {
octs: string;
}
export interface Contact { export interface Contact {
nickname: string; nickname: string;
email: string; bio: string;
phone: string; status: string;
website: string;
notes: string;
color: string; color: string;
avatar: string | null; avatar: string | null;
cover: string | null;
groups: Path[];
'last-updated': number;
} }
export type ContactEdit = { type ContactKeys = keyof Contact;
[k in keyof Contact]: Contact[k];
export type ContactEditFieldPrim = Exclude<ContactKeys, "groups" | "last-updated">;
export type ContactEditField = Partial<Pick<Contact, ContactEditFieldPrim>> & {
'add-group'?: Resource;
'remove-group'?: Resource;
}; };

View File

@ -1,83 +1,50 @@
import { Enc, Path, Patp, Poke } from ".."; import { Enc, Path, Patp, Poke } from "..";
import { Contact, ContactEdit, ContactUpdateCreate, ContactUpdateEdit, ContactUpdateRemove } from "./index.d"; import {
import { GroupPolicy, Resource } from "../groups/index.d" Contact,
ContactUpdateAdd,
ContactUpdateEdit,
ContactUpdateRemove,
ContactEditField,
ContactShare,
ContactUpdate,
} from "./index.d";
export const viewAction = <T>(data: T): Poke<T> => ({ export const storeAction = <T extends ContactUpdate>(data: T): Poke<T> => ({
app: 'contact-view', app: "contact-store",
mark: 'json', mark: "contact-action",
json: data json: data,
}); });
export const hookAction = <T>(data: T): Poke<T> => ({ export const add = (ship: Patp, contact: Contact): Poke<ContactUpdateAdd> => {
app: 'contact-hook', contact["last-updated"] = Date.now();
mark: 'contact-action',
json: data
});
export const create = ( return storeAction({
name: string, add: { ship, contact },
policy: Enc<GroupPolicy>, });
title: string, };
description: string
): Poke<ContactUpdateCreate> => viewAction({ // TODO which type is correct?
create: {
name,
policy,
title,
description
}
});
export const share = ( export const remove = (ship: Patp): Poke<ContactUpdateRemove> =>
recipient: Patp, storeAction({
path: Patp, remove: { ship },
ship: Patp, });
contact: Contact
): Poke<any> => viewAction({ // TODO type
share: {
recipient,
path,
ship,
contact
}
});
export const remove = ( export const share = (recipient: Patp): Poke<ContactShare> => ({
path: Path, app: "contact-push-hook",
ship: Patp mark: "contact-action",
): Poke<ContactUpdateRemove> => viewAction({ json: { share: recipient },
remove: {
path,
ship
}
}); });
export const edit = ( export const edit = (
path: Path, path: Path,
ship: Patp, ship: Patp,
editField: ContactEdit editField: ContactEditField
): Poke<ContactUpdateEdit> => hookAction({ ): Poke<ContactUpdateEdit> =>
edit: { storeAction({
path, edit: {
ship, path,
'edit-field': editField ship,
} "edit-field": editField,
}); timestamp: Date.now(),
},
});
export const invite = (
resource: Resource,
ship: Patp,
text: string = ''
): Poke<any> => viewAction({ // TODO type
invite: {
resource,
ship,
text
}
});
export const join = (
resource: Resource
): Poke<any> => viewAction({ // TODO type
join: resource
});

View File

@ -37,6 +37,15 @@ export interface Post {
"time-sent": number; "time-sent": number;
} }
export interface GraphNodePoke {
post: Post;
children: GraphChildrenPoke | null;
}
export interface GraphChildrenPoke {
[k: string]: GraphNodePoke;
}
export interface GraphNode { export interface GraphNode {
children: Graph; children: Graph;
post: Post; post: Post;

View File

@ -1,20 +1,20 @@
import _ from 'lodash'; import _ from 'lodash';
import { PatpNoSig, Patp, Poke, Thread, Path, Enc } from '..'; import { PatpNoSig, Patp, Poke, Thread, Path, Enc } from '..';
import { Content, GraphNode, Post } from './index.d'; import { Content, GraphNode, Post, GraphNodePoke, GraphChildrenPoke } from './index.d';
import { deSig, unixToDa } from '../lib/util'; import { deSig, unixToDa } from '../lib/util';
import { makeResource, resourceFromPath } from '../groups/index'; import { makeResource, resourceFromPath } from '../groups/index';
import { GroupPolicy } from '../groups'; import { GroupPolicy } from '../groups/update.d';
export const createBlankNodeWithChildPost = ( export const createBlankNodeWithChildPost = (
ship: PatpNoSig, ship: PatpNoSig,
parentIndex: string = '', parentIndex: string = '',
childIndex: string = '', childIndex: string = '',
contents: Content[] contents: Content[]
): GraphNode => { ): GraphNodePoke => {
const date = unixToDa(Date.now()).toString(); const date = unixToDa(Date.now()).toString();
const nodeIndex = parentIndex + '/' + date; const nodeIndex = parentIndex + '/' + date;
const childGraph = {}; const childGraph: GraphChildrenPoke = {};
childGraph[childIndex] = { childGraph[childIndex] = {
post: { post: {
author: `~${ship}`, author: `~${ship}`,
@ -253,7 +253,7 @@ export const addNode = (
let nodes = {}; let nodes = {};
nodes[node.post.index] = node; nodes[node.post.index] = node;
return this.addNodes(ship, name, nodes); return addNodes(ship, name, nodes);
} }
export const addNodes = ( export const addNodes = (

View File

@ -12,6 +12,7 @@ import {
Resource, Resource,
Tag Tag
} from "./index.d"; } from "./index.d";
import { GroupPolicy } from "./update";
export const proxyAction = <T>(data: T): Poke<T> => ({ export const proxyAction = <T>(data: T): Poke<T> => ({
app: 'group-push-hook', app: 'group-push-hook',
@ -106,6 +107,11 @@ export function makeResource(ship: string, name:string) {
return { ship, name }; return { ship, name };
} }
export const groupBunts = {
group: (): Group => ({ members: new Set(), tags: { role: {} }, hidden: false, policy: groupBunts.policy() }),
policy: (): GroupPolicy => ({ open: { banned: new Set(), banRanks: new Set() } })
};
export const joinError = ['no-perms', 'strange'] as const; export const joinError = ['no-perms', 'strange'] as const;
export const joinResult = ['done', ...joinError] as const; export const joinResult = ['done', ...joinError] as const;
export const joinProgress = ['start', 'added', ...joinResult] as const; export const joinProgress = ['start', 'added', ...joinResult] as const;

View File

@ -133,7 +133,7 @@ interface GroupUpdateRemoveTag {
removeTag: { removeTag: {
tag: Tag; tag: Tag;
resource: Resource; resource: Resource;
ships: PatpNoSig; ships: PatpNoSig[];
}; };
} }
@ -174,7 +174,4 @@ export type GroupUpdate =
export type GroupAction = Omit<GroupUpdate, 'initialGroup' | 'initial'>; export type GroupAction = Omit<GroupUpdate, 'initialGroup' | 'initial'>;
export const groupBunts = {
group: (): Group => ({ members: new Set(), tags: { role: {} }, hidden: false, policy: groupBunts.policy() }),
policy: (): GroupPolicy => ({ open: { banned: new Set(), banRanks: new Set() } })
};

View File

@ -1,6 +1,6 @@
import { Post } from "../graph/index.d"; import { Post } from "../graph/index.d";
import { GroupUpdate } from "../groups/index.d"; import { GroupUpdate } from "../groups/index.d";
import { BigIntOrderedMap } from "~/logic/lib/BigIntOrderedMap"; import BigIntOrderedMap from "../lib/BigIntOrderedMap";
export type GraphNotifDescription = "link" | "comment" | "note" | "mention"; export type GraphNotifDescription = "link" | "comment" | "note" | "mention";

View File

@ -1,14 +1,21 @@
import { Serial, PatpNoSig, Path } from '..'; import { Serial, PatpNoSig, Path } from '..';
import { Resource } from '../groups'; import { Resource } from "../groups/update.d";
export type InviteUpdate = export type InviteUpdate =
InviteUpdateInitial InviteUpdateInitial
| InviteUpdateCreate | InviteUpdateCreate
| InviteUpdateDelete | InviteUpdateDelete
| InviteUpdateInvite | InviteUpdateInvite
| InviteUpdateAccept
| InviteUpdateAccepted | InviteUpdateAccepted
| InviteUpdateDecline; | InviteUpdateDecline;
interface InviteUpdateAccept {
accept: {
term: string;
uid: Serial;
}
}
interface InviteUpdateInitial { interface InviteUpdateInitial {
initial: Invites; initial: Invites;
@ -16,19 +23,19 @@ interface InviteUpdateInitial {
interface InviteUpdateCreate { interface InviteUpdateCreate {
create: { create: {
path: Path; term: string;
}; };
} }
interface InviteUpdateDelete { interface InviteUpdateDelete {
delete: { delete: {
path: Path; term: string;
}; };
} }
interface InviteUpdateInvite { interface InviteUpdateInvite {
invite: { invite: {
path: Path; term: string;
uid: Serial; uid: Serial;
invite: Invite; invite: Invite;
}; };
@ -36,14 +43,14 @@ interface InviteUpdateInvite {
interface InviteUpdateAccepted { interface InviteUpdateAccepted {
accepted: { accepted: {
path: Path; term: string;
uid: Serial; uid: Serial;
}; };
} }
interface InviteUpdateDecline { interface InviteUpdateDecline {
decline: { decline: {
path: Path; term: string;
uid: Serial; uid: Serial;
}; };
} }

View File

@ -1,7 +1,7 @@
import { InviteAction, InviteActionAccept, InviteActionDecline } from "./index.d"; import { InviteUpdate, InviteUpdateAccept, InviteUpdateDecline } from "./index.d";
import { Poke, Serial } from ".."; import { Poke, Serial } from "..";
export const action = <T>(data: T): Poke<T> => ({ export const action = <T extends InviteUpdate>(data: T): Poke<T> => ({
app: 'invite-store', app: 'invite-store',
mark: 'invite-action', mark: 'invite-action',
json: data json: data
@ -10,7 +10,7 @@ export const action = <T>(data: T): Poke<T> => ({
export const accept = ( export const accept = (
app: string, app: string,
uid: Serial uid: Serial
): Poke<InviteActionAccept> => action({ ): Poke<InviteUpdateAccept> => action({
accept: { accept: {
term: app, term: app,
uid uid
@ -20,7 +20,7 @@ export const accept = (
export const decline = ( export const decline = (
app: string, app: string,
uid: Serial uid: Serial
): Poke<InviteActionDecline> => action({ ): Poke<InviteUpdateDecline> => action({
decline: { decline: {
term: app, term: app,
uid uid

View File

@ -2,6 +2,8 @@
* Martian embassy * Martian embassy
*/ */
import BigIntOrderedMap from "./BigIntOrderedMap";
// an urbit style path rendered as string // an urbit style path rendered as string
export type Path = string; export type Path = string;
@ -20,15 +22,6 @@ export type Jug<K,V> = Map<K,Set<V>>;
// name of app // name of app
export type AppName = 'chat' | 'link' | 'contacts' | 'publish' | 'graph'; export type AppName = 'chat' | 'link' | 'contacts' | 'publish' | 'graph';
export function getTagFromFrond<O>(frond: O): keyof O {
const tags = Object.keys(frond) as Array<keyof O>;
const tag = tags[0];
if(!tag) {
throw new Error("bad frond");
}
return tag;
}
export type ShipRank = 'czar' | 'king' | 'duke' | 'earl' | 'pawn'; export type ShipRank = 'czar' | 'king' | 'duke' | 'earl' | 'pawn';
export type Action = 'poke' | 'subscribe' | 'ack' | 'unsubscribe' | 'delete'; export type Action = 'poke' | 'subscribe' | 'ack' | 'unsubscribe' | 'delete';
@ -48,6 +41,8 @@ export type Enc<S> =
{ [s: string]: Enc<MapValue<S>> } : { [s: string]: Enc<MapValue<S>> } :
S extends object ? S extends object ?
{ [K in keyof S]: Enc<S[K]> } : { [K in keyof S]: Enc<S[K]> } :
S extends BigIntOrderedMap<infer T> ?
{ [index: string]: T } :
S; S;
export type Mark = string; export type Mark = string;

View File

@ -140,7 +140,7 @@ export function cite(ship: string): string {
let patp = ship, let patp = ship,
shortened = ""; shortened = "";
if (patp === null || patp === "") { if (patp === null || patp === "") {
return null; return "";
} }
if (patp.startsWith("~")) { if (patp.startsWith("~")) {
patp = patp.substr(1); patp = patp.substr(1);

View File

@ -15,15 +15,15 @@ type ResourceAssociations = {
} }
type MetadataUpdateAdd = { type MetadataUpdateAdd = {
add: Association; add: AssociationPoke;
} }
type MetadataUpdateUpdate = { type MetadataUpdateUpdate = {
update: Association; update: AssociationPoke;
} }
type MetadataUpdateRemove = { type MetadataUpdateRemove = {
remove: Resource & { remove: MdResource & {
group: Path; group: Path;
} }
} }
@ -42,16 +42,22 @@ export type AppAssociations = {
[p in Path]: Association; [p in Path]: Association;
} }
interface Resource { interface MdResource {
resource: Path; resource: Path;
'app-name': AppName; 'app-name': AppName;
} }
export type Association = Resource & { export type Association = MdResource & {
group: Path; group: Path;
metadata: Metadata; metadata: Metadata;
}; };
export interface AssociationPoke {
group: Path;
resource: MdResource;
metadata: Metadata;
}
export interface Metadata { export interface Metadata {
color: string; color: string;
creator: Patp; creator: Patp;

View File

@ -8,32 +8,19 @@ export const action = <T>(data: T): Poke<T> => ({
}); });
export const add = ( export const add = (
ship: PatpNoSig,
appName: AppName, appName: AppName,
appPath: Path, resource: string,
groupPath: Path, group: string,
title: string, metadata: Metadata,
description: string,
dateCreated: string,
color: string,
moduleName: string
): Poke<MetadataUpdateAdd> => { ): Poke<MetadataUpdateAdd> => {
const creator = `~${ship}`;
return action({ return action({
add: { add: {
'group-path': groupPath, group,
resource: { resource: {
'app-path': appPath, resource,
'app-name': appName 'app-name': appName
}, },
metadata: { metadata
title,
description,
color,
'date-created': dateCreated,
creator,
'module': moduleName
}
} }
}); });
} }
@ -41,15 +28,16 @@ export const add = (
export const update = ( export const update = (
association: Association, association: Association,
newMetadata: Partial<Metadata> newMetadata: Partial<Metadata>
): Poke<MetadataUpdateUpdate> => { ): Poke<MetadataUpdateAdd> => {
const { resource, metadata, group } = association;
return action({ return action({
add: { add: {
'group-path': association['group-path'], group,
resource: { resource: {
'app-path': association['app-path'], resource,
'app-name': association['app-name'], 'app-name': association['app-name'],
}, },
metadata: {...association.metadata, ...newMetadata } metadata: {...metadata, ...newMetadata }
} }
}); });
} }

View File

@ -19,9 +19,7 @@
} }
}, },
"include": [ "include": [
"src/**/*" "**/*"
], ],
"exclude": [ "exclude": [ "node_modules" ]
"node_modules",
]
} }