@sanity/client
Version:
Client for retrieving, creating and patching data from Sanity.io
304 lines (288 loc) • 8.26 kB
text/typescript
import type {
Any,
ListenOptions,
RequestOptions,
ResumableListenOptions,
SanityDocument,
} from '../types'
/** @internal */
export const possibleRequestOptions = ['headers', 'signal', 'tag', 'timeout', 'token'] as const
/**
* Request options honored by the collaboration comments methods.
*
* @alpha
*/
export type CollaborationCommentsRequestOptions = Pick<
RequestOptions,
(typeof possibleRequestOptions)[number]
>
/**
* Options for collaboration comments write methods.
*
* @alpha
*/
export type CollaborationCommentsWriteOptions = CollaborationCommentsRequestOptions & {
/** Transaction ID to associate the write with */
transactionId?: string
}
/**
* Listener options for `collaboration.comments.listen`.
*
* `includeAllVersions` is left out: comments are stored as `sanity.comment`
* documents with no drafts or versions, so it would never make a difference.
*
* @alpha
*/
export type CollaborationCommentsListenOptions =
| Omit<ListenOptions, 'includeAllVersions'>
| Omit<ResumableListenOptions, 'includeAllVersions'>
/**
* Status of a comment thread. Replies always share the status of their parent comment.
*
* @alpha
*/
export type CollaborationCommentStatus = 'open' | 'resolved'
/**
* Emoji short names that can be used as comment reactions.
*
* @alpha
*/
export type CollaborationCommentReactionShortName =
| ':-1:'
| ':+1:'
| ':eyes:'
| ':heart:'
| ':heavy_plus_sign:'
| ':rocket:'
/**
* A single Portable Text block, as used in comment messages and content snapshots.
*
* @alpha
*/
export interface CollaborationCommentPortableTextBlock {
_type: string
children: Array<{_type: string; [key: string]: Any}>
[key: string]: Any
}
/**
* Comment message, as an array of Portable Text blocks.
*
* @alpha
*/
export type CollaborationCommentMessage = CollaborationCommentPortableTextBlock[]
/**
* The text an inline comment was anchored to, resolved by the API when the
* comment was created.
*
* Holds one entry per Portable Text block the selection spans, keyed by the
* block it came from. `text` is the plain text of that block with the selected
* part wrapped in the marker characters `\uF000` (start) and `\uF001` (end).
*
* @alpha
*/
export interface CollaborationCommentSelection {
type: 'text'
value: {_key: string; text: string}[]
}
/**
* A comment document, as stored by the Comments API.
*
* @alpha
*/
export interface CollaborationCommentDocument extends SanityDocument {
_type: 'sanity.comment'
_system?: {
/** ID of the user that created the comment */
createdBy?: string
}
/** ID shared by a top-level comment and all of its replies */
threadId?: string
/** Set on replies, pointing to the comment being replied to */
parentCommentId?: string
message: CollaborationCommentMessage
reactions: {
_key: string
shortName: CollaborationCommentReactionShortName
userId: string
addedAt: string
}[]
/** Arbitrary metadata stored with the comment by the creating application */
context?: Record<string, unknown>
target: {
/** Global document reference (`resourceType:resourceId:documentId`, using the published document ID) */
document: {
_ref: `${string}:${string}:${string}`
_type: 'globalDocumentReference'
_weak: true
}
documentType: string
/** The exact document ID the comment was created against, e.g. a draft or version ID */
sourceDocumentId: string
documentRevisionId?: string
/**
* Set for field and inline comments. `field` is the `path` the comment was
* created with; `selection` is set for inline comments only.
*/
path?: {
field: string
selection?: CollaborationCommentSelection
}
}
/**
* Copy of the commented content, as it looked when the comment was created.
* Set for inline comments only, and holds just the selected fragment of each
* Portable Text block the selection spans.
*/
contentSnapshot?: CollaborationCommentPortableTextBlock[]
status: CollaborationCommentStatus
/** Set when the message has been updated after creation */
lastEditedAt?: string
}
/**
* Inline text selection within a Portable Text field.
* Each endpoint pairs the `_key` of a Portable Text block with a character
* offset into that block's plain text.
*
* @alpha
*/
export interface CollaborationCommentRange {
start: {_key: string; offset: number}
end: {_key: string; offset: number}
}
/**
* Portable Text covering a comment `range`. Callers can send just the blocks
* from the `range` start `_key` through end `_key`, or the full field.
*
* @alpha
*/
export type CollaborationCommentFieldValue = Array<{
_type: string
_key: string
[key: string]: Any
}>
/**
* Target for a top-level comment. Inline selections require both `path` and
* `range`; field-level comments may set `path` alone.
*
* The created comment stores this in a different shape: `path` becomes
* `target.path.field`, and `range` is resolved against the document into
* `target.path.selection` and `contentSnapshot` rather than being stored.
*
* An optional `fieldValue` is Portable Text covering the `range`. When set,
* the `range` is resolved from those blocks instead of from the live document.
*
* @alpha
*/
export type CollaborationCommentTarget = {
documentId: string
documentType: string
documentRevisionId?: string
} & (
| {
/** Path to the field containing the inline comment selection */
path: string
range: CollaborationCommentRange
/**
* Portable Text covering the `range`. When set, the `range` is resolved
* from these blocks instead of from the live document.
*/
fieldValue?: CollaborationCommentFieldValue
}
| {
/** Path to the commented field */
path?: string
range?: never
fieldValue?: never
}
)
/**
* Comment to create with `collaboration.comments.create`.
*
* A top-level comment requires `target`; a reply requires `parentCommentId` (never both).
* Replies inherit `target`, `status`, and `threadId` from the parent comment.
*
* ### Examples
*
* #### Top-level comment
* ```ts
* // `message` is an array of Portable Text blocks
* await client.collaboration.comments.create({
* message,
* target: {documentId: 'doc-1', documentType: 'article'},
* })
* ```
*
* #### Inline comment
* ```ts
* await client.collaboration.comments.create({
* message,
* target: {
* documentId: 'doc-1',
* documentType: 'article',
* path: 'body',
* range: {start: {_key: 'block-1', offset: 0}, end: {_key: 'block-1', offset: 5}},
* },
* })
* ```
*
* #### Reply
* ```ts
* await client.collaboration.comments.create({
* message,
* parentCommentId: 'comment-1',
* })
* ```
*
* @alpha
*/
export type CollaborationCommentCreate = {
/** Provide to control the ID of the created comment document */
_id?: string
message: CollaborationCommentMessage
context?: Record<string, unknown>
} & (
| {
target: CollaborationCommentTarget
threadId?: string
parentCommentId?: never
}
| {
parentCommentId: string
target?: never
threadId?: never
}
)
/**
* Fields that can be updated on an existing comment.
*
* A `range` re-anchors the comment within the field it already targets.
* Pass `null` to remove the selection and leave a field-level comment.
* An optional `fieldValue` is Portable Text covering that `range`; when set,
* the `range` is resolved from those blocks instead of from the live document.
* `fieldValue` cannot be sent alone or together with `range: null`.
*
* @alpha
*/
export type CollaborationCommentUpdate = {
/** Replaces the current message */
message?: CollaborationCommentMessage
/** Cascades to the comment's replies */
status?: CollaborationCommentStatus
} & (
| {
range: CollaborationCommentRange
/**
* Portable Text covering the `range`. When set, the `range` is resolved
* from these blocks instead of from the live document.
*/
fieldValue?: CollaborationCommentFieldValue
}
| {
range: null
fieldValue?: never
}
| {
range?: undefined
fieldValue?: never
}
)