Commit 3a234c83 authored by Robert Knight's avatar Robert Knight

Convert API types to TypeScript syntax

This is a purely syntactic change. There are no changes to the types or
documentation, except for the removal of an unused `groups` property on the
`Profile` type.
parent 84b7672a
......@@ -7,194 +7,203 @@
/**
* Metadata specifying how to call an API route.
*
* @typedef RouteMetadata
* @prop {string} method - HTTP method
* @prop {string} url - URL template
* @prop {string} desc - Description of API route
*/
export type RouteMetadata = {
/** HTTP method */
method: string;
/** URL template */
url: string;
/** Description of API route */
desc: string;
};
/**
* A nested map of API route name to route metadata.
*
* @typedef {{ [key: string]: RouteMap|RouteMetadata }} RouteMap
*/
/** A nested map of API route name to route metadata. */
export type RouteMap = { [key: string]: RouteMap | RouteMetadata };
/**
* Structure of the API index response (`/api`).
*
* @typedef IndexResponse
* @prop {RouteMap} links
*/
export type IndexResponse = {
links: RouteMap;
};
/**
* Structure of the Hypothesis links response (`/api/links`).
*
* This is a map of link name (eg. "account.settings") to URL. The URL may
* include ":"-prefixed placeholders/variables.
*
* @typedef {Record<string, string>} LinksResponse
*/
export type LinksResponse = Record<string, string>;
/**
* Selector which identifies a document region using the selected text plus
* the surrounding context.
*
* @typedef TextQuoteSelector
* @prop {'TextQuoteSelector'} type
* @prop {string} exact
* @prop {string} [prefix]
* @prop {string} [suffix]
*/
export type TextQuoteSelector = {
type: 'TextQuoteSelector';
exact: string;
prefix?: string;
suffix?: string;
};
/**
* Selector which identifies a document region using UTF-16 character offsets
* in the document body's `textContent`.
*
* @typedef TextPositionSelector
* @prop {'TextPositionSelector'} type
* @prop {number} start
* @prop {number} end
*/
export type TextPositionSelector = {
type: 'TextPositionSelector';
start: number;
end: number;
};
/**
* Selector which identifies a document region using XPaths and character offsets.
*
* @typedef RangeSelector
* @prop {'RangeSelector'} type
* @prop {string} startContainer
* @prop {string} endContainer
* @prop {number} startOffset
* @prop {number} endOffset
*/
export type RangeSelector = {
type: 'RangeSelector';
startContainer: string;
endContainer: string;
startOffset: number;
endOffset: number;
};
/**
* Serialized representation of a region of a document which an annotation
* pertains to.
*
* @typedef {TextQuoteSelector | TextPositionSelector | RangeSelector} Selector
*/
export type Selector = TextQuoteSelector | TextPositionSelector | RangeSelector;
/**
* An entry in the `target` field of an annotation which identifies the document
* and region of the document that it refers to.
*
* @typedef Target
* @prop {string} source - URI of the document
* @prop {Selector[]} [selector] - Region of the document
*/
export type Target = {
/** URI of the document */
source: string;
/** Region of the document */
selector?: Selector[];
};
/**
* TODO - Fill out remaining properties
*
* @typedef Annotation
* @prop {string} [id] -
export type Annotation = {
/**
* The server-assigned ID for the annotation. This is only set once the
* annotation has been saved to the backend.
* @prop {string} $tag - A locally-generated unique identifier for annotations.
* This is set for all annotations, whether they have been saved to the backend
* or not.
* @prop {string[]} [references]
* @prop {string} created
* @prop {boolean} [flagged]
* @prop {string} group
* @prop {string} updated
* @prop {string[]} tags
* @prop {string} text
* @prop {string} uri
* @prop {string} user
* @prop {boolean} hidden
*
* @prop {object} document
* @prop {string} document.title
*
* @prop {object} permissions
* @prop {string[]} permissions.read
* @prop {string[]} permissions.update
* @prop {string[]} permissions.delete
*
* @prop {Target[]} target - Which document and region this annotation refers to.
* The Hypothesis API structure allows for multiple targets, but the current
* h server only allows for one target per annotation.
*
* @prop {object} [moderation]
* @prop {number} moderation.flagCount
*
* @prop {object} links
* @prop {string} [links.incontext] - A "bouncer" URL to the annotation in
* context on its target document
* @prop {string} [links.html] - An `h`-website URL to view the annotation
* by itself
*
* @prop {object} [user_info]
* @prop {string|null} user_info.display_name
*
* // Properties not present on API objects, but added by utilities in the client.
* @prop {boolean} [$highlight]
* @prop {boolean} [$orphan]
* @prop {boolean} [$anchorTimeout]
*/
id?: string;
/**
* An annotation which has been saved to the backend and assigned an ID.
/**
* A locally-generated unique identifier for annotations.
*
* @typedef {Annotation & { id: string }} SavedAnnotation
* This is set for all annotations, whether they have been saved to the
* backend or not.
*/
$tag: string;
/**
* @typedef Profile
* @prop {string|null} userid
* @prop {object} preferences
* @prop {boolean} [preferences.show_sidebar_tutorial]
* @prop {Record<string, boolean>} features
* @prop {object} [user_info]
* @prop {string|null} user_info.display_name
*
* @prop {unknown} [groups] - Deprecated.
*/
references?: string[];
created: string;
flagged?: boolean;
group: string;
updated: string;
tags: string[];
text: string;
uri: string;
user: string;
hidden: boolean;
/**
* TODO - Fill out remaining properties
document: {
title: string;
};
permissions: {
read: string[];
update: string[];
delete: string[];
};
/**
* The document and region this annotation refers to.
*
* @typedef Organization
* @prop {string} name
* @prop {string} logo
* @prop {string} id
* @prop {boolean} [default]
* The Hypothesis API structure allows for multiple targets, but the h
* server only supports one target per annotation.
*/
target: Target[];
/**
* @typedef GroupScopes
* @prop {boolean} enforced
* @prop {string[]} uri_patterns;
moderation?: {
flagCount: number;
};
links: {
/**
* A "bouncer" URL that takes the user to see the annotation in context
*/
incontext?: string;
/** URL to view the annotation by itself. */
html?: string;
};
user_info?: {
display_name: string | null;
};
// Properties not present on API objects, but added by client.
$highlight?: boolean;
$orphan?: boolean;
$anchorTimeout?: boolean;
};
/**
* TODO - Fill out remaining properties
*
* @typedef Group
* @prop {string} id - a.k.a. "pubid", unique per authority.
* @prop {string} [groupid] - Fully-qualified ID with authority.
* Not all groups have a `groupid`.
* @prop {'private'|'open'} type
* @prop {Organization} organization - nb. This field is nullable in the API, but
* we assign a default organization on the client.
* @prop {GroupScopes|null} scopes
* @prop {object} links
* @prop {string} [links.html]
*
* // Properties not present on API objects, but added by utilities in the client.
* @prop {string} logo
* @prop {boolean} isMember
* @prop {boolean} isScopedToUri
* @prop {string} name
* @prop {boolean} canLeave
*
* An annotation which has been saved to the backend and assigned an ID.
*/
export type SavedAnnotation = Annotation & { id: string };
export type Profile = {
userid: string | null;
preferences: {
show_sidebar_tutorial?: boolean;
};
features: Record<string, boolean>;
user_info?: {
display_name: string | null;
};
};
export type Organization = {
name: string;
logo: string;
id: string;
default?: boolean;
};
export type GroupScopes = {
enforced: boolean;
uri_patterns: string[];
};
export type Group = {
/** The "pubid" of the group, unique per authority. */
id: string;
/** Fully-qualified ID with authority. */
groupid?: string;
type: 'private' | 'open';
/**
* Note: This field is nullable in the API, but we assign a default organization in the client.
*/
organization: Organization;
scopes: GroupScopes | null;
links: {
html?: string;
};
// Properties not present on API objects, but added in the client.
logo: string;
isMember: boolean;
isScopedToUri: boolean;
name: string;
canLeave: boolean;
};
/**
* @typedef {NonNullable<Group["id"]|Group["groupid"]>} GroupIdentifier
*
* All Groups have an `id`, which is a server-assigned identifier. This is the
* primary field used to identify a Group.
*
......@@ -205,6 +214,7 @@
* Application logic operates on `id`s, but we may receive `groupid`s in some
* cases from outside sevices, e.g. the `changeFocusModeUser` RPC method.
*/
export type GroupIdentifier = NonNullable<Group['id'] | Group['groupid']>;
/**
* Query parameters for an `/api/search` API call.
......@@ -213,30 +223,28 @@
*
* See https://h.readthedocs.io/en/latest/api-reference/#tag/annotations/paths/~1search/get
* for the complete list and usage of each.
*
* @typedef SearchQuery
* @prop {number} [limit]
* @prop {string[]} [uri]
* @prop {string} [group]
* @prop {string} [order]
* @prop {string} [references]
* @prop {string} [search_after]
* @prop {string} [sort]
* @prop {boolean} [_separate_replies] - Unofficial param that causes replies
* to be returned in a separate `replies` field
*/
export type SearchQuery = {
limit?: number;
uri?: string[];
group?: string;
order?: string;
references?: string;
search_after?: string;
sort?: string;
/** Undocument param that causes replies to be returned in a separate `replies` field. */
_separate_replies?: boolean;
};
/**
* Response to an `/api/search` API call.
*
* See https://h.readthedocs.io/en/latest/api-reference/#tag/annotations/paths/~1search/get
*
* @typedef SearchResponse
* @prop {number} total
* @prop {Annotation[]} rows
* @prop {Annotation[]} [replies] - Unofficial property that is populated if
* `_separate_replies` query param was specified
*/
export type SearchResponse = {
total: number;
rows: Annotation[];
// Make TypeScript treat this file as a module.
export const unused = {};
/** Undocumented property that is populated if `_separate_replies` query param was specified. */
replies?: Annotation[];
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment