@zapier/trello-connector 0.0.0 → 0.1.0
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.
- package/LICENSE +93 -0
- package/NOTICE +8 -0
- package/README.md +135 -2
- package/SKILL.md +139 -0
- package/cli.js +71 -0
- package/cli.ts +5 -0
- package/connections.ts +26 -0
- package/dist/cli.js +4 -0
- package/dist/index.js +2654 -0
- package/index.ts +145 -0
- package/package.json +59 -4
- package/preflight.sh +157 -0
- package/references/trello-api-gotchas.md +81 -0
- package/scripts/.gitkeep +0 -0
- package/scripts/addCardAttachment.ts +107 -0
- package/scripts/addCardLabel.ts +93 -0
- package/scripts/addCardMember.ts +93 -0
- package/scripts/addChecklistItem.ts +98 -0
- package/scripts/addMemberToBoard.ts +57 -0
- package/scripts/archiveCard.ts +67 -0
- package/scripts/closeBoard.ts +62 -0
- package/scripts/completeChecklistItem.ts +56 -0
- package/scripts/copyBoard.ts +81 -0
- package/scripts/createBoard.ts +72 -0
- package/scripts/createCard.ts +266 -0
- package/scripts/createChecklist.ts +50 -0
- package/scripts/createComment.ts +71 -0
- package/scripts/createLabel.ts +72 -0
- package/scripts/createList.ts +100 -0
- package/scripts/deleteChecklist.ts +38 -0
- package/scripts/findBoard.ts +62 -0
- package/scripts/findChecklist.ts +51 -0
- package/scripts/findChecklistItem.ts +49 -0
- package/scripts/findLabel.ts +54 -0
- package/scripts/findList.ts +55 -0
- package/scripts/findOrganizationMember.ts +59 -0
- package/scripts/getAction.ts +58 -0
- package/scripts/getBoard.ts +52 -0
- package/scripts/getCard.ts +79 -0
- package/scripts/getChecklist.ts +45 -0
- package/scripts/getChecklistItem.ts +48 -0
- package/scripts/getCurrentMember.ts +52 -0
- package/scripts/getLabel.ts +46 -0
- package/scripts/getList.ts +47 -0
- package/scripts/getMember.ts +52 -0
- package/scripts/getOrganization.ts +46 -0
- package/scripts/listBoardMembers.ts +58 -0
- package/scripts/listBoards.ts +78 -0
- package/scripts/listCardAttachments.ts +55 -0
- package/scripts/listCards.ts +129 -0
- package/scripts/listCustomFields.ts +62 -0
- package/scripts/listLabels.ts +52 -0
- package/scripts/listLists.ts +61 -0
- package/scripts/listOrganizations.ts +50 -0
- package/scripts/moveCard.ts +68 -0
- package/scripts/removeCardLabel.ts +43 -0
- package/scripts/searchCards.ts +153 -0
- package/scripts/updateCard.ts +184 -0
- package/tsup.config.ts +63 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Authored by the implementation agent: multi-step card create (POST /cards + optional
|
|
3
|
+
// member/label/attachment/checklist/custom-field follow-ups) — outside codegen's single-call model.
|
|
4
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
|
|
7
|
+
import { connectionResolvers } from "../connections.ts";
|
|
8
|
+
import {
|
|
9
|
+
TRELLO_BASE,
|
|
10
|
+
TRELLO_ID_REGEX,
|
|
11
|
+
trelloError,
|
|
12
|
+
trelloFormBody,
|
|
13
|
+
trelloFormHeaders,
|
|
14
|
+
} from "../lib/trello.ts";
|
|
15
|
+
|
|
16
|
+
const cardOutputSchema = z.object({
|
|
17
|
+
id: z.string().regex(TRELLO_ID_REGEX),
|
|
18
|
+
idShort: z.number().int().nullable().optional(),
|
|
19
|
+
name: z.string(),
|
|
20
|
+
desc: z.string().nullable().optional(),
|
|
21
|
+
idBoard: z.string(),
|
|
22
|
+
idList: z.string(),
|
|
23
|
+
shortUrl: z.string().nullable().optional(),
|
|
24
|
+
url: z.string(),
|
|
25
|
+
due: z.union([z.string().datetime({ offset: true }), z.null()]).optional(),
|
|
26
|
+
start: z.union([z.string().datetime({ offset: true }), z.null()]).optional(),
|
|
27
|
+
closed: z.boolean(),
|
|
28
|
+
idMembers: z.array(z.string()).optional(),
|
|
29
|
+
idLabels: z.array(z.string()).optional(),
|
|
30
|
+
labels: z
|
|
31
|
+
.array(
|
|
32
|
+
z.object({
|
|
33
|
+
id: z.string(),
|
|
34
|
+
name: z.string().nullable().optional(),
|
|
35
|
+
color: z.string().nullable().optional(),
|
|
36
|
+
}),
|
|
37
|
+
)
|
|
38
|
+
.optional(),
|
|
39
|
+
dateLastActivity: z.string().datetime({ offset: true }).nullable().optional(),
|
|
40
|
+
customFields: z.record(z.string(), z.json()).optional(),
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
const inputSchema = z
|
|
44
|
+
.object({
|
|
45
|
+
idList: z
|
|
46
|
+
.string()
|
|
47
|
+
.describe("Destination list id. Resolve via listLists or findList."),
|
|
48
|
+
name: z.string().describe("Card title."),
|
|
49
|
+
desc: z.string().describe("Card description (Trello Markdown).").optional(),
|
|
50
|
+
pos: z
|
|
51
|
+
.union([z.enum(["top", "bottom"]), z.number()])
|
|
52
|
+
.describe("Position in the destination list.")
|
|
53
|
+
.optional(),
|
|
54
|
+
due: z.string().datetime({ offset: true }).optional(),
|
|
55
|
+
start: z.string().datetime({ offset: true }).optional(),
|
|
56
|
+
idMembers: z
|
|
57
|
+
.array(z.string())
|
|
58
|
+
.describe("Member ids to assign. Resolve via listBoardMembers.")
|
|
59
|
+
.optional(),
|
|
60
|
+
idLabels: z
|
|
61
|
+
.array(z.string())
|
|
62
|
+
.describe("Label ids to add. Resolve via listLabels or findLabel.")
|
|
63
|
+
.optional(),
|
|
64
|
+
attachmentUrl: z
|
|
65
|
+
.string()
|
|
66
|
+
.url()
|
|
67
|
+
.describe("URL attachment to add after create.")
|
|
68
|
+
.optional(),
|
|
69
|
+
attachmentFileUrl: z
|
|
70
|
+
.string()
|
|
71
|
+
.url()
|
|
72
|
+
.describe("Remote file URL to fetch and upload as attachment.")
|
|
73
|
+
.optional(),
|
|
74
|
+
checklistName: z
|
|
75
|
+
.string()
|
|
76
|
+
.describe("Create a checklist with this name after card create.")
|
|
77
|
+
.optional(),
|
|
78
|
+
checklistItems: z
|
|
79
|
+
.array(z.string())
|
|
80
|
+
.describe("Checklist item names for the new checklist.")
|
|
81
|
+
.optional(),
|
|
82
|
+
customFieldValues: z
|
|
83
|
+
.record(z.string(), z.json())
|
|
84
|
+
.describe(
|
|
85
|
+
"Custom field values keyed by field name. Resolve names via listCustomFields.",
|
|
86
|
+
)
|
|
87
|
+
.optional(),
|
|
88
|
+
address: z.string().optional(),
|
|
89
|
+
coordinates: z.string().describe("latitude,longitude").optional(),
|
|
90
|
+
locationName: z.string().optional(),
|
|
91
|
+
})
|
|
92
|
+
.strict();
|
|
93
|
+
|
|
94
|
+
const definition = defineTool({
|
|
95
|
+
name: "createCard",
|
|
96
|
+
title: "Create Card",
|
|
97
|
+
description:
|
|
98
|
+
"Create a card on a list with optional members, labels, attachments, checklist, and custom fields. Resolve idList via listLists or findList first.",
|
|
99
|
+
inputSchema,
|
|
100
|
+
outputSchema: cardOutputSchema,
|
|
101
|
+
annotations: {
|
|
102
|
+
readOnlyHint: false,
|
|
103
|
+
destructiveHint: false,
|
|
104
|
+
idempotentHint: false,
|
|
105
|
+
openWorldHint: true,
|
|
106
|
+
},
|
|
107
|
+
connection: "trello",
|
|
108
|
+
run: async (input, ctx) => {
|
|
109
|
+
const createFields: Record<string, string | number> = {
|
|
110
|
+
name: input.name,
|
|
111
|
+
idList: input.idList,
|
|
112
|
+
};
|
|
113
|
+
if (input.desc !== undefined)
|
|
114
|
+
createFields.desc = input.desc.slice(0, 16383);
|
|
115
|
+
if (input.pos !== undefined) createFields.pos = input.pos;
|
|
116
|
+
if (input.due !== undefined) createFields.due = input.due;
|
|
117
|
+
if (input.start !== undefined) createFields.start = input.start;
|
|
118
|
+
if (input.address !== undefined) createFields.address = input.address;
|
|
119
|
+
if (input.coordinates !== undefined)
|
|
120
|
+
createFields.coordinates = input.coordinates;
|
|
121
|
+
if (input.locationName !== undefined)
|
|
122
|
+
createFields.locationName = input.locationName;
|
|
123
|
+
if (input.idLabels?.length)
|
|
124
|
+
createFields.idLabels = input.idLabels.join(",");
|
|
125
|
+
|
|
126
|
+
const createRes = await ctx.fetch(`${TRELLO_BASE}/cards`, {
|
|
127
|
+
method: "POST",
|
|
128
|
+
headers: trelloFormHeaders,
|
|
129
|
+
body: trelloFormBody(createFields),
|
|
130
|
+
});
|
|
131
|
+
if (!createRes.ok) await trelloError("createCard", createRes);
|
|
132
|
+
let card = (await createRes.json()) as z.infer<typeof cardOutputSchema>;
|
|
133
|
+
const cardId = card.id;
|
|
134
|
+
|
|
135
|
+
if (input.idMembers?.length) {
|
|
136
|
+
for (const memberId of input.idMembers) {
|
|
137
|
+
const memberRes = await ctx.fetch(
|
|
138
|
+
`${TRELLO_BASE}/cards/${cardId}/idMembers`,
|
|
139
|
+
{
|
|
140
|
+
method: "POST",
|
|
141
|
+
headers: trelloFormHeaders,
|
|
142
|
+
body: trelloFormBody({ value: memberId }),
|
|
143
|
+
},
|
|
144
|
+
);
|
|
145
|
+
if (!memberRes.ok) await trelloError("createCard", memberRes);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
const attachUrl = input.attachmentUrl ?? input.attachmentFileUrl;
|
|
150
|
+
if (attachUrl) {
|
|
151
|
+
if (input.attachmentFileUrl) {
|
|
152
|
+
const fileRes = await ctx.fetch(input.attachmentFileUrl);
|
|
153
|
+
if (!fileRes.ok) await trelloError("createCard", fileRes);
|
|
154
|
+
const buffer = await fileRes.arrayBuffer();
|
|
155
|
+
const form = new FormData();
|
|
156
|
+
form.append("file", new Blob([buffer]), "attachment");
|
|
157
|
+
form.append("name", "attachment");
|
|
158
|
+
const uploadRes = await ctx.fetch(
|
|
159
|
+
`${TRELLO_BASE}/cards/${cardId}/attachments`,
|
|
160
|
+
{ method: "POST", body: form },
|
|
161
|
+
);
|
|
162
|
+
if (!uploadRes.ok) await trelloError("createCard", uploadRes);
|
|
163
|
+
} else {
|
|
164
|
+
const urlRes = await ctx.fetch(
|
|
165
|
+
`${TRELLO_BASE}/cards/${cardId}/attachments`,
|
|
166
|
+
{
|
|
167
|
+
method: "POST",
|
|
168
|
+
headers: trelloFormHeaders,
|
|
169
|
+
body: trelloFormBody({ url: attachUrl, name: attachUrl }),
|
|
170
|
+
},
|
|
171
|
+
);
|
|
172
|
+
if (!urlRes.ok) await trelloError("createCard", urlRes);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
if (input.checklistName) {
|
|
177
|
+
const checklistRes = await ctx.fetch(`${TRELLO_BASE}/checklists`, {
|
|
178
|
+
method: "POST",
|
|
179
|
+
headers: trelloFormHeaders,
|
|
180
|
+
body: trelloFormBody({
|
|
181
|
+
idCard: cardId,
|
|
182
|
+
name: input.checklistName,
|
|
183
|
+
}),
|
|
184
|
+
});
|
|
185
|
+
if (!checklistRes.ok) await trelloError("createCard", checklistRes);
|
|
186
|
+
const checklist = (await checklistRes.json()) as { id: string };
|
|
187
|
+
if (input.checklistItems?.length) {
|
|
188
|
+
for (const itemName of input.checklistItems) {
|
|
189
|
+
const itemRes = await ctx.fetch(
|
|
190
|
+
`${TRELLO_BASE}/checklists/${checklist.id}/checkItems`,
|
|
191
|
+
{
|
|
192
|
+
method: "POST",
|
|
193
|
+
headers: trelloFormHeaders,
|
|
194
|
+
body: trelloFormBody({ name: itemName }),
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
if (!itemRes.ok) await trelloError("createCard", itemRes);
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
if (
|
|
203
|
+
input.customFieldValues &&
|
|
204
|
+
Object.keys(input.customFieldValues).length
|
|
205
|
+
) {
|
|
206
|
+
const boardId = card.idBoard;
|
|
207
|
+
const fieldsRes = await ctx.fetch(
|
|
208
|
+
`${TRELLO_BASE}/boards/${boardId}/customFields`,
|
|
209
|
+
);
|
|
210
|
+
if (!fieldsRes.ok) await trelloError("createCard", fieldsRes);
|
|
211
|
+
const fields = (await fieldsRes.json()) as Array<{
|
|
212
|
+
id: string;
|
|
213
|
+
name: string;
|
|
214
|
+
type: string;
|
|
215
|
+
}>;
|
|
216
|
+
const byName = new Map(fields.map((f) => [f.name, f]));
|
|
217
|
+
for (const [fieldName, rawValue] of Object.entries(
|
|
218
|
+
input.customFieldValues,
|
|
219
|
+
)) {
|
|
220
|
+
const field = byName.get(fieldName);
|
|
221
|
+
if (!field) {
|
|
222
|
+
throw new Error(
|
|
223
|
+
`Trello createCard: unknown custom field "${fieldName}". Resolve via listCustomFields.`,
|
|
224
|
+
);
|
|
225
|
+
}
|
|
226
|
+
let itemValue: Record<string, unknown> = {};
|
|
227
|
+
switch (field.type) {
|
|
228
|
+
case "checkbox":
|
|
229
|
+
itemValue = { checked: Boolean(rawValue) ? "true" : "false" };
|
|
230
|
+
break;
|
|
231
|
+
case "date":
|
|
232
|
+
itemValue = { date: String(rawValue) };
|
|
233
|
+
break;
|
|
234
|
+
case "number":
|
|
235
|
+
itemValue = { number: String(rawValue) };
|
|
236
|
+
break;
|
|
237
|
+
case "list": {
|
|
238
|
+
itemValue = { idValue: String(rawValue) };
|
|
239
|
+
break;
|
|
240
|
+
}
|
|
241
|
+
default:
|
|
242
|
+
itemValue = { text: String(rawValue) };
|
|
243
|
+
}
|
|
244
|
+
const cfRes = await ctx.fetch(
|
|
245
|
+
`${TRELLO_BASE}/cards/${cardId}/customField/${field.id}/item`,
|
|
246
|
+
{
|
|
247
|
+
method: "PUT",
|
|
248
|
+
headers: { "Content-Type": "application/json" },
|
|
249
|
+
body: JSON.stringify({ value: itemValue }),
|
|
250
|
+
},
|
|
251
|
+
);
|
|
252
|
+
if (!cfRes.ok) await trelloError("createCard", cfRes);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
const refreshRes = await ctx.fetch(`${TRELLO_BASE}/cards/${cardId}`);
|
|
257
|
+
if (refreshRes.ok) {
|
|
258
|
+
card = (await refreshRes.json()) as z.infer<typeof cardOutputSchema>;
|
|
259
|
+
}
|
|
260
|
+
return card;
|
|
261
|
+
},
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
export default definition;
|
|
265
|
+
|
|
266
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
|
|
7
|
+
const inputSchema = z.object({ idCard: z.string(), name: z.string() }).strict();
|
|
8
|
+
const outputSchema = z.object({
|
|
9
|
+
id: z
|
|
10
|
+
.string()
|
|
11
|
+
.regex(new RegExp("^[0-9a-fA-F]{24}$"))
|
|
12
|
+
.describe("Trello object id (24 hex chars)."),
|
|
13
|
+
name: z.string(),
|
|
14
|
+
idCard: z.string().nullable().optional(),
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
const definition = defineTool({
|
|
18
|
+
name: "createChecklist",
|
|
19
|
+
title: "Create Checklist",
|
|
20
|
+
description: "Create a checklist on a card.",
|
|
21
|
+
inputSchema,
|
|
22
|
+
outputSchema,
|
|
23
|
+
annotations: {
|
|
24
|
+
readOnlyHint: false,
|
|
25
|
+
destructiveHint: false,
|
|
26
|
+
idempotentHint: false,
|
|
27
|
+
openWorldHint: true,
|
|
28
|
+
},
|
|
29
|
+
connection: "trello",
|
|
30
|
+
run: async (input, ctx) => {
|
|
31
|
+
const url = `https://api.trello.com/1/checklists`;
|
|
32
|
+
const body: Record<string, unknown> = {};
|
|
33
|
+
if (input.idCard !== undefined) body["idCard"] = input.idCard;
|
|
34
|
+
if (input.name !== undefined) body["name"] = input.name;
|
|
35
|
+
const res = await ctx.fetch(url, {
|
|
36
|
+
method: "POST",
|
|
37
|
+
headers: { "Content-Type": "application/json" },
|
|
38
|
+
body: JSON.stringify(body),
|
|
39
|
+
});
|
|
40
|
+
if (!res.ok) {
|
|
41
|
+
const errBody = await res.text();
|
|
42
|
+
throw new Error(`Trello createChecklist ${res.status}: ${errBody}`);
|
|
43
|
+
}
|
|
44
|
+
return res.json();
|
|
45
|
+
},
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
export default definition;
|
|
49
|
+
|
|
50
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
|
|
7
|
+
const inputSchema = z
|
|
8
|
+
.object({
|
|
9
|
+
id: z.string().describe("24-char hex card id."),
|
|
10
|
+
text: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe(
|
|
13
|
+
"Comment body (Trello Markdown; @member mentions use @username).",
|
|
14
|
+
),
|
|
15
|
+
})
|
|
16
|
+
.strict();
|
|
17
|
+
const outputSchema = z.object({
|
|
18
|
+
id: z
|
|
19
|
+
.string()
|
|
20
|
+
.regex(new RegExp("^[0-9a-fA-F]{24}$"))
|
|
21
|
+
.describe("Trello object id (24 hex chars)."),
|
|
22
|
+
type: z.string(),
|
|
23
|
+
date: z.string().datetime({ offset: true }),
|
|
24
|
+
data: z
|
|
25
|
+
.object({
|
|
26
|
+
text: z.string().nullable().optional(),
|
|
27
|
+
card: z
|
|
28
|
+
.object({
|
|
29
|
+
id: z.string().nullable().optional(),
|
|
30
|
+
name: z.string().nullable().optional(),
|
|
31
|
+
})
|
|
32
|
+
.nullable()
|
|
33
|
+
.optional(),
|
|
34
|
+
})
|
|
35
|
+
.nullable()
|
|
36
|
+
.optional(),
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const definition = defineTool({
|
|
40
|
+
name: "createComment",
|
|
41
|
+
title: "Create Comment",
|
|
42
|
+
description: "Add a comment to a card.",
|
|
43
|
+
inputSchema,
|
|
44
|
+
outputSchema,
|
|
45
|
+
annotations: {
|
|
46
|
+
readOnlyHint: false,
|
|
47
|
+
destructiveHint: false,
|
|
48
|
+
idempotentHint: false,
|
|
49
|
+
openWorldHint: true,
|
|
50
|
+
},
|
|
51
|
+
connection: "trello",
|
|
52
|
+
run: async (input, ctx) => {
|
|
53
|
+
const url = `https://api.trello.com/1/cards/${encodeURIComponent(input.id)}/actions/comments`;
|
|
54
|
+
const body: Record<string, unknown> = {};
|
|
55
|
+
if (input.text !== undefined) body["text"] = input.text;
|
|
56
|
+
const res = await ctx.fetch(url, {
|
|
57
|
+
method: "POST",
|
|
58
|
+
headers: { "Content-Type": "application/json" },
|
|
59
|
+
body: JSON.stringify(body),
|
|
60
|
+
});
|
|
61
|
+
if (!res.ok) {
|
|
62
|
+
const errBody = await res.text();
|
|
63
|
+
throw new Error(`Trello createComment ${res.status}: ${errBody}`);
|
|
64
|
+
}
|
|
65
|
+
return res.json();
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
export default definition;
|
|
70
|
+
|
|
71
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
|
|
7
|
+
const inputSchema = z
|
|
8
|
+
.object({
|
|
9
|
+
name: z.string().optional(),
|
|
10
|
+
color: z
|
|
11
|
+
.enum([
|
|
12
|
+
"yellow",
|
|
13
|
+
"purple",
|
|
14
|
+
"blue",
|
|
15
|
+
"red",
|
|
16
|
+
"green",
|
|
17
|
+
"orange",
|
|
18
|
+
"black",
|
|
19
|
+
"sky",
|
|
20
|
+
"pink",
|
|
21
|
+
"lime",
|
|
22
|
+
])
|
|
23
|
+
.optional(),
|
|
24
|
+
idBoard: z.string(),
|
|
25
|
+
})
|
|
26
|
+
.strict();
|
|
27
|
+
const outputSchema = z.object({
|
|
28
|
+
id: z
|
|
29
|
+
.string()
|
|
30
|
+
.regex(new RegExp("^[0-9a-fA-F]{24}$"))
|
|
31
|
+
.describe("Trello object id (24 hex chars)."),
|
|
32
|
+
idBoard: z.string(),
|
|
33
|
+
name: z.string().nullable().optional(),
|
|
34
|
+
color: z.string().nullable().optional(),
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
const definition = defineTool({
|
|
38
|
+
name: "createLabel",
|
|
39
|
+
title: "Create Label",
|
|
40
|
+
description:
|
|
41
|
+
"Create a label on a board (or add a named label to a card when idCard set).",
|
|
42
|
+
inputSchema,
|
|
43
|
+
outputSchema,
|
|
44
|
+
annotations: {
|
|
45
|
+
readOnlyHint: false,
|
|
46
|
+
destructiveHint: false,
|
|
47
|
+
idempotentHint: false,
|
|
48
|
+
openWorldHint: true,
|
|
49
|
+
},
|
|
50
|
+
connection: "trello",
|
|
51
|
+
run: async (input, ctx) => {
|
|
52
|
+
const url = `https://api.trello.com/1/labels`;
|
|
53
|
+
const body: Record<string, unknown> = {};
|
|
54
|
+
if (input.name !== undefined) body["name"] = input.name;
|
|
55
|
+
if (input.color !== undefined) body["color"] = input.color;
|
|
56
|
+
if (input.idBoard !== undefined) body["idBoard"] = input.idBoard;
|
|
57
|
+
const res = await ctx.fetch(url, {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: { "Content-Type": "application/json" },
|
|
60
|
+
body: JSON.stringify(body),
|
|
61
|
+
});
|
|
62
|
+
if (!res.ok) {
|
|
63
|
+
const errBody = await res.text();
|
|
64
|
+
throw new Error(`Trello createLabel ${res.status}: ${errBody}`);
|
|
65
|
+
}
|
|
66
|
+
return res.json();
|
|
67
|
+
},
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
export default definition;
|
|
71
|
+
|
|
72
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
|
|
7
|
+
const inputSchema = z
|
|
8
|
+
.object({
|
|
9
|
+
name: z.string(),
|
|
10
|
+
idBoard: z.string().describe("Board id."),
|
|
11
|
+
pos: z
|
|
12
|
+
.any()
|
|
13
|
+
.superRefine((x, ctx) => {
|
|
14
|
+
const schemas = [z.enum(["top", "bottom"]), z.number()];
|
|
15
|
+
const { errors, failed } = schemas.reduce<{
|
|
16
|
+
errors: z.core.$ZodIssue[];
|
|
17
|
+
failed: number;
|
|
18
|
+
}>(
|
|
19
|
+
({ errors, failed }, schema) =>
|
|
20
|
+
((result) =>
|
|
21
|
+
result.error
|
|
22
|
+
? {
|
|
23
|
+
errors: [...errors, ...result.error.issues],
|
|
24
|
+
failed: failed + 1,
|
|
25
|
+
}
|
|
26
|
+
: { errors, failed })(schema.safeParse(x)),
|
|
27
|
+
{ errors: [], failed: 0 },
|
|
28
|
+
);
|
|
29
|
+
const passed = schemas.length - failed;
|
|
30
|
+
if (passed !== 1) {
|
|
31
|
+
ctx.addIssue(
|
|
32
|
+
errors.length
|
|
33
|
+
? {
|
|
34
|
+
path: [],
|
|
35
|
+
code: "invalid_union",
|
|
36
|
+
errors: [errors],
|
|
37
|
+
message:
|
|
38
|
+
"Invalid input: Should pass single schema. Passed " +
|
|
39
|
+
passed,
|
|
40
|
+
}
|
|
41
|
+
: {
|
|
42
|
+
path: [],
|
|
43
|
+
code: "custom",
|
|
44
|
+
errors: [errors],
|
|
45
|
+
message:
|
|
46
|
+
"Invalid input: Should pass single schema. Passed " +
|
|
47
|
+
passed,
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
.optional(),
|
|
53
|
+
})
|
|
54
|
+
.strict();
|
|
55
|
+
const outputSchema = z.object({
|
|
56
|
+
id: z
|
|
57
|
+
.string()
|
|
58
|
+
.regex(new RegExp("^[0-9a-fA-F]{24}$"))
|
|
59
|
+
.describe("Trello object id (24 hex chars)."),
|
|
60
|
+
name: z.string(),
|
|
61
|
+
closed: z.boolean().nullable().optional(),
|
|
62
|
+
idBoard: z.string(),
|
|
63
|
+
pos: z.number().nullable().optional(),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
const definition = defineTool({
|
|
67
|
+
name: "createList",
|
|
68
|
+
title: "Create List",
|
|
69
|
+
description: "Create a list on a board.",
|
|
70
|
+
inputSchema,
|
|
71
|
+
outputSchema,
|
|
72
|
+
annotations: {
|
|
73
|
+
readOnlyHint: false,
|
|
74
|
+
destructiveHint: false,
|
|
75
|
+
idempotentHint: false,
|
|
76
|
+
openWorldHint: true,
|
|
77
|
+
},
|
|
78
|
+
connection: "trello",
|
|
79
|
+
run: async (input, ctx) => {
|
|
80
|
+
const url = `https://api.trello.com/1/lists`;
|
|
81
|
+
const body: Record<string, unknown> = {};
|
|
82
|
+
if (input.name !== undefined) body["name"] = input.name;
|
|
83
|
+
if (input.idBoard !== undefined) body["idBoard"] = input.idBoard;
|
|
84
|
+
if (input.pos !== undefined) body["pos"] = input.pos;
|
|
85
|
+
const res = await ctx.fetch(url, {
|
|
86
|
+
method: "POST",
|
|
87
|
+
headers: { "Content-Type": "application/json" },
|
|
88
|
+
body: JSON.stringify(body),
|
|
89
|
+
});
|
|
90
|
+
if (!res.ok) {
|
|
91
|
+
const errBody = await res.text();
|
|
92
|
+
throw new Error(`Trello createList ${res.status}: ${errBody}`);
|
|
93
|
+
}
|
|
94
|
+
return res.json();
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
export default definition;
|
|
99
|
+
|
|
100
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
|
|
7
|
+
const inputSchema = z.object({ id: z.string() }).strict();
|
|
8
|
+
const outputSchema = z.object({ status: z.number() });
|
|
9
|
+
|
|
10
|
+
const definition = defineTool({
|
|
11
|
+
name: "deleteChecklist",
|
|
12
|
+
title: "Delete Checklist",
|
|
13
|
+
description: "Delete a checklist.",
|
|
14
|
+
inputSchema,
|
|
15
|
+
outputSchema,
|
|
16
|
+
annotations: {
|
|
17
|
+
readOnlyHint: false,
|
|
18
|
+
destructiveHint: true,
|
|
19
|
+
idempotentHint: true,
|
|
20
|
+
openWorldHint: true,
|
|
21
|
+
},
|
|
22
|
+
connection: "trello",
|
|
23
|
+
run: async (input, ctx) => {
|
|
24
|
+
const url = `https://api.trello.com/1/checklists/${encodeURIComponent(input.id)}`;
|
|
25
|
+
const res = await ctx.fetch(url, {
|
|
26
|
+
method: "DELETE",
|
|
27
|
+
});
|
|
28
|
+
if (!res.ok) {
|
|
29
|
+
const errBody = await res.text();
|
|
30
|
+
throw new Error(`Trello deleteChecklist ${res.status}: ${errBody}`);
|
|
31
|
+
}
|
|
32
|
+
return { status: res.status };
|
|
33
|
+
},
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
export default definition;
|
|
37
|
+
|
|
38
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
3
|
+
import { z } from "zod";
|
|
4
|
+
|
|
5
|
+
import { connectionResolvers } from "../connections.ts";
|
|
6
|
+
import { TRELLO_BASE, trelloError } from "../lib/trello.ts";
|
|
7
|
+
|
|
8
|
+
const inputSchema = z
|
|
9
|
+
.object({ query: z.string(), organizationId: z.string().optional() })
|
|
10
|
+
.strict();
|
|
11
|
+
const itemSchema = z.array(
|
|
12
|
+
z.object({
|
|
13
|
+
id: z
|
|
14
|
+
.string()
|
|
15
|
+
.regex(new RegExp("^[0-9a-fA-F]{24}$"))
|
|
16
|
+
.describe("Trello object id (24 hex chars)."),
|
|
17
|
+
name: z.string(),
|
|
18
|
+
desc: z.string().nullable().optional(),
|
|
19
|
+
closed: z.boolean().nullable().optional(),
|
|
20
|
+
idOrganization: z.string().nullable().optional(),
|
|
21
|
+
url: z.string().nullable().optional(),
|
|
22
|
+
shortUrl: z.string().nullable().optional(),
|
|
23
|
+
dateLastActivity: z
|
|
24
|
+
.string()
|
|
25
|
+
.datetime({ offset: true })
|
|
26
|
+
.nullable()
|
|
27
|
+
.optional(),
|
|
28
|
+
}),
|
|
29
|
+
);
|
|
30
|
+
const outputSchema = z.object({ items: itemSchema });
|
|
31
|
+
|
|
32
|
+
const definition = defineTool({
|
|
33
|
+
name: "findBoard",
|
|
34
|
+
title: "Find Board",
|
|
35
|
+
description: "Find boards by name via GET /search with modelTypes=boards.",
|
|
36
|
+
inputSchema,
|
|
37
|
+
outputSchema,
|
|
38
|
+
annotations: {
|
|
39
|
+
readOnlyHint: true,
|
|
40
|
+
destructiveHint: false,
|
|
41
|
+
idempotentHint: true,
|
|
42
|
+
openWorldHint: true,
|
|
43
|
+
},
|
|
44
|
+
connection: "trello",
|
|
45
|
+
run: async (input, ctx) => {
|
|
46
|
+
const url = new URL(`${TRELLO_BASE}/search`);
|
|
47
|
+
url.searchParams.set("query", input.query);
|
|
48
|
+
url.searchParams.set("modelTypes", "boards");
|
|
49
|
+
url.searchParams.set("boardsLimit", "50");
|
|
50
|
+
if (input.organizationId !== undefined) {
|
|
51
|
+
url.searchParams.set("idOrganizations", input.organizationId);
|
|
52
|
+
}
|
|
53
|
+
const res = await ctx.fetch(url.toString(), { method: "GET" });
|
|
54
|
+
if (!res.ok) await trelloError("findBoard", res);
|
|
55
|
+
const data = (await res.json()) as { boards?: unknown[] };
|
|
56
|
+
return { items: data.boards ?? [] };
|
|
57
|
+
},
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export default definition;
|
|
61
|
+
|
|
62
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|