11import { type Tag } from "./tag" ;
22import { type Callback } from "./tools/callbacks" ;
3+ import { type JSONValue } from "./utils/types" ;
34import { Uuid } from "./utils/uuid" ;
45
56export { Tag } from "./tag" ;
67export { Uuid } from "./utils/uuid" ;
8+ export { type JSONValue } from "./utils/types" ;
9+
10+ /**
11+ * @fileoverview
12+ * Core Plot entity types for working with activities, notes, priorities, and contacts.
13+ *
14+ * ## Type Pattern: Null vs Undefined Semantics
15+ *
16+ * Plot entity types use a consistent pattern to distinguish between missing, unset, and explicitly cleared values:
17+ *
18+ * ### Entity Types (Activity, Priority, Note, Actor)
19+ * - **Required fields**: No `?`, cannot be `undefined`
20+ * - Example: `id: Uuid`, `type: ActivityType`
21+ * - **Nullable fields**: Use `| null` to allow explicit clearing
22+ * - Example: `assignee: ActorId | null`, `done: Date | null`
23+ * - `null` = field is explicitly unset/cleared
24+ * - Non-null value = field has a value
25+ * - **Optional nullable fields**: Use `?` with `| null` for permission-based access
26+ * - Example: `email?: string | null`, `name?: string | null`
27+ * - `undefined` = field not included (e.g., no permission to access)
28+ * - `null` = field included but not set
29+ * - Value = field has a value
30+ *
31+ * ### New* Types (NewActivity, NewNote, NewPriority)
32+ * Used for creating or updating entities. Support partial updates by distinguishing omitted vs cleared fields:
33+ * - **Required fields**: Must be provided (no `?`)
34+ * - Example: `type: ActivityType` in NewActivity
35+ * - **Optional fields**: Use `?` to make them optional
36+ * - Example: `title?: string`, `author?: NewActor`
37+ * - `undefined` (omitted) = don't set/update this field
38+ * - Provided value = set/update this field
39+ * - **Optional nullable fields**: Use `?` with `| null` to support clearing
40+ * - Example: `assignee?: NewActor | null`
41+ * - `undefined` (omitted) = don't change assignee
42+ * - `null` = clear the assignee
43+ * - NewActor = set/update the assignee
44+ *
45+ * This pattern allows API consumers to:
46+ * 1. Omit fields they don't want to change (undefined)
47+ * 2. Explicitly clear fields by setting to null
48+ * 3. Set or update fields by providing values
49+ *
50+ * @example
51+ * ```typescript
52+ * // Creating a new activity
53+ * const newActivity: NewActivity = {
54+ * type: ActivityType.Action, // Required
55+ * title: "Review PR", // Optional, provided
56+ * assignee: null, // Optional nullable, explicitly clearing
57+ * // priority is omitted (undefined), will auto-select or use default
58+ * };
59+ *
60+ * // Updating an activity - only change what's specified
61+ * const update: ActivityUpdate = {
62+ * id: activityId,
63+ * done: new Date(), // Mark as done
64+ * assignee: null, // Clear assignee
65+ * // title is omitted, won't be changed
66+ * };
67+ * ```
68+ */
769
870/**
971 * Represents a unique user, contact, or twist in Plot.
@@ -24,21 +86,55 @@ export type ActorId = string & { readonly __brand: "ActorId" };
2486 */
2587export type Priority = {
2688 /** Unique identifier for the priority */
27- id : string ;
89+ id : Uuid ;
2890 /** Human-readable title for the priority */
2991 title : string ;
92+ /** Whether this priority has been archived */
93+ archived : boolean ;
3094} ;
3195
3296/**
3397 * Type for creating new priorities.
3498 *
35- * Excludes the auto-generated ID field and adds an optional parentId
36- * for creating hierarchical priority structures.
99+ * Supports multiple creation patterns:
100+ * - Provide a specific UUID for the priority
101+ * - Provide a key for upsert within the user's priorities
102+ * - Omit both to auto-generate a new UUID
103+ *
104+ * Optionally specify a parent priority by ID or key for hierarchical structures.
37105 */
38- export type NewPriority = Omit < Priority , "id" > & {
39- /** Optional ID of the parent priority for creating hierarchies */
40- parentId ?: string ;
41- } ;
106+ export type NewPriority = Pick < Priority , "title" > &
107+ Partial < Omit < Priority , "id" | "title" > > &
108+ (
109+ | {
110+ /**
111+ * Unique identifier for the priority, generated by Uuid.Generate().
112+ * Specifying an ID allows tools to track and upsert priorities.
113+ */
114+ id : Uuid ;
115+ }
116+ | {
117+ /**
118+ * Unique key for the priority within the user's priorities.
119+ * Can be used to upsert without knowing the UUID.
120+ * For example, "@plot" identifies the Plot priority.
121+ */
122+ key : string ;
123+ }
124+ | {
125+ /* Neither id nor key is required. An id will be generated and returned. */
126+ }
127+ ) & {
128+ /** Add the new priority as the child of another priority */
129+ parent ?: { id : Uuid } | { key : string } ;
130+ } ;
131+
132+ /**
133+ * Type for updating existing priorities.
134+ * Must provide either id or key to identify the priority to update.
135+ */
136+ export type PriorityUpdate = ( { id : Uuid } | { key : string } ) &
137+ Partial < Pick < Priority , "title" | "archived" > > ;
42138
43139/**
44140 * Enumeration of supported activity types in Plot.
@@ -178,6 +274,9 @@ export type ActivityLink =
178274 * which is useful for synchronization, linking back to external systems,
179275 * and storing tool-specific data.
180276 *
277+ * Must be valid JSON data (strings, numbers, booleans, null, objects, arrays).
278+ * Functions and other non-JSON values are not supported.
279+ *
181280 * @example
182281 * ```typescript
183282 * // Calendar event metadata
@@ -206,7 +305,7 @@ export type ActivityLink =
206305 */
207306export type ActivityMeta = {
208307 /** Source-specific properties and metadata */
209- [ key : string ] : any ;
308+ [ key : string ] : JSONValue ;
210309} ;
211310
212311/**
@@ -414,8 +513,8 @@ export type NewActivityWithNotes = NewActivity & {
414513 * // Score based on content (max 100 points) and require exact type match
415514 * pickPriority: { content: 100, type: true }
416515 *
417- * // Match on meta source and score content
418- * pickPriority: { "meta.source ": true, content: 50 }
516+ * // Match on meta and score content
517+ * pickPriority: { "meta.projectId ": true, content: 50 }
419518 * ```
420519 */
421520export type PickPriorityConfig = {
@@ -590,6 +689,7 @@ export type ActivityUpdate = (
590689 | "assignee"
591690 | "draft"
592691 | "private"
692+ | "archived"
593693 | "meta"
594694 | "recurrenceRule"
595695 | "recurrenceDates"
@@ -732,7 +832,9 @@ export type NewNote = Partial<
732832 * Must provide either id or key to identify the note to update.
733833 */
734834export type NoteUpdate = ( { id : Uuid } | { key : string } ) &
735- Partial < Pick < Note , "draft" | "private" | "content" | "links" > > & {
835+ Partial <
836+ Pick < Note , "draft" | "private" | "archived" | "content" | "links" >
837+ > & {
736838 /**
737839 * Format of the note content. Determines how the note is processed:
738840 * - 'text': Plain text that will be converted to markdown (auto-links URLs, preserves line breaks)
@@ -781,9 +883,19 @@ export type Actor = {
781883 id : ActorId ;
782884 /** Type of actor (User, Contact, or Twist) */
783885 type : ActorType ;
784- /** Email address (only included with ContactAccess.Read permission) */
785- email ?: string ;
786- /** Display name (undefined if not included due to permissions, null if not set) */
886+ /**
887+ * Email address (only included with ContactAccess.Read permission).
888+ * - `undefined`: No permission to read email
889+ * - `null`: Permission granted but email not set
890+ * - `string`: Email address
891+ */
892+ email ?: string | null ;
893+ /**
894+ * Display name.
895+ * - `undefined`: Not included due to permissions
896+ * - `null`: Not set
897+ * - `string`: Display name
898+ */
787899 name ?: string | null ;
788900} ;
789901
0 commit comments