Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions app/inngest/client.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { EventSchemas, Inngest } from 'inngest'

import { type Events } from './events'

export const inngest = new Inngest({
id: 'my-app',
schemas: new EventSchemas().fromRecord<Events>()
})
10 changes: 10 additions & 0 deletions app/inngest/events.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
type NoteCreated = {
data: {
title: string;
image_url: string | null;
};
};

export type Events = {
'note.created': NoteCreated;
};
63 changes: 63 additions & 0 deletions app/inngest/functions/sendWeeklyDigest.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import * as E from '@react-email/components'
import { prisma } from '#app/utils/db.server.ts'
import { sendEmail } from '#app/utils/email.server.ts'
import { inngest } from '../client'

export const sendWeeklyDigest = inngest.createFunction(
{ id: 'send-weekly-digest' },
{
cron: 'TZ=America/New_York 0 8 * * 1',
},
async ({ step }) => {
const users = await step.run('get-all-users', async () => {
return prisma.user.findMany()
})

for (const user of users) {
const digestData = await step.run('fetch-digest-data', async () => {
return {
notesCount: await prisma.note.count({
where: {
ownerId: user.id,
},
}),
}
})
await step.run(`send-digest`, async () => {
await sendEmail({
to: user.email,
subject: 'Epic Notes Weekly Digest',
react: <WeeklyDigestEmail digestData={digestData} />,
})
})
}

return {
result: `Sent ${users.length} weekly reports`,
}
},
)

function WeeklyDigestEmail({
digestData,
}: {
digestData: {
notesCount: number
}
}) {
return (
<E.Html lang="en" dir="ltr">
<E.Container>
<h1>
<E.Text>Your Epic notes weekly digest</E.Text>
</h1>
<p>
<E.Text>
You created {digestData.notesCount} notes this week. Great job, keep
it up!
</E.Text>
</p>
</E.Container>
</E.Html>
)
}
6 changes: 6 additions & 0 deletions app/inngest/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { sendWeeklyDigest } from './functions/sendWeeklyDigest'

export { inngest } from './client'
export const functions = [
sendWeeklyDigest,
]
30 changes: 2 additions & 28 deletions app/routes/resources+/inngest.ts
Original file line number Diff line number Diff line change
@@ -1,33 +1,7 @@
import { EventSchemas, Inngest } from 'inngest'
import { inngest, functions } from '#app/inngest'
import { serve } from 'inngest/remix'

// Define the event type
type HelloWorldEvent = {
name: 'test/hello.world'
data: {
name: string
}
}

// Create the schema
export const schemas = new EventSchemas().fromUnion<HelloWorldEvent>()

// Initialize the Inngest client with the schema
const inngest = new Inngest({ id: 'my-app', schemas })

// Define your functions here
const helloWorld = inngest.createFunction(
{ id: 'hello-world', name: 'Hello World' },
{ event: 'test/hello.world' },
async ({ event, step }) => {
await step.run('Say hello', () => {
console.log(`Hello, ${event.data.name}!`)
})
return { message: `Hello, ${event.data.name}!` }
},
)

// Create the serve handler
const inngestHandler = serve({ client: inngest, functions: [helloWorld] })
const inngestHandler = serve({ client: inngest, functions })

export { inngestHandler as action, inngestHandler as loader }