Skip to content

Commit 020f791

Browse files
committed
feat: add Dub plugin
1 parent 3436d68 commit 020f791

File tree

6 files changed

+674
-0
lines changed

6 files changed

+674
-0
lines changed

plugins/dub/credentials.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
export type DubCredentials = {
2+
DUB_API_KEY?: string;
3+
};

plugins/dub/icon.tsx

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export function DubIcon({ className }: { className?: string }) {
2+
return (
3+
<svg
4+
aria-label="Dub logo"
5+
className={className}
6+
fill="currentColor"
7+
viewBox="0 0 64 64"
8+
xmlns="http://www.w3.org/2000/svg"
9+
>
10+
<title>Dub</title>
11+
<path fill-rule="evenodd" clip-rule="evenodd" d="M32 64c17.673 0 32-14.327 32-32 0-11.844-6.435-22.186-16-27.719V48h-8v-2.14A15.9 15.9 0 0 1 32 48c-8.837 0-16-7.163-16-16s7.163-16 16-16c2.914 0 5.647.78 8 2.14V1.008A32 32 0 0 0 32 0C14.327 0 0 14.327 0 32s14.327 32 32 32" fill="currentColor"/>
12+
</svg>
13+
);
14+
}

plugins/dub/index.ts

Lines changed: 313 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,313 @@
1+
import type { IntegrationPlugin } from "../registry";
2+
import { registerIntegration } from "../registry";
3+
import { DubIcon } from "./icon";
4+
5+
const dubPlugin: IntegrationPlugin = {
6+
type: "dub",
7+
label: "Dub",
8+
description: "Create and manage short links",
9+
10+
icon: DubIcon,
11+
12+
formFields: [
13+
{
14+
id: "apiKey",
15+
label: "API Key",
16+
type: "password",
17+
placeholder: "dub_xxx",
18+
configKey: "apiKey",
19+
envVar: "DUB_API_KEY",
20+
helpText: "Get your API key from ",
21+
helpLink: {
22+
text: "Dub Dashboard",
23+
url: "https://app.dub.co/settings/tokens",
24+
},
25+
},
26+
],
27+
28+
testConfig: {
29+
getTestFunction: async () => {
30+
const { testDub } = await import("./test");
31+
return testDub;
32+
},
33+
},
34+
35+
actions: [
36+
{
37+
slug: "create-link",
38+
label: "Create Link",
39+
description: "Create a new short link",
40+
category: "Dub",
41+
stepFunction: "createLinkStep",
42+
stepImportPath: "create-link",
43+
outputFields: [
44+
{ field: "id", description: "Unique link ID" },
45+
{ field: "shortLink", description: "The full short URL" },
46+
{ field: "qrCode", description: "QR code URL for the link" },
47+
{ field: "domain", description: "Short link domain" },
48+
{ field: "key", description: "Short link slug" },
49+
{ field: "url", description: "Destination URL" },
50+
],
51+
configFields: [
52+
{
53+
key: "url",
54+
label: "Destination URL",
55+
type: "template-input",
56+
placeholder: "https://example.com/page",
57+
example: "https://example.com/landing-page",
58+
required: true,
59+
},
60+
{
61+
key: "key",
62+
label: "Custom Slug",
63+
type: "template-input",
64+
placeholder: "my-link",
65+
example: "summer-sale",
66+
},
67+
{
68+
key: "domain",
69+
label: "Domain",
70+
type: "template-input",
71+
placeholder: "dub.sh",
72+
example: "dub.sh",
73+
},
74+
{
75+
label: "Link IDs",
76+
type: "group",
77+
fields: [
78+
{
79+
key: "externalId",
80+
label: "External ID",
81+
type: "template-input",
82+
placeholder: "my-external-id",
83+
},
84+
{
85+
key: "tenantId",
86+
label: "Tenant ID",
87+
type: "template-input",
88+
placeholder: "tenant-123",
89+
},
90+
{
91+
key: "programId",
92+
label: "Program ID",
93+
type: "template-input",
94+
placeholder: "program-123",
95+
},
96+
{
97+
key: "partnerId",
98+
label: "Partner ID",
99+
type: "template-input",
100+
placeholder: "partner-123",
101+
},
102+
],
103+
},
104+
{
105+
label: "Link Preview",
106+
type: "group",
107+
fields: [
108+
{
109+
key: "title",
110+
label: "Title",
111+
type: "template-input",
112+
placeholder: "Custom preview title",
113+
},
114+
{
115+
key: "description",
116+
label: "Description",
117+
type: "template-input",
118+
placeholder: "Custom preview description",
119+
},
120+
{
121+
key: "image",
122+
label: "Image URL",
123+
type: "template-input",
124+
placeholder: "https://example.com/image.png",
125+
},
126+
{
127+
key: "video",
128+
label: "Video URL",
129+
type: "template-input",
130+
placeholder: "https://example.com/video.mp4",
131+
},
132+
],
133+
},
134+
{
135+
label: "UTM Parameters",
136+
type: "group",
137+
fields: [
138+
{
139+
key: "utm_source",
140+
label: "Source",
141+
type: "template-input",
142+
placeholder: "newsletter",
143+
},
144+
{
145+
key: "utm_medium",
146+
label: "Medium",
147+
type: "template-input",
148+
placeholder: "email",
149+
},
150+
{
151+
key: "utm_campaign",
152+
label: "Campaign",
153+
type: "template-input",
154+
placeholder: "summer-sale",
155+
},
156+
{
157+
key: "utm_term",
158+
label: "Term",
159+
type: "template-input",
160+
placeholder: "running+shoes",
161+
},
162+
{
163+
key: "utm_content",
164+
label: "Content",
165+
type: "template-input",
166+
placeholder: "logolink",
167+
},
168+
],
169+
},
170+
],
171+
},
172+
{
173+
slug: "upsert-link",
174+
label: "Upsert Link",
175+
description: "Create or update a link by URL or external ID",
176+
category: "Dub",
177+
stepFunction: "upsertLinkStep",
178+
stepImportPath: "upsert-link",
179+
outputFields: [
180+
{ field: "id", description: "Unique link ID" },
181+
{ field: "shortLink", description: "The full short URL" },
182+
{ field: "qrCode", description: "QR code URL for the link" },
183+
{ field: "domain", description: "Short link domain" },
184+
{ field: "key", description: "Short link slug" },
185+
{ field: "url", description: "Destination URL" },
186+
],
187+
configFields: [
188+
{
189+
key: "url",
190+
label: "Destination URL",
191+
type: "template-input",
192+
placeholder: "https://example.com/page",
193+
example: "https://example.com/landing-page",
194+
required: true,
195+
},
196+
{
197+
key: "key",
198+
label: "Custom Slug",
199+
type: "template-input",
200+
placeholder: "my-link",
201+
example: "summer-sale",
202+
},
203+
{
204+
key: "domain",
205+
label: "Domain",
206+
type: "template-input",
207+
placeholder: "dub.sh",
208+
example: "dub.sh",
209+
},
210+
{
211+
label: "Link IDs",
212+
type: "group",
213+
fields: [
214+
{
215+
key: "externalId",
216+
label: "External ID",
217+
type: "template-input",
218+
placeholder: "my-external-id",
219+
},
220+
{
221+
key: "tenantId",
222+
label: "Tenant ID",
223+
type: "template-input",
224+
placeholder: "tenant-123",
225+
},
226+
{
227+
key: "programId",
228+
label: "Program ID",
229+
type: "template-input",
230+
placeholder: "program-123",
231+
},
232+
{
233+
key: "partnerId",
234+
label: "Partner ID",
235+
type: "template-input",
236+
placeholder: "partner-123",
237+
},
238+
],
239+
},
240+
{
241+
label: "Link Preview",
242+
type: "group",
243+
fields: [
244+
{
245+
key: "title",
246+
label: "Title",
247+
type: "template-input",
248+
placeholder: "Custom preview title",
249+
},
250+
{
251+
key: "description",
252+
label: "Description",
253+
type: "template-input",
254+
placeholder: "Custom preview description",
255+
},
256+
{
257+
key: "image",
258+
label: "Image URL",
259+
type: "template-input",
260+
placeholder: "https://example.com/image.png",
261+
},
262+
{
263+
key: "video",
264+
label: "Video URL",
265+
type: "template-input",
266+
placeholder: "https://example.com/video.mp4",
267+
},
268+
],
269+
},
270+
{
271+
label: "UTM Parameters",
272+
type: "group",
273+
fields: [
274+
{
275+
key: "utm_source",
276+
label: "Source",
277+
type: "template-input",
278+
placeholder: "newsletter",
279+
},
280+
{
281+
key: "utm_medium",
282+
label: "Medium",
283+
type: "template-input",
284+
placeholder: "email",
285+
},
286+
{
287+
key: "utm_campaign",
288+
label: "Campaign",
289+
type: "template-input",
290+
placeholder: "summer-sale",
291+
},
292+
{
293+
key: "utm_term",
294+
label: "Term",
295+
type: "template-input",
296+
placeholder: "running+shoes",
297+
},
298+
{
299+
key: "utm_content",
300+
label: "Content",
301+
type: "template-input",
302+
placeholder: "logolink",
303+
},
304+
],
305+
},
306+
],
307+
},
308+
],
309+
};
310+
311+
registerIntegration(dubPlugin);
312+
313+
export default dubPlugin;

0 commit comments

Comments
 (0)