diff --git a/.github/workflows/cypress_tests.yml b/.github/workflows/cypress_tests.yml
index 52394586..56a85d3f 100644
--- a/.github/workflows/cypress_tests.yml
+++ b/.github/workflows/cypress_tests.yml
@@ -23,7 +23,7 @@ jobs:
steps:
- uses: actions/setup-node@v4
with:
- node-version: 18
+ node-version: 22
- name: Checkout
uses: actions/checkout@v4
- name: Cypress run
@@ -40,7 +40,8 @@ jobs:
CYPRESS_NODE_ENV: test
NEXT_PUBLIC_API_URL: ${{ secrets.NEXT_PUBLIC_API_URL }}
NEXT_PUBLIC_ORCID_API_URL: ${{ secrets.NEXT_PUBLIC_ORCID_API_URL }}
+ NEXT_PUBLIC_JWT_PUBLIC_KEY: ${{ secrets.CYPRESS_JWT_PUBLIC_KEY_2025}}
SITEMAPS_URL: ${{ secrets.SITEMAPS_URL }}
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
- CYPRESS_USER_COOKIE: ${{ secrets.CYPRESS_USER_COOKIE }}
+ CYPRESS_userCookie: ${{ secrets.CYPRESS_USER_COOKIE_2025 }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/cypress.config.ts b/cypress.config.ts
index 72876e20..fec6fd49 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -6,12 +6,12 @@ export default defineConfig({
projectId: 'yur1cf',
retries: 2,
e2e: {
- setupNodeEvents(on, config) {},
+ setupNodeEvents() {},
baseUrl: 'http://localhost:3000',
specPattern: 'cypress/e2e/**/*.test.*',
},
component: {
- setupNodeEvents(on, config) { },
+ setupNodeEvents() { },
specPattern: 'src/components/**/*.test.*',
devServer: {
bundler: 'webpack',
diff --git a/cypress/e2e/session.test.ts b/cypress/e2e/session.test.ts
new file mode 100644
index 00000000..821fde4a
--- /dev/null
+++ b/cypress/e2e/session.test.ts
@@ -0,0 +1,38 @@
+describe('useSession behavior', () => {
+ beforeEach(() => {
+ cy.setCookie('_consent', 'true');
+ });
+
+ it('shows logged in state with valid token', () => {
+ cy.then(() => {
+ let userCookie = Cypress.env('userCookie');
+ if (typeof userCookie === 'object') {
+ userCookie = JSON.stringify(userCookie);
+ }
+ Cypress.log({
+ name: 'diagnostics:userCookie',
+ message: [
+ `type=${typeof userCookie}`,
+ `present=${Boolean(userCookie)}`,
+ `stringLength=${typeof userCookie === 'string' ? userCookie.length : 'n/a'}`,
+ `preview=${userCookie.substring(0, 50)}...`,
+ ],
+ });
+ });
+
+ cy.setCookie('_datacite', String(Cypress.env('userCookie')), { log: false });
+ cy.visit('/');
+ cy.get('#sign-in').should('contain.text', 'DataCite Test User'); // Match your JWT payload name
+ });
+
+ it('shows logged out state without token', () => {
+ cy.visit('/');
+ cy.get('#sign-in').should('contain.text', 'Sign In');
+ });
+
+ it('shows logged out state with invalid token', () => {
+ cy.setCookie('_datacite', '{"authenticated":{"access_token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.invalid.signature"}}', { log: false });
+ cy.visit('/');
+ cy.get('#sign-in').should('contain.text', 'Sign In');
+ });
+});
\ No newline at end of file
diff --git a/package.json b/package.json
index d196db46..d9680426 100644
--- a/package.json
+++ b/package.json
@@ -42,7 +42,6 @@
"@testing-library/user-event": "^11.2.1",
"@types/gtag.js": "^0.0.3",
"@types/js-cookie": "^2.2.6",
- "@types/jsonwebtoken": "^8.5.0",
"@types/lodash": "^4.14.154",
"@types/react-content-loader": "^4.0.0",
"@types/testing-library__cypress": "^5.0.5",
@@ -56,8 +55,8 @@
"html-react-parser": "^5.1.12",
"iso-3166-1": "^2.1.1",
"iso-639-1": "^3.1.3",
+ "jose": "^6.1.3",
"js-yaml-loader": "^1.2.2",
- "jsonwebtoken": "^8.5.1",
"linkify-react": "^4.2.0",
"linkifyjs": "^4.2.0",
"maltipoo": "https://github.com/datacite/maltipoo#2.0.3",
diff --git a/src/app/(main)/layout.tsx b/src/app/(main)/layout.tsx
index 5bcf5cb8..4d52113e 100644
--- a/src/app/(main)/layout.tsx
+++ b/src/app/(main)/layout.tsx
@@ -42,6 +42,7 @@ const sourceSans3 = Source_Sans_3({
})
export default async function RootLayout({ children }: PropsWithChildren) {
+ const authToken = await getAuthToken()
return (
@@ -54,7 +55,7 @@ export default async function RootLayout({ children }: PropsWithChildren) {
-
+
{children}
diff --git a/src/components/Claim/Claim.tsx b/src/components/Claim/Claim.tsx
index 188f1396..c5b4526c 100644
--- a/src/components/Claim/Claim.tsx
+++ b/src/components/Claim/Claim.tsx
@@ -5,7 +5,7 @@ import { useEffect } from 'react';
import { useMutation, ApolloCache } from '@apollo/client'
import { faOrcid } from '@fortawesome/free-brands-svg-icons'
-import { session, User } from 'src/utils/session'
+import { useSession, User } from 'src/utils/session'
import { Claim as ClaimType } from 'src/data/types'
import Error from 'src/components/Error/Error'
import ClaimStatus from 'src/components/ClaimStatus/ClaimStatus'
@@ -80,7 +80,7 @@ export default function Claim({ doi_id }: Props) {
}
})
- const user = session()
+ const { user } = useSession()
const claim: ClaimType = data?.work.claims[0] || {
id: null,
diff --git a/src/components/DiscoverWorksAlert/DiscoverWorksAlert.tsx b/src/components/DiscoverWorksAlert/DiscoverWorksAlert.tsx
index 4dcde86f..f886c707 100644
--- a/src/components/DiscoverWorksAlert/DiscoverWorksAlert.tsx
+++ b/src/components/DiscoverWorksAlert/DiscoverWorksAlert.tsx
@@ -9,12 +9,12 @@ import DataCiteButton from 'src/components/DataCiteButton/DataCiteButton'
import { faSearch } from '@fortawesome/free-solid-svg-icons'
import { PROFILES_SETTINGS_URL } from 'src/data/constants'
-import { session } from "src/utils/session";
+import { useSession } from "src/utils/session";
import styles from './DiscoverWorksAlert.module.scss'
export default function DiscoverWorksAlert() {
- const user = session()
+ const { user } = useSession()
const [show, setShow] = useState(true);
diff --git a/src/components/Header/ClientButtons.tsx b/src/components/Header/ClientButtons.tsx
index f4b8ac32..fa151b2b 100644
--- a/src/components/Header/ClientButtons.tsx
+++ b/src/components/Header/ClientButtons.tsx
@@ -7,10 +7,10 @@ import { faAddressCard } from '@fortawesome/free-solid-svg-icons'
import { faOrcid } from '@fortawesome/free-brands-svg-icons'
import { ORCID_URL } from 'src/data/constants';
-import { session } from "src/utils/session";
+import { useSession } from "src/utils/session";
export function UserCommonsPageButton() {
- const user = session()
+ const { user } = useSession()
if (!user) throw new Error("User not signed in")
const href = '/orcid.org/' + user.uid
@@ -21,7 +21,7 @@ export function UserCommonsPageButton() {
export function UserOrcidButton() {
- const user = session()
+ const { user } = useSession()
if (!user) throw new Error("User not signed in")
const href = `${ORCID_URL}/${user.uid}`
diff --git a/src/components/Header/Dropdown.tsx b/src/components/Header/Dropdown.tsx
index 2abbb489..d0d643fa 100644
--- a/src/components/Header/Dropdown.tsx
+++ b/src/components/Header/Dropdown.tsx
@@ -1,11 +1,12 @@
'use client'
import React, { PropsWithChildren } from 'react'
-import { session } from 'src/utils/session'
+import { useSession } from 'src/utils/session'
import NavDropdown from 'react-bootstrap/NavDropdown'
export default function UserDropdown({ children }: PropsWithChildren) {
- const user = session()
+ const { user, loading } = useSession()
+ if (loading) return null // Or return a loading skeleton
if (!user) throw new Error("User not signed in")
return
diff --git a/src/components/Header/NavRight.tsx b/src/components/Header/NavRight.tsx
index f269b22e..782ff46b 100644
--- a/src/components/Header/NavRight.tsx
+++ b/src/components/Header/NavRight.tsx
@@ -1,7 +1,7 @@
'use client'
import React from 'react';
-import { session } from 'src/utils/session';
+import { useSession } from 'src/utils/session';
interface Props {
signedInContent: React.ReactNode
@@ -9,7 +9,7 @@ interface Props {
}
export default function NavRight({ signedInContent, signedOutContent }: Props) {
- const user = session()
+ const { user } = useSession()
if (!user) return signedOutContent
return signedInContent
diff --git a/src/utils/apolloClient/apolloClient.ts b/src/utils/apolloClient/apolloClient.ts
index f66be1c9..f2908d84 100644
--- a/src/utils/apolloClient/apolloClient.ts
+++ b/src/utils/apolloClient/apolloClient.ts
@@ -1,8 +1,9 @@
-import { cookies, type UnsafeUnwrappedCookies } from 'next/headers';
+import { cookies } from 'next/headers';
import apolloClientBuilder from './builder'
-export function getAuthToken() {
- const sessionCookie = JSON.parse(((cookies() as unknown as UnsafeUnwrappedCookies).get('_datacite') as any)?.value || '{}')
+export async function getAuthToken() {
+ const cookieStore = await cookies()
+ const sessionCookie = JSON.parse((cookieStore.get('_datacite') as any)?.value || '{}')
return sessionCookie?.authenticated?.access_token
}
diff --git a/src/utils/apolloClient/builder.ts b/src/utils/apolloClient/builder.ts
index e21a5946..c87083ee 100644
--- a/src/utils/apolloClient/builder.ts
+++ b/src/utils/apolloClient/builder.ts
@@ -8,16 +8,16 @@ import { DATACITE_API_URL } from 'src/data/constants'
* this throws an error unless the token is returned from a function that is called
* in the authLink setContext. I'm not sure why
*/
-export default function apolloClientBuilder(getToken: () => string) {
+export default function apolloClientBuilder(getToken: () => Promise) {
// needed for CORS, see https://www.apollographql.com/docs/react/networking/authentication/#cookie
const httpLink = createHttpLink({
uri: DATACITE_API_URL + '/graphql',
credentials: 'include'
})
- const authLink = setContext((_, { headers }) => {
+ const authLink = setContext(async (_, { headers }) => {
// return the headers to the context so httpLink can read them
- const token = getToken()
+ const token = await getToken()
return {
headers: {
diff --git a/src/utils/apolloClient/provider.tsx b/src/utils/apolloClient/provider.tsx
index 309cf8a0..c6e32824 100644
--- a/src/utils/apolloClient/provider.tsx
+++ b/src/utils/apolloClient/provider.tsx
@@ -2,9 +2,9 @@ import React, { PropsWithChildren } from 'react'
import apolloClientBuilder from 'src/utils/apolloClient/builder'
import { ApolloNextAppProvider } from "@apollo/experimental-nextjs-app-support";
-export default function ApolloProvider({ token, children }: PropsWithChildren<{ token: string }>) {
+export default function ApolloProvider({ token, children }: PropsWithChildren<{ token: string | null }>) {
return (
- apolloClientBuilder(() => token)}>
+ apolloClientBuilder(async () => token)}>
{children}
);
diff --git a/src/utils/session.ts b/src/utils/session.ts
index 2c4b7580..ae3f24b7 100644
--- a/src/utils/session.ts
+++ b/src/utils/session.ts
@@ -1,5 +1,6 @@
+import { useState, useEffect } from 'react'
import { Cookies } from 'react-cookie-consent'
-import JsonWebToken from 'jsonwebtoken'
+import { jwtVerify, importSPKI } from 'jose'
import { JWT_KEY } from 'src/data/constants'
export type User = {
@@ -7,26 +8,39 @@ export type User = {
name: string
} | null
-export const session = () => {
- // RSA public key
- if (!JWT_KEY) return null
+export const useSession = () => {
+ const [user, setUser] = useState(null)
+ const [loading, setLoading] = useState(true)
- const sessionCookie = Cookies.getJSON('_datacite')
- const token = sessionCookie?.authenticated?.access_token
- if (!token) return null
+ useEffect(() => {
+ const fetchUser = async () => {
+ // RSA public key
+ if (!JWT_KEY) {
+ setLoading(false)
+ return
+ }
- let user: any = null
- function setUser(error: any, payload: any) {
- if (error) {
- console.log('JWT verification error: ' + error.message)
- return
- }
+ const sessionCookie = Cookies.getJSON('_datacite')
+ const token = sessionCookie?.authenticated?.access_token
+ if (!token) {
+ setLoading(false)
+ return
+ }
- user = payload
- }
+ try {
+ const publicKey = await importSPKI(JWT_KEY, 'RS256')
+ const { payload } = await jwtVerify(token, publicKey)
+ setUser(payload as User)
+ } catch (error: any) {
+ console.log('JWT verification error: ' + error.message)
+ setUser(null)
+ } finally {
+ setLoading(false)
+ }
+ }
- // verify asymmetric token, using RSA with SHA-256 hash algorithm
- JsonWebToken.verify(token, JWT_KEY, { algorithms: ['RS256'] }, setUser)
+ fetchUser()
+ }, [])
- return user as User
+ return { user, loading }
}
diff --git a/yarn.lock b/yarn.lock
index 4626bf6c..f8815590 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2047,13 +2047,6 @@
resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==
-"@types/jsonwebtoken@^8.5.0":
- version "8.5.9"
- resolved "https://registry.yarnpkg.com/@types/jsonwebtoken/-/jsonwebtoken-8.5.9.tgz#2c064ecb0b3128d837d2764aa0b117b0ff6e4586"
- integrity sha512-272FMnFGzAVMGtu9tkr29hRL6bZj4Zs1KZNeHLnKqAvp06tAIcarTMwOh8/8bz4FmKRcMxZhZNeUAQsNLoiPhg==
- dependencies:
- "@types/node" "*"
-
"@types/lodash@^4.14.154":
version "4.17.20"
resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.17.20.tgz#1ca77361d7363432d29f5e55950d9ec1e1c6ea93"
@@ -3403,11 +3396,6 @@ buffer-crc32@~0.2.3:
resolved "https://registry.yarnpkg.com/buffer-crc32/-/buffer-crc32-0.2.13.tgz#0d333e3f00eac50aa1454abd30ef8c2a5d9a7242"
integrity sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==
-buffer-equal-constant-time@^1.0.1:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz#f8e71132f7ffe6e01a5c9697a4c6f3e48d5cc819"
- integrity sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==
-
buffer-from@^1.0.0:
version "1.1.2"
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
@@ -4559,13 +4547,6 @@ ecc-jsbn@~0.1.1:
jsbn "~0.1.0"
safer-buffer "^2.1.0"
-ecdsa-sig-formatter@1.0.11:
- version "1.0.11"
- resolved "https://registry.yarnpkg.com/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz#ae0f0fa2d85045ef14a817daa3ce9acd0489e5bf"
- integrity sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==
- dependencies:
- safe-buffer "^5.0.1"
-
edge-runtime@2.5.9:
version "2.5.9"
resolved "https://registry.yarnpkg.com/edge-runtime/-/edge-runtime-2.5.9.tgz#9daeb329f0339b8377483f230789b3d68f45f1d9"
@@ -6484,6 +6465,11 @@ joi@^17.3.0:
"@sideway/formula" "^3.0.1"
"@sideway/pinpoint" "^2.0.0"
+jose@^6.1.3:
+ version "6.1.3"
+ resolved "https://registry.yarnpkg.com/jose/-/jose-6.1.3.tgz#8453d7be88af7bb7d64a0481d6a35a0145ba3ea5"
+ integrity sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==
+
js-cookie@^2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-2.2.1.tgz#69e106dc5d5806894562902aa5baec3744e9b2b8"
@@ -6633,22 +6619,6 @@ jsonparse@^1.2.0:
resolved "https://registry.yarnpkg.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
-jsonwebtoken@^8.5.1:
- version "8.5.1"
- resolved "https://registry.yarnpkg.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
- integrity sha512-XjwVfRS6jTMsqYs0EsuJ4LGxXV14zQybNd4L2r0UvbVnSF9Af8x7p5MzbJ90Ioz/9TI41/hTCvznF/loiSzn8w==
- dependencies:
- jws "^3.2.2"
- lodash.includes "^4.3.0"
- lodash.isboolean "^3.0.3"
- lodash.isinteger "^4.0.4"
- lodash.isnumber "^3.0.3"
- lodash.isplainobject "^4.0.6"
- lodash.isstring "^4.0.1"
- lodash.once "^4.0.0"
- ms "^2.1.1"
- semver "^5.6.0"
-
jsprim@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-2.0.2.tgz#77ca23dbcd4135cd364800d22ff82c2185803d4d"
@@ -6669,23 +6639,6 @@ jsprim@^2.0.2:
object.assign "^4.1.4"
object.values "^1.1.6"
-jwa@^1.4.1:
- version "1.4.2"
- resolved "https://registry.yarnpkg.com/jwa/-/jwa-1.4.2.tgz#16011ac6db48de7b102777e57897901520eec7b9"
- integrity sha512-eeH5JO+21J78qMvTIDdBXidBd6nG2kZjg5Ohz/1fpa28Z4CcsWUzJ1ZZyFq/3z3N17aZy+ZuBoHljASbL1WfOw==
- dependencies:
- buffer-equal-constant-time "^1.0.1"
- ecdsa-sig-formatter "1.0.11"
- safe-buffer "^5.0.1"
-
-jws@^3.2.2:
- version "3.2.2"
- resolved "https://registry.yarnpkg.com/jws/-/jws-3.2.2.tgz#001099f3639468c9414000e99995fa52fb478304"
- integrity sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==
- dependencies:
- jwa "^1.4.1"
- safe-buffer "^5.0.1"
-
keyv@^4.5.3:
version "4.5.4"
resolved "https://registry.yarnpkg.com/keyv/-/keyv-4.5.4.tgz#a879a99e29452f942439f2a405e3af8b31d4de93"
@@ -6965,11 +6918,6 @@ lodash.identity@~2.4.1:
resolved "https://registry.yarnpkg.com/lodash.identity/-/lodash.identity-2.4.1.tgz#6694cffa65fef931f7c31ce86c74597cf560f4f1"
integrity sha512-VRYX+8XipeLjorag5bz3YBBRJ+5kj8hVBzfnaHgXPZAVTYowBdY5l0M5ZnOmlAMCOXBFabQtm7f5VqjMKEji0w==
-lodash.includes@^4.3.0:
- version "4.3.0"
- resolved "https://registry.yarnpkg.com/lodash.includes/-/lodash.includes-4.3.0.tgz#60bb98a87cb923c68ca1e51325483314849f553f"
- integrity sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==
-
lodash.isarray@~2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-2.4.1.tgz#b52a326c1f62f6d7da73a31d5401df6ef44f0fa1"
@@ -6977,26 +6925,11 @@ lodash.isarray@~2.4.1:
dependencies:
lodash._isnative "~2.4.1"
-lodash.isboolean@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz#6c2e171db2a257cd96802fd43b01b20d5f5870f6"
- integrity sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==
-
lodash.isfunction@~2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-2.4.1.tgz#2cfd575c73e498ab57e319b77fa02adef13a94d1"
integrity sha512-6XcAB3izeQxPOQQNAJbbdjXbvWEt2Pn9ezPrjr4CwoLwmqsLVbsiEXD19cmmt4mbzOCOCdHzOQiUivUOJLra7w==
-lodash.isinteger@^4.0.4:
- version "4.0.4"
- resolved "https://registry.yarnpkg.com/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz#619c0af3d03f8b04c31f5882840b77b11cd68343"
- integrity sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==
-
-lodash.isnumber@^3.0.3:
- version "3.0.3"
- resolved "https://registry.yarnpkg.com/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz#3ce76810c5928d03352301ac287317f11c0b1ffc"
- integrity sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==
-
lodash.isobject@~2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/lodash.isobject/-/lodash.isobject-2.4.1.tgz#5a2e47fe69953f1ee631a7eba1fe64d2d06558f5"
@@ -7004,16 +6937,6 @@ lodash.isobject@~2.4.1:
dependencies:
lodash._objecttypes "~2.4.1"
-lodash.isplainobject@^4.0.6:
- version "4.0.6"
- resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb"
- integrity sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==
-
-lodash.isstring@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/lodash.isstring/-/lodash.isstring-4.0.1.tgz#d527dfb5456eca7cc9bb95d5daeaf88ba54a5451"
- integrity sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==
-
lodash.keys@~2.4.1:
version "2.4.1"
resolved "https://registry.yarnpkg.com/lodash.keys/-/lodash.keys-2.4.1.tgz#48dea46df8ff7632b10d706b8acb26591e2b3727"
@@ -7038,7 +6961,7 @@ lodash.noop@~2.4.1:
resolved "https://registry.yarnpkg.com/lodash.noop/-/lodash.noop-2.4.1.tgz#4fb54f816652e5ae10e8f72f717a388c7326538a"
integrity sha512-uNcV98/blRhInPUGQEnj9ekXXfG+q+rfoNSFZgl/eBfog9yBDW9gfUv2AHX/rAF7zZRlzWhbslGhbGQFZlCkZA==
-lodash.once@^4.0.0, lodash.once@^4.1.1:
+lodash.once@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/lodash.once/-/lodash.once-4.1.1.tgz#0dd3971213c7c56df880977d504c88fb471a97ac"
integrity sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==
@@ -8477,11 +8400,6 @@ semver@7.3.5:
dependencies:
lru-cache "^6.0.0"
-semver@^5.6.0:
- version "5.7.2"
- resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.2.tgz#48d55db737c3287cd4835e17fa13feace1c41ef8"
- integrity sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==
-
semver@^7.1.3, semver@^7.2.1, semver@^7.3.2, semver@^7.3.4, semver@^7.3.5, semver@^7.5.3, semver@^7.5.4, semver@^7.6.0, semver@^7.6.3, semver@^7.7.1, semver@^7.7.2:
version "7.7.2"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.2.tgz#67d99fdcd35cec21e6f8b87a7fd515a33f982b58"