UNPKG

@theweave/api

Version:

This package contains the interfaces and contracts that a Holochain app UI needs to implement in order to run as a Tool in a Weave Frame like [Moss](theweave.social#tryit).

471 lines (470 loc) 11.7 kB
import { ProfilesClient } from '@holochain-open-dev/profiles'; import { Readable } from '@holochain-open-dev/stores'; import { AppClient, ActionHash, EntryHash, DnaHash, EntryHashB64, ActionHashB64, DnaHashB64, CallZomeRequest, AppAuthenticationToken, AgentPubKeyB64, AgentPubKey, CreateCloneCellRequest, DisableCloneCellRequest, EnableCloneCellRequest } from '@holochain/client'; export type AppletHash = EntryHash; export type AppletId = EntryHashB64; /** * Hash of Holohash lenght but all zeroes */ export type NullHash = Uint8Array; export type Hrl = [DnaHash, ActionHash | EntryHash]; export type HrlB64 = [DnaHashB64, ActionHashB64 | EntryHashB64]; export type OpenAssetMode = 'front' | 'side' | 'window'; /** * String of the format weave-0.13:// */ export type WeaveUrl = string; export type WeaveLocation = { type: 'group'; dnaHash: DnaHash; } | { type: 'applet'; appletHash: AppletHash; } | { type: 'asset'; wal: WAL; } | { type: 'invitation'; secret: string; }; export type WAL = { hrl: Hrl; context?: any; }; export type AssetInfo = { name: string; icon_src: string; }; export type GroupProfile = { name: string; icon_src: string; meta_data?: string; }; export type FrameNotification = { /** * Title of the message. */ title: string; /** * content of the notification */ body: string; /** * type of notification, in a chat app e.g. "message" or "mention" */ notification_type: string; /** * Icon for the message type. */ icon_src: string | undefined; /** * urgency level "low" only shows up in Activity Feed(s) * urgency level "medium" shows up as a dot in the system tray icon * urgency level "high" additionally triggers an OS notification */ urgency: 'low' | 'medium' | 'high'; /** * Timestamp **in milliseconds** of when the event that the notification is about * has occured. * Ideally the timestamp of the DHT Action associated to the notification. * It may be displayed by Moss in notification feeds and will be used to determine * whether an event is "fresh" or has occurred while the user was offline. * In the latter case, Moss will not show an OS notification for * that notification on startup of Moss. */ timestamp: number; aboutWal?: WAL; fromAgent?: AgentPubKey; forAgents?: AgentPubKey[]; }; export type NotificationId = string; export type NotificationCount = { low: number; medium: number; high: number; }; export interface OpenViews { openAppletMain(appletHash: EntryHash): void; openAppletBlock(appletHash: EntryHash, block: string, context: any): void; openWal(wal: WAL): void; openCrossGroupMain(appletBundleId: string): void; openCrossGroupBlock(appletBundleId: string, block: string, context: any): void; } export type AssetLocationAndInfo = { appletHash: AppletHash; assetInfo: AssetInfo; /** * Only set if Moss is run in applet development mode and the applet is running in hot-reloading mode */ appletDevPort?: number; }; export type AppletInfo = { appletBundleId: string; appletName: string; appletIcon: string; groupsHashes: Array<DnaHash>; }; export type AppletClients = { appletClient: AppClient; profilesClient: ProfilesClient; }; export type AppletView = { type: 'main'; } | { type: 'block'; block: string; context: any; } | { type: 'asset'; /** * If the WAL points to a Record (AnyDhtHash) recordInfo will be defined, if the WAL * points to a DNA (i.e. null hash for the AnyDhtHash) then recordInfo is not defined */ recordInfo?: RecordInfo; wal: WAL; } | { type: 'creatable'; name: CreatableName; /** * To be called after the creatable has been successfully created. Will close the creatable view. * @param wal * @returns */ resolve: (wal: WAL) => Promise<void>; /** * To be called if creation fails due to an error * @param error * @returns */ reject: (error: any) => Promise<void>; /** * To be called if user cancels the creation */ cancel: () => Promise<void>; }; export type CrossGroupView = { type: 'main'; } | { type: 'block'; block: string; context: any; }; export type CreatableType = { /** * The label for the creatable that's displayed in Moss to open the creatable view */ label: string; icon_src: string; width?: 'small' | 'medium' | 'large'; height?: 'small' | 'medium' | 'large'; }; /** * The name that's being used in RenderInfo to tell which creatable should be rendered */ export type CreatableName = string; export type CreatableResult = { type: 'success'; wal: WAL; } | { type: 'cancel'; } | { type: 'error'; error: any; }; export type BlockType = { label: string; icon_src: string; view: 'applet-view' | 'cross-group-view'; }; export type BlockName = string; export type RenderInfo = { type: 'applet-view'; view: AppletView; appletClient: AppClient; profilesClient: ProfilesClient; peerStatusStore: ReadonlyPeerStatusStore; appletHash: AppletHash; /** * Non-exhaustive array of profiles of the groups the given applet is shared with. * Note that an applet may be shared with other groups beyond the ones returned * by this array if the applet has been federated with groups that the agent * of the given Moss instance is not part of. */ groupProfiles: GroupProfile[]; } | { type: 'cross-group-view'; view: CrossGroupView; applets: ReadonlyMap<EntryHash, AppletClients>; }; export type RenderView = { type: 'applet-view'; view: AppletView; } | { type: 'cross-group-view'; view: CrossGroupView; }; export type ParentToAppletMessage = { type: 'get-applet-asset-info'; wal: WAL; recordInfo?: RecordInfo; } | { type: 'get-block-types'; } | { type: 'search'; filter: string; } | { type: 'peer-status-update'; payload: PeerStatusUpdate; } | { type: 'on-before-unload'; } | { type: 'asset-store-update'; /** * We can save ourselves one unnecessary stringification step * by sending it as stringified */ walStringified: string; value: AsyncStatus<AssetStoreContent>; } | { type: 'remote-signal-received'; payload: Uint8Array; }; export type AppletToParentMessage = { request: AppletToParentRequest; appletHash?: AppletHash; }; export type AppletToParentRequest = { type: 'ready'; } | { type: 'get-iframe-config'; crossGroup: boolean; } | { type: 'get-record-info'; hrl: Hrl; } | { type: 'sign-zome-call'; request: CallZomeRequest; } | { type: 'open-view'; request: OpenViewRequest; } | { type: 'search'; filter: string; } | { type: 'notify-frame'; notifications: Array<FrameNotification>; } | { type: 'get-applet-info'; appletHash: AppletHash; } | { type: 'get-group-profile'; groupHash: DnaHash; } | { type: 'my-group-permission-type'; } | { type: 'applet-participants'; } | { type: 'user-select-screen'; } | { type: 'toggle-pocket'; } | { type: 'update-creatable-types'; value: Record<CreatableName, CreatableType>; } | { type: 'creatable-result'; result: CreatableResult; /** * The id of the dialog this result is coming from */ dialogId: string; } | { type: 'localStorage.setItem'; key: string; value: string; } | { type: 'localStorage.removeItem'; key: string; } | { type: 'localStorage.clear'; } | { type: 'get-localStorage'; } | { type: 'get-applet-iframe-script'; } | { type: 'request-close'; } | { type: 'send-remote-signal'; payload: Uint8Array; } | { type: 'create-clone-cell'; req: CreateCloneCellRequest; publicToGroupMembers: boolean; } | { type: 'disable-clone-cell'; req: DisableCloneCellRequest; } | { type: 'enable-clone-cell'; req: EnableCloneCellRequest; } /** * Asset related requests */ | { type: 'asset-to-pocket'; wal: WAL; } | { type: 'user-select-asset'; from?: 'search' | 'pocket' | 'create'; } | { type: 'user-select-asset-relation-tag'; } | { type: 'get-global-asset-info'; wal: WAL; } | { type: 'drag-asset'; wal: WAL; } | { type: 'add-tags-to-asset'; wal: WAL; tags: string[]; } | { type: 'remove-tags-from-asset'; wal: WAL; tags: string[]; } | { type: 'add-asset-relation'; srcWal: WAL; dstWal: WAL; tags?: string[]; } | { type: 'remove-asset-relation'; relationHash: EntryHash; } | { type: 'add-tags-to-asset-relation'; relationHash: EntryHash; tags: string[]; } | { type: 'remove-tags-from-asset-relation'; relationHash: EntryHash; tags: string[]; } | { type: 'get-all-asset-relation-tags'; crossGroup?: boolean; } | { type: 'subscribe-to-asset-store'; wal: WAL; } | { type: 'unsubscribe-from-asset-store'; wal: WAL; }; export type OpenViewRequest = { type: 'applet-main'; appletHash: EntryHash; } | { type: 'cross-group-main'; appletBundleId: string; } | { type: 'applet-block'; appletHash: EntryHash; block: string; context: any; } | { type: 'cross-group-block'; appletBundleId: string; block: string; context: any; } | { type: 'asset'; wal: WAL; mode?: OpenAssetMode; }; export type IframeConfig = { type: 'applet'; appPort: number; /** * The origin of the main Moss UI. Used to validate iframe message origins. */ mainUiOrigin: string; appletHash: EntryHash; authenticationToken: AppAuthenticationToken; weaveProtocolVersion: string; mossVersion: string; profilesLocation: ProfilesLocation; groupProfiles: GroupProfile[]; } | { type: 'cross-applet'; appPort: number; /** * The origin of the main Moss UI. Used to validate iframe message origins. */ mainUiOrigin: string; weaveProtocolVersion: string; mossVersion: string; applets: Record<EntryHashB64, [AppAuthenticationToken, ProfilesLocation]>; } | { type: 'not-installed'; appletName: string; }; export type ProfilesLocation = { authenticationToken: AppAuthenticationToken; profilesRoleName: string; }; export type RecordInfo = { roleName: string; integrityZomeName: string; entryType: string; }; /** * * Events * */ export type UnsubscribeFunction = () => void; export type PeerStatus = { lastSeen: number; status: string; /** * Timezone offset from UTC, in minutes */ tzUtcOffset?: number; }; export type PeerStatusUpdate = Record<AgentPubKeyB64, PeerStatus>; export type ReadonlyPeerStatusStore = Readable<Record<AgentPubKeyB64, PeerStatus>>; export type GroupPermissionType = { type: 'Steward'; /** * Expiry date in ms since Unix epoch time */ expiry?: number; } | { type: 'Member'; } | { /** * Can only occur if the applet belongs to more than one group */ type: 'Ambiguous'; }; export type WalRelationAndTags = { relationHash: EntryHash; /** * Timestamp of when the asset relation to this WAL has been created */ createdAt: number; wal: WAL; tags: string[]; }; export type AssetStoreContent = { linkedTo: WalRelationAndTags[]; linkedFrom: WalRelationAndTags[]; tags: string[]; }; export type AsyncStatus<T> = { status: 'pending'; } | { status: 'complete'; value: T; } | { status: 'error'; error: any; }; export type AssetStore = Readable<AsyncStatus<AssetStoreContent>>;