first commit
This commit is contained in:
commit
0a45a1f5fb
|
@ -0,0 +1,5 @@
|
|||
summary: null
|
||||
display_name: App Custom Components
|
||||
extra_perms:
|
||||
g/all: false
|
||||
owners: []
|
|
@ -0,0 +1,5 @@
|
|||
summary: null
|
||||
display_name: App Groups
|
||||
extra_perms:
|
||||
g/all: false
|
||||
owners: []
|
|
@ -0,0 +1,5 @@
|
|||
summary: null
|
||||
display_name: App Themes
|
||||
extra_perms:
|
||||
g/all: false
|
||||
owners: []
|
|
@ -0,0 +1,155 @@
|
|||
// clickup/create_task.ts
|
||||
type TaskInput = {
|
||||
// REQUIRED FIELDS
|
||||
/** The ID of the list to put this task into */
|
||||
list_id: string;
|
||||
/** Name of the task (max 99840 chars) */
|
||||
name: string;
|
||||
|
||||
// OPTIONAL CORE FIELDS
|
||||
/** Detailed task description (supports markdown) */
|
||||
description?: string;
|
||||
/** Task status must match existing status in List */
|
||||
status?: string;
|
||||
/** Unix timestamp in milliseconds */
|
||||
due_date?: number;
|
||||
/** Unix timestamp in milliseconds */
|
||||
start_date?: number;
|
||||
/** Time estimate in milliseconds */
|
||||
time_estimate?: number;
|
||||
/** Markdown-formatted description */
|
||||
markdown_description?: string;
|
||||
/** Priority level (1-4) */
|
||||
priority?: 1 | 2 | 3 | 4;
|
||||
/** Parent task ID for subtasks */
|
||||
parent?: string;
|
||||
/** Custom task type ID */
|
||||
custom_item_id?: number;
|
||||
|
||||
// PEOPLE MANAGEMENT
|
||||
/** Array of user IDs */
|
||||
assignees?: number[];
|
||||
/** Notify all task members */
|
||||
notify_all?: boolean;
|
||||
|
||||
// TAGS & RELATIONSHIPS
|
||||
/** Array of tag names */
|
||||
tags?: string[];
|
||||
/** Task dependencies */
|
||||
depends_on?: string[];
|
||||
/** Linked task IDs */
|
||||
links_to?: string;
|
||||
|
||||
// CUSTOMIZATION
|
||||
/** Array of custom field objects */
|
||||
custom_fields?: {
|
||||
/** Custom field ID */
|
||||
id: string;
|
||||
/** Field value (type-specific) */
|
||||
value: string | number | boolean | string[];
|
||||
}[];
|
||||
|
||||
// VALIDATION FLAGS
|
||||
/** Enforce required custom fields */
|
||||
check_required_custom_fields?: boolean;
|
||||
|
||||
// ADVANCED OPTIONS
|
||||
/** Team ID for custom task IDs */
|
||||
team_id?: number;
|
||||
/** Custom task ID (requires team_id) */
|
||||
custom_task_id?: string;
|
||||
/** Task creation source (max 6 chars) */
|
||||
source?: string;
|
||||
};
|
||||
|
||||
// All we need here is the access token.
|
||||
type ClickupCredentials = {
|
||||
access_token: string;
|
||||
};
|
||||
|
||||
export async function main(
|
||||
params: TaskInput,
|
||||
credentials: ClickupCredentials
|
||||
) {
|
||||
// 1. Input Validation
|
||||
if (!params.list_id?.trim()) {
|
||||
throw new Error("Missing required field: list_id");
|
||||
}
|
||||
|
||||
if (!params.name?.trim()) {
|
||||
throw new Error("Missing required field: name");
|
||||
}
|
||||
|
||||
// 2. API Request Configuration
|
||||
const response = await fetch(`https://api.clickup.com/api/v2/list/${params.list_id}/task`, {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"accept": 'application/json',
|
||||
"Authorization": "Bearer " + credentials.access_token
|
||||
},
|
||||
body: JSON.stringify({
|
||||
// Required
|
||||
name: params.name,
|
||||
|
||||
// Core optional parameters
|
||||
description: params.description,
|
||||
status: params.status,
|
||||
due_date: params.due_date,
|
||||
start_date: params.start_date,
|
||||
time_estimate: params.time_estimate,
|
||||
markdown_description: params.markdown_description,
|
||||
priority: params.priority,
|
||||
parent: params.parent,
|
||||
custom_item_id: params.custom_item_id,
|
||||
|
||||
// People management
|
||||
assignees: params.assignees,
|
||||
notify_all: params.notify_all,
|
||||
|
||||
// Tags & relationships
|
||||
tags: params.tags,
|
||||
depends_on: params.depends_on,
|
||||
links_to: params.links_to,
|
||||
|
||||
// Customization
|
||||
custom_fields: params.custom_fields?.map(field => ({
|
||||
id: field.id,
|
||||
value: field.value
|
||||
})),
|
||||
|
||||
// Validation flags
|
||||
check_required_custom_fields: params.check_required_custom_fields,
|
||||
|
||||
// Advanced configurations
|
||||
team_id: params.team_id,
|
||||
custom_task_id: params.custom_task_id,
|
||||
source: params.source
|
||||
})
|
||||
|
||||
});
|
||||
|
||||
// 3. Error Handling
|
||||
if (!response.ok) {
|
||||
const errorBody = await response.text();
|
||||
throw new Error(`ClickUp API Error (${response.status}): ${errorBody}`);
|
||||
}
|
||||
|
||||
// 4. Response Processing
|
||||
const result = await response.json();
|
||||
|
||||
// Validate successful task creation
|
||||
if (!result?.id) {
|
||||
throw new Error("Failed to create task: No ID returned");
|
||||
}
|
||||
|
||||
return {
|
||||
task_id: result.id,
|
||||
url: result.url,
|
||||
status: result.status?.status || "created",
|
||||
_metadata: {
|
||||
clickup_space: result.space?.id,
|
||||
created_at: new Date().toISOString()
|
||||
}
|
||||
};
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
summary: Create Task
|
||||
description: ''
|
||||
lock: ''
|
||||
kind: script
|
||||
schema:
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema'
|
||||
type: object
|
||||
properties:
|
||||
credentials:
|
||||
type: object
|
||||
description: ''
|
||||
default: null
|
||||
format: resource-clickup_credentials
|
||||
params:
|
||||
type: object
|
||||
description: ''
|
||||
default: null
|
||||
format: resource-task_input
|
||||
required:
|
||||
- params
|
||||
- credentials
|
|
@ -0,0 +1,7 @@
|
|||
summary: ''
|
||||
display_name: clickup
|
||||
extra_perms:
|
||||
g/all: true
|
||||
u/peter: true
|
||||
owners:
|
||||
- u/peter
|
|
@ -0,0 +1,205 @@
|
|||
// clickup/get_task.ts
|
||||
interface TaskResponse {
|
||||
id: string;
|
||||
name: string;
|
||||
description?: string;
|
||||
text_content?: string;
|
||||
status?: {
|
||||
status: string;
|
||||
color: string;
|
||||
orderindex: number;
|
||||
type: "open" | "closed" | "custom";
|
||||
};
|
||||
orderindex?: string;
|
||||
date_created?: string;
|
||||
date_updated?: string;
|
||||
date_closed?: string | null;
|
||||
date_done?: string | null;
|
||||
archived?: boolean;
|
||||
creator?: {
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
color: string;
|
||||
profilePicture?: string;
|
||||
};
|
||||
assignees?: Array<{
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
color: string;
|
||||
initials: string;
|
||||
profilePicture?: string;
|
||||
}>;
|
||||
watchers?: Array<{
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
color: string;
|
||||
initials: string;
|
||||
profilePicture?: string;
|
||||
}>;
|
||||
checklists?: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
orderindex: number;
|
||||
resolved: number;
|
||||
unresolved: number;
|
||||
items: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
orderindex: number;
|
||||
assignee?: number;
|
||||
resolved: boolean;
|
||||
parent?: string;
|
||||
date_created: string;
|
||||
children?: string[];
|
||||
}>;
|
||||
}>;
|
||||
tags?: Array<{
|
||||
name: string;
|
||||
tag_fg: string;
|
||||
tag_bg: string;
|
||||
creator?: number;
|
||||
}>;
|
||||
parent?: string | null;
|
||||
priority?: {
|
||||
id: string;
|
||||
priority: "urgent" | "high" | "normal" | "low";
|
||||
color: string;
|
||||
};
|
||||
due_date?: string | null;
|
||||
start_date?: string | null;
|
||||
time_estimate?: number | null;
|
||||
time_spent?: number | null;
|
||||
custom_fields?: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
type_config: Record<string, any>;
|
||||
value: any;
|
||||
}>;
|
||||
list?: {
|
||||
id: string;
|
||||
name: string;
|
||||
access: boolean;
|
||||
};
|
||||
project?: {
|
||||
id: string;
|
||||
name: string;
|
||||
hidden: boolean;
|
||||
access: boolean;
|
||||
};
|
||||
folder?: {
|
||||
id: string;
|
||||
name: string;
|
||||
hidden: boolean;
|
||||
access: boolean;
|
||||
};
|
||||
space?: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
url?: string;
|
||||
permission_level?: string;
|
||||
custom_item_id?: number | null;
|
||||
custom_task_ids?: Array<{
|
||||
custom_task_id: string;
|
||||
team_id: string;
|
||||
}>;
|
||||
dependencies?: Array<{
|
||||
task_id: string;
|
||||
depends_on: string;
|
||||
type: number;
|
||||
date_created: string;
|
||||
userid: string;
|
||||
}>;
|
||||
linked_tasks?: Array<{
|
||||
task_id: string;
|
||||
link_id: string;
|
||||
date_created: string;
|
||||
userid: string;
|
||||
}>;
|
||||
team_id?: string;
|
||||
custom_id?: string | null;
|
||||
attachments?: Array<{
|
||||
id: string;
|
||||
version: string;
|
||||
date: string;
|
||||
title: string;
|
||||
extension: string;
|
||||
thumbnail_small: string;
|
||||
thumbnail_large: string;
|
||||
size: number;
|
||||
}>;
|
||||
shared?: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
access_level: string;
|
||||
team_id: string;
|
||||
}>;
|
||||
followers?: Array<{
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
color: string;
|
||||
initials: string;
|
||||
profilePicture?: string;
|
||||
}>;
|
||||
[key: string]: any; // For future API additions
|
||||
}
|
||||
|
||||
type FieldSelector = Array<keyof TaskResponse | string>;
|
||||
|
||||
// All we need here is the access token.
|
||||
type ClickupCredentials = {
|
||||
access_token: string;
|
||||
};
|
||||
|
||||
export async function main(
|
||||
task_id: string,
|
||||
fields: FieldSelector = ["id", "name", "status", "date_created"],
|
||||
credentials: ClickupCredentials,
|
||||
) {
|
||||
// Input validation
|
||||
if (!task_id?.trim()) throw new Error("Task ID is required");
|
||||
|
||||
// API call
|
||||
const response = await fetch(
|
||||
`https://api.clickup.com/api/v2/task/${task_id}`,
|
||||
{
|
||||
headers: {
|
||||
"Authorization": credentials.access_token,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
if (!response.ok) {
|
||||
const error = await response.text();
|
||||
throw new Error(`ClickUp Error ${response.status}: ${error}`);
|
||||
}
|
||||
|
||||
// Full response parsing
|
||||
const fullTask = await response.json();
|
||||
|
||||
// Field filtering
|
||||
return fields.length > 0 ? filterFields(fullTask, fields) : fullTask;
|
||||
}
|
||||
|
||||
// Recursive field filtering function
|
||||
function filterFields(obj: any, fields: FieldSelector): any {
|
||||
return fields.reduce((acc, field) => {
|
||||
const [root, ...nested] = (field as string).split(".");
|
||||
|
||||
if (obj[root] !== undefined) {
|
||||
if (nested.length > 0 && typeof obj[root] === "object") {
|
||||
acc[root] = filterFields(obj[root], [nested.join(".")]);
|
||||
} else {
|
||||
acc[root] = obj[root];
|
||||
}
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, {} as Record<string, any>);
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
summary: Get Task
|
||||
description: ''
|
||||
lock: ''
|
||||
kind: script
|
||||
schema:
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema'
|
||||
type: object
|
||||
properties:
|
||||
credentials:
|
||||
type: object
|
||||
description: ''
|
||||
default: null
|
||||
format: resource-clickup_credentials
|
||||
properties:
|
||||
access_token:
|
||||
type: string
|
||||
description: ''
|
||||
originalType: string
|
||||
fields:
|
||||
type: object
|
||||
description: ''
|
||||
default:
|
||||
- id
|
||||
- name
|
||||
- status
|
||||
- date_created
|
||||
format: resource-field_selector
|
||||
task_id:
|
||||
type: string
|
||||
description: ''
|
||||
default: null
|
||||
originalType: string
|
||||
required:
|
||||
- task_id
|
||||
- credentials
|
|
@ -0,0 +1,132 @@
|
|||
import * as wmill from "jsr:@windmill/windmill";
|
||||
|
||||
type ClickupCredentials = {
|
||||
client_id: string;
|
||||
expires_at: number;
|
||||
access_token: string;
|
||||
client_secret: string;
|
||||
};
|
||||
|
||||
// Function to initiate OAuth flow and get initial tokens
|
||||
export async function get_initial_token(
|
||||
client_id: string,
|
||||
client_secret: string,
|
||||
redirect_uri: string,
|
||||
) {
|
||||
const state = crypto.randomUUID();
|
||||
|
||||
const authUrl = `https://app.clickup.com/api?client_id=${encodeURIComponent(client_id)
|
||||
}&redirect_uri=${encodeURIComponent(redirect_uri)}&state=${encodeURIComponent(state)
|
||||
}&response_type=code&scope=*`;
|
||||
|
||||
console.log("Please visit this URL to authorize the application:", authUrl);
|
||||
|
||||
return {
|
||||
auth_url: authUrl,
|
||||
state: state,
|
||||
next_step:
|
||||
"After authorization, you will receive a code in the redirect URI. Use this code with exchange_code_for_token function and verify the state parameter matches.",
|
||||
};
|
||||
}
|
||||
|
||||
// Function to exchange authorization code for tokens
|
||||
export async function exchange_code_for_token(
|
||||
code: string,
|
||||
client_id: string,
|
||||
client_secret: string,
|
||||
expected_state?: string,
|
||||
received_state?: string,
|
||||
) {
|
||||
if (expected_state && received_state) {
|
||||
if (expected_state !== received_state) {
|
||||
throw new Error("State parameter mismatch - possible CSRF attack");
|
||||
}
|
||||
}
|
||||
|
||||
const formData = new URLSearchParams({
|
||||
client_id: client_id,
|
||||
client_secret: client_secret,
|
||||
code: code,
|
||||
grant_type: "authorization_code"
|
||||
});
|
||||
|
||||
try {
|
||||
const response = await fetch("https://api.clickup.com/api/v2/oauth/token", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded",
|
||||
},
|
||||
body: formData.toString(),
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const errorText = await response.text();
|
||||
console.error("Token exchange error details:", {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
error: errorText,
|
||||
requestBody: formData.toString(),
|
||||
});
|
||||
throw new Error(
|
||||
`Token exchange failed: ${response.status} ${errorText}`,
|
||||
);
|
||||
}
|
||||
|
||||
const tokens = await response.json();
|
||||
|
||||
const credentials: ClickupCredentials = {
|
||||
client_id,
|
||||
client_secret,
|
||||
access_token: tokens.access_token,
|
||||
expires_at: Date.now() + (tokens.expires_in * 1000),
|
||||
};
|
||||
|
||||
// Using setResource with string path instead of object
|
||||
await wmill.setResource("f/clickup/clickup_prod_creds", JSON.stringify(credentials));
|
||||
|
||||
return {
|
||||
status: "initialized",
|
||||
expires_at: new Date(credentials.expires_at).toISOString(),
|
||||
};
|
||||
} catch (error) {
|
||||
console.error("Detailed error:", error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
export async function main(
|
||||
clickupResource: ClickupCredentials,
|
||||
mode: "check" | "refresh" | "initialize" = "check",
|
||||
code?: string,
|
||||
redirect_uri?: string,
|
||||
state?: string,
|
||||
expected_state?: string,
|
||||
) {
|
||||
if (mode === "initialize") {
|
||||
if (!clickupResource.client_id || !clickupResource.client_secret) {
|
||||
throw new Error(
|
||||
"Client ID and Client Secret are required for initialization",
|
||||
);
|
||||
}
|
||||
if (!redirect_uri) {
|
||||
throw new Error("Redirect URI is required for initialization");
|
||||
}
|
||||
return await get_initial_token(
|
||||
clickupResource.client_id,
|
||||
clickupResource.client_secret,
|
||||
redirect_uri,
|
||||
);
|
||||
}
|
||||
|
||||
if (!code) {
|
||||
throw new Error("Clickup oAuth CODE required to get token. Use Initialize step first.");
|
||||
}
|
||||
|
||||
return await exchange_code_for_token(
|
||||
code,
|
||||
clickupResource.client_id,
|
||||
clickupResource.client_secret,
|
||||
expected_state,
|
||||
state,
|
||||
);
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"version": "4",
|
||||
"specifiers": {
|
||||
"jsr:@windmill/windmill@*": "1.458.2"
|
||||
},
|
||||
"jsr": {
|
||||
"@windmill/windmill@1.458.2": {
|
||||
"integrity": "c3188c099b9553cd92c5f3aa2b9a4f500feef31d8222237b527b7751de49558c"
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
summary: Rotate Tokens
|
||||
description: ''
|
||||
lock: '!inline f/clickup/rotate_tokens.script.lock'
|
||||
concurrency_time_window_s: 0
|
||||
kind: script
|
||||
schema:
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema'
|
||||
type: object
|
||||
order: []
|
||||
properties:
|
||||
clickupResource:
|
||||
type: object
|
||||
description: ''
|
||||
default: null
|
||||
format: resource-clickup_credentials
|
||||
code:
|
||||
type: string
|
||||
description: ''
|
||||
default: null
|
||||
originalType: string
|
||||
expected_state:
|
||||
type: string
|
||||
description: ''
|
||||
default: null
|
||||
originalType: string
|
||||
mode:
|
||||
type: string
|
||||
description: ''
|
||||
default: check
|
||||
enum:
|
||||
- check
|
||||
- refresh
|
||||
- initialize
|
||||
originalType: enum
|
||||
redirect_uri:
|
||||
type: string
|
||||
description: ''
|
||||
default: null
|
||||
originalType: string
|
||||
state:
|
||||
type: string
|
||||
description: ''
|
||||
default: null
|
||||
originalType: string
|
||||
required:
|
||||
- clickupResource
|
|
@ -0,0 +1,64 @@
|
|||
// utils/filter-task-fields.ts
|
||||
import type { TaskResponse } from '../types/clickup';
|
||||
|
||||
type FieldSelector = Array<string | NestedField>;
|
||||
type NestedField = {
|
||||
field: string;
|
||||
subfields?: FieldSelector;
|
||||
};
|
||||
|
||||
export function filterTaskFields(
|
||||
task: TaskResponse,
|
||||
fields: FieldSelector
|
||||
): Partial<TaskResponse> {
|
||||
return fields.reduce((acc, selector) => {
|
||||
if (typeof selector === 'string') {
|
||||
handleStringSelector(acc, task, selector);
|
||||
} else if (selector.subfields) {
|
||||
handleNestedSelector(acc, task, selector);
|
||||
}
|
||||
return acc;
|
||||
}, {} as Partial<TaskResponse>);
|
||||
}
|
||||
|
||||
function handleStringSelector(
|
||||
acc: Partial<TaskResponse>,
|
||||
task: TaskResponse,
|
||||
selector: string
|
||||
) {
|
||||
const [root, ...nested] = selector.split('.');
|
||||
|
||||
if (task[root as keyof TaskResponse] !== undefined) {
|
||||
if (nested.length > 0) {
|
||||
acc[root as keyof TaskResponse] = processNestedField(
|
||||
task[root as keyof TaskResponse],
|
||||
nested.join('.')
|
||||
);
|
||||
} else {
|
||||
acc[root as keyof TaskResponse] = task[root as keyof TaskResponse];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function handleNestedSelector(
|
||||
acc: Partial<TaskResponse>,
|
||||
task: TaskResponse,
|
||||
selector: NestedField
|
||||
) {
|
||||
const value = task[selector.field as keyof TaskResponse];
|
||||
if (value && typeof value === 'object') {
|
||||
acc[selector.field as keyof TaskResponse] = Array.isArray(value)
|
||||
? value.map(item => filterTaskFields(item as TaskResponse, selector.subfields!))
|
||||
: filterTaskFields(value as TaskResponse, selector.subfields!);
|
||||
}
|
||||
}
|
||||
|
||||
function processNestedField(value: any, nestedPath: string): any {
|
||||
const [current, ...remaining] = nestedPath.split('.');
|
||||
|
||||
if (value[current] === undefined) return undefined;
|
||||
|
||||
return remaining.length > 0
|
||||
? processNestedField(value[current], remaining.join('.'))
|
||||
: value[current];
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
summary: Filter Task Fields
|
||||
description: ''
|
||||
lock: ''
|
||||
kind: script
|
||||
no_main_func: true
|
||||
schema:
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema'
|
||||
type: object
|
||||
properties: {}
|
||||
required: []
|
|
@ -0,0 +1,6 @@
|
|||
summary: null
|
||||
display_name: clickup_utils
|
||||
extra_perms:
|
||||
u/peter: true
|
||||
owners:
|
||||
- u/peter
|
|
@ -0,0 +1,241 @@
|
|||
// types/clickup.d.ts
|
||||
|
||||
/**
|
||||
* Base Task Interface - Shared mutable fields across operations
|
||||
* Contains all fields that can be SENT in create/update requests
|
||||
* and RECEIVED in responses (excluding read-only metadata)
|
||||
*/
|
||||
interface TaskBase {
|
||||
// Core Content
|
||||
name: string;
|
||||
description?: string;
|
||||
text_content?: string;
|
||||
|
||||
// Status & Priority
|
||||
status?: string;
|
||||
priority?: 1 | 2 | 3 | 4;
|
||||
|
||||
// Time Management
|
||||
due_date?: number | null;
|
||||
start_date?: number | null;
|
||||
time_estimate?: number | null;
|
||||
time_spent?: number | null;
|
||||
|
||||
// People & Assignments
|
||||
assignees?: number[];
|
||||
tags?: string[];
|
||||
custom_fields?: Array<{
|
||||
id: string;
|
||||
value: any;
|
||||
}>;
|
||||
|
||||
// Task Relationships
|
||||
parent?: string | null;
|
||||
links_to?: string;
|
||||
|
||||
// Advanced Features
|
||||
markdown_description?: string;
|
||||
notify_all?: boolean;
|
||||
check_required_custom_fields?: boolean;
|
||||
custom_item_id?: number | null;
|
||||
source?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Task Creation Parameters
|
||||
* @see https://developer.clickup.com/reference/createtask
|
||||
*/
|
||||
interface TaskCreate extends TaskBase {
|
||||
/** Required Fields */
|
||||
list_id: string;
|
||||
name: string;
|
||||
|
||||
/** Creation-Specific Fields */
|
||||
custom_task_id?: string;
|
||||
team_id?: number;
|
||||
}
|
||||
|
||||
/**
|
||||
* Task Update Parameters
|
||||
* @see https://developer.clickup.com/reference/updatetask
|
||||
*/
|
||||
interface TaskUpdate extends Partial<TaskBase> {
|
||||
/** Required Identifier */
|
||||
id: string;
|
||||
|
||||
/** Update-Specific Fields */
|
||||
task_revision?: number;
|
||||
task_template_id?: string;
|
||||
idempotency_key?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full Task Response
|
||||
* @see https://developer.clickup.com/reference/gettask
|
||||
*/
|
||||
interface TaskResponse extends TaskBase {
|
||||
/** Read-Only Metadata */
|
||||
id: string;
|
||||
url: string;
|
||||
orderindex: string;
|
||||
date_created: string;
|
||||
date_updated: string;
|
||||
date_closed?: string | null;
|
||||
date_done?: string | null;
|
||||
archived: boolean;
|
||||
|
||||
/** System Relationships */
|
||||
list: {
|
||||
id: string;
|
||||
name: string;
|
||||
access: boolean;
|
||||
};
|
||||
space: {
|
||||
id: string;
|
||||
name: string;
|
||||
};
|
||||
folder: {
|
||||
id: string;
|
||||
name: string;
|
||||
hidden: boolean;
|
||||
access: boolean;
|
||||
};
|
||||
|
||||
/** People & Permissions */
|
||||
creator: User;
|
||||
watchers: User[];
|
||||
followers: User[];
|
||||
permission_level: string;
|
||||
shared: SharedAccess[];
|
||||
|
||||
/** Complex Structures */
|
||||
checklists: Checklist[];
|
||||
dependencies: Dependency[];
|
||||
linked_tasks: LinkedTask[];
|
||||
subtasks: TaskResponse[];
|
||||
attachments: Attachment[];
|
||||
|
||||
/** Status Details */
|
||||
status: {
|
||||
status: string;
|
||||
color: string;
|
||||
orderindex: number;
|
||||
type: 'open' | 'closed' | 'custom';
|
||||
};
|
||||
|
||||
/** Priority Details */
|
||||
priority: {
|
||||
id: string;
|
||||
priority: 'urgent' | 'high' | 'normal' | 'low';
|
||||
color: string;
|
||||
} | null;
|
||||
}
|
||||
|
||||
// Supporting Interfaces
|
||||
interface User {
|
||||
id: number;
|
||||
username: string;
|
||||
email: string;
|
||||
color: string;
|
||||
initials: string;
|
||||
profilePicture?: string;
|
||||
}
|
||||
|
||||
interface Checklist {
|
||||
id: string;
|
||||
name: string;
|
||||
orderindex: number;
|
||||
resolved: number;
|
||||
unresolved: number;
|
||||
items: ChecklistItem[];
|
||||
}
|
||||
|
||||
interface ChecklistItem {
|
||||
id: string;
|
||||
name: string;
|
||||
orderindex: number;
|
||||
assignee?: number;
|
||||
resolved: boolean;
|
||||
parent?: string;
|
||||
date_created: string;
|
||||
children?: string[];
|
||||
}
|
||||
|
||||
interface Tag {
|
||||
name: string;
|
||||
tag_fg: string;
|
||||
tag_bg: string;
|
||||
creator?: number;
|
||||
}
|
||||
|
||||
interface Dependency {
|
||||
task_id: string;
|
||||
depends_on: string;
|
||||
type: number;
|
||||
date_created: string;
|
||||
userid: string;
|
||||
}
|
||||
|
||||
interface LinkedTask {
|
||||
task_id: string;
|
||||
link_id: string;
|
||||
date_created: string;
|
||||
userid: string;
|
||||
}
|
||||
|
||||
interface CustomField {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
type_config: {
|
||||
[key: string]: any;
|
||||
options?: Array<{
|
||||
id: string;
|
||||
name: string;
|
||||
color?: string;
|
||||
orderindex?: number;
|
||||
}>;
|
||||
};
|
||||
value: any;
|
||||
}
|
||||
|
||||
interface Attachment {
|
||||
id: string;
|
||||
version: string;
|
||||
date: string;
|
||||
title: string;
|
||||
extension: string;
|
||||
thumbnail_small: string;
|
||||
thumbnail_large: string;
|
||||
size: number;
|
||||
}
|
||||
|
||||
interface SharedAccess {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
access_level: string;
|
||||
team_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Full task hierarchy types
|
||||
* Ref: https://developer.clickup.com/docs
|
||||
*/
|
||||
interface ClickUpHierarchy {
|
||||
workspace_id: string;
|
||||
space_id: string;
|
||||
folder_id?: string;
|
||||
list_id: string;
|
||||
task_id: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* API error response format
|
||||
* Ref: https://developer.clickup.com/docs/errors
|
||||
*/
|
||||
interface ClickUpError {
|
||||
err: string;
|
||||
code: number;
|
||||
message?: string;
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
summary: clickup
|
||||
description: ''
|
||||
lock: ''
|
||||
concurrency_time_window_s: 0
|
||||
kind: script
|
||||
no_main_func: true
|
||||
schema:
|
||||
$schema: 'https://json-schema.org/draft/2020-12/schema'
|
||||
type: object
|
||||
order:
|
||||
- a
|
||||
- b
|
||||
- d
|
||||
- e
|
||||
properties: {}
|
||||
required: []
|
|
@ -0,0 +1,6 @@
|
|||
summary: null
|
||||
display_name: types
|
||||
extra_perms:
|
||||
u/peter: true
|
||||
owners:
|
||||
- u/peter
|
|
@ -0,0 +1,6 @@
|
|||
summary: null
|
||||
display_name: utils
|
||||
extra_perms:
|
||||
u/peter: true
|
||||
owners:
|
||||
- u/peter
|
|
@ -0,0 +1,6 @@
|
|||
locks:
|
||||
f/clickup/create_task: 43a306643623f8d42f2e9432175d2061cb05bd4ac0825972c93559163b773ad0
|
||||
f/clickup/get_task: e1ac7c952de428bd53df01621c05ecb3995e38cf5f78de1ab03c6baeda9da760
|
||||
f/clickup/rotate_tokens: d0a53e8f1855ab682ebf0cc89d093e8e98db761d9225831c7c9c2d0014f4f6bb
|
||||
f/clickup/utils/filter-task-fields: a160d19c2fa752fa3828f2c87b498be1e79f383ac271678a7dc51c63a4237b4a
|
||||
f/types/clickup: eb03485311a666b6410b7a621f063dcc84aee0e3a198a721165abdccdf690fa4
|
|
@ -0,0 +1,10 @@
|
|||
defaultTs: bun
|
||||
includes:
|
||||
- f/**
|
||||
excludes: []
|
||||
codebases: []
|
||||
skipVariables: true
|
||||
skipResources: true
|
||||
skipSecrets: true
|
||||
includeSchedules: false
|
||||
includeTriggers: false
|
Loading…
Reference in New Issue