+ invalid query params. need identifier and callback url
+
+ }
+
+ const internalProvider = providers.find(p => p.id === provider)
+ if (!internalProvider) {
+ return
+ wrong provider type.. how'd we end up here?
+
+ }
+
+ // todo: implement better error handling
+ return (
+ {
const { query, body } = request
const { url, logger, provider } = options
@@ -50,11 +51,38 @@ export async function signin(
const redirect = await emailSignin(email, options, request)
return { redirect }
+ } else if (provider.type === "otp") {
+ // OTP TODO: enable non-email based OTP account creation
+ const normalizer = provider.normalizeIdentifier ?? defaultNormalizer
+ const email = normalizer(body?.identifier)
+
+ const user = (await options.adapter!.getUserByEmail(email)) ?? {
+ id: email,
+ email,
+ emailVerified: null,
+ }
+
+ const account: Account = {
+ providerAccountId: email,
+ userId: user.id,
+ type: "email",
+ provider: provider.id,
+ }
+
+ const unauthorizedOrError = await handleAuthorized(
+ { user, account, email: { verificationRequest: true } },
+ options
+ )
+ if (unauthorizedOrError) return unauthorizedOrError
+
+ const redirect = await otpSignIn(email, options, request)
+ return { redirect }
}
return { redirect: `${url}/signin` }
} catch (e) {
const error = new SignInError(e as Error, { provider: provider.id })
logger.error(error)
+ // todo: add otp handling here
const code = provider.type === "email" ? "EmailSignin" : "OAuthSignin"
url.searchParams.set("error", code)
url.pathname += "/signin"
diff --git a/packages/core/src/lib/web.ts b/packages/core/src/lib/web.ts
index db615bbbe0..bd0069f7e2 100644
--- a/packages/core/src/lib/web.ts
+++ b/packages/core/src/lib/web.ts
@@ -23,6 +23,7 @@ const actions: AuthAction[] = [
"signout",
"callback",
"verify-request",
+ "verify-otp",
"error",
]
diff --git a/packages/core/src/providers/index.ts b/packages/core/src/providers/index.ts
index a41c566360..5d46a7984c 100644
--- a/packages/core/src/providers/index.ts
+++ b/packages/core/src/providers/index.ts
@@ -6,6 +6,8 @@ import type {
} from "./credentials.js"
import type EmailProvider from "./email.js"
import type { EmailConfig, EmailProviderType } from "./email.js"
+import type OTPProvider from "./otp.js"
+import type { OTPConfig, OTPProviderType } from "./otp.js"
import type {
OAuth2Config,
OAuthConfig,
@@ -16,6 +18,7 @@ import type {
export * from "./credentials.js"
export * from "./email.js"
export * from "./oauth.js"
+export * from "./otp.js"
/**
* Providers passed to Auth.js must define one of these types.
@@ -25,7 +28,7 @@ export * from "./oauth.js"
* @see [Email or Passwordless Authentication](https://authjs.dev/concepts/oauth)
* @see [Credentials-based Authentication](https://authjs.dev/concepts/credentials)
*/
-export type ProviderType = "oidc" | "oauth" | "email" | "credentials"
+export type ProviderType = "oidc" | "oauth" | "email" | "credentials" | "otp"
/** Shared across all {@link ProviderType} */
export interface CommonProviderOptions {
@@ -63,11 +66,23 @@ interface InternalProviderOptions {
* @see [Credentials guide](https://authjs.dev/guides/providers/credentials)
*/
export type Provider = (
- | ((OIDCConfig
| OAuth2Config
| EmailConfig | CredentialsConfig) &
+ | ((
+ | OIDCConfig
+ | OAuth2Config
+ | EmailConfig
+ | CredentialsConfig
+ | OTPConfig
+ ) &
InternalProviderOptions)
| ((
...args: any
- ) => (OAuth2Config
| OIDCConfig
| EmailConfig | CredentialsConfig) &
+ ) => (
+ | OAuth2Config
+ | OIDCConfig
+ | EmailConfig
+ | CredentialsConfig
+ | OTPConfig
+ ) &
InternalProviderOptions)
) &
InternalProviderOptions
@@ -77,7 +92,8 @@ export type BuiltInProviders = Record<
(config: Partial>) => OAuthConfig
> &
Record &
- Record
+ Record &
+ Record
export type AppProviders = Array<
Provider | ReturnType
@@ -88,6 +104,6 @@ export interface AppProvider extends CommonProviderOptions {
callbackUrl: string
}
-export type RedirectableProviderType = "email" | "credentials"
+export type RedirectableProviderType = "email" | "credentials" | "otp"
export type BuiltInProviderType = RedirectableProviderType | OAuthProviderType
diff --git a/packages/core/src/providers/otp.ts b/packages/core/src/providers/otp.ts
new file mode 100644
index 0000000000..29d88b2e82
--- /dev/null
+++ b/packages/core/src/providers/otp.ts
@@ -0,0 +1,469 @@
+import type { CommonProviderOptions } from "./index.js"
+import type { Awaitable, Theme } from "../types.js"
+
+import { Transport, TransportOptions, createTransport } from "nodemailer"
+import * as JSONTransport from "nodemailer/lib/json-transport/index.js"
+import * as SendmailTransport from "nodemailer/lib/sendmail-transport/index.js"
+import * as SESTransport from "nodemailer/lib/ses-transport/index.js"
+import * as SMTPTransport from "nodemailer/lib/smtp-transport/index.js"
+import * as SMTPPool from "nodemailer/lib/smtp-pool/index.js"
+import * as StreamTransport from "nodemailer/lib/stream-transport/index.js"
+
+// TODO: Make use of https://www.typescriptlang.org/docs/handbook/2/template-literal-types.html for the string
+type AllTransportOptions =
+ | string
+ | SMTPTransport
+ | SMTPTransport.Options
+ | SMTPPool
+ | SMTPPool.Options
+ | SendmailTransport
+ | SendmailTransport.Options
+ | StreamTransport
+ | StreamTransport.Options
+ | JSONTransport
+ | JSONTransport.Options
+ | SESTransport
+ | SESTransport.Options
+ | Transport
+ | TransportOptions
+
+export interface SendOTPVerificationRequestParams {
+ identifier: string
+ url: string
+ expires: Date
+ provider: OTPConfig
+ token: string
+ theme: Theme
+ request: Request
+}
+
+/**
+ * Besides providing type safety inside {@link CredentialsConfig.authorize}
+ * it also determines how the credentials input fields will be rendered
+ * on the default sign in page.
+ */
+export interface OTPInput extends Partial {
+ label?: string
+}
+
+/**
+ * The Email Provider needs to be configured with an e-mail client.
+ * By default, it uses `nodemailer`, which you have to install if this
+ * provider is present.
+ *
+ * You can use a other services as well, like:
+ * - [Postmark](https://postmarkapp.com)
+ * - [Mailgun](https://www.mailgun.com)
+ * - [SendGrid](https://sendgrid.com)
+ * - etc.
+ *
+ * [Custom email service with Auth.js](https://authjs.dev/guides/providers/email#custom-email-service)
+ */
+export interface OTPUserConfig {
+ server?: AllTransportOptions
+ type?: "email"
+ /** @default `"Auth.js "` */
+ from?: string
+ /**
+ * How long until the e-mail can be used to log the user in,
+ * in seconds. Defaults to 1 day
+ *
+ * @default 86400
+ */
+ maxAge?: number
+ /** [Documentation](https://authjs.dev/guides/providers/email#customizing-emails) */
+ sendVerificationRequest?: (
+ params: SendOTPVerificationRequestParams
+ ) => Awaitable
+ /**
+ * By default, we are generating a random verification token.
+ * You can make it predictable or modify it as you like with this method.
+ *
+ * @example
+ * ```ts
+ * Providers.Email({
+ * async generateVerificationToken() {
+ * return "ABC123"
+ * }
+ * })
+ * ```
+ * [Documentation](https://authjs.dev/guides/providers/email#customizing-the-verification-token)
+ */
+ generateVerificationToken?: () => Awaitable
+ /** If defined, it is used to hash the verification token when saving to the database . */
+ secret?: string
+ /**
+ * Normalizes the user input before sending the verification request.
+ *
+ * ⚠️ Always make sure this method returns a single email address.
+ *
+ * @note Technically, the part of the email address local mailbox element
+ * (everything before the `@` symbol) should be treated as 'case sensitive'
+ * according to RFC 2821, but in practice this causes more problems than
+ * it solves, e.g.: when looking up users by e-mail from databases.
+ * By default, we treat email addresses as all lower case,
+ * but you can override this function to change this behavior.
+ *
+ * [Normalizing the email address](https://authjs.dev/reference/core/providers_email#normalizing-the-email-address) | [RFC 2821](https://tools.ietf.org/html/rfc2821) | [Email syntax](https://en.wikipedia.org/wiki/Email_address#Syntax)
+ */
+ normalizeIdentifier?: (identifier: string) => string
+}
+
+export interface OTPConfig extends CommonProviderOptions {
+ // defaults
+ id: "otp"
+ type: "otp"
+ name: "OTP"
+
+ identifierInput: OTPInput
+ otpInput: OTPInput
+
+ server: AllTransportOptions
+ from: string
+ maxAge: number
+ sendVerificationRequest: (
+ params: SendOTPVerificationRequestParams
+ ) => Awaitable
+
+ /**
+ * This is copied into OTPConfig in parseProviders() don't use elsewhere
+ */
+ options: OTPUserConfig
+
+ // user options
+ // TODO figure out a better way than copying from OTPUserConfig
+ secret?: string
+ generateVerificationToken?: () => Awaitable
+ normalizeIdentifier?: (identifier: string) => string
+}
+
+// TODO: Rename to Token provider
+// when started working on https://github.com/nextauthjs/next-auth/discussions/1465
+export type OTPProviderType = "otp"
+
+/**
+ * ## Overview
+ * The Email provider uses email to send "magic links" that can be used to sign in, you will likely have seen these if you have used services like Slack before.
+ *
+ * Adding support for signing in via email in addition to one or more OAuth services provides a way for users to sign in if they lose access to their OAuth account (e.g. if it is locked or deleted).
+ *
+ * The Email provider can be used in conjunction with (or instead of) one or more OAuth providers.
+ * ### How it works
+ *
+ * On initial sign in, a **Verification Token** is sent to the email address provided. By default this token is valid for 24 hours. If the Verification Token is used within that time (i.e. by clicking on the link in the email) an account is created for the user and they are signed in.
+ *
+ *
+ * If someone provides the email address of an _existing account_ when signing in, an email is sent and they are signed into the account associated with that email address when they follow the link in the email.
+ *
+ * :::tip
+ * The Email Provider can be used with both JSON Web Tokens and database sessions, but you **must** configure a database to use it. It is not possible to enable email sign in without using a database.
+ * :::
+ * ## Configuration
+
+ * 1. NextAuth.js does not include `nodemailer` as a dependency, so you'll need to install it yourself if you want to use the Email Provider. Run `npm install nodemailer` or `yarn add nodemailer`.
+ * 2. You will need an SMTP account; ideally for one of the [services known to work with `nodemailer`](https://community.nodemailer.com/2-0-0-beta/setup-smtp/well-known-services/).
+ * 3. There are two ways to configure the SMTP server connection.
+ *
+ * You can either use a connection string or a `nodemailer` configuration object.
+ *
+ * 3.1 **Using a connection string**
+ *
+ * Create an `.env` file to the root of your project and add the connection string and email address.
+ *
+ * ```js title=".env" {1}
+ * EMAIL_SERVER=smtp://username:password@smtp.example.com:587
+ * EMAIL_FROM=noreply@example.com
+ * ```
+ *
+ * Now you can add the email provider like this:
+ *
+ * ```js {3} title="pages/api/auth/[...nextauth].js"
+ * import EmailProvider from "next-auth/providers/email";
+ * ...
+ * providers: [
+ * EmailProvider({
+ * server: process.env.EMAIL_SERVER,
+ * from: process.env.EMAIL_FROM
+ * }),
+ * ],
+ * ```
+ *
+ * 3.2 **Using a configuration object**
+ *
+ * In your `.env` file in the root of your project simply add the configuration object options individually:
+ *
+ * ```js title=".env"
+ * EMAIL_SERVER_USER=username
+ * EMAIL_SERVER_PASSWORD=password
+ * EMAIL_SERVER_HOST=smtp.example.com
+ * EMAIL_SERVER_PORT=587
+ * EMAIL_FROM=noreply@example.com
+ * ```
+ *
+ * Now you can add the provider settings to the NextAuth.js options object in the Email Provider.
+ *
+ * ```js title="pages/api/auth/[...nextauth].js"
+ * import EmailProvider from "next-auth/providers/email";
+ * ...
+ * providers: [
+ * EmailProvider({
+ * server: {
+ * host: process.env.EMAIL_SERVER_HOST,
+ * port: process.env.EMAIL_SERVER_PORT,
+ * auth: {
+ * user: process.env.EMAIL_SERVER_USER,
+ * pass: process.env.EMAIL_SERVER_PASSWORD
+ * }
+ * },
+ * from: process.env.EMAIL_FROM
+ * }),
+ * ],
+ * ```
+ *
+ * 4. Do not forget to setup one of the database [adapters](https://authjs.dev/reference/adapters) for storing the Email verification token.
+ *
+ * 5. You can now sign in with an email address at `/api/auth/signin`.
+ *
+ * A user account (i.e. an entry in the Users table) will not be created for the user until the first time they verify their email address. If an email address is already associated with an account, the user will be signed in to that account when they use the link in the email.
+ *
+ * ## Customizing emails
+ *
+ * You can fully customize the sign in email that is sent by passing a custom function as the `sendVerificationRequest` option to `EmailProvider()`.
+ *
+ * e.g.
+ *
+ * ```js {3} title="pages/api/auth/[...nextauth].js"
+ * import EmailProvider from "next-auth/providers/email";
+ * ...
+ * providers: [
+ * EmailProvider({
+ * server: process.env.EMAIL_SERVER,
+ * from: process.env.EMAIL_FROM,
+ * sendVerificationRequest({
+ * identifier: email,
+ * url,
+ * provider: { server, from },
+ * }) {
+ * // your function
+ * },
+ * }),
+ * ]
+ * ```
+ *
+ * The following code shows the complete source for the built-in `sendVerificationRequest()` method:
+ *
+ * ```js
+ * import { createTransport } from "nodemailer"
+ *
+ * async function sendVerificationRequest(params) {
+ * const { identifier, url, provider, theme } = params
+ * const { host } = new URL(url)
+ * // NOTE: You are not required to use `nodemailer`, use whatever you want.
+ * const transport = createTransport(provider.server)
+ * const result = await transport.sendMail({
+ * to: identifier,
+ * from: provider.from,
+ * subject: `Sign in to ${host}`,
+ * text: text({ url, host }),
+ * html: html({ url, host, theme }),
+ * })
+ * const failed = result.rejected.concat(result.pending).filter(Boolean)
+ * if (failed.length) {
+ * throw new Error(`Email(s) (${failed.join(", ")}) could not be sent`)
+ * }
+ * }
+ *
+ * function html(params: { url: string; host: string; theme: Theme }) {
+ * const { url, host, theme } = params
+ *
+ * const escapedHost = host.replace(/\./g, ".")
+ *
+ * const brandColor = theme.brandColor || "#346df1"
+ * const color = {
+ * background: "#f9f9f9",
+ * text: "#444",
+ * mainBackground: "#fff",
+ * buttonBackground: brandColor,
+ * buttonBorder: brandColor,
+ * buttonText: theme.buttonText || "#fff",
+ * }
+ *
+ * return `
+ *
+ *
+ *
+ *
+ * Sign in to ${escapedHost}
+ * |
+ *
+ *
+ *
+ *
+ * |
+ *
+ *
+ *
+ * If you did not request this email you can safely ignore it.
+ * |
+ *
+ *
+ *
+ * `
+ * }
+ *
+ * // Email Text body (fallback for email clients that don't render HTML, e.g. feature phones)
+ * function text({ url, host }: { url: string; host: string }) {
+ * return `Sign in to ${host}\n${url}\n\n`
+ * }
+ * ```
+ *
+ * :::tip
+ * If you want to generate great looking email client compatible HTML with React, check out https://mjml.io
+ * :::
+ *
+ * ## Customizing the Verification Token
+ *
+ * By default, we are generating a random verification token. You can define a `generateVerificationToken` method in your provider options if you want to override it:
+ *
+ * ```js title="pages/api/auth/[...nextauth].js"
+ * providers: [
+ * EmailProvider({
+ * async generateVerificationToken() {
+ * return "ABC123"
+ * }
+ * })
+ * ],
+ * ```
+ *
+ * ## Normalizing the email address
+ *
+ * By default, Auth.js will normalize the email address. It treats values as case-insensitive (which is technically not compliant to the [RFC 2821 spec](https://datatracker.ietf.org/doc/html/rfc2821), but in practice this causes more problems than it solves, eg. when looking up users by e-mail from databases.) and also removes any secondary email address that was passed in as a comma-separated list. You can apply your own normalization via the `normalizeIdentifier` method on the `EmailProvider`. The following example shows the default behavior:
+ * ```ts
+ * EmailProvider({
+ * // ...
+ * normalizeIdentifier(identifier: string): string {
+ * // Get the first two elements only,
+ * // separated by `@` from user input.
+ * let [local, domain] = identifier.toLowerCase().trim().split("@")
+ * // The part before "@" can contain a ","
+ * // but we remove it on the domain part
+ * domain = domain.split(",")[0]
+ * return `${local}@${domain}`
+ *
+ * // You can also throw an error, which will redirect the user
+ * // to the sign-in page with error=EmailSignin in the URL
+ * // if (identifier.split("@").length > 2) {
+ * // throw new Error("Only one email allowed")
+ * // }
+ * },
+ * })
+ * ```
+ *
+ * :::warning
+ * Always make sure this returns a single e-mail address, even if multiple ones were passed in.
+ * :::
+ */
+export default function OTP(config: OTPUserConfig): OTPConfig {
+ return {
+ id: "otp",
+ type: "otp",
+ name: "OTP",
+ identifierInput: { label: "Email" },
+ otpInput: { label: "OTP", placeholder: "######" },
+ server: { host: "localhost", port: 25, auth: { user: "", pass: "" } },
+ from: "Auth.js ",
+ maxAge: 24 * 60 * 60,
+ async sendVerificationRequest(params) {
+ const { identifier, url, provider, theme } = params
+ const { host } = new URL(url)
+ const transport = createTransport(provider.server)
+ const result = await transport.sendMail({
+ to: identifier,
+ from: provider.from,
+ subject: `Your OTP code for ${host}`,
+ text: text({ url, host }),
+ html: html({ url, host, theme }),
+ })
+ const failed = result.rejected.concat(result.pending).filter(Boolean)
+ if (failed.length) {
+ throw new Error(`Email (${failed.join(", ")}) could not be sent`)
+ }
+ },
+ options: config,
+ }
+}
+
+/**
+ * Email HTML body
+ * Insert invisible space into domains from being turned into a hyperlink by email
+ * clients like Outlook and Apple mail, as this is confusing because it seems
+ * like they are supposed to click on it to sign in.
+ *
+ * @note We don't add the email address to avoid needing to escape it, if you do, remember to sanitize it!
+ */
+function html(params: { url: string; host: string; theme: Theme }) {
+ const { url, host, theme } = params
+
+ const escapedHost = host.replace(/\./g, ".")
+
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ const brandColor = theme.brandColor || "#346df1"
+ // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
+ const buttonText = theme.buttonText || "#fff"
+
+ const color = {
+ background: "#f9f9f9",
+ text: "#444",
+ mainBackground: "#fff",
+ buttonBackground: brandColor,
+ buttonBorder: brandColor,
+ buttonText,
+ }
+
+ return `
+
+
+
+
+ Sign in to ${escapedHost}
+ |
+
+
+
+
+ |
+
+
+
+ If you did not request this email you can safely ignore it.
+ |
+
+
+
+`
+}
+
+/** Email Text body (fallback for email clients that don't render HTML, e.g. feature phones) */
+function text({ url, host }: { url: string; host: string }) {
+ return `Sign in to ${host}\n${url}\n\n`
+}
diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts
index 9b6197c229..8eab99031a 100644
--- a/packages/core/src/types.ts
+++ b/packages/core/src/types.ts
@@ -72,6 +72,7 @@ import type {
OAuthConfigInternal,
OIDCConfigInternal,
ProviderType,
+ OTPConfig
} from "./providers/index.js"
export type { AuthConfig } from "./index.js"
@@ -421,6 +422,7 @@ export interface PagesOptions {
*/
error: string
verifyRequest: string
+ verifyOTP: string
/** If set, new users will be directed here on first sign in */
newUser: string
}
@@ -473,6 +475,8 @@ export type InternalProvider = (T extends "oauth"
? OIDCConfigInternal
: T extends "email"
? EmailConfig
+ : T extends "otp"
+ ? OTPConfig
: T extends "credentials"
? CredentialsConfig
: never) & {
@@ -507,6 +511,7 @@ export type InternalProvider = (T extends "oauth"
* - **`GET`**: Renders the built-in sign-out page.
* - **`POST`**: Initiates the sign-out flow. This will invalidate the user's session (deleting the cookie, and if there is a session in the database, it will be deleted as well).
* - **`"verify-request"`**: Renders the built-in verification request page.
+ * - **`"verify-otp"`**: Renders the built-in otp verification request page.
*/
export type AuthAction =
| "callback"
@@ -517,6 +522,7 @@ export type AuthAction =
| "signin"
| "signout"
| "verify-request"
+ | "verify-otp"
/** @internal */
export interface RequestInternal {
diff --git a/packages/frameworks-sveltekit/src/lib/client.ts b/packages/frameworks-sveltekit/src/lib/client.ts
index 6d8ff813b2..e55e669708 100644
--- a/packages/frameworks-sveltekit/src/lib/client.ts
+++ b/packages/frameworks-sveltekit/src/lib/client.ts
@@ -54,7 +54,8 @@ export async function signIn<
// TODO: Support custom providers
const isCredentials = providerId === "credentials"
const isEmail = providerId === "email"
- const isSupportingReturn = isCredentials || isEmail
+ const isOTP = providerId === "otp"
+ const isSupportingReturn = isCredentials || isEmail || isOTP
const basePath = base ?? ""
const signInUrl = `${basePath}/auth/${
@@ -83,6 +84,7 @@ export async function signIn<
const data = await res.clone().json()
+ // OTP TODO: handle otp here
if (redirect || !isSupportingReturn) {
// TODO: Do not redirect for Credentials and Email providers by default in next major
window.location.href = data.url ?? callbackUrl
diff --git a/packages/frameworks-sveltekit/src/lib/index.ts b/packages/frameworks-sveltekit/src/lib/index.ts
index 4c0efcb0b7..3d45a0ff70 100644
--- a/packages/frameworks-sveltekit/src/lib/index.ts
+++ b/packages/frameworks-sveltekit/src/lib/index.ts
@@ -250,6 +250,7 @@ const actions: AuthAction[] = [
"signout",
"callback",
"verify-request",
+ "verify-otp",
"error",
]
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 6c97d7e332..cbc3898d97 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -153,6 +153,37 @@ importers:
specifier: 0.3.17
version: 0.3.17(mssql@7.3.5)(pg@8.7.3)(sqlite3@5.0.8)
+ apps/dev/otp-example:
+ dependencies:
+ '@auth/core':
+ specifier: workspace:*
+ version: link:../../../packages/core
+ '@auth/sveltekit':
+ specifier: workspace:*
+ version: link:../../../packages/frameworks-sveltekit
+ '@sendgrid/mail':
+ specifier: ^7.7.0
+ version: 7.7.0
+ devDependencies:
+ '@sveltejs/adapter-auto':
+ specifier: next
+ version: 1.0.0-next.91(@sveltejs/kit@1.0.0-next.589)
+ '@sveltejs/kit':
+ specifier: next
+ version: 1.0.0-next.589(svelte@3.55.0)(vite@4.0.5)
+ svelte:
+ specifier: 3.55.0
+ version: 3.55.0
+ svelte-check:
+ specifier: 2.10.2
+ version: 2.10.2(svelte@3.55.0)
+ typescript:
+ specifier: 5.2.2
+ version: 5.2.2
+ vite:
+ specifier: 4.0.5
+ version: 4.0.5(@types/node@18.16.3)
+
apps/dev/sveltekit:
dependencies:
'@auth/core':
@@ -2713,7 +2744,7 @@ packages:
gensync: 1.0.0-beta.2
json5: 2.2.3
lodash: 4.17.21
- resolve: 1.22.1
+ resolve: 1.22.6
semver: 5.7.1
source-map: 0.5.7
transitivePeerDependencies:
@@ -3017,7 +3048,7 @@ packages:
'@babel/helper-plugin-utils': 7.21.5
debug: 4.3.4(supports-color@7.2.0)
lodash.debounce: 4.0.8
- resolve: 1.22.1
+ resolve: 1.22.6
semver: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -3033,7 +3064,7 @@ packages:
'@babel/helper-plugin-utils': 7.21.5
debug: 4.3.4(supports-color@7.2.0)
lodash.debounce: 4.0.8
- resolve: 1.22.1
+ resolve: 1.22.6
semver: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -3049,7 +3080,7 @@ packages:
'@babel/helper-plugin-utils': 7.21.5
debug: 4.3.4(supports-color@7.2.0)
lodash.debounce: 4.0.8
- resolve: 1.22.1
+ resolve: 1.22.6
semver: 6.3.0
transitivePeerDependencies:
- supports-color
@@ -10663,6 +10694,33 @@ packages:
unist-util-visit: 2.0.3
dev: false
+ /@sendgrid/client@7.7.0:
+ resolution: {integrity: sha512-SxH+y8jeAQSnDavrTD0uGDXYIIkFylCo+eDofVmZLQ0f862nnqbC3Vd1ej6b7Le7lboyzQF6F7Fodv02rYspuA==}
+ engines: {node: 6.* || 8.* || >=10.*}
+ dependencies:
+ '@sendgrid/helpers': 7.7.0
+ axios: 0.26.1
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
+ /@sendgrid/helpers@7.7.0:
+ resolution: {integrity: sha512-3AsAxfN3GDBcXoZ/y1mzAAbKzTtUZ5+ZrHOmWQ279AuaFXUNCh9bPnRpN504bgveTqoW+11IzPg3I0WVgDINpw==}
+ engines: {node: '>= 6.0.0'}
+ dependencies:
+ deepmerge: 4.3.0
+ dev: false
+
+ /@sendgrid/mail@7.7.0:
+ resolution: {integrity: sha512-5+nApPE9wINBvHSUxwOxkkQqM/IAAaBYoP9hw7WwgDNQPxraruVqHizeTitVtKGiqWCKm2mnjh4XGN3fvFLqaw==}
+ engines: {node: 6.* || 8.* || >=10.*}
+ dependencies:
+ '@sendgrid/client': 7.7.0
+ '@sendgrid/helpers': 7.7.0
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
/@shelf/jest-dynamodb@2.2.4(@aws-sdk/client-dynamodb@3.113.0)(@aws-sdk/lib-dynamodb@3.113.0)(@aws-sdk/util-dynamodb@3.113.0):
resolution: {integrity: sha512-OAnkP5sPcIoqL+q/tpp54psuK1gssm+nZLOHRy0S1eyAZGmuqiYAUzyAvmH5AhyqvDPSEHFkIkfbqlp1+KpHgw==}
engines: {node: '>=14'}
@@ -13581,6 +13639,14 @@ packages:
- debug
dev: true
+ /axios@0.26.1:
+ resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==}
+ dependencies:
+ follow-redirects: 1.15.1(debug@4.3.4)
+ transitivePeerDependencies:
+ - debug
+ dev: false
+
/babel-jest@26.6.3(@babel/core@7.22.1):
resolution: {integrity: sha512-pl4Q+GAVOHwvjrck6jKjvmGhnO3jHX/xuB9d27f+EJZ/6k+6nMuPjorrYp7s++bKKdANwzElBWnLWaObvTnaZA==}
engines: {node: '>= 10.14.2'}
@@ -19150,7 +19216,6 @@ packages:
optional: true
dependencies:
debug: 4.3.4(supports-color@7.2.0)
- dev: true
/for-each@0.3.3:
resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==}
@@ -20752,6 +20817,7 @@ packages:
resolution: {integrity: sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw==}
dependencies:
has: 1.0.3
+ dev: true
/is-core-module@2.13.0:
resolution: {integrity: sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==}
@@ -22418,7 +22484,7 @@ packages:
jest-pnp-resolver: 1.2.2(jest-resolve@27.5.1)
jest-util: 27.5.1
jest-validate: 27.5.1
- resolve: 1.22.1
+ resolve: 1.22.6
resolve.exports: 1.1.0
slash: 3.0.0
dev: true
@@ -22433,7 +22499,7 @@ packages:
jest-pnp-resolver: 1.2.2(jest-resolve@28.1.1)
jest-util: 28.1.3
jest-validate: 28.1.1
- resolve: 1.22.1
+ resolve: 1.22.6
resolve.exports: 1.1.0
slash: 3.0.0
dev: true
@@ -22448,7 +22514,7 @@ packages:
jest-pnp-resolver: 1.2.2(jest-resolve@29.5.0)
jest-util: 29.5.0
jest-validate: 29.5.0
- resolve: 1.22.1
+ resolve: 1.22.6
resolve.exports: 2.0.2
slash: 3.0.0
dev: true
@@ -25486,7 +25552,7 @@ packages:
resolution: {integrity: sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==}
dependencies:
hosted-git-info: 2.8.9
- resolve: 1.22.1
+ resolve: 1.22.6
semver: 5.7.1
validate-npm-package-license: 3.0.4
@@ -25495,7 +25561,7 @@ packages:
engines: {node: '>=10'}
dependencies:
hosted-git-info: 4.1.0
- is-core-module: 2.11.0
+ is-core-module: 2.13.0
semver: 7.5.4
validate-npm-package-license: 3.0.4
dev: true
@@ -27173,15 +27239,6 @@ packages:
source-map-js: 1.0.2
dev: true
- /postcss@8.4.24:
- resolution: {integrity: sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==}
- engines: {node: ^10 || ^12 || >=14}
- dependencies:
- nanoid: 3.3.6
- picocolors: 1.0.0
- source-map-js: 1.0.2
- dev: true
-
/postcss@8.4.31:
resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==}
engines: {node: ^10 || ^12 || >=14}
@@ -28195,14 +28252,14 @@ packages:
resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==}
engines: {node: '>= 0.10'}
dependencies:
- resolve: 1.22.1
+ resolve: 1.22.6
dev: true
/rechoir@0.8.0:
resolution: {integrity: sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==}
engines: {node: '>= 10.13.0'}
dependencies:
- resolve: 1.22.1
+ resolve: 1.22.6
dev: true
/recursive-readdir@2.2.2:
@@ -28504,6 +28561,7 @@ packages:
is-core-module: 2.11.0
path-parse: 1.0.7
supports-preserve-symlinks-flag: 1.0.0
+ dev: true
/resolve@1.22.6:
resolution: {integrity: sha512-njhxM7mV12JfufShqGy3Rz8j11RPdLy4xi15UurGJeoHLfJpVXKdh3ueuOqbYUcDZnffr6X739JBo5LzyahEsw==}
@@ -30146,8 +30204,8 @@ packages:
picocolors: 1.0.0
sade: 1.8.1
svelte: 3.54.0
- svelte-preprocess: 4.10.7(svelte@3.54.0)(typescript@5.2.2)
- typescript: 5.2.2
+ svelte-preprocess: 4.10.7(svelte@3.54.0)(typescript@4.9.5)
+ typescript: 4.9.5
transitivePeerDependencies:
- '@babel/core'
- coffeescript
@@ -30174,8 +30232,8 @@ packages:
picocolors: 1.0.0
sade: 1.8.1
svelte: 3.55.0
- svelte-preprocess: 4.10.7(svelte@3.55.0)(typescript@5.2.2)
- typescript: 5.2.2
+ svelte-preprocess: 4.10.7(svelte@3.55.0)(typescript@4.9.5)
+ typescript: 4.9.5
transitivePeerDependencies:
- '@babel/core'
- coffeescript
@@ -30207,7 +30265,7 @@ packages:
svelte: 3.55.0
dev: true
- /svelte-preprocess@4.10.7(svelte@3.54.0)(typescript@5.2.2):
+ /svelte-preprocess@4.10.7(svelte@3.54.0)(typescript@4.9.5):
resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==}
engines: {node: '>= 9.11.2'}
requiresBuild: true
@@ -30255,10 +30313,10 @@ packages:
sorcery: 0.10.0
strip-indent: 3.0.0
svelte: 3.54.0
- typescript: 5.2.2
+ typescript: 4.9.5
dev: true
- /svelte-preprocess@4.10.7(svelte@3.55.0)(typescript@5.2.2):
+ /svelte-preprocess@4.10.7(svelte@3.55.0)(typescript@4.9.5):
resolution: {integrity: sha512-sNPBnqYD6FnmdBrUmBCaqS00RyCsCpj2BG58A1JBswNF7b0OKviwxqVrOL/CKyJrLSClrSeqQv5BXNg2RUbPOw==}
engines: {node: '>= 9.11.2'}
requiresBuild: true
@@ -30306,7 +30364,7 @@ packages:
sorcery: 0.10.0
strip-indent: 3.0.0
svelte: 3.55.0
- typescript: 5.2.2
+ typescript: 4.9.5
dev: true
/svelte2tsx@0.5.22(svelte@3.54.0)(typescript@5.2.2):
@@ -31932,8 +31990,8 @@ packages:
dependencies:
'@types/node': 18.16.3
esbuild: 0.16.4
- postcss: 8.4.24
- resolve: 1.22.1
+ postcss: 8.4.31
+ resolve: 1.22.6
rollup: 3.15.0
optionalDependencies:
fsevents: 2.3.2