import type { Ref, UseMutationResult, UseQueryOptions, UseQueryResult } from "./core"; import type { CustomField } from "./customFields"; import type { Status, Task } from "./tasks"; /** * Typed records over a schema the `solution` CLI provisioned: a record is one * task in the entity's List, its custom fields named by the schema's logical * keys. Reads are shaped like TanStack Query's `useQuery`, writes like * `useMutation`, and every write waits for the viewer's approval. */ export declare function defineEntity(schema: EntitySchema): Entity; /** * Tasks by id, in the order given. An empty list is a settled `[]` with no * loading state, so a relationship hook fed an unlinked record renders its * empty state at once. */ export declare function useTasksByIds(ids: readonly string[], options?: UseQueryOptions): UseQueryResult; /** A property every task has, mapped to a record property by the schema. */ type NativeProperty = "name" | "status" | "assignees" | "dueDate" | "startDate" | "priority" | "description"; interface OptionSpec { id: string; /** The option's name in ClickUp; what the kit reads and writes. */ label: string; } interface FieldSpec { /** The record property; a relationship becomes Ids and Refs. */ key: string; /** The ClickUp custom field id. */ id: string; name: string; type: CustomField["type"]; required: boolean; /** False keeps a type the kit cannot read off the record and out of the drift check. */ readable: boolean; /** The kit cannot write this type yet; writes are rejected. */ readOnly: boolean; /** Drop-down and labels only: logical option key to ClickUp option. */ options?: Readonly>; targetEntity?: string; targetListId?: string; } /** One entity's frozen ids, as _schema.ts exports them. */ export interface EntitySchema { key: string; list: { id: string; name: string; url: string; }; taskType?: { id: number; name: string; }; natives: ReadonlyArray<{ key: string; native: NativeProperty; }>; fields: readonly FieldSpec[]; } export interface RecordBase { id: string; /** Link to the task in ClickUp; safe to render for the viewer. */ url: string; /** The underlying clickup-kit Task, for anything the schema does not model. */ task: Task; } /** * status, statusType, limit and includeClosed are applied by ClickUp; the * entity's task type, where and orderBy run in the browser on the decoded * records. With ids, ClickUp returns exactly those tasks and every filter * runs in the browser. */ export interface ListFilter { /** Status names as shown in ClickUp, case-insensitive. */ status?: readonly S[]; statusType?: ReadonlyArray; ids?: readonly string[]; limit?: number; /** ClickUp hides tasks in the closing status unless this is true. */ includeClosed?: boolean; where?: (record: R) => boolean; /** Unset values sort last. */ orderBy?: { field: keyof R; direction?: "asc" | "desc"; }; } interface EntityClient { list(filter?: ListFilter): Promise; get(id: string): Promise; /** Resolves with the new task's ref when the host reports it. */ create(input: I): Promise | undefined>; /** undefined leaves a property alone; null clears one that is optional. */ update(id: string, patch: P): Promise; /** Moves the task to the List's closing status. There is no delete. */ close(id: string): Promise; } export interface Entity { schema: EntitySchema; decode(task: Task): R; client: EntityClient; useList(filter?: ListFilter, options?: UseQueryOptions): UseQueryResult; /** data is undefined while loading and when no task has that id; isSuccess tells them apart. */ useOne(id: string | undefined, options?: UseQueryOptions): UseQueryResult; useMany(ids: readonly string[], options?: UseQueryOptions): UseQueryResult; useCreate(): UseMutationResult | undefined, I>; useUpdate(): UseMutationResult; useClose(): UseMutationResult; }