Compare commits

...

15 Commits

Author SHA1 Message Date
Balázs Orbán
24945895e9 chore(release): bump package version(s) [skip ci] 2022-09-28 18:10:38 +02:00
Balázs Orbán
6deccf610f fix(core): return JSON for non-HTML server route errors (#5442)
* fix(core): return JSON for non-HTML server route errors

* refactor: throw in `unstable_getServerSession`

* test: expect `unstable_getServerSession` to throw

* refactor: destructure

* fix unrelated test formatting

* catch error page
2022-09-28 17:01:39 +01:00
Etienne Martin
f770b90219 fix(react): safe use of localStorage API (#5444)
fix: safe use of localstorage

Co-authored-by: Etienne <>
2022-09-28 16:54:07 +01:00
Balázs Orbán
87f4786917 chore: bump release package 2022-09-28 13:51:41 +02:00
Balázs Orbán
191ef06471 chore(release): bump package version(s) [skip ci] 2022-09-28 13:00:32 +02:00
Philip
75e6d8f0aa docs(adapters): Update prisma.md (#5366)
* Update prisma.md

The referenced official doc page describes how to fix the `warn(prisma-client) There are already 10 instances of Prisma Client actively running.` error in development mode.

* Update prisma.md

Implemented best practice for Prisma Client creation.

* Fixed typo in Prisma db filename.
2022-09-28 11:15:55 +01:00
Yixuan Xu
17999edd30 chore(example): fix hydrate problem in react18 (#5439) 2022-09-28 10:50:40 +02:00
Tom Freudenberg
54b1845e58 fix(core): don't lock next in peerDependencies #5427 (#5430)
* Update peerDependencies #5427

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-09-27 00:04:50 +01:00
Tomas Pozo
879faf9fab docs(middleware): add tip on additional matcher patterns (#5404)
* docs(middleware): add tip on additional matcher patterns

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-09-26 13:39:32 +02:00
Balázs Orbán
3e3c36891e docs(example): use generic type in AppProps
closes #5401
2022-09-25 10:57:44 +01:00
Balázs Orbán
ac5d8a9795 chore(release): bump package version(s) [skip ci] 2022-09-25 11:42:17 +02:00
Matt Oliver
965c6267e2 feat(core): make session token with DB session strategy customizable (#5328)
* Add option for custom generateSessionToken

* Apply suggestions from code review

* Apply suggestions from code review

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-09-25 10:26:59 +01:00
Sébastien Vanvelthem
bfc429d20b fix: update jose to fix nextjs edge error with middleware (#5372)
fix: update jose to fix nextjs edge error
2022-09-25 15:46:02 +07:00
Balázs Orbán
2d8e910a19 chore(release): bump package version(s) [skip ci] 2022-09-25 10:29:56 +02:00
voinik
d16e04848e fix(adapters): check token during email verification in Upstash Adapter (#5377)
* Check token during email verification

* Undo accidental linter fix

* Update index.ts

Co-authored-by: Balázs Orbán <info@balazsorban.com>
2022-09-25 09:10:55 +01:00
18 changed files with 122 additions and 72 deletions

View File

@@ -2,12 +2,16 @@ import { SessionProvider } from "next-auth/react"
import "./styles.css" import "./styles.css"
import type { AppProps } from "next/app" import type { AppProps } from "next/app"
import type { Session } from "next-auth"
// Use of the <SessionProvider> is mandatory to allow components that call // Use of the <SessionProvider> is mandatory to allow components that call
// `useSession()` anywhere in your application to access the `session` object. // `useSession()` anywhere in your application to access the `session` object.
export default function App({ Component, pageProps }: AppProps) { export default function App({
Component,
pageProps: { session, ...pageProps },
}: AppProps<{ session: Session }>) {
return ( return (
<SessionProvider session={pageProps.session} refetchInterval={0}> <SessionProvider session={session}>
<Component {...pageProps} /> <Component {...pageProps} />
</SessionProvider> </SessionProvider>
) )

View File

@@ -4,8 +4,7 @@ import Layout from "../components/layout"
import AccessDenied from "../components/access-denied" import AccessDenied from "../components/access-denied"
export default function ProtectedPage() { export default function ProtectedPage() {
const { data: session, status } = useSession() const { data: session } = useSession()
const loading = status === "loading"
const [content, setContent] = useState() const [content, setContent] = useState()
// Fetch content from protected route // Fetch content from protected route
@@ -19,9 +18,7 @@ export default function ProtectedPage() {
} }
fetchData() fetchData()
}, [session]) }, [session])
// When rendering client side don't display anything until loading is complete
if (typeof window !== "undefined" && loading) return null
// If no session exists, display access denied message // If no session exists, display access denied message
if (!session) { if (!session) {

View File

@@ -12,15 +12,24 @@ npm install next-auth @prisma/client @next-auth/prisma-adapter
npm install prisma --save-dev npm install prisma --save-dev
``` ```
Create a file with your Prisma Client:
```javascript title="lib/prismadb.js"
import { PrismaClient } from "@prisma/client"
const client = globalThis.prisma || new PrismaClient()
if (process.env.NODE_ENV !== "production") globalThis.prisma = client
export default client
```
Configure your NextAuth.js to use the Prisma Adapter: Configure your NextAuth.js to use the Prisma Adapter:
```javascript title="pages/api/auth/[...nextauth].js" ```javascript title="pages/api/auth/[...nextauth].js"
import NextAuth from "next-auth" import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google" import GoogleProvider from "next-auth/providers/google"
import { PrismaAdapter } from "@next-auth/prisma-adapter" import { PrismaAdapter } from "@next-auth/prisma-adapter"
import { PrismaClient } from "@prisma/client" import prisma from "../../../lib/prismadb"
const prisma = new PrismaClient()
export default NextAuth({ export default NextAuth({
adapter: PrismaAdapter(prisma), adapter: PrismaAdapter(prisma),

View File

@@ -114,6 +114,12 @@ session: {
// Use it to limit write operations. Set to 0 to always update the database. // Use it to limit write operations. Set to 0 to always update the database.
// Note: This option is ignored if using JSON Web Tokens // Note: This option is ignored if using JSON Web Tokens
updateAge: 24 * 60 * 60, // 24 hours updateAge: 24 * 60 * 60, // 24 hours
// The session token is usually either a random UUID or string, however if you
// need a more customized session token string, you can define your own generate function.
generateSessionToken: () => {
return randomUUID?.() ?? randomBytes(32).toString("hex")
}
} }
``` ```

View File

@@ -42,7 +42,7 @@ export default function Page() {
### Next.js (Middleware) ### Next.js (Middleware)
With NextAuth.js 4.2.0 and Next.js 12, you can now protect your pages via the middleware pattern more easily. If you would like to protect all pages, you can create a `_middleware.js` file in your root `pages` directory which looks like this: With NextAuth.js 4.2.0 and Next.js 12, you can now protect your pages via the middleware pattern more easily. If you would like to protect all pages, you can create a `middleware.js` file in your root `pages` directory which looks like this:
```js title="/middleware.js" ```js title="/middleware.js"
export { default } from "next-auth/middleware" export { default } from "next-auth/middleware"
@@ -60,6 +60,12 @@ For the time being, the `withAuth` middleware only supports `"jwt"` as [session
More details can be found [here](https://next-auth.js.org/configuration/nextjs#middleware). More details can be found [here](https://next-auth.js.org/configuration/nextjs#middleware).
:::tip
To inclue all `dashboard` nested routes (sub pages like `/dashboard/settings`, `/dashboard/profile`) you can pass `matcher: "/dashboard/:path*"` to `config`.
For other patterns check out the [Next.js Middleware documentation](https://nextjs.org/docs/advanced-features/middleware#matcher).
:::
### Server Side ### Server Side
You can protect server side rendered pages using the `unstable_getServerSession` method. This is different from the old `getSession()` method, in that it does not do an extra fetch out over the internet to confirm data from itself, increasing performance significantly. You can protect server side rendered pages using the `unstable_getServerSession` method. This is different from the old `getSession()` method, in that it does not do an extra fetch out over the internet to confirm data from itself, increasing performance significantly.

View File

@@ -18,7 +18,7 @@
}, },
"devDependencies": { "devDependencies": {
"@actions/core": "^1.6.0", "@actions/core": "^1.6.0",
"@balazsorban/monorepo-release": "0.0.4", "@balazsorban/monorepo-release": "0.0.5",
"@types/jest": "^28.1.3", "@types/jest": "^28.1.3",
"@types/node": "^17.0.25", "@types/node": "^17.0.25",
"@typescript-eslint/eslint-plugin": "^5.10.2", "@typescript-eslint/eslint-plugin": "^5.10.2",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@next-auth/upstash-redis-adapter", "name": "@next-auth/upstash-redis-adapter",
"version": "3.0.1", "version": "3.0.2",
"description": "Upstash adapter for next-auth. It uses Upstash's connectionless (HTTP based) Redis client.", "description": "Upstash adapter for next-auth. It uses Upstash's connectionless (HTTP based) Redis client.",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth", "repository": "https://github.com/nextauthjs/next-auth",

View File

@@ -165,13 +165,20 @@ export function UpstashRedisAdapter(
}, },
async createVerificationToken(verificationToken) { async createVerificationToken(verificationToken) {
await setObjectAsJson( await setObjectAsJson(
verificationTokenKeyPrefix + verificationToken.identifier, verificationTokenKeyPrefix +
verificationToken.identifier +
":" +
verificationToken.token,
verificationToken verificationToken
) )
return verificationToken return verificationToken
}, },
async useVerificationToken(verificationToken) { async useVerificationToken(verificationToken) {
const tokenKey = verificationTokenKeyPrefix + verificationToken.identifier const tokenKey =
verificationTokenKeyPrefix +
verificationToken.identifier +
":" +
verificationToken.token
const token = await client.get<VerificationToken>(tokenKey) const token = await client.get<VerificationToken>(tokenKey)
if (!token) return null if (!token) return null

View File

@@ -1,6 +1,6 @@
{ {
"name": "next-auth", "name": "next-auth",
"version": "4.11.0", "version": "4.12.2",
"description": "Authentication for Next.js", "description": "Authentication for Next.js",
"homepage": "https://next-auth.js.org", "homepage": "https://next-auth.js.org",
"repository": "https://github.com/nextauthjs/next-auth.git", "repository": "https://github.com/nextauthjs/next-auth.git",
@@ -70,7 +70,7 @@
"@babel/runtime": "^7.16.3", "@babel/runtime": "^7.16.3",
"@panva/hkdf": "^1.0.1", "@panva/hkdf": "^1.0.1",
"cookie": "^0.5.0", "cookie": "^0.5.0",
"jose": "^4.3.7", "jose": "^4.9.3",
"oauth": "^0.9.15", "oauth": "^0.9.15",
"openid-client": "^5.1.0", "openid-client": "^5.1.0",
"preact": "^10.6.3", "preact": "^10.6.3",
@@ -78,7 +78,7 @@
"uuid": "^8.3.2" "uuid": "^8.3.2"
}, },
"peerDependencies": { "peerDependencies": {
"next": "12.2.5", "next": "^12.2.5",
"nodemailer": "^6.6.5", "nodemailer": "^6.6.5",
"react": "^17.0.2 || ^18", "react": "^17.0.2 || ^18",
"react-dom": "^17.0.2 || ^18" "react-dom": "^17.0.2 || ^18"

View File

@@ -94,10 +94,18 @@ export function BroadcastChannel(name = "nextauth.message") {
/** Notify other tabs/windows. */ /** Notify other tabs/windows. */
post(message: Record<string, unknown>) { post(message: Record<string, unknown>) {
if (typeof window === "undefined") return if (typeof window === "undefined") return
localStorage.setItem( try {
name, localStorage.setItem(
JSON.stringify({ ...message, timestamp: now() }) name,
) JSON.stringify({ ...message, timestamp: now() })
)
} catch {
/**
* The localStorage API isn't always available.
* It won't work in private mode prior to Safari 11 for example.
* Notifications are simply dropped if an error is encountered.
*/
}
}, },
} }
} }

View File

@@ -94,13 +94,21 @@ export async function NextAuthHandler<
assertionResult.forEach(logger.warn) assertionResult.forEach(logger.warn)
} else if (assertionResult instanceof Error) { } else if (assertionResult instanceof Error) {
// Bail out early if there's an error in the user config // Bail out early if there's an error in the user config
const { pages, theme } = userOptions
logger.error(assertionResult.code, assertionResult) logger.error(assertionResult.code, assertionResult)
const htmlPages = ["signin", "signout", "error", "verify-request"]
if (!htmlPages.includes(req.action) || req.method !== "GET") {
const message = `There is a problem with the server configuration. Check the server logs for more information.`
return {
status: 500,
headers: [{ key: "Content-Type", value: "application/json" }],
body: { message } as any,
}
}
const { pages, theme } = userOptions
const authOnErrorPage = const authOnErrorPage =
pages?.error && pages?.error && req.query?.callbackUrl?.startsWith(pages.error)
req.action === "signin" &&
req.query?.callbackUrl.startsWith(pages.error)
if (!pages?.error || authOnErrorPage) { if (!pages?.error || authOnErrorPage) {
if (authOnErrorPage) { if (authOnErrorPage) {

View File

@@ -1,3 +1,4 @@
import { randomBytes, randomUUID } from "crypto"
import { NextAuthOptions } from ".." import { NextAuthOptions } from ".."
import logger from "../utils/logger" import logger from "../utils/logger"
import parseUrl from "../utils/parse-url" import parseUrl from "../utils/parse-url"
@@ -86,6 +87,10 @@ export async function init({
strategy: userOptions.adapter ? "database" : "jwt", strategy: userOptions.adapter ? "database" : "jwt",
maxAge, maxAge,
updateAge: 24 * 60 * 60, updateAge: 24 * 60 * 60,
generateSessionToken: () => {
// Use `randomUUID` if available. (Node 15.6+)
return randomUUID?.() ?? randomBytes(32).toString("hex")
},
...userOptions.session, ...userOptions.session,
}, },
// JWT options // JWT options

View File

@@ -1,4 +1,3 @@
import { randomBytes, randomUUID } from "crypto"
import { AccountNotLinkedError } from "../errors" import { AccountNotLinkedError } from "../errors"
import { fromDate } from "./utils" import { fromDate } from "./utils"
@@ -37,7 +36,7 @@ export default async function callbackHandler(params: {
adapter, adapter,
jwt, jwt,
events, events,
session: { strategy: sessionStrategy }, session: { strategy: sessionStrategy, generateSessionToken },
} = options } = options
// If no adapter is configured then we don't have a database and cannot // If no adapter is configured then we don't have a database and cannot
@@ -219,8 +218,3 @@ export default async function callbackHandler(params: {
} }
} }
} }
function generateSessionToken() {
// Use `randomUUID` if available. (Node 15.6++)
return randomUUID?.() ?? randomBytes(32).toString("hex")
}

View File

@@ -468,6 +468,13 @@ export interface SessionOptions {
* @default 86400 // 1 day * @default 86400 // 1 day
*/ */
updateAge: number updateAge: number
/**
* Generate a custom session token for database-based sessions.
* By default, a random UUID or string is generated depending on the Node.js version.
* However, you can specify your own custom string (such as CUID) to be used.
* @default `randomUUID` or `randomBytes.toHex` depending on the Node.js version
*/
generateSessionToken: () => string
} }
export interface DefaultUser { export interface DefaultUser {

View File

@@ -118,12 +118,14 @@ export async function unstable_getServerSession(
}, },
}) })
const { body, cookies } = session const { body, cookies, status = 200 } = session
cookies?.forEach((cookie) => setCookie(res, cookie)) cookies?.forEach((cookie) => setCookie(res, cookie))
if (body && typeof body !== "string" && Object.keys(body).length) if (body && typeof body !== "string" && Object.keys(body).length) {
return body as Session if (status === 200) return body as Session
throw new Error((body as any).message)
}
return null return null
} }

View File

@@ -47,17 +47,19 @@ describe("Treat secret correctly", () => {
}) })
it("Error if missing NEXTAUTH_SECRET and secret", async () => { it("Error if missing NEXTAUTH_SECRET and secret", async () => {
const session = await unstable_getServerSession(req, res, { const configError = new Error(
providers: [], "There is a problem with the server configuration. Check the server logs for more information."
logger, )
}) await expect(
unstable_getServerSession(req, res, { providers: [], logger })
).rejects.toThrowError(configError)
expect(session).toEqual(null)
expect(logger.error).toBeCalledTimes(1) expect(logger.error).toBeCalledTimes(1)
expect(logger.error).toBeCalledWith("NO_SECRET", expect.any(MissingSecret)) expect(logger.error).toBeCalledWith("NO_SECRET", expect.any(MissingSecret))
}) })
it("Only logs warning once and in development", async () => { it("Only logs warning once and in development", async () => {
process.env.NEXTAUTH_SECRET = "secret"
// Expect console.warn to NOT be called due to NODE_ENV=production // Expect console.warn to NOT be called due to NODE_ENV=production
await unstable_getServerSession(req, res, { providers: [], logger }) await unstable_getServerSession(req, res, { providers: [], logger })
expect(console.warn).toBeCalledTimes(0) expect(console.warn).toBeCalledTimes(0)
@@ -71,6 +73,7 @@ describe("Treat secret correctly", () => {
// Expect console.warn to be still only be called ONCE // Expect console.warn to be still only be called ONCE
await unstable_getServerSession(req, res, { providers: [], logger }) await unstable_getServerSession(req, res, { providers: [], logger })
expect(console.warn).toBeCalledTimes(1) expect(console.warn).toBeCalledTimes(1)
delete process.env.NEXTAUTH_SECRET
}) })
}) })

View File

@@ -1,40 +1,40 @@
import { NextMiddleware } from "next/server" import { NextMiddleware } from "next/server"
import { NextAuthMiddlewareOptions, withAuth } from "../next/middleware" import { NextAuthMiddlewareOptions, withAuth } from "../src/next/middleware"
it("should not match pages as public paths", async () => { it("should not match pages as public paths", async () => {
const options: NextAuthMiddlewareOptions = { const options: NextAuthMiddlewareOptions = {
pages: { pages: {
signIn: "/", signIn: "/",
error: "/" error: "/",
}, },
secret: "secret" secret: "secret",
} }
const nextUrl: any = { const nextUrl: any = {
pathname: "/protected/pathA", pathname: "/protected/pathA",
search: "", search: "",
origin: "http://127.0.0.1" origin: "http://127.0.0.1",
} }
const req: any = { nextUrl, headers: { authorization: "" } } const req: any = { nextUrl, headers: { authorization: "" } }
const handleMiddleware = withAuth(options) as NextMiddleware const handleMiddleware = withAuth(options) as NextMiddleware
const res = await handleMiddleware(req, null) const res = await handleMiddleware(req, null as any)
expect(res).toBeDefined() expect(res).toBeDefined()
expect(res.status).toBe(307) expect(res?.status).toBe(307)
}) })
it("should not redirect on public paths", async () => { it("should not redirect on public paths", async () => {
const options: NextAuthMiddlewareOptions = { const options: NextAuthMiddlewareOptions = {
secret: "secret" secret: "secret",
} }
const nextUrl: any = { const nextUrl: any = {
pathname: "/_next/foo", pathname: "/_next/foo",
search: "", search: "",
origin: "http://127.0.0.1" origin: "http://127.0.0.1",
} }
const req: any = { nextUrl, headers: { authorization: "" } } const req: any = { nextUrl, headers: { authorization: "" } }
const handleMiddleware = withAuth(options) as NextMiddleware const handleMiddleware = withAuth(options) as NextMiddleware
const res = await handleMiddleware(req, null) const res = await handleMiddleware(req, null as any)
expect(res).toBeUndefined() expect(res).toBeUndefined()
}) })

38
pnpm-lock.yaml generated
View File

@@ -5,7 +5,7 @@ importers:
.: .:
specifiers: specifiers:
'@actions/core': ^1.6.0 '@actions/core': ^1.6.0
'@balazsorban/monorepo-release': 0.0.4 '@balazsorban/monorepo-release': 0.0.5
'@types/jest': ^28.1.3 '@types/jest': ^28.1.3
'@types/node': ^17.0.25 '@types/node': ^17.0.25
'@typescript-eslint/eslint-plugin': ^5.10.2 '@typescript-eslint/eslint-plugin': ^5.10.2
@@ -27,7 +27,7 @@ importers:
typescript: 4.7.4 typescript: 4.7.4
devDependencies: devDependencies:
'@actions/core': 1.9.0 '@actions/core': 1.9.0
'@balazsorban/monorepo-release': 0.0.4 '@balazsorban/monorepo-release': 0.0.5
'@types/jest': 28.1.3 '@types/jest': 28.1.3
'@types/node': 17.0.45 '@types/node': 17.0.45
'@typescript-eslint/eslint-plugin': 5.29.0_3ekaj7j3owlolnuhj3ykrb7u7i '@typescript-eslint/eslint-plugin': 5.29.0_3ekaj7j3owlolnuhj3ykrb7u7i
@@ -433,7 +433,7 @@ importers:
jest: ^28.1.1 jest: ^28.1.1
jest-environment-jsdom: ^28.1.1 jest-environment-jsdom: ^28.1.1
jest-watch-typeahead: ^1.1.0 jest-watch-typeahead: ^1.1.0
jose: ^4.3.7 jose: ^4.9.3
msw: ^0.42.3 msw: ^0.42.3
next: 12.2.5 next: 12.2.5
oauth: ^0.9.15 oauth: ^0.9.15
@@ -451,7 +451,7 @@ importers:
'@babel/runtime': 7.18.3 '@babel/runtime': 7.18.3
'@panva/hkdf': 1.0.2 '@panva/hkdf': 1.0.2
cookie: 0.5.0 cookie: 0.5.0
jose: 4.8.1 jose: 4.9.3
oauth: 0.9.15 oauth: 0.9.15
openid-client: 5.1.6 openid-client: 5.1.6
preact: 10.8.2 preact: 10.8.2
@@ -3638,8 +3638,8 @@ packages:
'@babel/helper-validator-identifier': 7.16.7 '@babel/helper-validator-identifier': 7.16.7
to-fast-properties: 2.0.0 to-fast-properties: 2.0.0
/@balazsorban/monorepo-release/0.0.4: /@balazsorban/monorepo-release/0.0.5:
resolution: {integrity: sha512-jjYc05vcRueT+nC7BD7C0D2JjE+H8xDdAIfwjtlbMHTnTwPx2KYXrbWohbL7bGVN8ZbhJDmXkXOQjppSrZCQBw==} resolution: {integrity: sha512-IeLswLrG7a+us5cQVxb1w8hbfgYYLIoIuodU6yDTo4Ln0qzS6AZGnwiL9ykAxewirFYCEjBGa0tqOymOpEvLtA==}
engines: {node: '>=16.16.0'} engines: {node: '>=16.16.0'}
hasBin: true hasBin: true
dependencies: dependencies:
@@ -7919,10 +7919,8 @@ packages:
clean-stack: 2.2.0 clean-stack: 2.2.0
indent-string: 4.0.0 indent-string: 4.0.0
/ajv-formats/2.1.1_ajv@8.11.0: /ajv-formats/2.1.1:
resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==} resolution: {integrity: sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==}
peerDependencies:
ajv: ^8.0.0
peerDependenciesMeta: peerDependenciesMeta:
ajv: ajv:
optional: true optional: true
@@ -9531,8 +9529,8 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
hasBin: true hasBin: true
dependencies: dependencies:
JSONStream: 1.3.5
is-text-path: 1.0.1 is-text-path: 1.0.1
JSONStream: 1.3.5
lodash: 4.17.21 lodash: 4.17.21
meow: 8.1.2 meow: 8.1.2
split2: 3.2.2 split2: 3.2.2
@@ -11709,7 +11707,7 @@ packages:
dependencies: dependencies:
'@apidevtools/json-schema-ref-parser': 9.0.9 '@apidevtools/json-schema-ref-parser': 9.0.9
ajv: 8.11.0 ajv: 8.11.0
ajv-formats: 2.1.1_ajv@8.11.0 ajv-formats: 2.1.1
body-parser: 1.20.0 body-parser: 1.20.0
content-type: 1.0.4 content-type: 1.0.4
deep-freeze: 0.0.1 deep-freeze: 0.0.1
@@ -12618,7 +12616,7 @@ packages:
dev: true dev: true
/git-log-parser/1.2.0: /git-log-parser/1.2.0:
resolution: {integrity: sha1-LmpMGxP8AAKCB7p5WnrDFme5/Uo=} resolution: {integrity: sha512-rnCVNfkTL8tdNryFuaY0fYiBWEBcgF748O6ZI61rslBvr2o7U65c2/6npCRqH40vuAhtgtDiqLTJjBVdrejCzA==}
dependencies: dependencies:
argv-formatter: 1.0.0 argv-formatter: 1.0.0
spawn-error-forwarder: 1.0.0 spawn-error-forwarder: 1.0.0
@@ -15426,8 +15424,8 @@ packages:
valid-url: 1.0.9 valid-url: 1.0.9
dev: true dev: true
/jose/4.8.1: /jose/4.9.3:
resolution: {integrity: sha512-+/hpTbRcCw9YC0TOfN1W47pej4a9lRmltdOVdRLz5FP5UvUq3CenhXjQK7u/8NdMIIShMXYAh9VLPhc7TjhvFw==} resolution: {integrity: sha512-f8E/z+T3Q0kA9txzH2DKvH/ds2uggcw0m3vVPSB9HrSkrQ7mojjifvS7aR8cw+lQl2Fcmx9npwaHpM/M3GD8UQ==}
dev: false dev: false
/js-beautify/1.14.4: /js-beautify/1.14.4:
@@ -17339,7 +17337,7 @@ packages:
resolution: {integrity: sha512-HTFaXWdUHvLFw4GaEMgC0jXYBgpjgzQQNHW1pZsSqJorSgrXzxJ+4u/LWCGaClDEse5HLjXRV+zU5Bn3OefiZw==} resolution: {integrity: sha512-HTFaXWdUHvLFw4GaEMgC0jXYBgpjgzQQNHW1pZsSqJorSgrXzxJ+4u/LWCGaClDEse5HLjXRV+zU5Bn3OefiZw==}
engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0} engines: {node: ^12.19.0 || ^14.15.0 || ^16.13.0}
dependencies: dependencies:
jose: 4.8.1 jose: 4.9.3
lru-cache: 6.0.0 lru-cache: 6.0.0
object-hash: 2.2.0 object-hash: 2.2.0
oidc-token-hash: 5.0.1 oidc-token-hash: 5.0.1
@@ -18833,12 +18831,6 @@ packages:
/react-dev-utils/12.0.1_webpack@5.73.0: /react-dev-utils/12.0.1_webpack@5.73.0:
resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==} resolution: {integrity: sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==}
engines: {node: '>=14'} engines: {node: '>=14'}
peerDependencies:
typescript: '>=2.7'
webpack: '>=4'
peerDependenciesMeta:
typescript:
optional: true
dependencies: dependencies:
'@babel/code-frame': 7.16.7 '@babel/code-frame': 7.16.7
address: 1.2.0 address: 1.2.0
@@ -18868,7 +18860,9 @@ packages:
transitivePeerDependencies: transitivePeerDependencies:
- eslint - eslint
- supports-color - supports-color
- typescript
- vue-template-compiler - vue-template-compiler
- webpack
dev: false dev: false
/react-dom/18.2.0_react@18.2.0: /react-dom/18.2.0_react@18.2.0:
@@ -19570,7 +19564,7 @@ packages:
dependencies: dependencies:
'@types/json-schema': 7.0.11 '@types/json-schema': 7.0.11
ajv: 8.11.0 ajv: 8.11.0
ajv-formats: 2.1.1_ajv@8.11.0 ajv-formats: 2.1.1
ajv-keywords: 5.1.0_ajv@8.11.0 ajv-keywords: 5.1.0_ajv@8.11.0
dev: false dev: false