@veltdev/sdk
Version:
Velt is an SDK to add collaborative features to your product within minutes. Example: Comments like Figma, Frame.io, Google docs or sheets, Recording like Loom, Huddles like Slack and much more.
178 lines (177 loc) • 7.62 kB
TypeScript
import { Observable } from 'rxjs';
import { BaseMetadata } from './base-metadata.data.model';
import { User } from './user.data.model';
/**
* Feature types that can generate activities.
*/
export type ActivityFeatureType = 'comment' | 'reaction' | 'recorder' | 'crdt' | 'custom';
/**
* Comment action type constants following the `entity_type.action` naming pattern.
* Annotation-level actions use `comment_annotation.*`, comment-level use `comment.*`.
*/
export declare const CommentActivityActionTypes: {
readonly ANNOTATION_ADD: "comment_annotation.add";
readonly ANNOTATION_DELETE: "comment_annotation.delete";
readonly COMMENT_ADD: "comment.add";
readonly COMMENT_UPDATE: "comment.update";
readonly COMMENT_DELETE: "comment.delete";
readonly STATUS_CHANGE: "comment_annotation.status_change";
readonly PRIORITY_CHANGE: "comment_annotation.priority_change";
readonly ASSIGN: "comment_annotation.assign";
readonly ACCESS_MODE_CHANGE: "comment_annotation.access_mode_change";
readonly CUSTOM_LIST_CHANGE: "comment_annotation.custom_list_change";
readonly APPROVE: "comment_annotation.approve";
readonly ACCEPT: "comment.accept";
readonly REJECT: "comment.reject";
readonly REACTION_ADD: "comment.reaction_add";
readonly REACTION_DELETE: "comment.reaction_delete";
readonly SUBSCRIBE: "comment_annotation.subscribe";
readonly UNSUBSCRIBE: "comment_annotation.unsubscribe";
};
export type CommentActivityActionType = typeof CommentActivityActionTypes[keyof typeof CommentActivityActionTypes];
/**
* Recorder action type constants following the `recording.*` naming pattern.
*/
export declare const RecorderActivityActionTypes: {
readonly RECORDING_ADD: "recording.add";
readonly RECORDING_DELETE: "recording.delete";
};
export type RecorderActivityActionType = typeof RecorderActivityActionTypes[keyof typeof RecorderActivityActionTypes];
/**
* Reaction action type constants following the `reaction.*` naming pattern.
*/
export declare const ReactionActivityActionTypes: {
readonly REACTION_ADD: "reaction.add";
readonly REACTION_DELETE: "reaction.delete";
};
export type ReactionActivityActionType = typeof ReactionActivityActionTypes[keyof typeof ReactionActivityActionTypes];
/**
* CRDT action type constants following the `crdt.*` naming pattern.
*/
export declare const CrdtActivityActionTypes: {
readonly EDITOR_EDIT: "crdt.editor_edit";
};
export type CrdtActivityActionType = typeof CrdtActivityActionTypes[keyof typeof CrdtActivityActionTypes];
/**
* Represents a single from/to change pair.
* `from` is always present (null for 'added' events) for uniform structure.
*/
export interface ActivityChange<T = unknown> {
from?: T | null;
to?: T | null;
}
/**
* Dynamic change tracking. Keys are domain-specific (e.g., 'status', 'commentText', 'assignedTo').
* No fixed keys — activities span multiple features.
*/
export interface ActivityChanges {
[]: ActivityChange | undefined;
}
/**
* Metadata for activity records. Extends BaseMetadata with denormalized IDs
* for efficient querying at the organization level.
*/
export declare class ActivityMetadata extends BaseMetadata {
[]: any;
}
/**
* Core activity record representing a single activity event.
*
* @typeParam TEntity - Type of the parent entity snapshot (e.g., CommentAnnotation)
* @typeParam TTarget - Type of the sub-entity snapshot (e.g., Comment)
*/
export declare class ActivityRecord<TEntity = unknown, TTarget = unknown> {
/** Auto-generated unique ID */
id: string;
/** Feature that generated this activity */
featureType: ActivityFeatureType;
/** Action that occurred, following `entity_type.action` pattern */
actionType: string;
/** Event type that occurred */
eventType?: string;
/** User who performed the action */
actionUser: User;
/** Server timestamp (set by backend) */
timestamp: number;
/** Denormalized IDs for querying */
metadata: ActivityMetadata;
/** ID of the parent entity (annotationId, recordingId, etc.) */
targetEntityId: string;
/** ID of the sub-entity acted on (commentId within annotation, null for entity-level actions) */
targetSubEntityId?: string | null;
/** Linear-style from/to change pairs */
changes?: ActivityChanges;
/** Full parent entity snapshot at time of action */
entityData?: TEntity;
/** Sub-entity snapshot (or user-provided data for custom activities) */
entityTargetData?: TTarget;
/** Display message template — ONLY for custom activities */
displayMessageTemplate?: string;
/** Template variable values — ONLY for custom activities */
displayMessageTemplateData?: Record<string, unknown>;
/** Computed display message (generated client-side, never stored in Firestore) */
displayMessage?: string;
/** Icon URL or identifier for display */
actionIcon?: string;
/** If true, this activity cannot be updated or deleted via REST API */
immutable?: boolean;
}
/**
* Configuration for subscribing to activities.
* Behavior is determined by the props passed:
* - No config → org-wide
* - documentIds → specific documents
* - currentDocumentOnly → current document only
*/
export interface ActivitySubscribeConfig {
/** Subscribe to activities for a specific organization (defaults to current org) */
organizationId?: string;
/** Subscribe to activities for specific document IDs */
documentIds?: string[];
/** Subscribe to activities for the current document only (auto-switches on setDocument) */
currentDocumentOnly?: boolean;
/** Only fetch activities from the last N days (default: 30) */
maxDays?: number;
/** Allowlist: only include activities with these feature types */
featureTypes?: ActivityFeatureType[];
/** Disallowlist: exclude activities with these feature types (ignored if featureTypes is set) */
excludeFeatureTypes?: ActivityFeatureType[];
/** Allowlist: only include activities with these action types */
actionTypes?: string[];
/** Disallowlist: exclude activities with these action types (ignored if actionTypes is set) */
excludeActionTypes?: string[];
/** Allowlist: only include activities by these user IDs */
userIds?: string[];
/** Disallowlist: exclude activities by these user IDs (ignored if userIds is set) */
excludeUserIds?: string[];
}
/**
* Represents an active activity subscription.
* Returned by `activityService.subscribe()`.
*/
export interface ActivitySubscription {
/** Observable stream of activities for this subscription's scope. null = not yet loaded. */
getActivities$(): Observable<ActivityRecord[] | null>;
/** Unsubscribe and clean up this subscription */
unsubscribe(): void;
}
/**
* Data required to create an activity.
* Used for all activity types: comment, reaction, recorder, custom, etc.
*/
export interface CreateActivityData<TEntity = unknown, TTarget = unknown> {
featureType: ActivityFeatureType;
actionType: string;
eventType?: string;
targetEntityId: string;
targetSubEntityId?: string | null;
changes?: ActivityChanges;
entityData?: TEntity;
entityTargetData?: TTarget;
/** Icon URL or identifier — typically used for custom activities */
actionIcon?: string;
/** Display message template — only for custom activities */
displayMessageTemplate?: string;
/** Template variable values — only for custom activities */
displayMessageTemplateData?: Record<string, unknown>;
}