@baack-software/baack-ts-editor 0.1.4 → 0.1.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../node_modules/@baack-software/baack-ts-tasks/src/types.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/refs.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/time.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/tasks.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/draft.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/conflicts.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/blockers.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/activity.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/card.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/errors.ts", "../../node_modules/@baack-software/baack-ts-tasks/src/task-client.ts"],
4
+ "sourcesContent": ["import type {\n Pagination,\n TaskActivity,\n TaskLog,\n TaskPriority,\n TaskStatus,\n} from '@baack-software/baack-ts-client';\n\n/**\n * A reference to another representation by URN. The API resolves references by `urn`, so this is all a request needs,\n * unlike the client's read types (for example `Identity` requires `owner`).\n */\nexport interface Ref {\n urn: string;\n url?: string | null;\n}\n\n/** A URN, or anything carrying one, such as a task or identity read from the API. */\nexport type RefLike = string | Ref;\n\n/**\n * Task log activities, with both spellings of completed: earlier versions of baack-ts-client's `TaskActivity` have only\n * `STATUS_COMPL_ETED`, later ones only `STATUS_COMPLETED`.\n */\nexport type Activity = TaskActivity | 'STATUS_COMPLETED' | 'STATUS_COMPL_ETED';\n\n/**\n * Task fields to create or change. The API stores what an update sends, so `TaskClient.update` sends these changes on\n * top of the whole task (see `updateBody`). Lists are sent whole: the server compares them with the current lists and\n * logs each addition and removal.\n */\nexport interface TaskInput {\n owner?: Ref;\n /** `null` unsets. */\n assignee?: Ref | null;\n /** `null` unsets. */\n project?: Ref | null;\n /** `null` unsets. */\n workflowStage?: Ref | null;\n status?: TaskStatus;\n priority?: TaskPriority;\n title?: string;\n description?: string;\n /** ISO 8601 in UTC without a zone, see `toTimestamp`. `null` unsets. */\n dueTimestamp?: string | null;\n blockedBy?: Ref[];\n blocking?: Ref[];\n associatedTasks?: Ref[];\n associatedEntities?: Ref[];\n associatedIdentities?: Ref[];\n associatedCompanies?: Ref[];\n /** Attributes the change in the activity log without assigning the task. */\n identityForLogs?: Ref;\n}\n\n/** A new task, with the fields the API requires on create. Build one with `draft`. */\nexport interface TaskDraft extends TaskInput {\n owner: Ref;\n status: TaskStatus;\n priority: TaskPriority;\n title: string;\n description: string;\n blockedBy: Ref[];\n blocking: Ref[];\n associatedTasks: Ref[];\n associatedEntities: Ref[];\n associatedIdentities: Ref[];\n associatedCompanies: Ref[];\n}\n\n/**\n * The body of a task update: the whole task as it should be stored. The server requires `urn`, `owner`, `status`,\n * `priority`, `title` and `description`, and clears any optional field left out. Build one with `updateBody`.\n */\nexport interface TaskUpdate extends TaskDraft {\n urn: string;\n}\n\n/** One page of a task's activity log, newest first. */\nexport interface TaskLogPage {\n logs: TaskLog[];\n pagination?: Pagination | null;\n}\n\n/** The fields of a task that hold lists of references. */\nexport type TaskListField =\n | 'blockedBy'\n | 'blocking'\n | 'associatedTasks'\n | 'associatedEntities'\n | 'associatedIdentities'\n | 'associatedCompanies';\n\nexport const TASK_LIST_FIELDS: readonly TaskListField[] = [\n 'blockedBy',\n 'blocking',\n 'associatedTasks',\n 'associatedEntities',\n 'associatedIdentities',\n 'associatedCompanies',\n];\n", "import type { Ref, RefLike } from './types.ts';\n\n/** The URN of a reference or a URN string. */\nexport function urnOf(value: RefLike): string {\n return typeof value === 'string' ? value : value.urn;\n}\n\n/** A bare `{ urn }` reference, dropping any other fields of a read representation. */\nexport function ref(value: RefLike): Ref {\n return { urn: urnOf(value) };\n}\n\n/** Bare references for a list, without duplicates, in their original order. */\nexport function refs(values: readonly RefLike[] | null | undefined): Ref[] {\n const seen = new Set<string>();\n const result: Ref[] = [];\n for (const value of values ?? []) {\n const urn = urnOf(value);\n if (!seen.has(urn)) {\n seen.add(urn);\n result.push({ urn });\n }\n }\n return result;\n}\n\n/** Whether two references point at the same representation. Absent references are equal to each other. */\nexport function sameRef(a: RefLike | null | undefined, b: RefLike | null | undefined): boolean {\n if (a == null || b == null) return a == null && b == null;\n return urnOf(a) === urnOf(b);\n}\n\n/** Whether two lists hold the same references, ignoring order and duplicates. */\nexport function sameRefs(a: readonly RefLike[] | null | undefined, b: readonly RefLike[] | null | undefined): boolean {\n const left = new Set((a ?? []).map(urnOf));\n const right = new Set((b ?? []).map(urnOf));\n return left.size === right.size && [...left].every((urn) => right.has(urn));\n}\n\n/** A copy of `list` with `value` added, unless it is already there. */\nexport function withRef(list: readonly RefLike[] | null | undefined, value: RefLike): Ref[] {\n return refs([...(list ?? []), value]);\n}\n\n/** A copy of `list` without `value`. */\nexport function withoutRef(list: readonly RefLike[] | null | undefined, value: RefLike): Ref[] {\n const urn = urnOf(value);\n return refs(list).filter((item) => item.urn !== urn);\n}\n", "/**\n * Baack timestamps are ISO 8601 in UTC without a zone, for example `2025-09-13T17:08:00` or `2025-09-13T17:08:00.000`.\n * A plain `new Date(timestamp)` would read them as local time, so use these helpers instead.\n */\n\nconst HAS_ZONE = /(?:Z|[+-]\\d{2}:?\\d{2})$/i;\n\n/** Reads a Baack timestamp as a `Date`, or undefined when it is empty or not a valid timestamp. */\nexport function parseTimestamp(timestamp: string | null | undefined): Date | undefined {\n if (!timestamp) return undefined;\n const date = new Date(HAS_ZONE.test(timestamp) ? timestamp : timestamp + 'Z');\n return Number.isNaN(date.getTime()) ? undefined : date;\n}\n\n/** Writes a `Date` as a Baack timestamp: UTC, with milliseconds, without a zone. */\nexport function toTimestamp(date: Date): string {\n return date.toISOString().replace(/Z$/, '');\n}\n\n/**\n * The value for an `<input type=\"datetime-local\">` showing a Baack timestamp in the viewer's local time, or `''`.\n */\nexport function toLocalInput(timestamp: string | null | undefined): string {\n const date = parseTimestamp(timestamp);\n if (!date) return '';\n const pad = (n: number) => String(n).padStart(2, '0');\n return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}T${pad(date.getHours())}:${pad(date.getMinutes())}`;\n}\n\n/** Reads an `<input type=\"datetime-local\">` value (local time) as a Baack timestamp, or undefined when empty. */\nexport function fromLocalInput(value: string | null | undefined): string | undefined {\n if (!value) return undefined;\n const date = new Date(value);\n return Number.isNaN(date.getTime()) ? undefined : toTimestamp(date);\n}\n", "import type { Task, TaskPriority, TaskStatus, Workflow, WorkflowStage } from '@baack-software/baack-ts-client';\nimport { urnOf } from './refs.ts';\nimport { parseTimestamp } from './time.ts';\nimport type { RefLike } from './types.ts';\n\n/** Statuses in board order, from not started to done. */\nexport const TASK_STATUSES: readonly TaskStatus[] = [\n 'UNDEFINED',\n 'PENDING',\n 'IN_PROGRESS',\n 'BLOCKED',\n 'COMPLETED',\n 'CLOSED',\n];\n\n/** Priorities from lowest to highest. */\nexport const TASK_PRIORITIES: readonly TaskPriority[] = ['NONE', 'LOW', 'MEDIUM', 'HIGH', 'CRITICAL'];\n\nexport const STATUS_LABELS: Readonly<Record<TaskStatus, string>> = {\n UNDEFINED: 'Undefined',\n PENDING: 'Pending',\n IN_PROGRESS: 'In progress',\n BLOCKED: 'Blocked',\n COMPLETED: 'Completed',\n CLOSED: 'Closed',\n};\n\nexport const PRIORITY_LABELS: Readonly<Record<TaskPriority, string>> = {\n NONE: 'None',\n LOW: 'Low',\n MEDIUM: 'Medium',\n HIGH: 'High',\n CRITICAL: 'Critical',\n};\n\nconst DONE: ReadonlySet<TaskStatus> = new Set(['COMPLETED', 'CLOSED']);\n\n/** Whether a status means the work is finished: completed or closed. */\nexport function isDoneStatus(status: TaskStatus | null | undefined): boolean {\n return status != null && DONE.has(status);\n}\n\n/** Whether the task still needs work: not completed or closed. */\nexport function isOpen(task: Pick<Task, 'status'>): boolean {\n return !isDoneStatus(task.status);\n}\n\n/** The task's due date, or undefined when it has none. */\nexport function dueDate(task: Pick<Task, 'dueTimestamp'>): Date | undefined {\n return parseTimestamp(task.dueTimestamp);\n}\n\n/** Whether an open task is past its due date. */\nexport function isOverdue(task: Pick<Task, 'status' | 'dueTimestamp'>, now: Date = new Date()): boolean {\n const due = dueDate(task);\n return isOpen(task) && due !== undefined && due.getTime() < now.getTime();\n}\n\n/** Whether an open task is due within `ms` from now, and not yet overdue. */\nexport function isDueWithin(\n task: Pick<Task, 'status' | 'dueTimestamp'>,\n ms: number,\n now: Date = new Date(),\n): boolean {\n const due = dueDate(task);\n if (!isOpen(task) || due === undefined) return false;\n const left = due.getTime() - now.getTime();\n return left >= 0 && left <= ms;\n}\n\n// ==========================================\n// SORTING\n// ==========================================\n\nexport type TaskComparator = (a: Task, b: Task) => number;\n\n/** Highest priority first. */\nexport const byPriority: TaskComparator = (a, b) =>\n TASK_PRIORITIES.indexOf(b.priority) - TASK_PRIORITIES.indexOf(a.priority);\n\n/** Board order of status. */\nexport const byStatus: TaskComparator = (a, b) => TASK_STATUSES.indexOf(a.status) - TASK_STATUSES.indexOf(b.status);\n\n/** Soonest due first; tasks without a due date last. */\nexport const byDue: TaskComparator = (a, b) => {\n const [first, second] = [timeOrInfinity(a.dueTimestamp), timeOrInfinity(b.dueTimestamp)];\n // Two tasks without due dates tie (Infinity - Infinity is NaN, which would stop the next comparator breaking it).\n return first === second ? 0 : first - second;\n};\n\n/** Most recently updated first. */\nexport const byUpdated: TaskComparator = (a, b) =>\n -(timeOrInfinity(a.updatedTimestamp, 0) - timeOrInfinity(b.updatedTimestamp, 0));\n\n/** Title, alphabetically. */\nexport const byTitle: TaskComparator = (a, b) => a.title.localeCompare(b.title);\n\n/** Sorts by each comparator in turn, using the next to break ties. */\nexport function compareBy(...comparators: TaskComparator[]): TaskComparator {\n return (a, b) => {\n for (const compare of comparators) {\n const result = compare(a, b);\n if (result !== 0) return result;\n }\n return 0;\n };\n}\n\n/** Open tasks before completed and closed ones. */\nexport const byOpen: TaskComparator = (a, b) => Number(isOpen(b)) - Number(isOpen(a));\n\n/** A sensible default for work lists: open first, then overdue and soonest due, then highest priority. */\nexport const byUrgency: TaskComparator = compareBy(byOpen, byDue, byPriority, byTitle);\n\n/** Within a board column: open first, then highest priority, soonest due and title, so ties are stable. */\nexport const byPriorityThenDue: TaskComparator = compareBy(byOpen, byPriority, byDue, byTitle);\n\nfunction timeOrInfinity(timestamp: string | null | undefined, fallback = Number.POSITIVE_INFINITY): number {\n return parseTimestamp(timestamp)?.getTime() ?? fallback;\n}\n\n// ==========================================\n// FILTERING\n// ==========================================\n\n/**\n * Criteria for `matchesFilter`. Each criterion left out matches every task; all given criteria must match. For\n * `assignee`, `project` and `workflowStage`, `null` in the list matches tasks with none set.\n */\nexport interface TaskFilter {\n status?: readonly TaskStatus[];\n priority?: readonly TaskPriority[];\n assignee?: readonly (RefLike | null)[];\n project?: readonly (RefLike | null)[];\n workflowStage?: readonly (RefLike | null)[];\n /** Tasks that block on, are blocking, or are associated with this representation. */\n relatedTo?: RefLike;\n /** `true` for open tasks only, `false` for done tasks only. */\n open?: boolean;\n /** Only open tasks past their due date. */\n overdue?: boolean;\n /** Case-insensitive match against the title and description. */\n text?: string;\n}\n\nexport function matchesFilter(task: Task, filter: TaskFilter, now: Date = new Date()): boolean {\n if (filter.status && !filter.status.includes(task.status)) return false;\n if (filter.priority && !filter.priority.includes(task.priority)) return false;\n if (filter.assignee && !matchesRef(task.assignee, filter.assignee)) return false;\n if (filter.project && !matchesRef(task.project, filter.project)) return false;\n if (filter.workflowStage && !matchesRef(task.workflowStage, filter.workflowStage)) return false;\n if (filter.relatedTo !== undefined && !isRelatedTo(task, filter.relatedTo)) return false;\n if (filter.open !== undefined && isOpen(task) !== filter.open) return false;\n if (filter.overdue && !isOverdue(task, now)) return false;\n if (filter.text) {\n const needle = filter.text.toLocaleLowerCase();\n const haystack = `${task.title}\\n${task.description}`.toLocaleLowerCase();\n if (!haystack.includes(needle)) return false;\n }\n return true;\n}\n\nexport function filterTasks(tasks: readonly Task[], filter: TaskFilter, now: Date = new Date()): Task[] {\n return tasks.filter((task) => matchesFilter(task, filter, now));\n}\n\n/** Whether the task refers to `target` in its blockers, blocked tasks or associations. */\nexport function isRelatedTo(task: Task, target: RefLike): boolean {\n const urn = urnOf(target);\n const lists = [\n task.blockedBy,\n task.blocking,\n task.associatedTasks,\n task.associatedEntities,\n task.associatedIdentities,\n task.associatedCompanies,\n ];\n return lists.some((list) => list?.some((item) => item.urn === urn));\n}\n\nfunction matchesRef(value: { urn: string } | null | undefined, wanted: readonly (RefLike | null)[]): boolean {\n return wanted.some((candidate) => (candidate === null ? value == null : value?.urn === urnOf(candidate)));\n}\n\n// ==========================================\n// GROUPING\n// ==========================================\n\nexport type TaskGrouping = 'status' | 'priority' | 'assignee' | 'project' | 'workflow' | 'workflowStage';\n\n/** The key used for tasks without an assignee, project, workflow or workflow stage. */\nexport const NONE_KEY = '';\n\n/**\n * Groups tasks into columns, keyed by status, priority, or the URN of the assignee, project or workflow stage\n * (`NONE_KEY` when unset). Status and priority groups always contain every value in order, so a board shows empty\n * columns; priority runs highest first. Other groups appear in order of first use.\n */\nexport function groupTasks(tasks: readonly Task[], by: TaskGrouping): Map<string, Task[]> {\n const groups = new Map<string, Task[]>();\n if (by === 'status') TASK_STATUSES.forEach((status) => groups.set(status, []));\n if (by === 'priority') [...TASK_PRIORITIES].reverse().forEach((priority) => groups.set(priority, []));\n for (const task of tasks) {\n const key = groupKey(task, by);\n const group = groups.get(key);\n if (group) group.push(task);\n else groups.set(key, [task]);\n }\n return groups;\n}\n\n/** A workflow's stages in order. */\nexport function workflowStages(workflow: Workflow): WorkflowStage[] {\n return [...(workflow.stages ?? [])].sort((a, b) => (a.order ?? 0) - (b.order ?? 0));\n}\n\n/**\n * Groups tasks into a workflow's stages, keyed by stage URN, every stage in order even when empty. Tasks in no stage,\n * or in another workflow's, go under `NONE_KEY`, last, which is left out when empty.\n */\nexport function groupByStage(tasks: readonly Task[], workflow: Workflow): Map<string, Task[]> {\n const groups = new Map<string, Task[]>(workflowStages(workflow).map((stage) => [stage.urn, []]));\n const rest: Task[] = [];\n for (const task of tasks) (groups.get(task.workflowStage?.urn ?? NONE_KEY) ?? rest).push(task);\n if (rest.length > 0) groups.set(NONE_KEY, rest);\n return groups;\n}\n\n/** The workflow a task is in: the one its stage belongs to, as a task records only its stage. */\nexport function workflowOf(task: Task, workflows: readonly Workflow[]): Workflow | undefined {\n const stage = task.workflowStage?.urn;\n return stage ? workflows.find((workflow) => workflow.stages?.some((s) => s.urn === stage)) : undefined;\n}\n\n/**\n * Groups tasks by workflow, keyed by workflow URN, every workflow in the order given even when empty. Tasks in no\n * workflow's stage go under `NONE_KEY`, last, which is left out when empty.\n */\nexport function groupByWorkflow(tasks: readonly Task[], workflows: readonly Workflow[]): Map<string, Task[]> {\n const groups = new Map<string, Task[]>(workflows.map((workflow) => [workflow.urn, []]));\n const rest: Task[] = [];\n for (const task of tasks) (groups.get(workflowOf(task, workflows)?.urn ?? NONE_KEY) ?? rest).push(task);\n if (rest.length > 0) groups.set(NONE_KEY, rest);\n return groups;\n}\n\nfunction groupKey(task: Task, by: TaskGrouping): string {\n switch (by) {\n case 'status':\n return task.status;\n case 'priority':\n return task.priority;\n case 'assignee':\n return task.assignee?.urn ?? NONE_KEY;\n case 'project':\n return task.project?.urn ?? NONE_KEY;\n case 'workflowStage':\n return task.workflowStage?.urn ?? NONE_KEY;\n // A task's workflow is found from its stage, which needs the workflows: `groupByWorkflow`.\n case 'workflow':\n return NONE_KEY;\n }\n}\n", "import type { Task } from '@baack-software/baack-ts-client';\nimport { ref, refs, sameRef, sameRefs, urnOf } from './refs.ts';\nimport { parseTimestamp } from './time.ts';\nimport { TASK_LIST_FIELDS, type RefLike, type TaskDraft, type TaskInput, type TaskUpdate } from './types.ts';\n\nexport const TITLE_MAX_LENGTH = 1024;\nexport const DESCRIPTION_MAX_LENGTH = 65536;\n\n/** What `draft` needs: an owner and a title. Everything else has a default. */\nexport type DraftInput = Omit<Partial<TaskDraft>, 'owner' | 'title'> & {\n owner: RefLike;\n title: string;\n};\n\n/**\n * A new task ready to create: status `PENDING`, priority `NONE`, an empty description and empty lists unless given.\n * References are reduced to bare `{ urn }`.\n */\nexport function draft(input: DraftInput): TaskDraft {\n const { owner, ...rest } = input;\n const result: TaskDraft = {\n status: 'PENDING',\n priority: 'NONE',\n description: '',\n ...rest,\n owner: ref(owner),\n blockedBy: refs(rest.blockedBy),\n blocking: refs(rest.blocking),\n associatedTasks: refs(rest.associatedTasks),\n associatedEntities: refs(rest.associatedEntities),\n associatedIdentities: refs(rest.associatedIdentities),\n associatedCompanies: refs(rest.associatedCompanies),\n };\n return result;\n}\n\nexport interface ValidationIssue {\n field: keyof TaskInput;\n message: string;\n}\n\n/**\n * Checks a create or update body against the API's documented rules, so a form can show problems before sending.\n * Pass the task's URN when updating, to catch a task blocking itself.\n */\nexport function validateTask(input: TaskInput, options: { creating?: boolean; urn?: string } = {}): ValidationIssue[] {\n const issues: ValidationIssue[] = [];\n const { creating = false, urn } = options;\n\n if (creating && !input.owner) issues.push({ field: 'owner', message: 'A task needs an owning company.' });\n if (input.title !== undefined || creating) {\n const title = input.title?.trim() ?? '';\n if (title === '') issues.push({ field: 'title', message: 'A task needs a title.' });\n else if (title.length > TITLE_MAX_LENGTH)\n issues.push({ field: 'title', message: `The title is longer than ${TITLE_MAX_LENGTH} characters.` });\n }\n if (input.description !== undefined && input.description.length > DESCRIPTION_MAX_LENGTH) {\n issues.push({\n field: 'description',\n message: `The description is longer than ${DESCRIPTION_MAX_LENGTH} characters.`,\n });\n }\n if (input.dueTimestamp != null && !parseTimestamp(input.dueTimestamp)) {\n issues.push({ field: 'dueTimestamp', message: 'The due date is not a valid timestamp.' });\n }\n if (urn !== undefined) {\n if (input.blockedBy?.some((item) => item.urn === urn))\n issues.push({ field: 'blockedBy', message: 'A task cannot block itself.' });\n if (input.blocking?.some((item) => item.urn === urn))\n issues.push({ field: 'blocking', message: 'A task cannot block itself.' });\n }\n const blockedBy = new Set((input.blockedBy ?? []).map(urnOf));\n if (input.blocking?.some((item) => blockedBy.has(item.urn))) {\n issues.push({ field: 'blocking', message: 'A task cannot both block and be blocked by the same task.' });\n }\n return issues;\n}\n\n/**\n * The update body that turns `before` into `after`: only the fields that differ. Lists count as changed when they hold\n * different references, regardless of order, and are sent whole. Returns `{}` when nothing changed.\n */\nexport function taskChanges(before: Task, after: Task | TaskInput): TaskInput {\n const changes: TaskInput = {};\n\n for (const field of ['status', 'priority', 'title', 'description'] as const) {\n const value = after[field];\n if (value !== undefined && value !== before[field]) (changes as Record<string, unknown>)[field] = value;\n }\n if (after.dueTimestamp !== undefined && !sameTime(before.dueTimestamp, after.dueTimestamp)) {\n changes.dueTimestamp = after.dueTimestamp || null;\n }\n for (const field of ['assignee', 'project', 'workflowStage'] as const) {\n const value = after[field];\n if (value !== undefined && !sameRef(before[field], value)) changes[field] = value === null ? null : ref(value);\n }\n for (const field of TASK_LIST_FIELDS) {\n const value = after[field];\n if (value !== undefined && !sameRefs(before[field], value)) changes[field] = refs(value);\n }\n return changes;\n}\n\n/**\n * The task as it will look once `changes` are applied, for showing a change before the server confirms it. References\n * keep only what the change carries (usually just the URN), so names need looking up separately.\n */\nexport function applyChanges(task: Task, changes: TaskInput): Task {\n const result: Task = { ...task };\n for (const field of ['status', 'priority', 'title', 'description'] as const) {\n if (changes[field] !== undefined) (result as unknown as Record<string, unknown>)[field] = changes[field];\n }\n if (changes.dueTimestamp !== undefined) result.dueTimestamp = changes.dueTimestamp ?? '';\n for (const field of ['assignee', 'project', 'workflowStage', ...TASK_LIST_FIELDS] as const) {\n const value = changes[field];\n if (value !== undefined) (result as unknown as Record<string, unknown>)[field] = value;\n }\n return result;\n}\n\n/**\n * The update body that stores `task` with `changes` applied. The API stores the task as an update sends it: required\n * fields must be present and optional fields left out are cleared, so the body carries the whole task. A `null` change\n * clears a field. References are reduced to bare `{ urn }`.\n */\nexport function updateBody(task: Task, changes: TaskInput): TaskUpdate {\n const owner = changes.owner ?? task.owner;\n if (!owner) throw new TypeError(`Task ${task.urn} has no owner, which every update must send.`);\n const body: TaskUpdate = {\n urn: task.urn,\n owner: ref(owner),\n status: changes.status ?? task.status,\n priority: changes.priority ?? task.priority,\n title: changes.title ?? task.title,\n description: changes.description ?? task.description ?? '',\n blockedBy: refs(changes.blockedBy ?? task.blockedBy),\n blocking: refs(changes.blocking ?? task.blocking),\n associatedTasks: refs(changes.associatedTasks ?? task.associatedTasks),\n associatedEntities: refs(changes.associatedEntities ?? task.associatedEntities),\n associatedIdentities: refs(changes.associatedIdentities ?? task.associatedIdentities),\n associatedCompanies: refs(changes.associatedCompanies ?? task.associatedCompanies),\n };\n for (const field of ['assignee', 'project', 'workflowStage'] as const) {\n const value = changes[field] === undefined ? task[field] : changes[field];\n if (value) body[field] = ref(value);\n else if (changes[field] === null) body[field] = null;\n }\n const due = changes.dueTimestamp === undefined ? task.dueTimestamp : changes.dueTimestamp;\n if (due) body.dueTimestamp = due;\n else if (changes.dueTimestamp !== undefined) body.dueTimestamp = null;\n if (changes.identityForLogs) body.identityForLogs = ref(changes.identityForLogs);\n return body;\n}\n\n/** Whether a body has nothing to send. */\nexport function isEmptyChange(input: TaskInput): boolean {\n return Object.keys(input).every((key) => key === 'identityForLogs');\n}\n\nfunction sameTime(a: string | null | undefined, b: string | null | undefined): boolean {\n return parseTimestamp(a)?.getTime() === parseTimestamp(b)?.getTime();\n}\n", "import type { Task } from '@baack-software/baack-ts-client';\nimport { refs, sameRef, sameRefs, urnOf } from './refs.ts';\nimport { parseTimestamp } from './time.ts';\nimport { TASK_LIST_FIELDS, type Ref, type TaskInput, type TaskListField } from './types.ts';\n\n/**\n * Finding and resolving conflicting edits.\n *\n * An editor shows a task (the base), the person changes some fields, and by the time the change is sent someone else\n * may have changed the task too. Fields only the other person changed are kept, since an update applies only this\n * person's changes on top of the task as it is now. A field both changed is a conflict, which the person resolves by\n * keeping their value or using the other one. Lists never conflict: their changes are applied as additions and\n * removals.\n */\n\n/** The task fields that hold one value, which can conflict. */\nexport type TaskField =\n | 'title'\n | 'description'\n | 'status'\n | 'priority'\n | 'dueTimestamp'\n | 'assignee'\n | 'project'\n | 'workflowStage';\n\nexport const TASK_FIELDS: readonly TaskField[] = [\n 'title',\n 'description',\n 'status',\n 'priority',\n 'dueTimestamp',\n 'assignee',\n 'project',\n 'workflowStage',\n];\n\n/** A field's value: text, a timestamp, or a reference. Absent and empty values are the same. */\nexport type TaskFieldValue = string | Ref | null | undefined;\n\n/** A field this person and someone else both changed since the base. */\nexport interface TaskConflict {\n field: TaskField;\n /** The value when this person started editing. */\n base: TaskFieldValue;\n /** The value someone else saved since. */\n theirs: TaskFieldValue;\n /** The value this person is saving. */\n mine: TaskFieldValue;\n}\n\n/** Which value to keep for each conflicting field. */\nexport type ConflictChoices = Partial<Record<TaskField, 'mine' | 'theirs'>>;\n\n/** Whether two values of a field are the same: references by URN, timestamps by instant, absent equal to empty. */\nexport function sameValue(field: TaskField, a: TaskFieldValue, b: TaskFieldValue): boolean {\n if (field === 'assignee' || field === 'project' || field === 'workflowStage') {\n return sameRef(a as Ref | null | undefined, b as Ref | null | undefined);\n }\n if (field === 'dueTimestamp') {\n return parseTimestamp(a as string | null | undefined)?.getTime() === parseTimestamp(b as string | null | undefined)?.getTime();\n }\n return ((a as string | null | undefined) ?? '') === ((b as string | null | undefined) ?? '');\n}\n\n/** The fields that differ between two versions of a task, single values first, then lists. */\nexport function changedFields(before: Task, after: Task): (TaskField | TaskListField)[] {\n return [\n ...TASK_FIELDS.filter((field) => !sameValue(field, before[field], after[field])),\n ...TASK_LIST_FIELDS.filter((field) => !sameRefs(before[field], after[field])),\n ];\n}\n\n/** The single-value fields `changes` sets. */\nexport function fieldsChanged(changes: TaskInput): TaskField[] {\n return TASK_FIELDS.filter((field) => changes[field] !== undefined);\n}\n\n/**\n * The fields `changes` sets that someone else also changed between `base` and `theirs`, to a different value.\n * Empty when the change can be saved as it is.\n */\nexport function findConflicts(base: Task, theirs: Task, changes: TaskInput): TaskConflict[] {\n return fieldsChanged(changes)\n .filter((field) => !sameValue(field, base[field], theirs[field]) && !sameValue(field, theirs[field], changes[field]))\n .map((field) => ({ field, base: base[field], theirs: theirs[field], mine: changes[field] }));\n}\n\n/**\n * `changes` with the choices applied: a field resolved to theirs is dropped, so the other person's value stays. Fields\n * without a choice keep this person's value.\n */\nexport function resolveConflicts(changes: TaskInput, choices: ConflictChoices): TaskInput {\n const result: TaskInput = { ...changes };\n for (const field of TASK_FIELDS) if (choices[field] === 'theirs') delete result[field];\n return result;\n}\n\n/**\n * List changes made against `base`, replayed on `theirs` as additions and removals, so items someone else added or\n * removed since are kept. Other fields are unchanged.\n */\nexport function rebaseLists(base: Task, theirs: Task, changes: TaskInput): TaskInput {\n const result: TaskInput = { ...changes };\n for (const field of TASK_LIST_FIELDS) {\n const mine = changes[field];\n if (mine === undefined) continue;\n const before = new Set((base[field] ?? []).map(urnOf));\n const after = new Set(mine.map(urnOf));\n const removed = new Set([...before].filter((urn) => !after.has(urn)));\n const added = mine.filter((item) => !before.has(urnOf(item)));\n result[field] = refs([...(theirs[field] ?? []).filter((item) => !removed.has(urnOf(item))), ...added]);\n }\n return result;\n}\n", "import type { Task } from '@baack-software/baack-ts-client';\nimport { urnOf } from './refs.ts';\nimport { isOpen } from './tasks.ts';\nimport type { RefLike } from './types.ts';\n\n/** Finds a task by URN, for example from a store or a `Map`. */\nexport type TaskLookup = (urn: string) => Task | undefined;\n\n/** A lookup over a list of tasks. */\nexport function lookupFrom(tasks: Iterable<Task>): TaskLookup {\n const byUrn = new Map<string, Task>();\n for (const task of tasks) byUrn.set(task.urn, task);\n return (urn) => byUrn.get(urn);\n}\n\n/**\n * The URNs of the tasks blocking `task` that are still open. A blocker the lookup doesn't know counts as open, since\n * the task may be blocked by work the reader can't see.\n */\nexport function openBlockers(task: Task, lookup: TaskLookup): string[] {\n return (task.blockedBy ?? [])\n .map((blocker) => blocker.urn)\n .filter((urn) => {\n const blocker = lookup(urn);\n return blocker === undefined || isOpen(blocker);\n });\n}\n\n/** Whether every task blocking `task` is done, so work can start. */\nexport function isUnblocked(task: Task, lookup: TaskLookup): boolean {\n return openBlockers(task, lookup).length === 0;\n}\n\n/**\n * Blocking edges among `tasks`, from each task to the tasks it blocks. Reads both `blocking` and `blockedBy`, so an\n * edge recorded on only one side still counts.\n */\nexport function blockingGraph(tasks: Iterable<Task>): Map<string, Set<string>> {\n const graph = new Map<string, Set<string>>();\n const edge = (from: string, to: string) => {\n const targets = graph.get(from) ?? new Set<string>();\n targets.add(to);\n graph.set(from, targets);\n };\n for (const task of tasks) {\n if (!graph.has(task.urn)) graph.set(task.urn, new Set());\n for (const blocked of task.blocking ?? []) edge(task.urn, blocked.urn);\n for (const blocker of task.blockedBy ?? []) edge(blocker.urn, task.urn);\n }\n return graph;\n}\n\n/** A cycle of blocking tasks as a list of URNs (the first task blocks the second, and so on, back to the first), or undefined. */\nexport function findBlockingCycle(tasks: Iterable<Task>): string[] | undefined {\n const graph = blockingGraph(tasks);\n const state = new Map<string, 'visiting' | 'done'>();\n const path: string[] = [];\n\n const visit = (urn: string): string[] | undefined => {\n state.set(urn, 'visiting');\n path.push(urn);\n for (const next of graph.get(urn) ?? []) {\n const seen = state.get(next);\n if (seen === 'visiting') return path.slice(path.indexOf(next));\n if (seen === undefined) {\n const cycle = visit(next);\n if (cycle) return cycle;\n }\n }\n path.pop();\n state.set(urn, 'done');\n return undefined;\n };\n\n for (const urn of graph.keys()) {\n if (state.get(urn) === undefined) {\n const cycle = visit(urn);\n if (cycle) return cycle;\n }\n }\n return undefined;\n}\n\n/** Whether making `blocker` block `task` would create a cycle, given the current `tasks`. */\nexport function wouldCreateCycle(tasks: Iterable<Task>, task: RefLike, blocker: RefLike): boolean {\n const from = urnOf(blocker);\n const to = urnOf(task);\n if (from === to) return true;\n // A cycle appears when the blocker is already reachable from the task it would block.\n const graph = blockingGraph(tasks);\n const queue = [to];\n const seen = new Set(queue);\n for (let urn = queue.shift(); urn !== undefined; urn = queue.shift()) {\n for (const next of graph.get(urn) ?? []) {\n if (next === from) return true;\n if (!seen.has(next)) {\n seen.add(next);\n queue.push(next);\n }\n }\n }\n return false;\n}\n\n/**\n * Tasks in an order where each comes after the tasks blocking it, keeping the given order otherwise. Tasks in a\n * cycle are placed at the end in their given order.\n */\nexport function dependencyOrder(tasks: readonly Task[]): Task[] {\n const known = new Set(tasks.map((task) => task.urn));\n const graph = blockingGraph(tasks);\n const waiting = new Map<string, number>(tasks.map((task) => [task.urn, 0]));\n for (const [from, targets] of graph) {\n if (!known.has(from)) continue;\n for (const to of targets) if (known.has(to)) waiting.set(to, (waiting.get(to) ?? 0) + 1);\n }\n\n const ordered: Task[] = [];\n const placed = new Set<string>();\n let progress = true;\n while (progress) {\n progress = false;\n for (const task of tasks) {\n if (placed.has(task.urn) || waiting.get(task.urn) !== 0) continue;\n ordered.push(task);\n placed.add(task.urn);\n progress = true;\n for (const to of graph.get(task.urn) ?? []) {\n if (known.has(to)) waiting.set(to, (waiting.get(to) ?? 0) - 1);\n }\n }\n }\n return [...ordered, ...tasks.filter((task) => !placed.has(task.urn))];\n}\n", "import type { TaskLog } from '@baack-software/baack-ts-client';\nimport type { Activity } from './types.ts';\n\n/** What happened, as a short sentence without the subject, e.g. \"Status set to In progress\". */\nexport const ACTIVITY_LABELS: Readonly<Record<Activity, string>> = {\n CREATED: 'Created',\n STATUS_UNDEFINED: 'Status set to Undefined',\n STATUS_PENDING: 'Status set to Pending',\n STATUS_IN_PROGRESS: 'Status set to In progress',\n STATUS_BLOCKED: 'Status set to Blocked',\n STATUS_COMPLETED: 'Status set to Completed',\n STATUS_COMPL_ETED: 'Status set to Completed',\n STATUS_CLOSED: 'Status set to Closed',\n PRIORITY_NONE: 'Priority set to None',\n PRIORITY_LOW: 'Priority set to Low',\n PRIORITY_MEDIUM: 'Priority set to Medium',\n PRIORITY_HIGH: 'Priority set to High',\n PRIORITY_CRITICAL: 'Priority set to Critical',\n WORKFLOW_STAGE_SET: 'Moved to a workflow stage',\n WORKFLOW_STAGE_UNSET: 'Removed from its workflow stage',\n COMMENT_ADDED: 'Commented',\n WORK_TASK_ASSOCIATION_ADDED: 'Related task added',\n WORK_TASK_ASSOCIATION_REMOVED: 'Related task removed',\n WORK_TASK_BLOCKER_ADDED: 'Blocker added',\n WORK_TASK_BLOCKER_REMOVED: 'Blocker removed',\n WORK_TASK_BLOCKING_ADDED: 'Now blocking a task',\n WORK_TASK_BLOCKING_REMOVED: 'No longer blocking a task',\n WORK_TASK_ENTITY_ADDED: 'Content added',\n WORK_TASK_ENTITY_REMOVED: 'Content removed',\n WORK_TASK_IDENTITY_ADDED: 'Person added',\n WORK_TASK_IDENTITY_REMOVED: 'Person removed',\n WORK_TASK_COMPANY_ADDED: 'Company added',\n WORK_TASK_COMPANY_REMOVED: 'Company removed',\n WORK_PROJECT_SET: 'Added to a project',\n WORK_PROJECT_UNSET: 'Removed from its project',\n ASSIGNED: 'Assigned',\n UNASSIGNED: 'Unassigned',\n TITLE_UPDATED: 'Title changed',\n DESCRIPTION_UPDATED: 'Description changed',\n DUE_DATE_UPDATED: 'Due date changed',\n DUE_DATE_UNSET: 'Due date removed',\n};\n\n/** A readable label for an activity, falling back to the raw value in lower case for activities added later. */\nexport function activityLabel(activity: string): string {\n return (ACTIVITY_LABELS as Record<string, string>)[activity] ?? activity.toLowerCase().replaceAll('_', ' ');\n}\n\n/** Whether the log entry is a comment rather than a recorded change. */\nexport function isComment(log: Pick<TaskLog, 'activity'>): boolean {\n return log.activity === 'COMMENT_ADDED';\n}\n\n/** A comment and the replies to it, oldest reply first. */\nexport interface CommentThread {\n comment: TaskLog;\n replies: TaskLog[];\n}\n\n/**\n * Groups comments into threads by `replyTo`, most recently active thread first. Expects `logs` newest first, as the\n * API returns them.\n * A reply whose parent is not in `logs` (for example on an older page) starts its own thread.\n */\nexport function commentThreads(logs: readonly TaskLog[]): CommentThread[] {\n const comments = logs.filter(isComment);\n const byUrn = new Map(comments.map((log) => [log.urn, log]));\n const rootOf = (log: TaskLog): TaskLog => {\n const seen = new Set<string>();\n let current = log;\n while (current.replyTo && byUrn.has(current.replyTo.urn) && !seen.has(current.urn)) {\n seen.add(current.urn);\n current = byUrn.get(current.replyTo.urn)!;\n }\n return current;\n };\n\n const threads = new Map<string, CommentThread>();\n for (const log of comments) {\n const root = rootOf(log);\n const thread = threads.get(root.urn) ?? { comment: root, replies: [] };\n if (root !== log) thread.replies.unshift(log);\n threads.set(root.urn, thread);\n }\n return [...threads.values()];\n}\n", "import type { Identity, Task, TaskPriority, TaskStatus, Workflow } from '@baack-software/baack-ts-client';\nimport { lookupFrom, openBlockers, type TaskLookup } from './blockers.ts';\nimport { dueDate, isOpen, isOverdue, PRIORITY_LABELS, STATUS_LABELS } from './tasks.ts';\nimport type { Ref } from './types.ts';\n\n/**\n * A task as its card shows it, for any UI: the React components draw it with shadcn/ui, and the Baack editor in its\n * own shadow DOM. Facts only; each UI chooses its words (the labels here are the en-GB defaults), formats dates in\n * its viewer's locale, and styles the tones.\n */\n\n/** A person, project or task a UI can name. */\nexport interface Named {\n urn: string;\n name: string;\n /** A person's email address, shown beside their name where there is room. */\n email?: string | undefined;\n}\n\n/**\n * What a UI knows beyond the tasks themselves: people to assign, projects, and the tasks a blocker or related task\n * refers to. From `TaskStore` state, or from any other source. Companies and content (entities) are offered as related\n * items when given, and workflows give stage columns and a stage picker.\n */\nexport interface TaskDirectory {\n people: readonly Named[];\n projects: readonly Named[];\n tasks: readonly Task[];\n companies?: readonly Named[] | undefined;\n entities?: readonly Named[] | undefined;\n workflows?: readonly Workflow[] | undefined;\n}\n\nexport const EMPTY_DIRECTORY: TaskDirectory = { people: [], projects: [], tasks: [] };\n\n/**\n * A person's name from their identity: its first person's name, held securely. An identity's `label` isn't one: it's a\n * non-secure label such as initials or a business name. Undefined when the identity carries no person's name.\n */\nexport function personName(identity: { persons?: Identity['persons'] | undefined }): string | undefined {\n const name = identity.persons?.[0]?.names?.[0];\n return [name?.givenName, name?.familyName].filter(Boolean).join(' ') || undefined;\n}\n\n/** An identity's first email address, if it has one. */\nexport function identityEmail(identity: Pick<Identity, 'emails'>): string | undefined {\n return identity.emails?.find((entry) => entry.email)?.email || undefined;\n}\n\n/**\n * A person from a search result, for `TaskDirectory.people`: named as `TaskClient.list` and `about` name them, with\n * the email of the identity they read (in `item`) when it has one.\n */\nexport function personFrom(item: { urn: string; name?: string | null; item?: unknown }): Named {\n const identity = item.item as Pick<Identity, 'emails'> | undefined;\n const email = identity && typeof identity === 'object' ? identityEmail(identity) : undefined;\n return { urn: item.urn, name: item.name ?? '', ...(email ? { email } : {}) };\n}\n\n/** What to call an identity: its person's name, else its label, else its email. Undefined when it has none. */\nexport function identityName(identity: Pick<Identity, 'persons' | 'label' | 'emails'>): string | undefined {\n return personName(identity) || identity.label?.trim() || identity.emails?.[0]?.email || undefined;\n}\n\n/**\n * The name of a person, project, task or stage, from the reference itself or the directory, else the end of its URN.\n * A person's name comes before an identity's label, which may only be initials.\n */\nexport function nameOf(\n directory: TaskDirectory,\n ref: Ref & { name?: string | null; label?: string | null; title?: string; persons?: Identity['persons'] | undefined },\n): string {\n return (\n ref.name ||\n personName(ref) ||\n directory.people.find((p) => p.urn === ref.urn)?.name ||\n ref.label ||\n ref.title ||\n directory.projects.find((p) => p.urn === ref.urn)?.name ||\n directory.tasks.find((t) => t.urn === ref.urn)?.title ||\n directory.companies?.find((c) => c.urn === ref.urn)?.name ||\n directory.entities?.find((e) => e.urn === ref.urn)?.name ||\n directory.workflows?.flatMap((w) => w.stages ?? []).find((s) => s.urn === ref.urn)?.name ||\n `\u2026${ref.urn.slice(-6)}`\n );\n}\n\n/** Up to two initials, for an avatar. */\nexport function initials(name: string): string {\n return name\n .split(/\\s+/)\n .filter(Boolean)\n .map((part) => part[0])\n .join('')\n .slice(0, 2)\n .toUpperCase();\n}\n\n/** How many avatar colours a UI offers; `TaskCardView.assignee.colour` is an index below it. */\nexport const AVATAR_COLOURS = 6;\n\n/** The same colour for a person every time, from their URN. */\nexport function avatarColour(urn: string): number {\n let hash = 0;\n for (const char of urn) hash = (hash * 31 + char.charCodeAt(0)) | 0;\n return Math.abs(hash) % AVATAR_COLOURS;\n}\n\n/** How a status reads: not started, under way, stuck, done, or set aside. */\nexport type StatusTone = 'muted' | 'default' | 'active' | 'danger' | 'success';\n\nexport const STATUS_TONES: Readonly<Record<TaskStatus, StatusTone>> = {\n UNDEFINED: 'muted',\n PENDING: 'default',\n IN_PROGRESS: 'active',\n BLOCKED: 'danger',\n COMPLETED: 'success',\n CLOSED: 'muted',\n};\n\nexport interface TaskCardView {\n urn: string;\n title: string;\n status: { value: TaskStatus; label: string; tone: StatusTone };\n priority: { value: TaskPriority; label: string };\n /** Not completed or closed. */\n open: boolean;\n /** Open tasks this one waits on, with their titles. */\n blockedBy: Named[];\n /** The due date, flagged when an open task is past it; undefined without one. */\n due: { date: Date; overdue: boolean } | undefined;\n /** Undefined when no one is assigned. `email` from the task's identity, or else the directory's person. */\n assignee: (Named & { initials: string; colour: number }) | undefined;\n}\n\nexport interface TaskCardOptions {\n /** Names people and blockers; its tasks are the ones blockers are looked up in. */\n directory?: TaskDirectory | undefined;\n /** Finds blockers; default a lookup over the directory's tasks. Pass one built once when making many cards. */\n lookup?: TaskLookup | undefined;\n /** For overdue; default now. */\n now?: Date | undefined;\n}\n\n/** A task as its card shows it: title, status, priority, blockers, due date and assignee. */\nexport function taskCard(task: Task, { directory = EMPTY_DIRECTORY, lookup, now }: TaskCardOptions = {}): TaskCardView {\n const due = dueDate(task);\n const assignee = task.assignee\n ? {\n urn: task.assignee.urn,\n name: nameOf(directory, task.assignee),\n email: identityEmail(task.assignee) ?? directory.people.find((person) => person.urn === task.assignee!.urn)?.email,\n }\n : undefined;\n return {\n urn: task.urn,\n title: task.title,\n status: { value: task.status, label: STATUS_LABELS[task.status], tone: STATUS_TONES[task.status] },\n priority: { value: task.priority, label: PRIORITY_LABELS[task.priority] },\n open: isOpen(task),\n blockedBy: openBlockers(task, lookup ?? lookupFrom(directory.tasks)).map((urn) => ({ urn, name: nameOf(directory, { urn }) })),\n due: due ? { date: due, overdue: isOverdue(task, now) } : undefined,\n assignee: assignee && { ...assignee, initials: initials(assignee.name), colour: avatarColour(assignee.urn) },\n };\n}\n", "import type { Task } from '@baack-software/baack-ts-client';\nimport type { TaskConflict } from './conflicts.ts';\nimport type { ValidationIssue } from './draft.ts';\n\n/** Thrown before sending a create or update the API would reject. */\nexport class TaskValidationError extends Error {\n override readonly name = 'TaskValidationError';\n\n constructor(readonly issues: ValidationIssue[]) {\n super(issues.map((issue) => issue.message).join(' '));\n }\n}\n\n/** Thrown when a search hasn't reached its full result in the time allowed. */\nexport class TaskSearchTimeoutError extends Error {\n override readonly name = 'TaskSearchTimeoutError';\n\n constructor(\n readonly searchUrn: string | undefined,\n readonly timeoutMs: number,\n ) {\n super(`Search ${searchUrn ?? ''} did not finish within ${timeoutMs} ms`);\n }\n}\n\n/**\n * Thrown before writing when someone else changed a field this update also changes, since the base the change was\n * made against. Nothing was saved. Resolve with `resolveConflicts` and update again with `current` as the base.\n */\nexport class TaskConflictError extends Error {\n override readonly name = 'TaskConflictError';\n\n constructor(\n readonly conflicts: TaskConflict[],\n /** The task as it is now. */\n readonly current: Task,\n ) {\n super(`Someone else changed ${conflicts.map((conflict) => conflict.field).join(', ')} on task ${current.urn}`);\n }\n}\n", "import {\n Endpoint,\n isBaackApiError,\n type BaackClient,\n type Company,\n type Identity,\n type IncludeScope,\n type Search,\n type SearchContext,\n type SearchItem,\n type Task,\n type TaskLog,\n type TaskPriority,\n type TaskStatus,\n type Workflow,\n} from '@baack-software/baack-ts-client';\nimport { identityName } from './card.ts';\nimport { draft as makeDraft, isEmptyChange, updateBody, validateTask, type DraftInput } from './draft.ts';\nimport { changedFields, fieldsChanged, findConflicts, rebaseLists, type TaskField } from './conflicts.ts';\nimport { TaskConflictError, TaskSearchTimeoutError, TaskValidationError } from './errors.ts';\nimport { ref, urnOf, withRef, withoutRef } from './refs.ts';\nimport { TASK_LIST_FIELDS, type RefLike, type TaskDraft, type TaskInput, type TaskListField, type TaskLogPage } from './types.ts';\n\n/** Options for a change: who made it, for the activity log. */\nexport interface ChangeOptions {\n /** The identity the change is attributed to in the activity log. It does not assign the task. */\n actor?: RefLike;\n}\n\nexport interface UpdateOptions extends ChangeOptions {\n /**\n * The task as the person saw it when they made the change, usually the copy the editor shows. When given, the update\n * is checked against it: if someone else changed a field this update also changes, it throws `TaskConflictError`\n * and saves nothing; list changes are applied as additions and removals to the lists as they are now.\n */\n base?: Task | undefined;\n /** Told which fields someone else changed since `base` that this update leaves as they are. */\n onChangedElsewhere?: ((fields: (TaskField | TaskListField)[], current: Task) => void) | undefined;\n}\n\nexport interface CommentOptions {\n /** The identity making the comment. */\n actor?: RefLike;\n /** The log entry this comment replies to. */\n replyTo?: RefLike;\n}\n\nexport interface PollOptions {\n /** First wait between reads of a running search. Default 250 ms. */\n intervalMs?: number;\n /** Longest wait between reads; waits grow by half each time up to this. Default 2000 ms. */\n maxIntervalMs?: number;\n /** Give up with `TaskSearchTimeoutError` after this long. Default 30000 ms. */\n timeoutMs?: number;\n}\n\nexport interface ListOptions {\n /** The company whose tasks to list. */\n owner: RefLike;\n /**\n * Also return the identities and projects the reader can see, for assignee and project pickers and names.\n * Default true. Turn off for readers without access to them.\n */\n includeRelated?: boolean;\n /** How many tasks to read at once. Default 6. */\n concurrency?: number;\n poll?: PollOptions;\n /** Stops polling and reading. A request already sent still completes. */\n signal?: AbortSignal;\n}\n\nexport interface AboutOptions extends Omit<ListOptions, 'includeRelated'> {\n /** Also return the identities related to the entity, the assignees of its tasks among them. Default true. */\n includeRelated?: boolean;\n}\n\nexport interface TaskListing {\n /** The tasks, in the search's order. Tasks deleted between the search and the read are left out. */\n tasks: Task[];\n /**\n * Identities seen by the search, with their names and, when it could be read, the identity itself as `item` (for its\n * emails; `personFrom` makes a directory's person of one): the company's for `list`, those related to the entity for\n * `about`. Empty when `includeRelated` is false.\n */\n identities: SearchItem[];\n /** Projects seen by the search, with their names. Empty when `includeRelated` is false, and for `about`. */\n projects: SearchItem[];\n}\n\n/**\n * Typed access to Baack tasks and their activity logs, on top of a `BaackClient` that holds the base URL and\n * credentials.\n *\n * ```ts\n * const tasks = new TaskClient(new BaackClient({ baseUrl: 'https://api.baack.co', credentials: 'include' }));\n * const { tasks: all } = await tasks.list({ owner: companyUrn });\n * await tasks.setStatus(all[0], 'IN_PROGRESS', { actor: me });\n * ```\n */\nexport class TaskClient {\n constructor(readonly client: BaackClient) {}\n\n // ==========================================\n // TASKS\n // ==========================================\n\n async get(task: RefLike): Promise<Task> {\n return this.client.read<Task>(Endpoint.TASK, urnOf(task));\n }\n\n /** Reads a workflow: its name and its stages, which tasks move through. */\n async getWorkflow(workflow: RefLike): Promise<Workflow> {\n return this.client.read<Workflow>(Endpoint.WORKFLOW, urnOf(workflow));\n }\n\n /**\n * Creates a task. Accepts a full `TaskDraft`, or the owner and title plus any other fields, which `draft` fills in.\n * Throws `TaskValidationError` before sending when the task breaks the API's rules.\n */\n async create(input: TaskDraft | DraftInput, options: ChangeOptions = {}): Promise<Task> {\n const body: TaskInput = withActor(makeDraft(input), options);\n const issues = validateTask(body, { creating: true });\n if (issues.length > 0) throw new TaskValidationError(issues);\n return this.client.create<Task>(Endpoint.TASK, body);\n }\n\n /**\n * Changes the task. The API stores the task as an update sends it, clearing optional fields left out, so this reads\n * the task, applies `changes` and sends it whole (see `updateBody`). Lists are sent whole and the server applies the\n * difference. Updates to the same task from this client run one at a time, so each builds on the last.\n *\n * `changes` can be a function of the task as just read, for changes built from its current state, such as adding\n * to a list.\n *\n * Throws `TaskValidationError` before sending when the changes break the API's rules. Returns the task as the\n * server has it after the change.\n *\n * The `BaackClient`'s `failureGuard` applies: retrying a failed update before its backoff has passed fails at once\n * with the same error, sending nothing.\n */\n async update(\n task: RefLike,\n changes: TaskInput | ((current: Task) => TaskInput),\n options: UpdateOptions = {},\n ): Promise<Task> {\n const urn = urnOf(task);\n const { base, onChangedElsewhere, ...change } = options;\n if (typeof changes !== 'function') {\n check(changes, urn);\n if (isEmptyChange(changes) && typeof task !== 'string' && isTask(task)) return task;\n }\n return this.#inTurn(urn, async () => {\n const current = await this.get(urn);\n let changed = typeof changes === 'function' ? changes(current) : changes;\n if (typeof changes === 'function') check(changed, urn);\n if (base) {\n // Reported even when the update then stops on a conflict, since the person sees the task as it is now.\n const touched = new Set<string>([...fieldsChanged(changed), ...TASK_LIST_FIELDS.filter((f) => changed[f] !== undefined)]);\n const elsewhere = changedFields(base, current).filter((field) => !touched.has(field));\n if (elsewhere.length > 0) onChangedElsewhere?.(elsewhere, current);\n const conflicts = findConflicts(base, current, changed);\n if (conflicts.length > 0) throw new TaskConflictError(conflicts, current);\n changed = rebaseLists(base, current, changed);\n }\n return this.client.update<Task>(Endpoint.TASK, urn, withActor(updateBody(current, changed), change));\n });\n }\n\n /** Updates waiting or running, by task URN. */\n readonly #turns = new Map<string, Promise<unknown>>();\n\n /** Runs `work` after the task's earlier updates settle, whether they succeeded or not. */\n #inTurn<T>(urn: string, work: () => Promise<T>): Promise<T> {\n const result = (this.#turns.get(urn) ?? Promise.resolve()).catch(() => undefined).then(work);\n this.#turns.set(urn, result);\n const forget = () => {\n if (this.#turns.get(urn) === result) this.#turns.delete(urn);\n };\n result.then(forget, forget);\n return result;\n }\n\n async delete(task: RefLike): Promise<void> {\n await this.client.delete(Endpoint.TASK, urnOf(task));\n }\n\n setStatus(task: RefLike, status: TaskStatus, options?: ChangeOptions): Promise<Task> {\n return this.update(task, { status }, options);\n }\n\n setPriority(task: RefLike, priority: TaskPriority, options?: ChangeOptions): Promise<Task> {\n return this.update(task, { priority }, options);\n }\n\n /** Assigns the task to `assignee`, or unassigns it with `null`. */\n assign(task: RefLike, assignee: RefLike | null, options?: ChangeOptions): Promise<Task> {\n return this.update(task, { assignee: assignee === null ? null : ref(assignee) }, options);\n }\n\n /** Sets the due date (a Baack timestamp, see `toTimestamp`), or removes it with `null`. */\n setDue(task: RefLike, dueTimestamp: string | null, options?: ChangeOptions): Promise<Task> {\n return this.update(task, { dueTimestamp }, options);\n }\n\n /** Moves the task into `project`, or out of its project with `null`. */\n setProject(task: RefLike, project: RefLike | null, options?: ChangeOptions): Promise<Task> {\n return this.update(task, { project: project === null ? null : ref(project) }, options);\n }\n\n /** Moves the task to a workflow stage, or out of its stage with `null`. */\n setWorkflowStage(task: RefLike, stage: RefLike | null, options?: ChangeOptions): Promise<Task> {\n return this.update(task, { workflowStage: stage === null ? null : ref(stage) }, options);\n }\n\n /** Marks `blocker` as blocking `task`. */\n addBlocker(task: RefLike, blocker: RefLike, options?: ChangeOptions): Promise<Task> {\n return this.addTo(task, 'blockedBy', blocker, options);\n }\n\n removeBlocker(task: RefLike, blocker: RefLike, options?: ChangeOptions): Promise<Task> {\n return this.removeFrom(task, 'blockedBy', blocker, options);\n }\n\n /** Adds a reference to one of the task's lists, as the server has the list when the update is sent. */\n addTo(task: RefLike, field: TaskListField, value: RefLike, options?: ChangeOptions): Promise<Task> {\n return this.update(task, (current) => ({ [field]: withRef(current[field], value) }), options);\n }\n\n /** Removes a reference from one of the task's lists, as the server has the list when the update is sent. */\n removeFrom(task: RefLike, field: TaskListField, value: RefLike, options?: ChangeOptions): Promise<Task> {\n return this.update(task, (current) => ({ [field]: withoutRef(current[field], value) }), options);\n }\n\n // ==========================================\n // ACTIVITY LOG\n // ==========================================\n\n /** One page of the task's activity log, newest first. Pass `pagination.after` from a page to read the next. */\n async logs(task: RefLike, options: { after?: string } = {}): Promise<TaskLogPage> {\n const page = await this.client.read<TaskLogPage | undefined>(Endpoint.TASK_LOGS, urnOf(task), {\n after: options.after,\n });\n return { logs: page?.logs ?? [], pagination: page?.pagination ?? null };\n }\n\n /** The task's activity log across pages, newest first, stopping after `limit` entries when given. */\n async allLogs(task: RefLike, options: { limit?: number } = {}): Promise<TaskLog[]> {\n const { limit = Number.POSITIVE_INFINITY } = options;\n const logs: TaskLog[] = [];\n let after: string | undefined;\n do {\n const page = await this.logs(task, after === undefined ? {} : { after });\n logs.push(...page.logs);\n after = page.pagination?.isMorePages ? (page.pagination.after ?? undefined) : undefined;\n } while (after !== undefined && logs.length < limit);\n return logs.slice(0, limit);\n }\n\n /** Adds a comment to the task's activity log. */\n async comment(task: RefLike, comment: string, options: CommentOptions = {}): Promise<TaskLog> {\n const body: Record<string, unknown> = { task: ref(task), activity: 'COMMENT_ADDED', comment };\n if (options.actor !== undefined) body['identity'] = ref(options.actor);\n if (options.replyTo !== undefined) body['replyTo'] = ref(options.replyTo);\n return this.client.create<TaskLog>(Endpoint.TASK_LOG, body);\n }\n\n // ==========================================\n // LISTING\n // ==========================================\n\n /**\n * Lists a company's tasks. Runs a search, waits for its full result, follows its pages, then\n * reads each task (search results don't carry the task itself yet).\n */\n async list(options: ListOptions): Promise<TaskListing> {\n const scopes: IncludeScope[] = options.includeRelated === false ? ['TASK'] : ['TASK', 'IDENTITY', 'PROJECT'];\n return this.listing({ owner: options.owner, scopes }, options);\n }\n\n /**\n * Lists the tasks associated with an entity, and the people related to it: its author, its contributors and the\n * assignees of its tasks. Runs a search in the entity's context, which returns only those, then reads each task as\n * `list` does. Every status is returned; `isOpen` picks the open ones.\n */\n async about(entity: RefLike, options: AboutOptions): Promise<TaskListing> {\n const scopes: IncludeScope[] = options.includeRelated === false ? ['TASK'] : ['TASK', 'IDENTITY'];\n return this.listing({ owner: options.owner, scopes, context: { entities: [ref(entity)] } }, options);\n }\n\n private async listing(query: SearchQuery, options: Omit<ListOptions, 'owner' | 'includeRelated'>): Promise<TaskListing> {\n const { concurrency = 6, signal } = options;\n const items = await this.search(query, { ...(options.poll ?? {}), ...(signal ? { signal } : {}) });\n\n const taskItems = items.filter((item) => item.type === 'TASK');\n const tasks = await mapLimit(taskItems, concurrency, signal, async (item) => {\n if (item.item && isTask(item.item)) return item.item;\n try {\n return await this.get(item.urn);\n } catch (error) {\n if (isBaackApiError(error) && error.isNotFound) return undefined;\n throw error;\n }\n });\n\n // A search result's name for an identity is its non-secure label (initials, or none), so each is read for its\n // person's name, and kept as the item (with its emails, see `personFrom`); one that can't be read keeps the\n // search's name.\n const identities = await mapLimit(\n items.filter((item) => item.type === 'IDENTITY'),\n concurrency,\n signal,\n async (item) => {\n try {\n const identity = await this.client.read<Identity>(Endpoint.IDENTITY, item.urn);\n return { ...item, name: identityName(identity) ?? item.name ?? null, item: identity };\n } catch (error) {\n if (isBaackApiError(error)) return item;\n throw error;\n }\n },\n );\n\n return {\n tasks: tasks.filter((task): task is Task => task !== undefined),\n identities: identities.filter((item): item is SearchItem => item !== undefined),\n projects: items.filter((item) => item.type === 'PROJECT'),\n };\n }\n\n /**\n * Runs a search and returns every item once the result is full, across pages. Exposed for callers that want other\n * scopes alongside tasks.\n */\n async search(\n query: SearchQuery,\n options: PollOptions & { signal?: AbortSignal } = {},\n ): Promise<SearchItem[]> {\n const { intervalMs = 250, maxIntervalMs = 2000, timeoutMs = 30000, signal } = options;\n const deadline = Date.now() + timeoutMs;\n\n // The API resolves the owner by URN; the client's Company type also wants a url.\n const body: Search = {\n owner: ref(query.owner) as Company,\n includeScopes: query.scopes,\n ...(query.context ? { context: query.context } : {}),\n };\n\n signal?.throwIfAborted();\n let search = await this.client.search(body);\n let wait = intervalMs;\n while (search.status !== 'FULL_RESULT') {\n if (!search.urn) throw new Error('The search API returned a search without a URN');\n if (Date.now() + wait > deadline) throw new TaskSearchTimeoutError(search.urn, timeoutMs);\n await sleep(wait, signal);\n search = await this.client.searchResult(search.urn);\n wait = Math.min(Math.round(wait * 1.5), maxIntervalMs);\n }\n\n const items = [...(search.items ?? [])];\n let pagination = search.pagination;\n while (pagination?.isMorePages && pagination.after && search.urn) {\n signal?.throwIfAborted();\n const page = await this.client.searchResult(search.urn, pagination.after);\n items.push(...(page.items ?? []));\n pagination = page.pagination;\n }\n return items;\n }\n}\n\n/** What to search for: the owner's items in these scopes, limited to what is related to `context` when given. */\nexport interface SearchQuery {\n owner: RefLike;\n scopes: IncludeScope[];\n context?: SearchContext;\n}\n\n/** Throws `TaskValidationError` when the changes break the API's rules. */\nfunction check(changes: TaskInput, urn: string): void {\n const issues = validateTask(changes, { urn });\n if (issues.length > 0) throw new TaskValidationError(issues);\n}\n\nfunction withActor<T extends TaskInput>(input: T, options: ChangeOptions): T {\n return options.actor === undefined ? input : { ...input, identityForLogs: ref(options.actor) };\n}\n\nfunction isTask(value: unknown): value is Task {\n return typeof value === 'object' && value !== null && 'urn' in value && 'title' in value && 'status' in value;\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n return new Promise((resolve, reject) => {\n if (signal?.aborted) return reject(signal.reason);\n const timer = setTimeout(() => {\n signal?.removeEventListener('abort', onAbort);\n resolve();\n }, ms);\n const onAbort = () => {\n clearTimeout(timer);\n reject(signal?.reason);\n };\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n}\n\n/** Maps `items` with at most `limit` calls running at once, keeping the input order. */\nasync function mapLimit<T, R>(\n items: readonly T[],\n limit: number,\n signal: AbortSignal | undefined,\n fn: (item: T) => Promise<R>,\n): Promise<R[]> {\n const results = new Array<R>(items.length);\n let next = 0;\n const worker = async () => {\n while (next < items.length) {\n signal?.throwIfAborted();\n const index = next++;\n results[index] = await fn(items[index]!);\n }\n };\n await Promise.all(Array.from({ length: Math.min(Math.max(1, limit), items.length) }, worker));\n return results;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["TASK_LIST_FIELDS", "urnOf", "value", "ref", "refs", "values", "seen", "result", "urn", "sameRef", "a", "b", "sameRefs", "left", "right", "withRef", "list", "withoutRef", "item", "HAS_ZONE", "parseTimestamp", "timestamp", "date", "toTimestamp", "toLocalInput", "pad", "n", "fromLocalInput", "value", "TASK_STATUSES", "TASK_PRIORITIES", "STATUS_LABELS", "PRIORITY_LABELS", "DONE", "isDoneStatus", "status", "isOpen", "task", "dueDate", "parseTimestamp", "isOverdue", "now", "due", "isDueWithin", "ms", "left", "byPriority", "a", "b", "byStatus", "byDue", "first", "second", "timeOrInfinity", "byUpdated", "byTitle", "compareBy", "comparators", "compare", "result", "byOpen", "byUrgency", "byPriorityThenDue", "timestamp", "fallback", "matchesFilter", "filter", "matchesRef", "isRelatedTo", "needle", "filterTasks", "tasks", "target", "urn", "urnOf", "list", "item", "value", "wanted", "candidate", "NONE_KEY", "groupTasks", "by", "groups", "priority", "key", "groupKey", "group", "workflowStages", "workflow", "groupByStage", "stage", "rest", "workflowOf", "workflows", "s", "groupByWorkflow", "TITLE_MAX_LENGTH", "DESCRIPTION_MAX_LENGTH", "draft", "input", "owner", "rest", "ref", "refs", "validateTask", "options", "issues", "creating", "urn", "title", "parseTimestamp", "item", "blockedBy", "urnOf", "taskChanges", "before", "after", "changes", "field", "value", "sameTime", "sameRef", "TASK_LIST_FIELDS", "sameRefs", "applyChanges", "task", "result", "updateBody", "body", "due", "isEmptyChange", "key", "a", "b", "TASK_FIELDS", "sameValue", "field", "a", "b", "sameRef", "parseTimestamp", "changedFields", "before", "after", "TASK_LIST_FIELDS", "sameRefs", "fieldsChanged", "changes", "findConflicts", "base", "theirs", "resolveConflicts", "choices", "result", "rebaseLists", "mine", "urnOf", "removed", "urn", "added", "item", "refs", "lookupFrom", "tasks", "byUrn", "task", "urn", "openBlockers", "lookup", "blocker", "isOpen", "isUnblocked", "blockingGraph", "graph", "edge", "from", "to", "targets", "blocked", "findBlockingCycle", "state", "path", "visit", "next", "seen", "cycle", "wouldCreateCycle", "urnOf", "queue", "dependencyOrder", "known", "waiting", "ordered", "placed", "progress", "ACTIVITY_LABELS", "activityLabel", "activity", "isComment", "log", "commentThreads", "logs", "comments", "byUrn", "rootOf", "seen", "current", "threads", "root", "thread", "EMPTY_DIRECTORY", "personName", "identity", "name", "identityEmail", "entry", "personFrom", "item", "email", "identityName", "nameOf", "directory", "ref", "p", "t", "c", "e", "w", "s", "initials", "part", "AVATAR_COLOURS", "avatarColour", "urn", "hash", "char", "STATUS_TONES", "taskCard", "task", "lookup", "now", "due", "dueDate", "assignee", "person", "STATUS_LABELS", "PRIORITY_LABELS", "isOpen", "openBlockers", "lookupFrom", "isOverdue", "TaskValidationError", "issues", "issue", "TaskSearchTimeoutError", "searchUrn", "timeoutMs", "TaskConflictError", "conflicts", "current", "conflict", "TaskClient", "client", "task", "Endpoint", "urnOf", "workflow", "input", "options", "body", "withActor", "draft", "issues", "validateTask", "TaskValidationError", "changes", "urn", "base", "onChangedElsewhere", "change", "check", "isEmptyChange", "isTask", "#inTurn", "current", "changed", "touched", "fieldsChanged", "TASK_LIST_FIELDS", "f", "elsewhere", "changedFields", "field", "conflicts", "findConflicts", "TaskConflictError", "rebaseLists", "updateBody", "#turns", "work", "result", "forget", "status", "priority", "assignee", "ref", "dueTimestamp", "project", "stage", "blocker", "value", "withRef", "withoutRef", "page", "limit", "logs", "after", "comment", "scopes", "entity", "query", "concurrency", "signal", "items", "taskItems", "item", "tasks", "mapLimit", "error", "isBaackApiError", "identities", "identity", "identityName", "intervalMs", "maxIntervalMs", "timeoutMs", "deadline", "search", "wait", "TaskSearchTimeoutError", "sleep", "pagination", "ms", "resolve", "reject", "timer", "onAbort", "fn", "results", "next", "worker", "index"]
7
+ }
@@ -0,0 +1,2 @@
1
+ import{$,A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z,_,a,aa,b,ba,c,ca,d,da,e,ea,f,fa,g,ga,h,ha,i,ia,j,ja,k,ka,l,la,m,ma,n,na,o,oa,p,pa,q,qa,r,ra,s,sa,t,ta,u,ua,v,va,w,wa,x,xa,y,ya,z,za}from"./chunk-VNUXOULZ.js";import"./chunk-5RFN34CS.js";export{ha as ACTIVITY_LABELS,sa as AVATAR_COLOURS,O as DESCRIPTION_MAX_LENGTH,la as EMPTY_DIRECTORY,H as NONE_KEY,p as PRIORITY_LABELS,o as STATUS_LABELS,ua as STATUS_TONES,V as TASK_FIELDS,a as TASK_LIST_FIELDS,n as TASK_PRIORITIES,m as TASK_STATUSES,N as TITLE_MAX_LENGTH,za as TaskClient,ya as TaskConflictError,xa as TaskSearchTimeoutError,wa as TaskValidationError,ia as activityLabel,S as applyChanges,ta as avatarColour,da as blockingGraph,x as byDue,B as byOpen,v as byPriority,D as byPriorityThenDue,w as byStatus,z as byTitle,y as byUpdated,C as byUrgency,X as changedFields,ka as commentThreads,A as compareBy,ga as dependencyOrder,P as draft,s as dueDate,Y as fieldsChanged,F as filterTasks,ea as findBlockingCycle,Z as findConflicts,l as fromLocalInput,K as groupByStage,M as groupByWorkflow,I as groupTasks,na as identityEmail,pa as identityName,ra as initials,ja as isComment,q as isDoneStatus,u as isDueWithin,U as isEmptyChange,r as isOpen,t as isOverdue,G as isRelatedTo,ca as isUnblocked,aa as lookupFrom,E as matchesFilter,qa as nameOf,ba as openBlockers,i as parseTimestamp,oa as personFrom,ma as personName,$ as rebaseLists,c as ref,d as refs,_ as resolveConflicts,e as sameRef,f as sameRefs,W as sameValue,va as taskCard,R as taskChanges,k as toLocalInput,j as toTimestamp,T as updateBody,b as urnOf,Q as validateTask,g as withRef,h as withoutRef,L as workflowOf,J as workflowStages,fa as wouldCreateCycle};
2
+ //# sourceMappingURL=dist-CF3GEGCB.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": [],
4
+ "sourcesContent": [],
5
+ "mappings": "",
6
+ "names": []
7
+ }