Skip to content
Merged
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ Visit [http://localhost:3000](http://localhost:3000) to get started.
<!-- PLUGINS:START - Do not remove. Auto-generated by discover-plugins -->
- **AI Gateway**: Generate Text, Generate Image
- **Blob**: Put Blob, List Blobs
- **Clerk**: Get User, Create User, Update User, Delete User
- **fal.ai**: Generate Image, Generate Video, Upscale Image, Remove Background, Image to Image
- **Firecrawl**: Scrape URL, Search Web
- **GitHub**: Create Issue, List Issues, Get Issue, Update Issue
Expand Down
83 changes: 83 additions & 0 deletions lib/workflow-codegen-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,84 @@ export function generateWorkflowSDKCode(
"apiKey: process.env.V0_API_KEY!",
];
}

function buildClerkGetUserParams(config: Record<string, unknown>): string[] {
return [
`userId: \`${convertTemplateToJS((config.userId as string) || "")}\``,
];
}

function buildClerkCreateUserParams(
config: Record<string, unknown>
): string[] {
const params = [
`emailAddress: \`${convertTemplateToJS((config.emailAddress as string) || "")}\``,
];
if (config.password) {
params.push(
`password: \`${convertTemplateToJS(config.password as string)}\``
);
}
if (config.firstName) {
params.push(
`firstName: \`${convertTemplateToJS(config.firstName as string)}\``
);
}
if (config.lastName) {
params.push(
`lastName: \`${convertTemplateToJS(config.lastName as string)}\``
);
}
if (config.publicMetadata) {
params.push(
`publicMetadata: \`${convertTemplateToJS(config.publicMetadata as string)}\``
);
}
if (config.privateMetadata) {
params.push(
`privateMetadata: \`${convertTemplateToJS(config.privateMetadata as string)}\``
);
}
return params;
}

function buildClerkUpdateUserParams(
config: Record<string, unknown>
): string[] {
const params = [
`userId: \`${convertTemplateToJS((config.userId as string) || "")}\``,
];
if (config.firstName) {
params.push(
`firstName: \`${convertTemplateToJS(config.firstName as string)}\``
);
}
if (config.lastName) {
params.push(
`lastName: \`${convertTemplateToJS(config.lastName as string)}\``
);
}
if (config.publicMetadata) {
params.push(
`publicMetadata: \`${convertTemplateToJS(config.publicMetadata as string)}\``
);
}
if (config.privateMetadata) {
params.push(
`privateMetadata: \`${convertTemplateToJS(config.privateMetadata as string)}\``
);
}
return params;
}

function buildClerkDeleteUserParams(
config: Record<string, unknown>
): string[] {
return [
`userId: \`${convertTemplateToJS((config.userId as string) || "")}\``,
];
}

function buildStepInputParams(
actionType: string,
config: Record<string, unknown>
Expand All @@ -410,6 +488,11 @@ export function generateWorkflowSDKCode(
Search: () => buildFirecrawlParams(actionType, config),
"Create Chat": () => buildV0CreateChatParams(config),
"Send Message": () => buildV0SendMessageParams(config),
// Clerk
"Get User": () => buildClerkGetUserParams(config),
"Create User": () => buildClerkCreateUserParams(config),
"Update User": () => buildClerkUpdateUserParams(config),
"Delete User": () => buildClerkDeleteUserParams(config),
};

const builder = paramBuilders[actionType];
Expand Down
163 changes: 163 additions & 0 deletions lib/workflow-codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,147 @@ export function generateWorkflowCode(
return lines;
}

// Clerk action generators
function generateClerkGetUserActionCode(
node: WorkflowNode,
indent: string,
varName: string
): string[] {
const stepInfo = getStepInfo("Get User");
imports.add(
`import { ${stepInfo.functionName} } from '${stepInfo.importPath}';`
);

const config = node.data.config || {};
const userId = (config.userId as string) || "";

const lines = [
`${indent}const ${varName} = await ${stepInfo.functionName}({`,
`${indent} userId: ${formatTemplateValue(userId)},`,
`${indent}});`,
];

return lines;
}

function generateClerkCreateUserActionCode(
node: WorkflowNode,
indent: string,
varName: string
): string[] {
const stepInfo = getStepInfo("Create User");
imports.add(
`import { ${stepInfo.functionName} } from '${stepInfo.importPath}';`
);

const config = node.data.config || {};
const emailAddress = (config.emailAddress as string) || "";
const firstName = (config.firstName as string) || "";
const lastName = (config.lastName as string) || "";
const password = (config.password as string) || "";
const publicMetadata = (config.publicMetadata as string) || "";
const privateMetadata = (config.privateMetadata as string) || "";

const lines = [
`${indent}const ${varName} = await ${stepInfo.functionName}({`,
];

if (emailAddress) {
lines.push(
`${indent} emailAddress: ${formatTemplateValue(emailAddress)},`
);
}
if (firstName) {
lines.push(`${indent} firstName: ${formatTemplateValue(firstName)},`);
}
if (lastName) {
lines.push(`${indent} lastName: ${formatTemplateValue(lastName)},`);
}
if (password) {
lines.push(`${indent} password: ${formatTemplateValue(password)},`);
}
if (publicMetadata) {
lines.push(
`${indent} publicMetadata: ${formatTemplateValue(publicMetadata)},`
);
}
if (privateMetadata) {
lines.push(
`${indent} privateMetadata: ${formatTemplateValue(privateMetadata)},`
);
}

lines.push(`${indent}});`);

return lines;
}

function generateClerkUpdateUserActionCode(
node: WorkflowNode,
indent: string,
varName: string
): string[] {
const stepInfo = getStepInfo("Update User");
imports.add(
`import { ${stepInfo.functionName} } from '${stepInfo.importPath}';`
);

const config = node.data.config || {};
const userId = (config.userId as string) || "";
const firstName = (config.firstName as string) || "";
const lastName = (config.lastName as string) || "";
const publicMetadata = (config.publicMetadata as string) || "";
const privateMetadata = (config.privateMetadata as string) || "";

const lines = [
`${indent}const ${varName} = await ${stepInfo.functionName}({`,
`${indent} userId: ${formatTemplateValue(userId)},`,
];

if (firstName) {
lines.push(`${indent} firstName: ${formatTemplateValue(firstName)},`);
}
if (lastName) {
lines.push(`${indent} lastName: ${formatTemplateValue(lastName)},`);
}
if (publicMetadata) {
lines.push(
`${indent} publicMetadata: ${formatTemplateValue(publicMetadata)},`
);
}
if (privateMetadata) {
lines.push(
`${indent} privateMetadata: ${formatTemplateValue(privateMetadata)},`
);
}

lines.push(`${indent}});`);

return lines;
}

function generateClerkDeleteUserActionCode(
node: WorkflowNode,
indent: string,
varName: string
): string[] {
const stepInfo = getStepInfo("Delete User");
imports.add(
`import { ${stepInfo.functionName} } from '${stepInfo.importPath}';`
);

const config = node.data.config || {};
const userId = (config.userId as string) || "";

const lines = [
`${indent}const ${varName} = await ${stepInfo.functionName}({`,
`${indent} userId: ${formatTemplateValue(userId)},`,
`${indent}});`,
];

return lines;
}

// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Action type routing requires many conditionals
function generateActionNodeCode(
node: WorkflowNode,
Expand Down Expand Up @@ -725,6 +866,28 @@ export function generateWorkflowCode(
lines.push(
...wrapActionCall(generateHTTPActionCode(node, indent, varName))
);
} else if (actionType === "Get User") {
lines.push(
...wrapActionCall(generateClerkGetUserActionCode(node, indent, varName))
);
} else if (actionType === "Create User") {
lines.push(
...wrapActionCall(
generateClerkCreateUserActionCode(node, indent, varName)
)
);
} else if (actionType === "Update User") {
lines.push(
...wrapActionCall(
generateClerkUpdateUserActionCode(node, indent, varName)
)
);
} else if (actionType === "Delete User") {
lines.push(
...wrapActionCall(
generateClerkDeleteUserActionCode(node, indent, varName)
)
);
} else if (outputIsUsed) {
lines.push(`${indent}const ${varName} = { status: 'success' };`);
} else {
Expand Down
3 changes: 3 additions & 0 deletions plugins/clerk/credentials.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export type ClerkCredentials = {
CLERK_SECRET_KEY?: string;
};
21 changes: 21 additions & 0 deletions plugins/clerk/icon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
export function ClerkIcon({ className }: { className?: string }) {
return (
<svg
className={className}
role="img"
viewBox="0 0 128 128"
xmlns="http://www.w3.org/2000/svg"
>
<circle cx="64" cy="64" r="20" fill="currentColor" />
<path
fill="currentColor"
fillOpacity="0.6"
d="M99.5716 10.788C101.571 12.1272 101.742 14.9444 100.04 16.646L85.4244 31.2618C84.1035 32.5828 82.0542 32.7914 80.3915 31.9397C75.4752 29.421 69.9035 28 64 28C44.1177 28 28 44.1177 28 64C28 69.9035 29.421 75.4752 31.9397 80.3915C32.7914 82.0542 32.5828 84.1035 31.2618 85.4244L16.646 100.04C14.9444 101.742 12.1272 101.571 10.788 99.5716C3.97411 89.3989 0 77.1635 0 64C0 28.6538 28.6538 0 64 0C77.1635 0 89.3989 3.97411 99.5716 10.788Z"
/>
<path
fill="currentColor"
d="M100.04 111.354C101.742 113.056 101.571 115.873 99.5717 117.212C89.3989 124.026 77.1636 128 64 128C50.8364 128 38.6011 124.026 28.4283 117.212C26.4289 115.873 26.2581 113.056 27.9597 111.354L42.5755 96.7382C43.8965 95.4172 45.9457 95.2085 47.6084 96.0603C52.5248 98.579 58.0964 100 64 100C69.9036 100 75.4753 98.579 80.3916 96.0603C82.0543 95.2085 84.1036 95.4172 85.4245 96.7382L100.04 111.354Z"
/>
</svg>
);
}
Loading