MCP Server 2.0 (#452)
* MCP Server 2.0 - Updated application version from 2.23.14 to 2.24.0 in package.json. - MCP Server improved with new features - Migrated functionality from Dev Tools to MCP Server - Improved getMonitoringProvider not to crash application when misconfigured
This commit is contained in:
committed by
GitHub
parent
059408a70a
commit
f3ac595d06
@@ -1,10 +1,12 @@
|
||||
import { EmailTesterForm } from '@/app/emails/[id]/components/email-tester-form';
|
||||
import { loadEmailTemplate } from '@/app/emails/lib/email-loader';
|
||||
import { getVariable } from '@/app/variables/lib/env-scanner';
|
||||
import { EnvMode } from '@/app/variables/lib/types';
|
||||
import { EnvModeSelector } from '@/components/env-mode-selector';
|
||||
import { IFrame } from '@/components/iframe';
|
||||
|
||||
import {
|
||||
createKitEmailsDeps,
|
||||
createKitEmailsService,
|
||||
} from '@kit/mcp-server/emails';
|
||||
import { findWorkspaceRoot, getVariable } from '@kit/mcp-server/env';
|
||||
import { AppBreadcrumbs } from '@kit/ui/app-breadcrumbs';
|
||||
import { Button } from '@kit/ui/button';
|
||||
import {
|
||||
@@ -15,6 +17,8 @@ import {
|
||||
} from '@kit/ui/dialog';
|
||||
import { Page, PageBody, PageHeader } from '@kit/ui/page';
|
||||
|
||||
type EnvMode = 'development' | 'production';
|
||||
|
||||
type EmailPageProps = React.PropsWithChildren<{
|
||||
params: Promise<{
|
||||
id: string;
|
||||
@@ -31,25 +35,28 @@ export default async function EmailPage(props: EmailPageProps) {
|
||||
const { id } = await props.params;
|
||||
const mode = (await props.searchParams).mode ?? 'development';
|
||||
|
||||
const template = await loadEmailTemplate(id);
|
||||
const emailSettings = await getEmailSettings(mode);
|
||||
const rootPath = findWorkspaceRoot(process.cwd());
|
||||
const service = createKitEmailsService(createKitEmailsDeps(rootPath));
|
||||
|
||||
const values: Record<string, string> = {
|
||||
emails: 'Emails',
|
||||
'invite-email': 'Invite Email',
|
||||
'account-delete-email': 'Account Delete Email',
|
||||
'confirm-email': 'Confirm Email',
|
||||
'change-email-address-email': 'Change Email Address Email',
|
||||
'reset-password-email': 'Reset Password Email',
|
||||
'magic-link-email': 'Magic Link Email',
|
||||
'otp-email': 'OTP Email',
|
||||
};
|
||||
const [result, { templates }, emailSettings] = await Promise.all([
|
||||
service.read({ id }),
|
||||
service.list(),
|
||||
getEmailSettings(mode),
|
||||
]);
|
||||
|
||||
const html = result.renderedHtml ?? result.source;
|
||||
|
||||
const values: Record<string, string> = { emails: 'Emails' };
|
||||
|
||||
for (const t of templates) {
|
||||
values[t.id] = t.name;
|
||||
}
|
||||
|
||||
return (
|
||||
<Page style={'custom'}>
|
||||
<PageHeader
|
||||
displaySidebarTrigger={false}
|
||||
title={values[id]}
|
||||
title={values[id] ?? id}
|
||||
description={<AppBreadcrumbs values={values} />}
|
||||
>
|
||||
<EnvModeSelector mode={mode} />
|
||||
@@ -77,7 +84,7 @@ export default async function EmailPage(props: EmailPageProps) {
|
||||
<IFrame className={'flex flex-1 flex-col'}>
|
||||
<div
|
||||
className={'flex flex-1 flex-col'}
|
||||
dangerouslySetInnerHTML={{ __html: template.html }}
|
||||
dangerouslySetInnerHTML={{ __html: html }}
|
||||
/>
|
||||
</IFrame>
|
||||
</PageBody>
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
import {
|
||||
renderAccountDeleteEmail,
|
||||
renderInviteEmail,
|
||||
renderOtpEmail,
|
||||
} from '@kit/email-templates';
|
||||
|
||||
export async function loadEmailTemplate(id: string) {
|
||||
switch (id) {
|
||||
case 'account-delete-email':
|
||||
return renderAccountDeleteEmail({
|
||||
productName: 'Makerkit',
|
||||
userDisplayName: 'Giancarlo',
|
||||
});
|
||||
|
||||
case 'invite-email':
|
||||
return renderInviteEmail({
|
||||
teamName: 'Makerkit',
|
||||
teamLogo: '',
|
||||
inviter: 'Giancarlo',
|
||||
invitedUserEmail: 'test@makerkit.dev',
|
||||
link: 'https://makerkit.dev',
|
||||
productName: 'Makerkit',
|
||||
});
|
||||
|
||||
case 'otp-email':
|
||||
return renderOtpEmail({
|
||||
productName: 'Makerkit',
|
||||
otp: '123456',
|
||||
});
|
||||
|
||||
case 'magic-link-email':
|
||||
return loadFromFileSystem('magic-link');
|
||||
|
||||
case 'reset-password-email':
|
||||
return loadFromFileSystem('reset-password');
|
||||
|
||||
case 'change-email-address-email':
|
||||
return loadFromFileSystem('change-email-address');
|
||||
|
||||
case 'confirm-email':
|
||||
return loadFromFileSystem('confirm-email');
|
||||
|
||||
default:
|
||||
throw new Error(`Email template not found: ${id}`);
|
||||
}
|
||||
}
|
||||
|
||||
async function loadFromFileSystem(fileName: string) {
|
||||
const { readFileSync } = await import('node:fs');
|
||||
const { join } = await import('node:path');
|
||||
|
||||
const filePath = join(
|
||||
process.cwd(),
|
||||
`../web/supabase/templates/${fileName}.html`,
|
||||
);
|
||||
|
||||
return {
|
||||
html: readFileSync(filePath, 'utf8'),
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,10 @@
|
||||
'use server';
|
||||
|
||||
import { loadEmailTemplate } from '@/app/emails/lib/email-loader';
|
||||
import {
|
||||
createKitEmailsDeps,
|
||||
createKitEmailsService,
|
||||
} from '@kit/mcp-server/emails';
|
||||
import { findWorkspaceRoot } from '@kit/mcp-server/env';
|
||||
|
||||
export async function sendEmailAction(params: {
|
||||
template: string;
|
||||
@@ -27,7 +31,10 @@ export async function sendEmailAction(params: {
|
||||
},
|
||||
});
|
||||
|
||||
const { html } = await loadEmailTemplate(params.template);
|
||||
const rootPath = findWorkspaceRoot(process.cwd());
|
||||
const service = createKitEmailsService(createKitEmailsDeps(rootPath));
|
||||
const result = await service.read({ id: params.template });
|
||||
const html = result.renderedHtml ?? result.source;
|
||||
|
||||
return transporter.sendMail({
|
||||
html,
|
||||
|
||||
@@ -1,5 +1,10 @@
|
||||
import Link from 'next/link';
|
||||
|
||||
import {
|
||||
createKitEmailsDeps,
|
||||
createKitEmailsService,
|
||||
} from '@kit/mcp-server/emails';
|
||||
import { findWorkspaceRoot } from '@kit/mcp-server/env';
|
||||
import {
|
||||
CardButton,
|
||||
CardButtonHeader,
|
||||
@@ -12,7 +17,16 @@ export const metadata = {
|
||||
title: 'Emails',
|
||||
};
|
||||
|
||||
const CATEGORY_LABELS: Record<string, string> = {
|
||||
'supabase-auth': 'Supabase Auth Emails',
|
||||
transactional: 'Transactional Emails',
|
||||
};
|
||||
|
||||
export default async function EmailsPage() {
|
||||
const rootPath = findWorkspaceRoot(process.cwd());
|
||||
const service = createKitEmailsService(createKitEmailsDeps(rootPath));
|
||||
const { templates, categories } = await service.list();
|
||||
|
||||
return (
|
||||
<Page style={'custom'}>
|
||||
<PageHeader
|
||||
@@ -22,73 +36,31 @@ export default async function EmailsPage() {
|
||||
/>
|
||||
|
||||
<PageBody className={'gap-y-8'}>
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<Heading level={5}>Supabase Auth Emails</Heading>
|
||||
{categories.map((category) => {
|
||||
const categoryTemplates = templates.filter(
|
||||
(t) => t.category === category,
|
||||
);
|
||||
|
||||
<div className={'grid grid-cols-1 gap-4 md:grid-cols-4'}>
|
||||
<CardButton asChild>
|
||||
<Link href={'/emails/confirm-email'}>
|
||||
<CardButtonHeader>
|
||||
<CardButtonTitle>Confirm Email</CardButtonTitle>
|
||||
</CardButtonHeader>
|
||||
</Link>
|
||||
</CardButton>
|
||||
return (
|
||||
<div key={category} className={'flex flex-col space-y-4'}>
|
||||
<Heading level={5}>
|
||||
{CATEGORY_LABELS[category] ?? category}
|
||||
</Heading>
|
||||
|
||||
<CardButton asChild>
|
||||
<Link href={'/emails/change-email-address-email'}>
|
||||
<CardButtonHeader>
|
||||
<CardButtonTitle>Change Email Address Email</CardButtonTitle>
|
||||
</CardButtonHeader>
|
||||
</Link>
|
||||
</CardButton>
|
||||
|
||||
<CardButton asChild>
|
||||
<Link href={'/emails/reset-password-email'}>
|
||||
<CardButtonHeader>
|
||||
<CardButtonTitle>Reset Password Email</CardButtonTitle>
|
||||
</CardButtonHeader>
|
||||
</Link>
|
||||
</CardButton>
|
||||
|
||||
<CardButton asChild>
|
||||
<Link href={'/emails/magic-link-email'}>
|
||||
<CardButtonHeader>
|
||||
<CardButtonTitle>Magic Link Email</CardButtonTitle>
|
||||
</CardButtonHeader>
|
||||
</Link>
|
||||
</CardButton>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={'flex flex-col space-y-4'}>
|
||||
<Heading level={5}>Transactional Emails</Heading>
|
||||
|
||||
<div className={'grid grid-cols-1 gap-4 md:grid-cols-4'}>
|
||||
<CardButton asChild>
|
||||
<Link href={'/emails/account-delete-email'}>
|
||||
<CardButtonHeader>
|
||||
<CardButtonTitle>Account Delete Email</CardButtonTitle>
|
||||
</CardButtonHeader>
|
||||
</Link>
|
||||
</CardButton>
|
||||
|
||||
<CardButton asChild>
|
||||
<Link href={'/emails/invite-email'}>
|
||||
<CardButtonHeader>
|
||||
<CardButtonTitle>Invite Email</CardButtonTitle>
|
||||
</CardButtonHeader>
|
||||
</Link>
|
||||
</CardButton>
|
||||
|
||||
<CardButton asChild>
|
||||
<Link href={'/emails/otp-email'}>
|
||||
<CardButtonHeader>
|
||||
<CardButtonTitle>OTP Email</CardButtonTitle>
|
||||
</CardButtonHeader>
|
||||
</Link>
|
||||
</CardButton>
|
||||
</div>
|
||||
</div>
|
||||
<div className={'grid grid-cols-1 gap-4 md:grid-cols-4'}>
|
||||
{categoryTemplates.map((template) => (
|
||||
<CardButton key={template.id} asChild>
|
||||
<Link href={`/emails/${template.id}`}>
|
||||
<CardButtonHeader>
|
||||
<CardButtonTitle>{template.name}</CardButtonTitle>
|
||||
</CardButtonHeader>
|
||||
</Link>
|
||||
</CardButton>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
</PageBody>
|
||||
</Page>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user