Skip to content
This repository has been archived by the owner on Dec 10, 2024. It is now read-only.

Commit

Permalink
feat(nuxt): add SES module (#59)
Browse files Browse the repository at this point in the history
* feat(nuxt): add 'ses' module

* Add @aws-sdk/client-ses devdependency

* docs: Add SES configuration for test environment

* refactor SES and S3 module names

* Remove empty object argument in use() method call
  • Loading branch information
productdevbook authored Dec 12, 2023
1 parent b50b00f commit 49613b9
Show file tree
Hide file tree
Showing 15 changed files with 494 additions and 103 deletions.
8 changes: 4 additions & 4 deletions .docs/content/pergel/3.nuxt/1.index.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ Nuxt is a framework for creating Vue applications. Pergel is a full stack Nuxt a
NodeCron is a simple cron-like job scheduler for Node.js.
::

::card{icon="i-ph-cube-duotone" title="SES" to="/pergel/nuxt/ses/installation"}
SES is a highly scalable and cost-effective email sending service for businesses and developers.
::

::card{icon="i-ph-cube-duotone" title="Drizzle - Soon" to="#"}
It's awful Typescript ORM.
::
Expand All @@ -41,10 +45,6 @@ Nuxt is a framework for creating Vue applications. Pergel is a full stack Nuxt a
RabbitMQ is the most widely deployed open source message broker.
::

::card{icon="i-ph-cube-duotone" title="SES - Soon" to="#"}
SES is a highly scalable and cost-effective email sending service for businesses and developers.
::

::card{icon="i-ph-cube-duotone" title="... More Modules" to="#
Soon ...
::
Expand Down
116 changes: 116 additions & 0 deletions .docs/content/pergel/3.nuxt/ses/1.installation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
---
title: Installation
description: 'Pergel Nuxt Module for AWS SES'
---

1. Add it to your `modules` section of `nuxt.config`:

::code-group
```ts [nuxt.config.ts]
export default defineNuxtConfig({
modules: ['@pergel/nuxt'],
pergel: {
projects: {
myproject: {
ses: true,
},
// bookList: {
// ses: false
// },
},
},
})
```
::

::callout{color="amber" icon="i-ph-warning-duotone"}
Node >= 20.8.0 is required.
Nuxt >= 3.9.0 is required.
::


2. Auto install dependencies:

::code-group
```sh [pnpm]
pergel install
```
::

:read-more{title="Install Pergel CLI" to="/pergel/cli"}

3. Add your server code

::code-group
```ts [server/api/sendemail.ts]
export default defineEventHandler(async (event) => {
try {
const { sendEmail, templates, ... } = await pergelMyproject().ses().use(event)

const _emailParams = {
Destination: {
ToAddresses: ['[email protected]'],
},
Message: {
Body: {
Text: {
Data: 'Test email',
},
},
Subject: {
Data: 'Test email',
},
},
Source: '[email protected]',
}

const send = await sendEmail(sendEmail)

// const result = await sendEmail(templates().changeEmail({
// to: '[email protected]',
// code: '123456',
// webUrl: 'https://productdevbook.com',
// source: '[email protected]',
// }))

return {
data: {
mailResult: send,
},
}
}
catch (error: any) {
return error.message
}
})

```

```ts [composables]
pergelMyproject().ses().use()
```

::

4. Add .env file

Root directory of your project `pergel` folder inside `README.yaml` file. Check for `projectName` and `ses` section.

::code-group
```sh [.env]
# You see this in your README.yaml file
env:
NUXT_TEST_SES_REGION:
NUXT_TEST_SES_ACCESS_KEY_ID:
NUXT_TEST_SES_SECRET_ACCESS_KEY:

# Copy and change `:` to `=` and add your credentials
NUXT_TEST_SES_REGION=us-east-1
NUXT_TEST_SES_ACCESS_KEY_ID=123456
NUXT_TEST_SES_SECRET_ACCESS_KEY=123456
```
::

::callout{icon="i-ph-check-circle-duotone" color="green"}
Well done! You have successfully installed Pergel SES module.
::
2 changes: 2 additions & 0 deletions .docs/content/pergel/3.nuxt/ses/_dir.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
title: SES
icon: i-simple-icons-amazonsimpleemailservice
1 change: 1 addition & 0 deletions packages/nuxt/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
"sirv": "^2.0.3"
},
"devDependencies": {
"@aws-sdk/client-ses": "^3.465.0",
"@iconify-json/carbon": "^1.1.24",
"@nuxt/devtools-ui-kit": "^1.0.5",
"@nuxt/module-builder": "^0.5.4",
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt/playground/nuxt.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ export default defineNuxtConfig({
test: {
S3: true,
nodeCron: true,
ses: true,
},
test2: {
S3: true,
Expand Down
9 changes: 9 additions & 0 deletions packages/nuxt/playground/pergel/README.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,15 @@ pergel:
# This file is generated by pergel. Do not edit it manually.
# Version: 0.0.3
test:
ses:
env:
NUXT_TEST_SES_REGION:
NUXT_TEST_SES_ACCESS_KEY_ID:
NUXT_TEST_SES_SECRET_ACCESS_KEY:
# If pergel cli is installed, you can run `pergel install` automatically to install
packageJson:
dependencies: "@aws-sdk/client-ses@^3.470.0"
devDependencies: ""
nodeCron:
# If pergel cli is installed, you can run `pergel install` automatically to install
packageJson:
Expand Down
40 changes: 40 additions & 0 deletions packages/nuxt/playground/server/api/ses.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
export default defineEventHandler(async (event) => {
try {
const { sendEmail, templates } = await pergelTest().ses().use(event)

const _emailParams = {
Destination: {
ToAddresses: ['[email protected]'],
},
Message: {
Body: {
Text: {
Data: 'Test email',
},
},
Subject: {
Data: 'Test email',
},
},
Source: '[email protected]',
}

// const sendtest = await sendEmail(_emailParams)

const result = await sendEmail(templates().changeEmail({
to: '[email protected]',
code: '123456',
webUrl: 'https://productdevbook.com',
source: '[email protected]',
}))

return {
data: {
mailResult: result,
},
}
}
catch (error: any) {
return error.message
}
})
1 change: 1 addition & 0 deletions packages/nuxt/src/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ export default defineNuxtModule<PergelOptions>({
},
modules: [
'S3',
'ses',
'nodeCron',
],
resolver: _resolver,
Expand Down
1 change: 1 addition & 0 deletions packages/nuxt/src/runtime/core/types/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import type { Nuxt } from '@nuxt/schema'

export interface Modules {
S3?: true
ses?: true
nodeCron?: true
}

Expand Down
3 changes: 3 additions & 0 deletions packages/nuxt/src/runtime/modules/S3/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,10 @@ export default definePergelModule({
content: /* TypeScript */ `
function S3() {
return {
// TODO: change name to 'usePergelS3Client'
client: pergelS3Client.bind(ctx),
// TODO: change name to 'usePergelS3'
// TODO: useS3 key name change -> 'use'
useS3: useS3.bind(ctx),
}
}
Expand Down
53 changes: 53 additions & 0 deletions packages/nuxt/src/runtime/modules/ses/composables/usePergelSES.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
import { CreateTemplateCommand, type CreateTemplateCommandInput, SESClient, SendEmailCommand, type SendEmailCommandInput } from '@aws-sdk/client-ses'
import type { H3Event } from 'h3'
import type { SesModuleRuntimeConfig } from '../types'
import { templates } from '../templates'
import { clientFunctionTemplate } from '../../../../runtime/core/useClient'
import type { PergelGlobalContextOmitModule } from '#pergel'

export interface Credentials {
accessKeyId: string
secretAccessKey: string
}

const { clientInit } = clientFunctionTemplate<SESClient, SesModuleRuntimeConfig>('ses')

export async function usePergelSES(
this: PergelGlobalContextOmitModule,
event?: H3Event,
data?: PergelGlobalContextOmitModule,
) {
const _pergel = data ?? this

if (!_pergel || !_pergel.projectName)
throw new Error('Pergel is not defined')

const { client } = await clientInit(_pergel, (runtime) => {
return new SESClient({
region: runtime.region,
credentials: {
accessKeyId: runtime.accessKeyId,
secretAccessKey: runtime.secretAccessKey,
},
})
}, event)

async function sendEmail(params: SendEmailCommandInput) {
const command = new SendEmailCommand(params)
const data = await client.send(command)
return data
}

async function createTemplate(params: CreateTemplateCommandInput) {
const command = new CreateTemplateCommand(params)
const data = await client.send(command)
return data
}

return {
sendEmail,
createTemplate,
templates,
client,
}
}
42 changes: 42 additions & 0 deletions packages/nuxt/src/runtime/modules/ses/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { addServerImportsDir, createResolver } from '@nuxt/kit'
import { definePergelModule } from '../../core/definePergel'
import { generateModuleRuntimeConfig } from '../../core/utils/moduleRuntimeConfig'
import type { SesModuleRuntimeConfig } from './types'

export default definePergelModule({
meta: {
name: 'ses',
version: '0.0.1',
dependencies: {
'@aws-sdk/client-ses': '^3.470.0',
},
},
defaults: {},
async setup(options, nuxt) {
const resolver = createResolver(import.meta.url)
const projectName = options.resolvedModule.projectName

generateModuleRuntimeConfig<SesModuleRuntimeConfig>(nuxt, options, {
region: '',
accessKeyId: '',
secretAccessKey: '',
})

addServerImportsDir(resolver.resolve('./composables'))

options._contents.push({
moduleName: 'ses',
projectName,
content: /* ts */`
function ses() {
return {
use: usePergelSES.bind(ctx),
}
}
`,
resolve: /* ts */`
ses: ses,
`,
})
},
})
Loading

0 comments on commit 49613b9

Please sign in to comment.