@zapier/youtube-connector 0.0.0 → 0.0.1
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 +117 -2
- package/SKILL.md +162 -0
- package/cli.js +71 -0
- package/cli.ts +5 -0
- package/connections.ts +8 -0
- package/dist/cli.js +4 -0
- package/dist/index.js +1550 -0
- package/index.ts +79 -0
- package/package.json +59 -4
- package/preflight.sh +157 -0
- package/references/youtube-api-gotchas.md +252 -0
- package/scripts/addVideoToPlaylist.ts +75 -0
- package/scripts/createPlaylist.ts +73 -0
- package/scripts/deletePlaylist.ts +46 -0
- package/scripts/deleteVideo.ts +42 -0
- package/scripts/downloadCaption.ts +66 -0
- package/scripts/getChannel.ts +85 -0
- package/scripts/getVideo.ts +71 -0
- package/scripts/listCaptions.ts +54 -0
- package/scripts/listComments.ts +98 -0
- package/scripts/listPlaylistItems.ts +90 -0
- package/scripts/listPlaylists.ts +107 -0
- package/scripts/listSubscriptions.ts +103 -0
- package/scripts/listVideoCategories.ts +63 -0
- package/scripts/postComment.ts +65 -0
- package/scripts/rateVideo.ts +50 -0
- package/scripts/removeVideoFromPlaylist.ts +49 -0
- package/scripts/replyToComment.ts +90 -0
- package/scripts/searchVideos.ts +169 -0
- package/scripts/subscribeToChannel.ts +122 -0
- package/scripts/unsubscribeFromChannel.ts +49 -0
- package/scripts/updatePlaylist.ts +75 -0
- package/scripts/updateVideo.ts +143 -0
- package/tsup.config.ts +63 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// subscriptions.insert is a single POST, but YouTube returns subscriptionDuplicate
|
|
3
|
+
// when the user is already subscribed —
|
|
4
|
+
// a postcondition-satisfied "soft success". We catch it and look up the existing
|
|
5
|
+
// subscription so the tool still returns a valid Subscription (with the id the
|
|
6
|
+
// agent needs) rather than throwing on a state it actually wanted.
|
|
7
|
+
import {
|
|
8
|
+
ConnectorHttpError,
|
|
9
|
+
defineTool,
|
|
10
|
+
handleIfScriptMain,
|
|
11
|
+
} from "@zapier/connectors-sdk";
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
|
|
14
|
+
import { connectionResolvers } from "../connections.ts";
|
|
15
|
+
import {
|
|
16
|
+
hasYouTubeReason,
|
|
17
|
+
SubscriptionSchema,
|
|
18
|
+
throwForYouTube,
|
|
19
|
+
} from "../lib/youtube.ts";
|
|
20
|
+
|
|
21
|
+
const inputSchema = z
|
|
22
|
+
.object({
|
|
23
|
+
snippet: z
|
|
24
|
+
.object({
|
|
25
|
+
resourceId: z
|
|
26
|
+
.object({
|
|
27
|
+
kind: z.string().default("youtube#channel"),
|
|
28
|
+
channelId: z
|
|
29
|
+
.string()
|
|
30
|
+
.describe("The id (UC...) of the channel to subscribe to."),
|
|
31
|
+
})
|
|
32
|
+
.strict()
|
|
33
|
+
.describe(
|
|
34
|
+
"The channel to subscribe to. Set kind to youtube#channel and channelId to the target channel id.",
|
|
35
|
+
),
|
|
36
|
+
})
|
|
37
|
+
.strict(),
|
|
38
|
+
part: z
|
|
39
|
+
.string()
|
|
40
|
+
.describe("Resource parts being written. Leave as the default.")
|
|
41
|
+
.default("snippet"),
|
|
42
|
+
})
|
|
43
|
+
.strict();
|
|
44
|
+
|
|
45
|
+
const outputSchema = SubscriptionSchema.extend({
|
|
46
|
+
alreadySatisfied: z
|
|
47
|
+
.literal(true)
|
|
48
|
+
.describe("Present and true when the user was already subscribed.")
|
|
49
|
+
.optional(),
|
|
50
|
+
alreadySatisfiedReason: z
|
|
51
|
+
.string()
|
|
52
|
+
.describe('The upstream code, e.g. "subscriptionDuplicate".')
|
|
53
|
+
.optional(),
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
const definition = defineTool({
|
|
57
|
+
name: "subscribeToChannel",
|
|
58
|
+
title: "Subscribe To Channel",
|
|
59
|
+
description:
|
|
60
|
+
"Subscribe the authenticated user to a channel. Returns the subscription id (used by unsubscribeFromChannel — distinct from the channel id). If the user is already subscribed, returns the existing subscription with alreadySatisfied: true rather than failing.",
|
|
61
|
+
inputSchema,
|
|
62
|
+
outputSchema,
|
|
63
|
+
annotations: {
|
|
64
|
+
readOnlyHint: false,
|
|
65
|
+
destructiveHint: false,
|
|
66
|
+
idempotentHint: true,
|
|
67
|
+
openWorldHint: true,
|
|
68
|
+
},
|
|
69
|
+
connection: "youtube",
|
|
70
|
+
run: async (input, ctx) => {
|
|
71
|
+
const url = new URL(`https://www.googleapis.com/youtube/v3/subscriptions`);
|
|
72
|
+
url.searchParams.set("part", input.part);
|
|
73
|
+
|
|
74
|
+
const res = await ctx.fetch(url.toString(), {
|
|
75
|
+
method: "POST",
|
|
76
|
+
headers: { "Content-Type": "application/json" },
|
|
77
|
+
body: JSON.stringify({ snippet: input.snippet }),
|
|
78
|
+
});
|
|
79
|
+
if (res.ok) return res.json();
|
|
80
|
+
|
|
81
|
+
// Soft-success: already subscribed → look up the existing subscription so we
|
|
82
|
+
// can return its id, flagged with alreadySatisfied.
|
|
83
|
+
if (res.status === 400) {
|
|
84
|
+
const body = (await res.json().catch(() => null)) as unknown;
|
|
85
|
+
if (hasYouTubeReason(body, "subscriptionDuplicate")) {
|
|
86
|
+
const channelId = input.snippet.resourceId.channelId;
|
|
87
|
+
const lookup = new URL(
|
|
88
|
+
`https://www.googleapis.com/youtube/v3/subscriptions`,
|
|
89
|
+
);
|
|
90
|
+
lookup.searchParams.set("part", "snippet,contentDetails");
|
|
91
|
+
lookup.searchParams.set("mine", "true");
|
|
92
|
+
lookup.searchParams.set("forChannelId", channelId);
|
|
93
|
+
const lres = await ctx.fetch(lookup.toString(), { method: "GET" });
|
|
94
|
+
await throwForYouTube(lres, "subscribeToChannel");
|
|
95
|
+
const lpayload = (await lres.json()) as {
|
|
96
|
+
items?: Array<Record<string, unknown>>;
|
|
97
|
+
};
|
|
98
|
+
const existing = lpayload.items?.[0];
|
|
99
|
+
if (existing) {
|
|
100
|
+
return {
|
|
101
|
+
...existing,
|
|
102
|
+
alreadySatisfied: true as const,
|
|
103
|
+
alreadySatisfiedReason: "subscriptionDuplicate",
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
throw ConnectorHttpError.fromResponseBody(res, body, {
|
|
108
|
+
message: `YouTube subscribeToChannel 400: ${
|
|
109
|
+
(body as { error?: { message?: string } })?.error?.message ??
|
|
110
|
+
"bad request"
|
|
111
|
+
}`,
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
await throwForYouTube(res, "subscribeToChannel");
|
|
116
|
+
return res.json();
|
|
117
|
+
},
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
export default definition;
|
|
121
|
+
|
|
122
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,49 @@
|
|
|
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 { SuccessResultSchema, throwForYouTube } from "../lib/youtube.ts";
|
|
7
|
+
|
|
8
|
+
const inputSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
id: z
|
|
11
|
+
.string()
|
|
12
|
+
.describe(
|
|
13
|
+
"The subscription id to delete (from listSubscriptions, not the channel id).",
|
|
14
|
+
),
|
|
15
|
+
})
|
|
16
|
+
.strict();
|
|
17
|
+
const outputSchema = SuccessResultSchema;
|
|
18
|
+
|
|
19
|
+
const definition = defineTool({
|
|
20
|
+
name: "unsubscribeFromChannel",
|
|
21
|
+
title: "Unsubscribe From Channel",
|
|
22
|
+
description:
|
|
23
|
+
"Unsubscribe the authenticated user from a channel. The id is the subscription id from listSubscriptions (NOT the channel id).",
|
|
24
|
+
inputSchema,
|
|
25
|
+
outputSchema,
|
|
26
|
+
annotations: {
|
|
27
|
+
readOnlyHint: false,
|
|
28
|
+
// Reversible — the user can re-subscribe with subscribeToChannel.
|
|
29
|
+
destructiveHint: false,
|
|
30
|
+
idempotentHint: true,
|
|
31
|
+
openWorldHint: true,
|
|
32
|
+
},
|
|
33
|
+
connection: "youtube",
|
|
34
|
+
run: async (input, ctx) => {
|
|
35
|
+
const url = new URL(`https://www.googleapis.com/youtube/v3/subscriptions`);
|
|
36
|
+
if (input.id !== undefined) {
|
|
37
|
+
url.searchParams.set("id", String(input.id));
|
|
38
|
+
}
|
|
39
|
+
const res = await ctx.fetch(url.toString(), {
|
|
40
|
+
method: "DELETE",
|
|
41
|
+
});
|
|
42
|
+
await throwForYouTube(res, "unsubscribeFromChannel");
|
|
43
|
+
return { success: true as const };
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
export default definition;
|
|
48
|
+
|
|
49
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,75 @@
|
|
|
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 { PlaylistSchema, throwForYouTube } from "../lib/youtube.ts";
|
|
7
|
+
|
|
8
|
+
const inputSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
id: z.string().describe("The id of the playlist to update."),
|
|
11
|
+
snippet: z
|
|
12
|
+
.object({
|
|
13
|
+
title: z.string().describe("Playlist title (required)."),
|
|
14
|
+
description: z.string().describe("Playlist description.").optional(),
|
|
15
|
+
defaultLanguage: z
|
|
16
|
+
.string()
|
|
17
|
+
.describe(
|
|
18
|
+
"BCP-47 language code of the title/description text, e.g. en.",
|
|
19
|
+
)
|
|
20
|
+
.optional(),
|
|
21
|
+
})
|
|
22
|
+
.strict(),
|
|
23
|
+
status: z
|
|
24
|
+
.object({
|
|
25
|
+
privacyStatus: z
|
|
26
|
+
.enum(["public", "unlisted", "private"])
|
|
27
|
+
.describe("Playlist visibility. Defaults to private if omitted.")
|
|
28
|
+
.optional(),
|
|
29
|
+
})
|
|
30
|
+
.strict()
|
|
31
|
+
.optional(),
|
|
32
|
+
part: z
|
|
33
|
+
.string()
|
|
34
|
+
.describe("Resource parts being written. Leave as the default.")
|
|
35
|
+
.default("snippet,status"),
|
|
36
|
+
})
|
|
37
|
+
.strict();
|
|
38
|
+
const outputSchema = PlaylistSchema;
|
|
39
|
+
|
|
40
|
+
const definition = defineTool({
|
|
41
|
+
name: "updatePlaylist",
|
|
42
|
+
title: "Update Playlist",
|
|
43
|
+
description:
|
|
44
|
+
"Update a playlist's title, description, or privacy. Send the complete desired snippet — omitted fields within a written part are reset (the API replaces, not merges). Resolve id via listPlaylists.",
|
|
45
|
+
inputSchema,
|
|
46
|
+
outputSchema,
|
|
47
|
+
annotations: {
|
|
48
|
+
readOnlyHint: false,
|
|
49
|
+
destructiveHint: false,
|
|
50
|
+
idempotentHint: true,
|
|
51
|
+
openWorldHint: true,
|
|
52
|
+
},
|
|
53
|
+
connection: "youtube",
|
|
54
|
+
run: async (input, ctx) => {
|
|
55
|
+
const url = new URL(`https://www.googleapis.com/youtube/v3/playlists`);
|
|
56
|
+
if (input.part !== undefined) {
|
|
57
|
+
url.searchParams.set("part", String(input.part));
|
|
58
|
+
}
|
|
59
|
+
const body: Record<string, unknown> = {};
|
|
60
|
+
if (input.id !== undefined) body["id"] = input.id;
|
|
61
|
+
if (input.snippet !== undefined) body["snippet"] = input.snippet;
|
|
62
|
+
if (input.status !== undefined) body["status"] = input.status;
|
|
63
|
+
const res = await ctx.fetch(url.toString(), {
|
|
64
|
+
method: "PUT",
|
|
65
|
+
headers: { "Content-Type": "application/json" },
|
|
66
|
+
body: JSON.stringify(body),
|
|
67
|
+
});
|
|
68
|
+
await throwForYouTube(res, "updatePlaylist");
|
|
69
|
+
return res.json();
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
export default definition;
|
|
74
|
+
|
|
75
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// This is a read-modify-write composition, not a single HTTP call. videos.update
|
|
3
|
+
// REPLACES every field
|
|
4
|
+
// within a written part — any mutable snippet/status field omitted from the request
|
|
5
|
+
// is reset to its default. So "change just the title" must first read the current
|
|
6
|
+
// snippet+status, merge the agent's changes onto it, then PUT the full object back.
|
|
7
|
+
// The API also requires snippet.title and snippet.categoryId on every update, so the
|
|
8
|
+
// merge carries those forward when the agent doesn't supply them.
|
|
9
|
+
import { defineTool, handleIfScriptMain } from "@zapier/connectors-sdk";
|
|
10
|
+
import { z } from "zod";
|
|
11
|
+
|
|
12
|
+
import { connectionResolvers } from "../connections.ts";
|
|
13
|
+
import { throwForYouTube, VideoSchema } from "../lib/youtube.ts";
|
|
14
|
+
|
|
15
|
+
const inputSchema = z
|
|
16
|
+
.object({
|
|
17
|
+
video_id: z
|
|
18
|
+
.string()
|
|
19
|
+
.describe("The id of the video to update (you must own it)."),
|
|
20
|
+
title: z.string().describe("New title. Max 100 characters.").optional(),
|
|
21
|
+
description: z.string().describe("New description.").optional(),
|
|
22
|
+
tags: z
|
|
23
|
+
.array(z.string())
|
|
24
|
+
.describe("New tag list (replaces the existing tags).")
|
|
25
|
+
.optional(),
|
|
26
|
+
category_id: z
|
|
27
|
+
.string()
|
|
28
|
+
.describe("New category id (from listVideoCategories).")
|
|
29
|
+
.optional(),
|
|
30
|
+
privacy_status: z
|
|
31
|
+
.enum(["private", "public", "unlisted"])
|
|
32
|
+
.describe("New privacy status.")
|
|
33
|
+
.optional(),
|
|
34
|
+
publish_at: z
|
|
35
|
+
.string()
|
|
36
|
+
.describe(
|
|
37
|
+
"Reschedule publication (RFC3339). Requires privacy_status=private.",
|
|
38
|
+
)
|
|
39
|
+
.optional(),
|
|
40
|
+
made_for_kids: z
|
|
41
|
+
.boolean()
|
|
42
|
+
.describe("COPPA self-declaration (status.selfDeclaredMadeForKids).")
|
|
43
|
+
.optional(),
|
|
44
|
+
})
|
|
45
|
+
.strict();
|
|
46
|
+
|
|
47
|
+
const outputSchema = VideoSchema;
|
|
48
|
+
|
|
49
|
+
interface VideoSnippet {
|
|
50
|
+
title?: string;
|
|
51
|
+
description?: string;
|
|
52
|
+
tags?: string[];
|
|
53
|
+
categoryId?: string;
|
|
54
|
+
defaultLanguage?: string;
|
|
55
|
+
[k: string]: unknown;
|
|
56
|
+
}
|
|
57
|
+
interface VideoStatus {
|
|
58
|
+
privacyStatus?: string;
|
|
59
|
+
publishAt?: string;
|
|
60
|
+
selfDeclaredMadeForKids?: boolean;
|
|
61
|
+
license?: string;
|
|
62
|
+
embeddable?: boolean;
|
|
63
|
+
publicStatsViewable?: boolean;
|
|
64
|
+
[k: string]: unknown;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const definition = defineTool({
|
|
68
|
+
name: "updateVideo",
|
|
69
|
+
title: "Update Video",
|
|
70
|
+
description:
|
|
71
|
+
"Update an existing video's metadata (title, description, tags, category, privacy) without disturbing the fields you don't change. Reads the current video first, merges your changes, then writes — so omitting a field leaves it as-is. You must own the video.",
|
|
72
|
+
inputSchema,
|
|
73
|
+
outputSchema,
|
|
74
|
+
annotations: {
|
|
75
|
+
readOnlyHint: false,
|
|
76
|
+
destructiveHint: false,
|
|
77
|
+
idempotentHint: true,
|
|
78
|
+
openWorldHint: true,
|
|
79
|
+
},
|
|
80
|
+
connection: "youtube",
|
|
81
|
+
run: async (input, ctx) => {
|
|
82
|
+
// 1. Read the current snippet + status.
|
|
83
|
+
const getUrl = new URL(`https://www.googleapis.com/youtube/v3/videos`);
|
|
84
|
+
getUrl.searchParams.set("part", "snippet,status");
|
|
85
|
+
getUrl.searchParams.set("id", input.video_id);
|
|
86
|
+
const getRes = await ctx.fetch(getUrl.toString(), { method: "GET" });
|
|
87
|
+
await throwForYouTube(getRes, "updateVideo");
|
|
88
|
+
const current = (await getRes.json()) as {
|
|
89
|
+
items?: Array<{ snippet?: VideoSnippet; status?: VideoStatus }>;
|
|
90
|
+
};
|
|
91
|
+
const video = current.items?.[0];
|
|
92
|
+
if (!video) {
|
|
93
|
+
throw new Error(
|
|
94
|
+
`YouTube updateVideo 404: no video found with id '${input.video_id}'. Verify the id (resolve via searchVideos/getVideo); you can only update videos you own.`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 2. Merge the provided fields onto the current snippet/status. The API requires
|
|
99
|
+
// snippet.title and snippet.categoryId on update — carried forward from the
|
|
100
|
+
// current video unless the agent overrides them. Only writable fields are sent.
|
|
101
|
+
const cur = video.snippet ?? {};
|
|
102
|
+
const snippet: VideoSnippet = {
|
|
103
|
+
title: input.title ?? cur.title,
|
|
104
|
+
categoryId: input.category_id ?? cur.categoryId,
|
|
105
|
+
};
|
|
106
|
+
if (input.description !== undefined)
|
|
107
|
+
snippet.description = input.description;
|
|
108
|
+
else if (cur.description !== undefined)
|
|
109
|
+
snippet.description = cur.description;
|
|
110
|
+
if (input.tags !== undefined) snippet.tags = input.tags;
|
|
111
|
+
else if (cur.tags !== undefined) snippet.tags = cur.tags;
|
|
112
|
+
if (cur.defaultLanguage !== undefined)
|
|
113
|
+
snippet.defaultLanguage = cur.defaultLanguage;
|
|
114
|
+
|
|
115
|
+
const curStatus = video.status ?? {};
|
|
116
|
+
const status: VideoStatus = {
|
|
117
|
+
privacyStatus: input.privacy_status ?? curStatus.privacyStatus,
|
|
118
|
+
};
|
|
119
|
+
if (input.publish_at !== undefined) status.publishAt = input.publish_at;
|
|
120
|
+
else if (curStatus.publishAt !== undefined)
|
|
121
|
+
status.publishAt = curStatus.publishAt;
|
|
122
|
+
if (input.made_for_kids !== undefined)
|
|
123
|
+
status.selfDeclaredMadeForKids = input.made_for_kids;
|
|
124
|
+
else if (curStatus.selfDeclaredMadeForKids !== undefined)
|
|
125
|
+
status.selfDeclaredMadeForKids = curStatus.selfDeclaredMadeForKids;
|
|
126
|
+
if (curStatus.license !== undefined) status.license = curStatus.license;
|
|
127
|
+
|
|
128
|
+
// 3. Write the full merged object back.
|
|
129
|
+
const putUrl = new URL(`https://www.googleapis.com/youtube/v3/videos`);
|
|
130
|
+
putUrl.searchParams.set("part", "snippet,status");
|
|
131
|
+
const putRes = await ctx.fetch(putUrl.toString(), {
|
|
132
|
+
method: "PUT",
|
|
133
|
+
headers: { "Content-Type": "application/json" },
|
|
134
|
+
body: JSON.stringify({ id: input.video_id, snippet, status }),
|
|
135
|
+
});
|
|
136
|
+
await throwForYouTube(putRes, "updateVideo");
|
|
137
|
+
return putRes.json();
|
|
138
|
+
},
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
export default definition;
|
|
142
|
+
|
|
143
|
+
await handleIfScriptMain(import.meta, definition, { connectionResolvers });
|
package/tsup.config.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* tsup build config for connectors.
|
|
3
|
+
*
|
|
4
|
+
* Compiles index.ts (library entry, bundled) and cli.ts (CLI, bundled but
|
|
5
|
+
* with the connector's index module kept external).
|
|
6
|
+
*
|
|
7
|
+
* The cli.ts entry externalises ./index.ts → ./index.js via an esbuild plugin
|
|
8
|
+
* so that dist/cli.js imports the pre-built dist/index.js as a separate module
|
|
9
|
+
* rather than inlining scripts. Without this, each script's top-level
|
|
10
|
+
* `await handleIfScriptMain(import.meta, …)` ends up inside the single-file
|
|
11
|
+
* bundle; in Node 22.18+ import.meta.main is true for the bundle entry,
|
|
12
|
+
* causing every script to execute when the dispatch CLI starts instead of
|
|
13
|
+
* routing via runDispatchCli.
|
|
14
|
+
*
|
|
15
|
+
* Managed by @zapier/connectors-dev — do not edit; synced byte-for-byte
|
|
16
|
+
* across every connector.
|
|
17
|
+
*/
|
|
18
|
+
import { defineConfig } from "tsup";
|
|
19
|
+
|
|
20
|
+
export default defineConfig([
|
|
21
|
+
{
|
|
22
|
+
entry: ["index.ts"],
|
|
23
|
+
format: ["esm"],
|
|
24
|
+
dts: false,
|
|
25
|
+
clean: true,
|
|
26
|
+
target: "es2022",
|
|
27
|
+
external: [
|
|
28
|
+
"@modelcontextprotocol/sdk",
|
|
29
|
+
"@zapier/zapier-sdk",
|
|
30
|
+
"zod",
|
|
31
|
+
"@zapier/connectors-sdk",
|
|
32
|
+
],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
entry: ["cli.ts"],
|
|
36
|
+
format: ["esm"],
|
|
37
|
+
dts: false,
|
|
38
|
+
clean: false,
|
|
39
|
+
target: "es2022",
|
|
40
|
+
external: [
|
|
41
|
+
"@modelcontextprotocol/sdk",
|
|
42
|
+
"@zapier/zapier-sdk",
|
|
43
|
+
"zod",
|
|
44
|
+
"@zapier/connectors-sdk",
|
|
45
|
+
],
|
|
46
|
+
esbuildPlugins: [
|
|
47
|
+
{
|
|
48
|
+
name: "externalize-connector-index",
|
|
49
|
+
setup(build) {
|
|
50
|
+
// Resolve ./index.ts to the pre-built ./index.js and mark it external
|
|
51
|
+
// so scripts are not inlined into dist/cli.js. When dist/index.js is
|
|
52
|
+
// imported (not the entry), import.meta.main is false inside it and
|
|
53
|
+
// handleIfScriptMain's existing !meta.main guard suppresses per-script
|
|
54
|
+
// execution — no SDK changes required.
|
|
55
|
+
build.onResolve({ filter: /^\.\/index(\.ts)?$/ }, () => ({
|
|
56
|
+
path: "./index.js",
|
|
57
|
+
external: true,
|
|
58
|
+
}));
|
|
59
|
+
},
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
},
|
|
63
|
+
]);
|