schemas.ts•12.5 kB
import { z } from "zod";
/**
* Task Operation Schemas
*/
// Completion filter schema
export const completionFilterSchema = z.enum([
"all",
"incomplete",
"completed",
]);
// Get tasks by day parameters
export const getTasksByDaySchema = z.object({
day: z.string().regex(
/^\d{4}-\d{2}-\d{2}$/,
"Day must be in YYYY-MM-DD format",
),
timezone: z.string().optional().describe(
"Timezone string (e.g., 'America/New_York'). If not provided, uses user's default timezone",
),
completionFilter: completionFilterSchema.optional().describe(
"Filter tasks by completion status. 'all' returns all tasks, 'incomplete' returns only incomplete tasks, 'completed' returns only completed tasks. Defaults to 'all'",
),
});
// Get tasks backlog parameters (no parameters needed)
export const getTasksBacklogSchema = z.object({});
// Get archived tasks parameters
export const getArchivedTasksSchema = z.object({
offset: z.number().int().min(0).optional().describe(
"Pagination offset (defaults to 0)",
),
limit: z.number().int().min(1).max(1000).optional().describe(
"Maximum number of tasks to return (defaults to 100)",
),
});
// Get task by ID parameters
export const getTaskByIdSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to retrieve",
),
});
/**
* User Operation Schemas
*/
// Get user parameters (no parameters needed)
export const getUserSchema = z.object({});
/**
* Stream Operation Schemas
*/
// Get streams parameters (no parameters needed, uses cached group ID)
export const getStreamsSchema = z.object({});
/**
* Task Integration Schemas
*/
// GitHub integration identifier schema
const githubIntegrationIdentifierSchema = z.object({
id: z.string().describe("GitHub issue or PR ID"),
repositoryOwnerLogin: z.string().describe("GitHub repository owner login"),
repositoryName: z.string().describe("GitHub repository name"),
number: z.number().int().describe("GitHub issue or PR number"),
type: z.enum(["Issue", "PullRequest"]).describe("Type of GitHub item"),
url: z.string().url().describe("URL to the GitHub issue or PR"),
__typename: z.literal("TaskGithubIntegrationIdentifier"),
});
// GitHub integration schema
const githubIntegrationSchema = z.object({
service: z.literal("github"),
identifier: githubIntegrationIdentifierSchema,
__typename: z.literal("TaskGithubIntegration"),
});
// Gmail integration identifier schema
const gmailIntegrationIdentifierSchema = z.object({
id: z.string().describe("Gmail message ID"),
messageId: z.string().describe("Gmail message ID (duplicate of id)"),
accountId: z.string().describe("Gmail account ID"),
url: z.string().url().describe("URL to the Gmail message"),
__typename: z.literal("TaskGmailIntegrationIdentifier"),
});
// Gmail integration schema
const gmailIntegrationSchema = z.object({
service: z.literal("gmail"),
identifier: gmailIntegrationIdentifierSchema,
__typename: z.literal("TaskGmailIntegration"),
});
// Union schema for all task integrations
const taskIntegrationSchema = z.discriminatedUnion("service", [
githubIntegrationSchema,
gmailIntegrationSchema,
]);
/**
* Task Mutation Operation Schemas
*/
// Create task parameters
export const createTaskSchema = z.object({
text: z.string().min(1, "Task text is required").describe(
"Task title/description",
),
notes: z.string().optional().describe("Additional task notes"),
streamIds: z.array(z.string()).optional().describe(
"Array of stream IDs to associate with the task",
),
timeEstimate: z.number().int().positive().optional().describe(
"Time estimate in minutes",
),
dueDate: z.string().optional().describe("Due date string (ISO format)"),
snoozeUntil: z.string().optional().describe(
"Snooze until date string (ISO format) - the date the task is scheduled for",
),
private: z.boolean().optional().describe("Whether the task is private"),
taskId: z.string().optional().describe(
"Custom task ID (auto-generated if not provided)",
),
integration: taskIntegrationSchema.optional().describe(
"Integration information for linking task to external services (GitHub, Gmail, etc.)",
),
});
// Update task complete parameters
export const updateTaskCompleteSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to mark as complete",
),
completeOn: z.string().optional().describe(
"Completion timestamp (ISO format). Defaults to current time",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit the response payload size",
),
});
// Delete task parameters
export const deleteTaskSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to delete",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit response size",
),
wasTaskMerged: z.boolean().optional().describe(
"Whether the task was merged before deletion",
),
});
// Update task snooze date parameters
export const updateTaskSnoozeDateSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to reschedule",
),
newDay: z.string().date("Must be a valid date in YYYY-MM-DD format").describe(
"Target date in YYYY-MM-DD format",
),
timezone: z.string().optional().describe(
"Timezone string (e.g., 'America/New_York'). If not provided, uses user's default timezone",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit the response payload size",
),
});
// Update task backlog parameters
export const updateTaskBacklogSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to move to backlog",
),
timezone: z.string().optional().describe(
"Timezone string (e.g., 'America/New_York'). If not provided, uses user's default timezone",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit the response payload size",
),
});
// Update task planned time parameters
export const updateTaskPlannedTimeSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to update planned time for",
),
timeEstimateMinutes: z.number().int().min(0).describe(
"Time estimate in minutes (use 0 to clear the time estimate)",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit the response payload size",
),
});
// Update task notes parameters with XOR content validation
export const updateTaskNotesSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to update notes for",
),
html: z.string().optional().describe(
"HTML content for the task notes (mutually exclusive with markdown)",
),
markdown: z.string().optional().describe(
"Markdown content for the task notes (mutually exclusive with html)",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit the response payload size (defaults to true)",
),
}).refine(
(data) => {
// Exactly one of html or markdown must be provided
const hasHtml = data.html !== undefined;
const hasMarkdown = data.markdown !== undefined;
return hasHtml !== hasMarkdown; // XOR: exactly one must be true
},
{
message: "Exactly one of 'html' or 'markdown' must be provided",
path: [], // This will show the error at the root level
},
);
// Update task due date parameters
export const updateTaskDueDateSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to update due date for",
),
dueDate: z.union([
z.string().datetime("Must be a valid ISO date-time string"),
z.null(),
]).describe(
"Due date in ISO format (YYYY-MM-DDTHH:mm:ssZ) or null to clear the due date",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit the response payload size",
),
});
// Update task text parameters
export const updateTaskTextSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to update",
),
text: z.string().min(1, "Task text is required").describe(
"The new text/title for the task",
),
recommendedStreamId: z.string().nullable().optional().describe(
"Recommended stream ID (optional)",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit the response payload size",
),
});
// Update task stream parameters
export const updateTaskStreamSchema = z.object({
taskId: z.string().min(1, "Task ID is required").describe(
"The ID of the task to update stream assignment for",
),
streamId: z.string().min(1, "Stream ID is required").describe(
"Stream ID to assign to the task",
),
limitResponsePayload: z.boolean().optional().describe(
"Whether to limit the response payload size",
),
});
/**
* Response Type Schemas (for validation and documentation)
*/
// Basic user profile schema
export const userProfileSchema = z.object({
_id: z.string(),
email: z.string().email(),
firstName: z.string(),
lastName: z.string(),
timezone: z.string(),
avatarUrl: z.string().url().optional(),
});
// Group schema
export const groupSchema = z.object({
groupId: z.string(),
name: z.string(),
role: z.string().optional(),
});
// User schema with primary group
export const userSchema = z.object({
_id: z.string(),
email: z.string().email(),
profile: userProfileSchema,
primaryGroup: groupSchema.optional(),
});
// Task schema (simplified - based on common task properties)
export const taskSchema = z.object({
_id: z.string(),
title: z.string(),
description: z.string().optional(),
status: z.string(),
createdAt: z.string(),
updatedAt: z.string(),
scheduledDate: z.string().optional(),
completedAt: z.string().optional(),
streamId: z.string().optional(),
userId: z.string(),
groupId: z.string(),
});
// Stream schema
export const streamSchema = z.object({
_id: z.string(),
name: z.string(),
color: z.string().optional(),
groupId: z.string(),
isActive: z.boolean(),
createdAt: z.string(),
updatedAt: z.string(),
});
/**
* API Response Schemas
*/
// User response
export const userResponseSchema = z.object({
user: userSchema,
});
// Tasks response
export const tasksResponseSchema = z.object({
tasks: z.array(taskSchema),
count: z.number(),
});
// Streams response
export const streamsResponseSchema = z.object({
streams: z.array(streamSchema),
count: z.number(),
});
/**
* Error Response Schema
*/
export const errorResponseSchema = z.object({
error: z.string(),
message: z.string(),
code: z.string().optional(),
});
/**
* Type Exports (for use in tools)
*/
export type CompletionFilter = z.infer<typeof completionFilterSchema>;
export type GetTasksByDayInput = z.infer<typeof getTasksByDaySchema>;
export type GetTasksBacklogInput = z.infer<typeof getTasksBacklogSchema>;
export type GetArchivedTasksInput = z.infer<typeof getArchivedTasksSchema>;
export type GetTaskByIdInput = z.infer<typeof getTaskByIdSchema>;
export type GetUserInput = z.infer<typeof getUserSchema>;
export type GetStreamsInput = z.infer<typeof getStreamsSchema>;
export type CreateTaskInput = z.infer<typeof createTaskSchema>;
export type UpdateTaskCompleteInput = z.infer<typeof updateTaskCompleteSchema>;
export type DeleteTaskInput = z.infer<typeof deleteTaskSchema>;
export type UpdateTaskSnoozeDateInput = z.infer<
typeof updateTaskSnoozeDateSchema
>;
export type UpdateTaskBacklogInput = z.infer<typeof updateTaskBacklogSchema>;
export type UpdateTaskPlannedTimeInput = z.infer<
typeof updateTaskPlannedTimeSchema
>;
export type UpdateTaskNotesInput = z.infer<typeof updateTaskNotesSchema>;
export type UpdateTaskDueDateInput = z.infer<typeof updateTaskDueDateSchema>;
export type UpdateTaskTextInput = z.infer<typeof updateTaskTextSchema>;
export type UpdateTaskStreamInput = z.infer<typeof updateTaskStreamSchema>;
export type User = z.infer<typeof userSchema>;
export type Task = z.infer<typeof taskSchema>;
export type Stream = z.infer<typeof streamSchema>;
export type UserResponse = z.infer<typeof userResponseSchema>;
export type TasksResponse = z.infer<typeof tasksResponseSchema>;
export type StreamsResponse = z.infer<typeof streamsResponseSchema>;
export type ErrorResponse = z.infer<typeof errorResponseSchema>;