feat: create email-nodemailer package
This commit is contained in:
@@ -18,6 +18,7 @@
|
|||||||
"build:create-payload-app": "turbo build --filter create-payload-app",
|
"build:create-payload-app": "turbo build --filter create-payload-app",
|
||||||
"build:db-mongodb": "turbo build --filter db-mongodb",
|
"build:db-mongodb": "turbo build --filter db-mongodb",
|
||||||
"build:db-postgres": "turbo build --filter db-postgres",
|
"build:db-postgres": "turbo build --filter db-postgres",
|
||||||
|
"build:email-nodemailer": "turbo build --filter email-nodemailer",
|
||||||
"build:eslint-config-payload": "turbo build --filter eslint-config-payload",
|
"build:eslint-config-payload": "turbo build --filter eslint-config-payload",
|
||||||
"build:graphql": "turbo build --filter graphql",
|
"build:graphql": "turbo build --filter graphql",
|
||||||
"build:live-preview": "turbo build --filter live-preview",
|
"build:live-preview": "turbo build --filter live-preview",
|
||||||
|
|||||||
10
packages/email-nodemailer/.eslintignore
Normal file
10
packages/email-nodemailer/.eslintignore
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.tmp
|
||||||
|
**/.git
|
||||||
|
**/.hg
|
||||||
|
**/.pnp.*
|
||||||
|
**/.svn
|
||||||
|
**/.yarn/**
|
||||||
|
**/build
|
||||||
|
**/dist/**
|
||||||
|
**/node_modules
|
||||||
|
**/temp
|
||||||
7
packages/email-nodemailer/.eslintrc.cjs
Normal file
7
packages/email-nodemailer/.eslintrc.cjs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/** @type {import('eslint').Linter.Config} */
|
||||||
|
module.exports = {
|
||||||
|
parserOptions: {
|
||||||
|
project: ['./tsconfig.json'],
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
},
|
||||||
|
}
|
||||||
10
packages/email-nodemailer/.prettierignore
Normal file
10
packages/email-nodemailer/.prettierignore
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
.tmp
|
||||||
|
**/.git
|
||||||
|
**/.hg
|
||||||
|
**/.pnp.*
|
||||||
|
**/.svn
|
||||||
|
**/.yarn/**
|
||||||
|
**/build
|
||||||
|
**/dist/**
|
||||||
|
**/node_modules
|
||||||
|
**/temp
|
||||||
15
packages/email-nodemailer/.swcrc
Normal file
15
packages/email-nodemailer/.swcrc
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://json.schemastore.org/swcrc",
|
||||||
|
"sourceMaps": true,
|
||||||
|
"jsc": {
|
||||||
|
"target": "esnext",
|
||||||
|
"parser": {
|
||||||
|
"syntax": "typescript",
|
||||||
|
"tsx": true,
|
||||||
|
"dts": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"module": {
|
||||||
|
"type": "es6"
|
||||||
|
}
|
||||||
|
}
|
||||||
22
packages/email-nodemailer/LICENSE.md
Normal file
22
packages/email-nodemailer/LICENSE.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2018-2022 Payload CMS, LLC <info@payloadcms.com>
|
||||||
|
Portions Copyright (c) Meta Platforms, Inc. and affiliates.
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
1
packages/email-nodemailer/README.md
Normal file
1
packages/email-nodemailer/README.md
Normal file
@@ -0,0 +1 @@
|
|||||||
|
# Nodemailer Email Adapter
|
||||||
58
packages/email-nodemailer/package.json
Normal file
58
packages/email-nodemailer/package.json
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"name": "@payloadcms/email-nodemailer",
|
||||||
|
"version": "0.0.0",
|
||||||
|
"description": "Payload Nodemailer Email Adapter",
|
||||||
|
"repository": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/payloadcms/payload.git",
|
||||||
|
"directory": "packages/email-nodemailer"
|
||||||
|
},
|
||||||
|
"license": "MIT",
|
||||||
|
"homepage": "https://payloadcms.com",
|
||||||
|
"author": "Payload CMS, Inc.",
|
||||||
|
"main": "./src/index.ts",
|
||||||
|
"types": "./src/index.ts",
|
||||||
|
"type": "module",
|
||||||
|
"scripts": {
|
||||||
|
"build": "pnpm build:swc && pnpm build:types",
|
||||||
|
"build:swc": "swc ./src -d ./dist --config-file .swcrc",
|
||||||
|
"build:types": "tsc --emitDeclarationOnly --outDir dist",
|
||||||
|
"build:clean": "find . \\( -type d \\( -name build -o -name dist -o -name .cache \\) -o -type f -name tsconfig.tsbuildinfo \\) -exec rm -rf {} + && pnpm build",
|
||||||
|
"clean": "rimraf {dist,*.tsbuildinfo}",
|
||||||
|
"prepublishOnly": "pnpm clean && pnpm turbo build"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"nodemailer": "6.9.10"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"payload": "workspace:*"
|
||||||
|
},
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./src/index.ts",
|
||||||
|
"require": "./src/index.ts",
|
||||||
|
"types": "./src/index.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"publishConfig": {
|
||||||
|
"exports": {
|
||||||
|
".": {
|
||||||
|
"import": "./dist/index.js",
|
||||||
|
"require": "./dist/index.js",
|
||||||
|
"types": "./dist/index.d.ts"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"main": "./dist/index.js",
|
||||||
|
"registry": "https://registry.npmjs.org/",
|
||||||
|
"types": "./dist/index.d.ts"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=18.20.2"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/nodemailer": "6.4.14"
|
||||||
|
}
|
||||||
|
}
|
||||||
126
packages/email-nodemailer/src/index.ts
Normal file
126
packages/email-nodemailer/src/index.ts
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
/* eslint-disable no-console */
|
||||||
|
import type { SendMailOptions, Transporter } from 'nodemailer'
|
||||||
|
import type SMTPConnection from 'nodemailer/lib/smtp-connection'
|
||||||
|
import type { EmailAdapter } from 'payload/types'
|
||||||
|
|
||||||
|
import nodemailer from 'nodemailer'
|
||||||
|
import { InvalidConfiguration } from 'payload/errors'
|
||||||
|
|
||||||
|
type Email = {
|
||||||
|
defaultFromAddress: string
|
||||||
|
defaultFromName: string
|
||||||
|
logMockCredentials?: boolean
|
||||||
|
}
|
||||||
|
|
||||||
|
type EmailTransportOptions = Email & {
|
||||||
|
transport?: Transporter
|
||||||
|
transportOptions: SMTPConnection.Options
|
||||||
|
}
|
||||||
|
|
||||||
|
export type NodemailerAdapterArgs = Email | EmailTransportOptions
|
||||||
|
export type NodemailerAdapter = EmailAdapter<SendMailOptions, unknown>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an email adapter using nodemailer
|
||||||
|
*
|
||||||
|
* If no email configuration is provided, an ethereal email test account is returned
|
||||||
|
*/
|
||||||
|
export const createNodemailerAdapter = async (
|
||||||
|
args?: NodemailerAdapterArgs,
|
||||||
|
): Promise<NodemailerAdapter> => {
|
||||||
|
const { defaultFromAddress, defaultFromName, transport } = await buildEmail(args)
|
||||||
|
|
||||||
|
const adapter: NodemailerAdapter = {
|
||||||
|
defaultFromAddress,
|
||||||
|
defaultFromName,
|
||||||
|
sendEmail: async (message) => {
|
||||||
|
return await transport.sendMail({
|
||||||
|
from: `${defaultFromName} <${defaultFromAddress}>`,
|
||||||
|
...message,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return adapter
|
||||||
|
}
|
||||||
|
|
||||||
|
async function buildEmail(
|
||||||
|
emailConfig?: NodemailerAdapterArgs,
|
||||||
|
): Promise<{ defaultFromAddress: string; defaultFromName: string; transport: Transporter }> {
|
||||||
|
if (!emailConfig) {
|
||||||
|
return {
|
||||||
|
defaultFromAddress: 'info@payloadcms.com',
|
||||||
|
defaultFromName: 'Payload',
|
||||||
|
transport: await createMockAccount(emailConfig),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ensureConfigHasFrom(emailConfig)
|
||||||
|
|
||||||
|
// Create or extract transport
|
||||||
|
let transport: Transporter
|
||||||
|
if ('transport' in emailConfig && emailConfig.transport) {
|
||||||
|
;({ transport } = emailConfig)
|
||||||
|
} else if ('transportOptions' in emailConfig && emailConfig.transportOptions) {
|
||||||
|
transport = nodemailer.createTransport(emailConfig.transportOptions)
|
||||||
|
} else {
|
||||||
|
transport = await createMockAccount(emailConfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
await verifyTransport(transport)
|
||||||
|
return {
|
||||||
|
defaultFromAddress: emailConfig.defaultFromAddress,
|
||||||
|
defaultFromName: emailConfig.defaultFromName,
|
||||||
|
transport,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function verifyTransport(transport: Transporter) {
|
||||||
|
try {
|
||||||
|
await transport.verify()
|
||||||
|
} catch (err: unknown) {
|
||||||
|
console.error({ err, msg: 'Error verifying Nodemailer transport.' })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const ensureConfigHasFrom = (emailConfig: NodemailerAdapterArgs) => {
|
||||||
|
if (!emailConfig?.defaultFromName || !emailConfig?.defaultFromAddress) {
|
||||||
|
throw new InvalidConfiguration(
|
||||||
|
'Email fromName and fromAddress must be configured when transport is configured',
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Use ethereal.email to create a mock email account
|
||||||
|
*/
|
||||||
|
async function createMockAccount(emailConfig: NodemailerAdapterArgs) {
|
||||||
|
try {
|
||||||
|
const etherealAccount = await nodemailer.createTestAccount()
|
||||||
|
|
||||||
|
const smtpOptions = {
|
||||||
|
...emailConfig,
|
||||||
|
auth: {
|
||||||
|
pass: etherealAccount.pass,
|
||||||
|
user: etherealAccount.user,
|
||||||
|
},
|
||||||
|
fromAddress: emailConfig?.defaultFromAddress,
|
||||||
|
fromName: emailConfig?.defaultFromName,
|
||||||
|
host: 'smtp.ethereal.email',
|
||||||
|
port: 587,
|
||||||
|
secure: false,
|
||||||
|
}
|
||||||
|
const transport = nodemailer.createTransport(smtpOptions)
|
||||||
|
const { pass, user, web } = etherealAccount
|
||||||
|
|
||||||
|
if (emailConfig?.logMockCredentials) {
|
||||||
|
console.info('E-mail configured with mock configuration')
|
||||||
|
console.info(`Log into mock email provider at ${web}`)
|
||||||
|
console.info(`Mock email account username: ${user}`)
|
||||||
|
console.info(`Mock email account password: ${pass}`)
|
||||||
|
}
|
||||||
|
return transport
|
||||||
|
} catch (err) {
|
||||||
|
console.error({ err, msg: 'There was a problem setting up the mock email handler' })
|
||||||
|
}
|
||||||
|
}
|
||||||
18
packages/email-nodemailer/tsconfig.json
Normal file
18
packages/email-nodemailer/tsconfig.json
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
{
|
||||||
|
"extends": "../../tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"composite": true, // Make sure typescript knows that this module depends on their references
|
||||||
|
"noEmit": false /* Do not emit outputs. */,
|
||||||
|
"emitDeclarationOnly": true,
|
||||||
|
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
|
||||||
|
"rootDir": "./src" /* Specify the root folder within your source files. */,
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"dist",
|
||||||
|
"src/**/*.spec.js",
|
||||||
|
"src/**/*.spec.jsx",
|
||||||
|
"src/**/*.spec.ts",
|
||||||
|
"src/**/*.spec.tsx"
|
||||||
|
],
|
||||||
|
"include": ["src/**/*.ts", "src/**/*.tsx", "src/**/*.d.ts", "src/**/*.json"],
|
||||||
|
}
|
||||||
@@ -531,7 +531,7 @@ export type Config = {
|
|||||||
*
|
*
|
||||||
* @see https://payloadcms.com/docs/email/overview
|
* @see https://payloadcms.com/docs/email/overview
|
||||||
*/
|
*/
|
||||||
email?: EmailAdapter<any, unknown>
|
email?: EmailAdapter<any, unknown> | Promise<EmailAdapter<any, unknown>>
|
||||||
/** Custom REST endpoints */
|
/** Custom REST endpoints */
|
||||||
endpoints?: Endpoint[]
|
endpoints?: Endpoint[]
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,7 +3,9 @@ export type * from '../admin/types.js'
|
|||||||
export type * from '../uploads/types.js'
|
export type * from '../uploads/types.js'
|
||||||
|
|
||||||
export type { DocumentPermissions, FieldPermissions } from '../auth/index.js'
|
export type { DocumentPermissions, FieldPermissions } from '../auth/index.js'
|
||||||
|
|
||||||
export type { MeOperationResult } from '../auth/operations/me.js'
|
export type { MeOperationResult } from '../auth/operations/me.js'
|
||||||
|
export type { EmailAdapter } from '../email/types.js'
|
||||||
|
|
||||||
export type {
|
export type {
|
||||||
CollapsedPreferences,
|
CollapsedPreferences,
|
||||||
|
|||||||
@@ -49,9 +49,6 @@ import { APIKeyAuthentication } from './auth/strategies/apiKey.js'
|
|||||||
import { JWTAuthentication } from './auth/strategies/jwt.js'
|
import { JWTAuthentication } from './auth/strategies/jwt.js'
|
||||||
import localOperations from './collections/operations/local/index.js'
|
import localOperations from './collections/operations/local/index.js'
|
||||||
import { validateSchema } from './config/validate.js'
|
import { validateSchema } from './config/validate.js'
|
||||||
import { createNodemailerAdapter } from './email/adapters/nodemailer/index.js'
|
|
||||||
import { emailDefaults } from './email/defaults.js'
|
|
||||||
import { sendEmail } from './email/sendEmail.js'
|
|
||||||
import { fieldAffectsData } from './exports/types.js'
|
import { fieldAffectsData } from './exports/types.js'
|
||||||
import localGlobalOperations from './globals/operations/local/index.js'
|
import localGlobalOperations from './globals/operations/local/index.js'
|
||||||
import flattenFields from './utilities/flattenTopLevelFields.js'
|
import flattenFields from './utilities/flattenTopLevelFields.js'
|
||||||
@@ -366,8 +363,12 @@ export class BasePayload<TGeneratedTypes extends GeneratedTypes> {
|
|||||||
await this.db.connect()
|
await this.db.connect()
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Move nodemailer adapter into separate package after verifying all existing functionality
|
// Load email adapter
|
||||||
this.email = await createNodemailerAdapter(emailDefaults)
|
if (this.config.email instanceof Promise) {
|
||||||
|
this.email = await this.config.email
|
||||||
|
} else {
|
||||||
|
this.email = this.config.email
|
||||||
|
}
|
||||||
|
|
||||||
this.sendEmail = this.email.sendEmail
|
this.sendEmail = this.email.sendEmail
|
||||||
|
|
||||||
|
|||||||
16
pnpm-lock.yaml
generated
16
pnpm-lock.yaml
generated
@@ -440,6 +440,19 @@ importers:
|
|||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../payload
|
version: link:../payload
|
||||||
|
|
||||||
|
packages/email-nodemailer:
|
||||||
|
dependencies:
|
||||||
|
nodemailer:
|
||||||
|
specifier: 6.9.10
|
||||||
|
version: 6.9.10
|
||||||
|
payload:
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../payload
|
||||||
|
devDependencies:
|
||||||
|
'@types/nodemailer':
|
||||||
|
specifier: 6.4.14
|
||||||
|
version: 6.4.14
|
||||||
|
|
||||||
packages/eslint-config-payload:
|
packages/eslint-config-payload:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@types/eslint':
|
'@types/eslint':
|
||||||
@@ -1502,6 +1515,9 @@ importers:
|
|||||||
'@payloadcms/db-postgres':
|
'@payloadcms/db-postgres':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../packages/db-postgres
|
version: link:../packages/db-postgres
|
||||||
|
'@payloadcms/email-nodemailer':
|
||||||
|
specifier: workspace:*
|
||||||
|
version: link:../packages/email-nodemailer
|
||||||
'@payloadcms/eslint-config':
|
'@payloadcms/eslint-config':
|
||||||
specifier: workspace:*
|
specifier: workspace:*
|
||||||
version: link:../packages/eslint-config-payload
|
version: link:../packages/eslint-config-payload
|
||||||
|
|||||||
8
test/email-nodemailer/.eslintrc.cjs
Normal file
8
test/email-nodemailer/.eslintrc.cjs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
/** @type {import('eslint').Linter.Config} */
|
||||||
|
module.exports = {
|
||||||
|
ignorePatterns: ['payload-types.ts'],
|
||||||
|
parserOptions: {
|
||||||
|
project: ['./tsconfig.eslint.json'],
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
},
|
||||||
|
}
|
||||||
2
test/email-nodemailer/.gitignore
vendored
Normal file
2
test/email-nodemailer/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
/media
|
||||||
|
/media-gif
|
||||||
40
test/email-nodemailer/config.ts
Normal file
40
test/email-nodemailer/config.ts
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import { createNodemailerAdapter } from '@payloadcms/email-nodemailer'
|
||||||
|
import path from 'path'
|
||||||
|
import { getFileByPath } from 'payload/uploads'
|
||||||
|
import { fileURLToPath } from 'url'
|
||||||
|
|
||||||
|
import { buildConfigWithDefaults } from '../buildConfigWithDefaults.js'
|
||||||
|
import { devUser } from '../credentials.js'
|
||||||
|
|
||||||
|
const filename = fileURLToPath(import.meta.url)
|
||||||
|
const dirname = path.dirname(filename)
|
||||||
|
|
||||||
|
export default buildConfigWithDefaults({
|
||||||
|
// ...extend config here
|
||||||
|
collections: [],
|
||||||
|
email: createNodemailerAdapter(),
|
||||||
|
onInit: async (payload) => {
|
||||||
|
await payload.create({
|
||||||
|
collection: 'users',
|
||||||
|
data: {
|
||||||
|
email: devUser.email,
|
||||||
|
password: devUser.password,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const email = await payload.sendEmail({
|
||||||
|
to: 'test@example.com',
|
||||||
|
subject: 'This was sent on init',
|
||||||
|
})
|
||||||
|
|
||||||
|
// Create image
|
||||||
|
const imageFilePath = path.resolve(dirname, '../uploads/image.png')
|
||||||
|
const imageFile = await getFileByPath(imageFilePath)
|
||||||
|
|
||||||
|
await payload.create({
|
||||||
|
collection: 'media',
|
||||||
|
data: {},
|
||||||
|
file: imageFile,
|
||||||
|
})
|
||||||
|
},
|
||||||
|
})
|
||||||
50
test/email-nodemailer/payload-types.ts
Normal file
50
test/email-nodemailer/payload-types.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
/* tslint:disable */
|
||||||
|
/**
|
||||||
|
* This file was automatically generated by Payload.
|
||||||
|
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||||
|
* and re-run `payload generate:types` to regenerate this file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
export interface Config {
|
||||||
|
collections: {
|
||||||
|
posts: Post
|
||||||
|
media: Media
|
||||||
|
users: User
|
||||||
|
}
|
||||||
|
globals: {
|
||||||
|
menu: Menu
|
||||||
|
}
|
||||||
|
}
|
||||||
|
export interface Post {
|
||||||
|
id: string
|
||||||
|
text?: string
|
||||||
|
associatedMedia?: string | Media
|
||||||
|
updatedAt: string
|
||||||
|
createdAt: string
|
||||||
|
}
|
||||||
|
export interface Media {
|
||||||
|
id: string
|
||||||
|
updatedAt: string
|
||||||
|
createdAt: string
|
||||||
|
url?: string
|
||||||
|
filename?: string
|
||||||
|
mimeType?: string
|
||||||
|
filesize?: number
|
||||||
|
width?: number
|
||||||
|
height?: number
|
||||||
|
}
|
||||||
|
export interface User {
|
||||||
|
id: string
|
||||||
|
updatedAt: string
|
||||||
|
createdAt: string
|
||||||
|
email?: string
|
||||||
|
resetPasswordToken?: string
|
||||||
|
resetPasswordExpiration?: string
|
||||||
|
loginAttempts?: number
|
||||||
|
lockUntil?: string
|
||||||
|
password?: string
|
||||||
|
}
|
||||||
|
export interface Menu {
|
||||||
|
id: string
|
||||||
|
globalText?: string
|
||||||
|
}
|
||||||
13
test/email-nodemailer/tsconfig.eslint.json
Normal file
13
test/email-nodemailer/tsconfig.eslint.json
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
// extend your base config to share compilerOptions, etc
|
||||||
|
//"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
// ensure that nobody can accidentally use this config for a build
|
||||||
|
"noEmit": true
|
||||||
|
},
|
||||||
|
"include": [
|
||||||
|
// whatever paths you intend to lint
|
||||||
|
"./**/*.ts",
|
||||||
|
"./**/*.tsx"
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -31,6 +31,11 @@ export default buildConfigWithDefaults({
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
|
const email = await payload.sendEmail({
|
||||||
|
to: 'test@example.com',
|
||||||
|
subject: 'This was sent on init',
|
||||||
|
})
|
||||||
|
|
||||||
// Create image
|
// Create image
|
||||||
const imageFilePath = path.resolve(dirname, '../uploads/image.png')
|
const imageFilePath = path.resolve(dirname, '../uploads/image.png')
|
||||||
const imageFile = await getFileByPath(imageFilePath)
|
const imageFile = await getFileByPath(imageFilePath)
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
"@payloadcms/db-mongodb": "workspace:*",
|
"@payloadcms/db-mongodb": "workspace:*",
|
||||||
"@payloadcms/db-postgres": "workspace:*",
|
"@payloadcms/db-postgres": "workspace:*",
|
||||||
"@payloadcms/eslint-config": "workspace:*",
|
"@payloadcms/eslint-config": "workspace:*",
|
||||||
|
"@payloadcms/email-nodemailer": "workspace:*",
|
||||||
"@payloadcms/graphql": "workspace:*",
|
"@payloadcms/graphql": "workspace:*",
|
||||||
"@payloadcms/live-preview": "workspace:*",
|
"@payloadcms/live-preview": "workspace:*",
|
||||||
"@payloadcms/live-preview-react": "workspace:*",
|
"@payloadcms/live-preview-react": "workspace:*",
|
||||||
|
|||||||
Reference in New Issue
Block a user