From 76a110fbf8076241a7736576d06eba6e0d03f595 Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Wed, 24 Apr 2024 21:10:41 -0600 Subject: [PATCH 1/6] wip --- apps/consent/app/graphql/generated.ts | 9 ++ apps/dashboard/services/graphql/generated.ts | 20 ++++ apps/map/services/galoy/graphql/generated.ts | 9 ++ apps/pay/lib/graphql/generated.ts | 9 ++ bats/core/api/user.bats | 2 + bats/gql/list-sessions.gql | 11 ++ bats/helpers/user.bash | 13 ++- core/api/src/app/users/index.ts | 1 + core/api/src/app/users/list-sessions.ts | 11 ++ .../domain/authentication/index.types.d.ts | 10 +- core/api/src/graphql/public/schema.graphql | 9 ++ .../public/types/object/mobile-session.ts | 14 +++ .../src/graphql/public/types/object/user.ts | 9 ++ core/api/src/services/hydra/index.ts | 35 ++++++ core/api/src/services/kratos/index.ts | 6 +- core/api/src/services/kratos/index.types.d.ts | 2 +- core/api/src/services/kratos/private.ts | 21 +--- .../integration/app/user/consent-list.spec.ts | 110 ++++++++++++++++++ .../apollo-federation/supergraph.graphql | 11 ++ docs/hydra.md | 34 ++---- 20 files changed, 300 insertions(+), 46 deletions(-) create mode 100644 bats/gql/list-sessions.gql create mode 100644 core/api/src/app/users/list-sessions.ts create mode 100644 core/api/src/graphql/public/types/object/mobile-session.ts create mode 100644 core/api/src/services/hydra/index.ts create mode 100644 core/api/test/integration/app/user/consent-list.spec.ts diff --git a/apps/consent/app/graphql/generated.ts b/apps/consent/app/graphql/generated.ts index c355da8406..e689c2696d 100644 --- a/apps/consent/app/graphql/generated.ts +++ b/apps/consent/app/graphql/generated.ts @@ -877,6 +877,13 @@ export type MerchantPayload = { readonly merchant?: Maybe; }; +export type MobileSession = { + readonly __typename: 'MobileSession'; + readonly expiresAt: Scalars['Timestamp']['output']; + readonly id: Scalars['ID']['output']; + readonly issuedAt: Scalars['Timestamp']['output']; +}; + export type MobileVersions = { readonly __typename: 'MobileVersions'; readonly currentSupported: Scalars['Int']['output']; @@ -1922,6 +1929,8 @@ export type User = { * When value is 'default' the intent is to use preferred language from OS settings. */ readonly language: Scalars['Language']['output']; + /** List of mobile sessions */ + readonly mobileSessions: ReadonlyArray; /** Phone number with international calling code. */ readonly phone?: Maybe; readonly supportChat: ReadonlyArray; diff --git a/apps/dashboard/services/graphql/generated.ts b/apps/dashboard/services/graphql/generated.ts index a243655abd..82fe5a8b81 100644 --- a/apps/dashboard/services/graphql/generated.ts +++ b/apps/dashboard/services/graphql/generated.ts @@ -917,6 +917,13 @@ export type MerchantPayload = { readonly merchant?: Maybe; }; +export type MobileSession = { + readonly __typename: 'MobileSession'; + readonly expiresAt: Scalars['Timestamp']['output']; + readonly id: Scalars['ID']['output']; + readonly issuedAt: Scalars['Timestamp']['output']; +}; + export type MobileVersions = { readonly __typename: 'MobileVersions'; readonly currentSupported: Scalars['Int']['output']; @@ -2019,6 +2026,8 @@ export type User = { * When value is 'default' the intent is to use preferred language from OS settings. */ readonly language: Scalars['Language']['output']; + /** List of mobile sessions */ + readonly mobileSessions: ReadonlyArray; /** Phone number with international calling code. */ readonly phone?: Maybe; readonly statefulNotifications: StatefulNotificationConnection; @@ -3527,6 +3536,7 @@ export type ResolversTypes = { MerchantMapSuggestInput: MerchantMapSuggestInput; MerchantPayload: ResolverTypeWrapper; Minutes: ResolverTypeWrapper; + MobileSession: ResolverTypeWrapper; MobileVersions: ResolverTypeWrapper; Mutation: ResolverTypeWrapper<{}>; MyUpdatesPayload: ResolverTypeWrapper & { update?: Maybe }>; @@ -3752,6 +3762,7 @@ export type ResolversParentTypes = { MerchantMapSuggestInput: MerchantMapSuggestInput; MerchantPayload: MerchantPayload; Minutes: Scalars['Minutes']['output']; + MobileSession: MobileSession; MobileVersions: MobileVersions; Mutation: {}; MyUpdatesPayload: Omit & { update?: Maybe }; @@ -4360,6 +4371,13 @@ export interface MinutesScalarConfig extends GraphQLScalarTypeConfig = { + expiresAt?: Resolver; + id?: Resolver; + issuedAt?: Resolver; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type MobileVersionsResolvers = { currentSupported?: Resolver; minSupported?: Resolver; @@ -4820,6 +4838,7 @@ export type UserResolvers, ParentType, ContextType>; id?: Resolver; language?: Resolver; + mobileSessions?: Resolver, ParentType, ContextType>; phone?: Resolver, ParentType, ContextType>; statefulNotifications?: Resolver>; supportChat?: Resolver, ParentType, ContextType>; @@ -5011,6 +5030,7 @@ export type Resolvers = { Merchant?: MerchantResolvers; MerchantPayload?: MerchantPayloadResolvers; Minutes?: GraphQLScalarType; + MobileSession?: MobileSessionResolvers; MobileVersions?: MobileVersionsResolvers; Mutation?: MutationResolvers; MyUpdatesPayload?: MyUpdatesPayloadResolvers; diff --git a/apps/map/services/galoy/graphql/generated.ts b/apps/map/services/galoy/graphql/generated.ts index 383fc968a0..279cf2cb2a 100644 --- a/apps/map/services/galoy/graphql/generated.ts +++ b/apps/map/services/galoy/graphql/generated.ts @@ -877,6 +877,13 @@ export type MerchantPayload = { readonly merchant?: Maybe; }; +export type MobileSession = { + readonly __typename: 'MobileSession'; + readonly expiresAt: Scalars['Timestamp']['output']; + readonly id: Scalars['ID']['output']; + readonly issuedAt: Scalars['Timestamp']['output']; +}; + export type MobileVersions = { readonly __typename: 'MobileVersions'; readonly currentSupported: Scalars['Int']['output']; @@ -1922,6 +1929,8 @@ export type User = { * When value is 'default' the intent is to use preferred language from OS settings. */ readonly language: Scalars['Language']['output']; + /** List of mobile sessions */ + readonly mobileSessions: ReadonlyArray; /** Phone number with international calling code. */ readonly phone?: Maybe; readonly supportChat: ReadonlyArray; diff --git a/apps/pay/lib/graphql/generated.ts b/apps/pay/lib/graphql/generated.ts index 68a092c98d..ccd77bf613 100644 --- a/apps/pay/lib/graphql/generated.ts +++ b/apps/pay/lib/graphql/generated.ts @@ -876,6 +876,13 @@ export type MerchantPayload = { readonly merchant?: Maybe; }; +export type MobileSession = { + readonly __typename: 'MobileSession'; + readonly expiresAt: Scalars['Timestamp']; + readonly id: Scalars['ID']; + readonly issuedAt: Scalars['Timestamp']; +}; + export type MobileVersions = { readonly __typename: 'MobileVersions'; readonly currentSupported: Scalars['Int']; @@ -1921,6 +1928,8 @@ export type User = { * When value is 'default' the intent is to use preferred language from OS settings. */ readonly language: Scalars['Language']; + /** List of mobile sessions */ + readonly mobileSessions: ReadonlyArray; /** Phone number with international calling code. */ readonly phone?: Maybe; readonly supportChat: ReadonlyArray; diff --git a/bats/core/api/user.bats b/bats/core/api/user.bats index 54e427cada..e8fe4ce578 100644 --- a/bats/core/api/user.bats +++ b/bats/core/api/user.bats @@ -5,6 +5,8 @@ setup_file() { } @test "account: updates language" { + "skip" + local new_language="de" exec_graphql 'alice' 'user-details' diff --git a/bats/gql/list-sessions.gql b/bats/gql/list-sessions.gql new file mode 100644 index 0000000000..fa43e65b7e --- /dev/null +++ b/bats/gql/list-sessions.gql @@ -0,0 +1,11 @@ +query userDetails { + me { + id + phone + mobileSessions { + id + expiresAt + issuedAt + } + } +} diff --git a/bats/helpers/user.bash b/bats/helpers/user.bash index d4800a9d5c..14b26073ca 100644 --- a/bats/helpers/user.bash +++ b/bats/helpers/user.bash @@ -75,9 +75,20 @@ create_user_with_metadata() { } random_phone() { - printf "+1%010d\n" $(( ($RANDOM * 1000000) + ($RANDOM % 1000000) )) + # Generate an area code: cannot start with 0 or 1 + local area_code=415 + + # Generate an exchange code: cannot start with 0 or 1 + local exchange=$(( $RANDOM % 800 + 200 )) + + # Generate a subscriber number: four-digit number + local subscriber=$(( $RANDOM % 10000 )) + + # Print formatted phone number + printf "+1%03d%03d%04d\n" $area_code $exchange $subscriber } + user_update_username() { local token_name="$1" diff --git a/core/api/src/app/users/index.ts b/core/api/src/app/users/index.ts index 3748c982fb..e742c12ab0 100644 --- a/core/api/src/app/users/index.ts +++ b/core/api/src/app/users/index.ts @@ -3,6 +3,7 @@ import { UsersRepository } from "@/services/mongoose" export * from "./update-language" export * from "./get-user-language" export * from "./add-device-token" +export * from "./list-sessions" const users = UsersRepository() diff --git a/core/api/src/app/users/list-sessions.ts b/core/api/src/app/users/list-sessions.ts new file mode 100644 index 0000000000..a08885cf38 --- /dev/null +++ b/core/api/src/app/users/list-sessions.ts @@ -0,0 +1,11 @@ +import { listSessions as listSessionsService } from "@/services/kratos" + +export const listMobileSessions = async (userId: UserId) => { + const list = await listSessionsService(userId) + console.dir(list) + return list +} + +export const listDeleguateSessions = async (userId: UserId) => { + +} diff --git a/core/api/src/domain/authentication/index.types.d.ts b/core/api/src/domain/authentication/index.types.d.ts index 4c553d297b..8863f43b20 100644 --- a/core/api/src/domain/authentication/index.types.d.ts +++ b/core/api/src/domain/authentication/index.types.d.ts @@ -61,10 +61,18 @@ type AnyIdentity = | IdentityPhoneEmail | IdentityDeviceAccount -type Session = { +type MobileSession = { identity: AnyIdentity id: SessionId expiresAt: Date + issuedAt: Date +} + +type ConsentSession = { + scope: string[] + handledAt: Date + remember: boolean + app: string } type WithSessionResponse = { diff --git a/core/api/src/graphql/public/schema.graphql b/core/api/src/graphql/public/schema.graphql index 2270e381ef..0e693edd93 100644 --- a/core/api/src/graphql/public/schema.graphql +++ b/core/api/src/graphql/public/schema.graphql @@ -865,6 +865,12 @@ type MerchantPayload { """(Positive) amount of minutes""" scalar Minutes +type MobileSession { + expiresAt: Timestamp! + id: ID! + issuedAt: Timestamp! +} + type MobileVersions { currentSupported: Int! minSupported: Int! @@ -1599,6 +1605,9 @@ type User { """ language: Language! + """List of mobile sessions""" + mobileSessions: [MobileSession!]! + """Phone number with international calling code.""" phone: Phone supportChat: [SupportMessage!]! diff --git a/core/api/src/graphql/public/types/object/mobile-session.ts b/core/api/src/graphql/public/types/object/mobile-session.ts new file mode 100644 index 0000000000..4368a04c6f --- /dev/null +++ b/core/api/src/graphql/public/types/object/mobile-session.ts @@ -0,0 +1,14 @@ +import Timestamp from "@/graphql/shared/types/scalar/timestamp" + +import { GT } from "@/graphql/index" + +const MobileSession = GT.Object({ + name: "MobileSession", + fields: () => ({ + id: { type: GT.NonNullID }, + issuedAt: { type: GT.NonNull(Timestamp) }, + expiresAt: { type: GT.NonNull(Timestamp) }, + }), +}) + +export default MobileSession diff --git a/core/api/src/graphql/public/types/object/user.ts b/core/api/src/graphql/public/types/object/user.ts index a55c425130..51b7f6772b 100644 --- a/core/api/src/graphql/public/types/object/user.ts +++ b/core/api/src/graphql/public/types/object/user.ts @@ -19,6 +19,7 @@ import Language from "@/graphql/shared/types/scalar/language" import Username from "@/graphql/shared/types/scalar/username" import Timestamp from "@/graphql/shared/types/scalar/timestamp" import GraphQLEmail from "@/graphql/shared/types/object/email" +import MobileSession from "./mobile-session" const GraphQLUser = GT.Object({ name: "User", @@ -75,6 +76,14 @@ const GraphQLUser = GT.Object({ }, }, + mobileSessions: { + type: GT.NonNullList(MobileSession), + description: "List of mobile sessions", + resolve: async (source, args, { user }) => { + return Users.listMobileSessions(user.id) + }, + }, + contacts: { deprecationReason: "will be moved to account", type: GT.NonNullList(AccountContact), // TODO: Make it a Connection Interface diff --git a/core/api/src/services/hydra/index.ts b/core/api/src/services/hydra/index.ts new file mode 100644 index 0000000000..e06108cab9 --- /dev/null +++ b/core/api/src/services/hydra/index.ts @@ -0,0 +1,35 @@ +import axios, { AxiosResponse } from "axios" + +const hydraUrl = process.env.HYDRA_ADMIN_URL || "http://localhost:4445" + +export const consentList = async (userId: UserId): Promise => { + let res: AxiosResponse + + try { + res = await axios.get( + `${hydraUrl}/admin/oauth2/auth/sessions/consent?subject=${userId}`, + ) + } catch (err) { + // TODO + console.error(err) + return [] + } + + let sessions: ConsentSession[] + + try { + console.dir(res.data, { depth: null }) + sessions = res.data.map((request) => ({ + scope: request.grant_scope, + handledAt: new Date(request.handled_at), + remember: request.remember, + app: request.consent_request.client.client_name, + })) + } catch (err) { + // TODO + console.error(err) + return [] + } + + return sessions +} diff --git a/core/api/src/services/kratos/index.ts b/core/api/src/services/kratos/index.ts index 33abee3733..5fba743ff4 100644 --- a/core/api/src/services/kratos/index.ts +++ b/core/api/src/services/kratos/index.ts @@ -61,7 +61,7 @@ export const checkedToAuthToken = (value: string) => { export const validateKratosToken = async ( authToken: AuthToken, ): Promise => { - let session: Session + let session: MobileSession try { const { data } = await kratosPublic.toSession({ xSessionToken: authToken }) @@ -80,7 +80,9 @@ export const validateKratosToken = async ( } } -export const listSessions = async (userId: UserId): Promise => { +export const listSessions = async ( + userId: UserId, +): Promise => { try { const res = await kratosAdmin.listIdentitySessions({ id: userId }) if (res.data === null) return [] diff --git a/core/api/src/services/kratos/index.types.d.ts b/core/api/src/services/kratos/index.types.d.ts index cb59e9f9da..69d0715d57 100644 --- a/core/api/src/services/kratos/index.types.d.ts +++ b/core/api/src/services/kratos/index.types.d.ts @@ -14,7 +14,7 @@ type IdentitySchemaContainer = import("@ory/client").IdentitySchemaContainer type ValidateKratosTokenResult = { kratosUserId: UserId - session: Session + session: MobileSession } type KratosPublicMetadata = { diff --git a/core/api/src/services/kratos/private.ts b/core/api/src/services/kratos/private.ts index bf7abad862..a9f1b243c3 100644 --- a/core/api/src/services/kratos/private.ts +++ b/core/api/src/services/kratos/private.ts @@ -1,13 +1,8 @@ import knex from "knex" -import { Configuration, FrontendApi, IdentityApi } from "@ory/client" +import { Configuration, FrontendApi, Identity, IdentityApi } from "@ory/client" -import { - InvalidIdentitySessionKratosError, - MissingCreatedAtKratosError, - MissingExpiredAtKratosError, - UnknownKratosError, -} from "./errors" +import { MissingCreatedAtKratosError, UnknownKratosError } from "./errors" import { SchemaIdType } from "./schema" @@ -30,16 +25,12 @@ export const getKratosPostgres = () => connection: KRATOS_PG_CON, }) -export const toDomainSession = (session: KratosSession): Session => { - // is throw ok? this should not happen I (nb) believe but the type say it can - // this may probably be a type issue in kratos SDK - if (!session.identity) throw new InvalidIdentitySessionKratosError() - if (!session.expires_at) throw new MissingExpiredAtKratosError() - +export const toDomainSession = (session: KratosSession): MobileSession => { return { id: session.id as SessionId, - identity: toDomainIdentity(session.identity), - expiresAt: new Date(session?.expires_at), + identity: toDomainIdentity(session.identity as Identity), + expiresAt: new Date(session?.expires_at as string), + issuedAt: new Date(session?.issued_at as string), } } diff --git a/core/api/test/integration/app/user/consent-list.spec.ts b/core/api/test/integration/app/user/consent-list.spec.ts new file mode 100644 index 0000000000..0e9a04f873 --- /dev/null +++ b/core/api/test/integration/app/user/consent-list.spec.ts @@ -0,0 +1,110 @@ +import { consentList } from "@/services/hydra" +import axios from "axios" + +import { createUserAndWalletFromPhone, getUserIdByPhone, randomPhone } from "test/helpers" + +let userId: UserId +const phone = randomPhone() +// const phone = "+14152991378" as PhoneNumber + +const redirectUri = "http://localhost/callback" +const scope = "offline read write" +const grant_types = ["authorization_code", "refresh_token"] + +beforeAll(async () => { + await createUserAndWalletFromPhone(phone) + userId = await getUserIdByPhone(phone) +}) + +async function createOAuthClient() { + const hydraAdminUrl = "http://localhost:4445/admin/clients" + + try { + const response = await axios.post(hydraAdminUrl, { + client_name: "integration_test", + grant_types, + response_types: ["code", "id_token"], + redirect_uris: [redirectUri], + scope, + skip_consent: true, + }) + + const clientId = response.data.client_id + const clientSecret = response.data.client_secret + + return { clientId, clientSecret } + } catch (error) { + console.error("Error creating OAuth client:", error.response) + } +} + +async function performOAuthLogin({ + clientId, + clientSecret, +}: { + clientId: string + clientSecret: string +}) { + // create oauth2 client + + const responseType = "code" + const randomState = "MKfNw-q60talMJ4GU_h1kHFvcPtnQkZI0XLpTkHvJL4" + + const authUrl = `http://localhost:4444/oauth2/auth?response_type=${responseType}&client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&state=${randomState}` + + // https://oauth.blink.sv/oauth2/auth?client_id=73ae7c3e-e526-412a-856c-25d1ae0cbc55&scope=read%20write&response_type=code&redirect_uri=https%3A%2F%2Fdashboard.blink.sv%2Fapi%2Fauth%2Fcallback%2Fblink&state=MKfNw-q60talMJ4GU_h1kHFvcPtnQkZI0XLpTkHvJL4 + + // Simulate user going to the authorization URL and logging in + // This part would require a real user interaction or a browser automation tool like puppeteer + + let data + try { + const res = await axios.get(authUrl) + data = res.data + } catch (error) { + console.error("Error getting auth URL:", error) + return + } + + // You need to extract the code from the callback response + const code = data.code // Simplified: Actual extraction depends on your OAuth provider + + console.log("data", data) + console.log("code", code) + + try { + // Exchange the code for a token + const tokenResponse = await axios.post("http://localhost:4444/oauth2/token", { + code, + redirect_uri: redirectUri, + client_id: clientId, + client_secret: clientSecret, + grant_type: "authorization_code", + }) + + const accessToken = tokenResponse.data.access_token + + // Use the access token to get user info or other secured resources + // Update the consent list as needed + return accessToken // This might be used for further secured requests + } catch (error) { + console.error("Error exchanging code for token:", error) + } +} + +describe("Hydra", () => { + it("get an empty consent list", async () => { + const res = await consentList(userId) + expect(res).toEqual([]) + }) + + it("get consent list when the user had perform oauth2 login", async () => { + const res = await createOAuthClient() + if (!res) return + const { clientId, clientSecret } = res + console.log("clientId", clientId, "clientSecret", clientSecret) + + const accessToken = await performOAuthLogin({ clientId, clientSecret }) + console.log("accessToken", accessToken) + }) +}) diff --git a/dev/config/apollo-federation/supergraph.graphql b/dev/config/apollo-federation/supergraph.graphql index 8a31227676..35daf5baeb 100644 --- a/dev/config/apollo-federation/supergraph.graphql +++ b/dev/config/apollo-federation/supergraph.graphql @@ -1142,6 +1142,14 @@ type MerchantPayload scalar Minutes @join__type(graph: PUBLIC) +type MobileSession + @join__type(graph: PUBLIC) +{ + expiresAt: Timestamp! + id: ID! + issuedAt: Timestamp! +} + type MobileVersions @join__type(graph: PUBLIC) { @@ -2086,6 +2094,9 @@ type User """ language: Language! @join__field(graph: PUBLIC) + """List of mobile sessions""" + mobileSessions: [MobileSession!]! @join__field(graph: PUBLIC) + """Phone number with international calling code.""" phone: Phone @join__field(graph: PUBLIC) supportChat: [SupportMessage!]! @join__field(graph: PUBLIC) diff --git a/docs/hydra.md b/docs/hydra.md index f0657fc4bc..e2ba42b179 100644 --- a/docs/hydra.md +++ b/docs/hydra.md @@ -10,27 +10,15 @@ Make sure you have `hydra` command line installed brew install ory-hydra ``` -# run the experiment: +### list oauth2 client generated from tilt -Follow the instructions below +hydra list oauth2-clients -e http://localhost:4445 +## loading env from automatically created client: -On console 1: - -launch the hydra login consent node, which will provide the authentication (interactive with kratos API) and consent page. - -```sh -apps/consent % HYDRA_ADMIN_URL=http://localhost:4445 yarn start -``` - -On console 2: -```sh -galoy % make start -``` - -On console 3: -Follow the instructions below +. ./dev/.dashboard-hydra-client.env +TODO: dashboard should have consent: true automatically ## create a OAuth2 client @@ -41,8 +29,8 @@ The client is concourse in this example. For the galoy stack, some examples of clients could be Alby, a boltcard service, a nostr wallet connect service, an accountant that access the wallet in read only. - from :dashboard + ```sh . ./.env @@ -84,7 +72,6 @@ pnpm next note: skip consent should be true for trust client, ie: dashboard, but not for third party clients - to do a PKCE session: ```sh @@ -132,7 +119,6 @@ hydra introspect token \ OR - ```sh curl -X POST http://localhost:4445/admin/oauth2/introspect -d token=$ory_at_TOKEN @@ -177,7 +163,6 @@ but the response is not returning the scope in the jwt curl -s -I -X POST http://localhost:4456/decisions/graphql --user $client_id:$client_secret ``` - ## list OAuth 2.0 consent ```sh @@ -185,14 +170,13 @@ export subject="9818ea5e-30a8-4b52-879d-d34590e7250e" curl "http://localhost:4445/admin/oauth2/auth/sessions/consent?subject=$subject" ``` -login_session_id (optional): The login session id to list the consent sessions for. +login_session_id (optional): The login session id to list the consent sessions for. ## change client token lifespans https://www.ory.sh/docs/reference/api#tag/oAuth2/operation/setOAuth2ClientLifespans - ## delete token by session id export session_id="b3fc4e84-4f73-4229-acdd-9bbaba00ca60" @@ -201,10 +185,8 @@ curl -v -X DELETE "http://localhost:4445/admin/oauth2/auth/sessions/login?sid=$s export subject=9818ea5e-30a8-4b52-879d-d34590e7250e curl -v -X DELETE "http://localhost:4445/admin/oauth2/auth/sessions/login?subject=$subject" - # delete all -curl -v -X DELETE "http://localhost:4445/admin/oauth2/auth/sessions/consent?subject=$subject&client=$CLIENT_ID_APP_API_KEY" - +curl -v -X DELETE "http://localhost:4445/admin/oauth2/auth/sessions/consent?subject=$subject&client=$CLIENT_ID_APP_API_KEY" curl http://localhost:4445/admin/oauth2/auth/requests/logout From 8454854aeed7f42e33fb8bb5f8444fd4a23a421c Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Tue, 30 Apr 2024 14:50:19 -0600 Subject: [PATCH 2/6] chore: exposing consent list --- .../cypress/e2e/consent-integration.cy.ts | 16 - .../cypress/e2e/consent-integration.cy.ts | 16 - core/api/package.json | 2 + core/api/src/services/hydra/index.ts | 3 +- .../integration/app/user/consent-list.spec.ts | 161 +++--- dev/bin/setup-hydra-client.sh | 3 +- pnpm-lock.yaml | 462 +++++++++++++----- 7 files changed, 433 insertions(+), 230 deletions(-) diff --git a/apps/dashboard/cypress/e2e/consent-integration.cy.ts b/apps/dashboard/cypress/e2e/consent-integration.cy.ts index 1f16fb1b18..08e9d9b023 100644 --- a/apps/dashboard/cypress/e2e/consent-integration.cy.ts +++ b/apps/dashboard/cypress/e2e/consent-integration.cy.ts @@ -32,22 +32,6 @@ describe("Consent integration Test", () => { cy.get("[data-testid=verification_code_input]").should("not.be.disabled") cy.get("[data-testid=verification_code_input]").type(code) - cy.contains("label", "read").should("exist") - cy.contains("label", "read").should("be.visible") - cy.contains("label", "read").should("not.be.disabled") - cy.contains("label", "read").should("not.be.disabled") - cy.contains("label", "read").click() - - cy.contains("label", "write").should("exist") - cy.contains("label", "write").should("be.visible") - cy.contains("label", "write").should("not.be.disabled") - cy.contains("label", "write").click() - - cy.get("[data-testid=submit_consent_btn]").should("exist") - cy.get("[data-testid=submit_consent_btn]").should("be.visible") - cy.get("[data-testid=submit_consent_btn]").should("not.be.disabled") - cy.get("[data-testid=submit_consent_btn]").click() - cy.url().should("eq", Cypress.config().baseUrl + "/") cy.getCookie("next-auth.session-token").then((cookie) => { if (cookie && cookie.value) { diff --git a/apps/voucher/cypress/e2e/consent-integration.cy.ts b/apps/voucher/cypress/e2e/consent-integration.cy.ts index 1f16fb1b18..08e9d9b023 100644 --- a/apps/voucher/cypress/e2e/consent-integration.cy.ts +++ b/apps/voucher/cypress/e2e/consent-integration.cy.ts @@ -32,22 +32,6 @@ describe("Consent integration Test", () => { cy.get("[data-testid=verification_code_input]").should("not.be.disabled") cy.get("[data-testid=verification_code_input]").type(code) - cy.contains("label", "read").should("exist") - cy.contains("label", "read").should("be.visible") - cy.contains("label", "read").should("not.be.disabled") - cy.contains("label", "read").should("not.be.disabled") - cy.contains("label", "read").click() - - cy.contains("label", "write").should("exist") - cy.contains("label", "write").should("be.visible") - cy.contains("label", "write").should("not.be.disabled") - cy.contains("label", "write").click() - - cy.get("[data-testid=submit_consent_btn]").should("exist") - cy.get("[data-testid=submit_consent_btn]").should("be.visible") - cy.get("[data-testid=submit_consent_btn]").should("not.be.disabled") - cy.get("[data-testid=submit_consent_btn]").click() - cy.url().should("eq", Cypress.config().baseUrl + "/") cy.getCookie("next-auth.session-token").then((cookie) => { if (cookie && cookie.value) { diff --git a/core/api/package.json b/core/api/package.json index 9bcbb5ca03..42d1d150e3 100644 --- a/core/api/package.json +++ b/core/api/package.json @@ -161,6 +161,7 @@ "@typescript-eslint/parser": "^7.7.0", "@xascode/tscpaths": "0.1.4", "axios-mock-adapter": "^1.22.0", + "child_process": "^1.0.2", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", @@ -182,6 +183,7 @@ "pino-pretty": "^10.3.1", "prettier": "^3.2.5", "protoc-gen-js": "^3.21.2", + "puppeteer": "^22.7.1", "react": "^18.2.0", "spectaql": "^2.3.1", "tiny-secp256k1": "^2.2.3", diff --git a/core/api/src/services/hydra/index.ts b/core/api/src/services/hydra/index.ts index e06108cab9..cef1a89daf 100644 --- a/core/api/src/services/hydra/index.ts +++ b/core/api/src/services/hydra/index.ts @@ -18,7 +18,8 @@ export const consentList = async (userId: UserId): Promise => let sessions: ConsentSession[] try { - console.dir(res.data, { depth: null }) + /* eslint @typescript-eslint/ban-ts-comment: "off" */ + // @ts-ignore-next-line no-implicit-any error sessions = res.data.map((request) => ({ scope: request.grant_scope, handledAt: new Date(request.handled_at), diff --git a/core/api/test/integration/app/user/consent-list.spec.ts b/core/api/test/integration/app/user/consent-list.spec.ts index 0e9a04f873..a6bbe5b83c 100644 --- a/core/api/test/integration/app/user/consent-list.spec.ts +++ b/core/api/test/integration/app/user/consent-list.spec.ts @@ -1,95 +1,82 @@ +import { Admin } from "@/app" import { consentList } from "@/services/hydra" -import axios from "axios" - -import { createUserAndWalletFromPhone, getUserIdByPhone, randomPhone } from "test/helpers" +import { sleep } from "@/utils" +import { exec } from "child_process" +import puppeteer from "puppeteer" let userId: UserId -const phone = randomPhone() -// const phone = "+14152991378" as PhoneNumber - -const redirectUri = "http://localhost/callback" -const scope = "offline read write" -const grant_types = ["authorization_code", "refresh_token"] +const email = "test@galoy.io" as EmailAddress beforeAll(async () => { - await createUserAndWalletFromPhone(phone) - userId = await getUserIdByPhone(phone) + const account = await Admin.getAccountByUserEmail(email) + if (account instanceof Error) throw account + + userId = account.kratosUserId }) -async function createOAuthClient() { - const hydraAdminUrl = "http://localhost:4445/admin/clients" - - try { - const response = await axios.post(hydraAdminUrl, { - client_name: "integration_test", - grant_types, - response_types: ["code", "id_token"], - redirect_uris: [redirectUri], - scope, - skip_consent: true, +const getOTP = (email: string): Promise => { + return new Promise((resolve, reject) => { + const query = `docker exec -i galoy-dev-kratos-pg-1 psql -U dbuser -d default -t -c "SELECT body FROM courier_messages WHERE recipient='${email}' ORDER BY created_at DESC LIMIT 1;"` + exec(query, (error, stdout, stderr) => { + if (error) { + reject(`error: ${error.message}`) + return + } + if (stderr) { + reject(`stderr: ${stderr}`) + return + } + const otpMatch = stdout.match(/(\d{6})/) + if (otpMatch && otpMatch[1]) { + resolve(otpMatch[1]) + } else { + reject("OTP not found in the message") + } }) + }) +} - const clientId = response.data.client_id - const clientSecret = response.data.client_secret +async function performOAuthLogin() { + const screenshots = false - return { clientId, clientSecret } - } catch (error) { - console.error("Error creating OAuth client:", error.response) - } -} + const browser = await puppeteer.launch() + // const browser = await puppeteer.launch({ headless: true }) + const page = await browser.newPage() -async function performOAuthLogin({ - clientId, - clientSecret, -}: { - clientId: string - clientSecret: string -}) { - // create oauth2 client - - const responseType = "code" - const randomState = "MKfNw-q60talMJ4GU_h1kHFvcPtnQkZI0XLpTkHvJL4" - - const authUrl = `http://localhost:4444/oauth2/auth?response_type=${responseType}&client_id=${clientId}&redirect_uri=${encodeURIComponent(redirectUri)}&scope=${encodeURIComponent(scope)}&state=${randomState}` - - // https://oauth.blink.sv/oauth2/auth?client_id=73ae7c3e-e526-412a-856c-25d1ae0cbc55&scope=read%20write&response_type=code&redirect_uri=https%3A%2F%2Fdashboard.blink.sv%2Fapi%2Fauth%2Fcallback%2Fblink&state=MKfNw-q60talMJ4GU_h1kHFvcPtnQkZI0XLpTkHvJL4 - - // Simulate user going to the authorization URL and logging in - // This part would require a real user interaction or a browser automation tool like puppeteer - - let data - try { - const res = await axios.get(authUrl) - data = res.data - } catch (error) { - console.error("Error getting auth URL:", error) - return - } - - // You need to extract the code from the callback response - const code = data.code // Simplified: Actual extraction depends on your OAuth provider - - console.log("data", data) - console.log("code", code) - - try { - // Exchange the code for a token - const tokenResponse = await axios.post("http://localhost:4444/oauth2/token", { - code, - redirect_uri: redirectUri, - client_id: clientId, - client_secret: clientSecret, - grant_type: "authorization_code", - }) + // Navigate the page to a URL + await page.goto("http://localhost:3001/api/auth/signin") + + screenshots && (await page.screenshot({ path: "screenshot0.png" })) - const accessToken = tokenResponse.data.access_token + await page.waitForSelector(".button") + await page.click(".button") - // Use the access token to get user info or other secured resources - // Update the consent list as needed - return accessToken // This might be used for further secured requests - } catch (error) { - console.error("Error exchanging code for token:", error) - } + screenshots && (await page.screenshot({ path: "screenshot1.png" })) + + await page.waitForSelector('[data-testid="email_id_input"]') + await page.waitForFunction( + "document.querySelector(\"[data-testid='email_id_input']\").isConnected", + ) + await page.type('[data-testid="email_id_input"]', email) + screenshots && (await page.screenshot({ path: "screenshot2.png" })) + await sleep(250) + + await page.click("#accept") + + await sleep(500) + screenshots && (await page.screenshot({ path: "screenshot3.png" })) + + const otp = await getOTP(email) + + await page.waitForSelector("#code") + await page.type("#code", otp, { delay: 100 }) + + screenshots && (await page.screenshot({ path: "screenshot4.png" })) + await sleep(1500) + screenshots && (await page.screenshot({ path: "screenshot5.png" })) + + await page.close() + await browser.close() } describe("Hydra", () => { @@ -99,12 +86,16 @@ describe("Hydra", () => { }) it("get consent list when the user had perform oauth2 login", async () => { - const res = await createOAuthClient() - if (!res) return - const { clientId, clientSecret } = res - console.log("clientId", clientId, "clientSecret", clientSecret) + await performOAuthLogin() - const accessToken = await performOAuthLogin({ clientId, clientSecret }) - console.log("accessToken", accessToken) + const res = await consentList(userId) + expect(res).toEqual([ + { + app: "dashboard", + handledAt: expect.any(Date), + remember: false, + scope: ["read", "write"], + }, + ]) }) }) diff --git a/dev/bin/setup-hydra-client.sh b/dev/bin/setup-hydra-client.sh index c650c6bd9f..ecf77ffa24 100755 --- a/dev/bin/setup-hydra-client.sh +++ b/dev/bin/setup-hydra-client.sh @@ -21,7 +21,8 @@ hydra_cli create client \ --format json \ --scope read --scope write \ --redirect-uri "$redirect_uri" > "${HYDRA_CLIENT_JSON}" \ - --name "${hydra_client_name}" + --name "${hydra_client_name}" \ + --skip-consent CLIENT_ID=$(jq -r '.client_id' < "${HYDRA_CLIENT_JSON}") CLIENT_SECRET=$(jq -r '.client_secret' < "${HYDRA_CLIENT_JSON}") diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index ac7ee703f1..2f8c3a6b36 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1408,6 +1408,9 @@ importers: axios-mock-adapter: specifier: ^1.22.0 version: 1.22.0(axios@1.6.8) + child_process: + specifier: ^1.0.2 + version: 1.0.2 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -1471,6 +1474,9 @@ importers: protoc-gen-js: specifier: ^3.21.2 version: 3.21.2 + puppeteer: + specifier: ^22.7.1 + version: 22.7.1(typescript@5.4.5) react: specifier: ^18.2.0 version: 18.2.0 @@ -2895,7 +2901,7 @@ packages: '@babel/traverse': 7.24.0 '@babel/types': 7.24.0 convert-source-map: 1.9.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -2918,7 +2924,7 @@ packages: '@babel/traverse': 7.23.5 '@babel/types': 7.23.5 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -2941,7 +2947,7 @@ packages: '@babel/traverse': 7.24.0 '@babel/types': 7.24.0 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -2963,7 +2969,7 @@ packages: '@babel/traverse': 7.24.1 '@babel/types': 7.24.0 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -3161,7 +3167,7 @@ packages: '@babel/core': 7.23.5 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-plugin-utils': 7.24.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -3176,7 +3182,7 @@ packages: '@babel/core': 7.24.4 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-plugin-utils': 7.24.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -3191,7 +3197,7 @@ packages: '@babel/core': 7.24.0 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-plugin-utils': 7.24.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -3206,7 +3212,7 @@ packages: '@babel/core': 7.24.4 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-plugin-utils': 7.24.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -3221,7 +3227,7 @@ packages: '@babel/core': 7.24.4 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-plugin-utils': 7.24.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -6938,7 +6944,7 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.24.0 '@babel/types': 7.24.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -6956,7 +6962,7 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.24.4 '@babel/types': 7.24.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -6973,7 +6979,7 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.24.4 '@babel/types': 7.24.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -7711,7 +7717,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -7728,7 +7734,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -9763,7 +9769,7 @@ packages: '@types/json-stable-stringify': 1.0.34 '@whatwg-node/fetch': 0.8.8 chalk: 4.1.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) dotenv: 16.4.5 graphql: 16.8.1 graphql-request: 6.1.0(graphql@16.8.1) @@ -9796,7 +9802,7 @@ packages: '@types/json-stable-stringify': 1.0.36 '@whatwg-node/fetch': 0.9.17 chalk: 4.1.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) dotenv: 16.4.5 graphql: 16.8.1 graphql-request: 6.1.0(graphql@16.8.1) @@ -9829,7 +9835,7 @@ packages: '@types/json-stable-stringify': 1.0.36 '@whatwg-node/fetch': 0.9.17 chalk: 4.1.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) dotenv: 16.4.5 graphql: 16.8.1 graphql-request: 6.1.0(graphql@16.8.1) @@ -10221,7 +10227,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 2.0.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -10232,7 +10238,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -12276,6 +12282,23 @@ packages: resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} dev: false + /@puppeteer/browsers@2.2.3: + resolution: {integrity: sha512-bJ0UBsk0ESOs6RFcLXOt99a3yTDcOKlzfjad+rhFwdaG1Lu/Wzq58GHYCDTlZ9z6mldf4g+NTb+TXEfe0PpnsQ==} + engines: {node: '>=18'} + hasBin: true + dependencies: + debug: 4.3.4(supports-color@8.1.1) + extract-zip: 2.0.1(supports-color@8.1.1) + progress: 2.0.3 + proxy-agent: 6.4.0 + semver: 7.6.0 + tar-fs: 3.0.5 + unbzip2-stream: 1.4.3 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: true + /@radix-ui/number@1.0.1: resolution: {integrity: sha512-T5gIdVO2mmPW3NNhjNgEP3cqMXjXL9UbO0BzWcXfvdBs+BohbQxvd/K5hSVKmn9/lbTdsQVKbUcP5WLCwvUbBg==} dependencies: @@ -15133,7 +15156,7 @@ packages: typescript: '>= 4.x' webpack: '>= 4' dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) endent: 2.1.0 find-cache-dir: 3.3.2 flat-cache: 3.2.0 @@ -15961,6 +15984,10 @@ packages: engines: {node: '>= 10'} requiresBuild: true + /@tootallnate/quickjs-emscripten@0.23.0: + resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} + dev: true + /@trysound/sax@0.2.0: resolution: {integrity: sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==} engines: {node: '>=10.13.0'} @@ -16795,7 +16822,7 @@ packages: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@8.54.0)(typescript@5.2.2) '@typescript-eslint/utils': 5.62.0(eslint@8.54.0)(typescript@5.2.2) - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.54.0 graphemer: 1.4.0 ignore: 5.3.0 @@ -16823,7 +16850,7 @@ packages: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/type-utils': 5.62.0(eslint@8.54.0)(typescript@5.2.2) '@typescript-eslint/utils': 5.62.0(eslint@8.54.0)(typescript@5.2.2) - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.54.0 graphemer: 1.4.0 ignore: 5.3.0 @@ -16852,7 +16879,7 @@ packages: '@typescript-eslint/type-utils': 7.1.1(eslint@8.57.0)(typescript@5.3.3) '@typescript-eslint/utils': 7.1.1(eslint@8.57.0)(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.1.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -16881,7 +16908,7 @@ packages: '@typescript-eslint/type-utils': 7.1.1(eslint@8.57.0)(typescript@5.2.2) '@typescript-eslint/utils': 7.1.1(eslint@8.57.0)(typescript@5.2.2) '@typescript-eslint/visitor-keys': 7.1.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -16910,7 +16937,7 @@ packages: '@typescript-eslint/type-utils': 7.7.0(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/utils': 7.7.0(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/visitor-keys': 7.7.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -16948,7 +16975,7 @@ packages: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.4.5) - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.40.0 typescript: 5.4.5 transitivePeerDependencies: @@ -16968,7 +16995,7 @@ packages: '@typescript-eslint/scope-manager': 5.62.0 '@typescript-eslint/types': 5.62.0 '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.2.2) - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.54.0 typescript: 5.2.2 transitivePeerDependencies: @@ -16989,7 +17016,7 @@ packages: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.2.2) '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.54.0 typescript: 5.2.2 transitivePeerDependencies: @@ -17010,7 +17037,7 @@ packages: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.2.2) '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 typescript: 5.2.2 transitivePeerDependencies: @@ -17031,7 +17058,7 @@ packages: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/typescript-estree': 6.21.0(typescript@5.3.3) '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 typescript: 5.3.3 transitivePeerDependencies: @@ -17052,7 +17079,7 @@ packages: '@typescript-eslint/types': 7.0.2 '@typescript-eslint/typescript-estree': 7.0.2(typescript@5.2.2) '@typescript-eslint/visitor-keys': 7.0.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.54.0 typescript: 5.2.2 transitivePeerDependencies: @@ -17073,7 +17100,7 @@ packages: '@typescript-eslint/types': 7.1.1 '@typescript-eslint/typescript-estree': 7.1.1(typescript@5.3.3) '@typescript-eslint/visitor-keys': 7.1.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 typescript: 5.3.3 transitivePeerDependencies: @@ -17094,7 +17121,7 @@ packages: '@typescript-eslint/types': 7.7.0 '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.4.5) '@typescript-eslint/visitor-keys': 7.7.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 typescript: 5.4.5 transitivePeerDependencies: @@ -17115,7 +17142,7 @@ packages: '@typescript-eslint/types': 7.7.1 '@typescript-eslint/typescript-estree': 7.7.1(typescript@5.2.2) '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 typescript: 5.2.2 transitivePeerDependencies: @@ -17181,7 +17208,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 5.62.0(typescript@5.2.2) '@typescript-eslint/utils': 5.62.0(eslint@8.54.0)(typescript@5.2.2) - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.54.0 tsutils: 3.21.0(typescript@5.2.2) typescript: 5.2.2 @@ -17201,7 +17228,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 7.1.1(typescript@5.2.2) '@typescript-eslint/utils': 7.1.1(eslint@8.57.0)(typescript@5.2.2) - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 ts-api-utils: 1.2.1(typescript@5.2.2) typescript: 5.2.2 @@ -17221,7 +17248,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 7.1.1(typescript@5.3.3) '@typescript-eslint/utils': 7.1.1(eslint@8.57.0)(typescript@5.3.3) - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 ts-api-utils: 1.2.1(typescript@5.3.3) typescript: 5.3.3 @@ -17241,7 +17268,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.4.5) '@typescript-eslint/utils': 7.7.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) typescript: 5.4.5 @@ -17294,7 +17321,7 @@ packages: dependencies: '@typescript-eslint/types': 4.33.0 '@typescript-eslint/visitor-keys': 4.33.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 @@ -17315,7 +17342,7 @@ packages: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 @@ -17336,7 +17363,7 @@ packages: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 @@ -17357,7 +17384,7 @@ packages: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 @@ -17378,7 +17405,7 @@ packages: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -17400,7 +17427,7 @@ packages: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -17422,7 +17449,7 @@ packages: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -17444,7 +17471,7 @@ packages: dependencies: '@typescript-eslint/types': 7.0.2 '@typescript-eslint/visitor-keys': 7.0.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -17466,7 +17493,7 @@ packages: dependencies: '@typescript-eslint/types': 7.1.1 '@typescript-eslint/visitor-keys': 7.1.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -17488,7 +17515,7 @@ packages: dependencies: '@typescript-eslint/types': 7.1.1 '@typescript-eslint/visitor-keys': 7.1.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -17510,7 +17537,7 @@ packages: dependencies: '@typescript-eslint/types': 7.7.0 '@typescript-eslint/visitor-keys': 7.7.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 @@ -17532,7 +17559,7 @@ packages: dependencies: '@typescript-eslint/types': 7.7.1 '@typescript-eslint/visitor-keys': 7.7.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 @@ -18258,7 +18285,7 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -18266,9 +18293,18 @@ packages: resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} engines: {node: '>= 14'} dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) + transitivePeerDependencies: + - supports-color + + /agent-base@7.1.1: + resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} + engines: {node: '>= 14'} + dependencies: + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color + dev: true /agentkeepalive@4.5.0: resolution: {integrity: sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==} @@ -18655,6 +18691,13 @@ packages: /ast-types-flow@0.0.8: resolution: {integrity: sha512-OH/2E5Fg20h2aPrbe+QL8JZQFko0YZaF+j4mnQ7BGhfavO7OpSLa8a0y9sBwomHdSbkhTS8TQNayBfnW5DwbvQ==} + /ast-types@0.13.4: + resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} + engines: {node: '>=4'} + dependencies: + tslib: 2.6.2 + dev: true + /ast-types@0.16.1: resolution: {integrity: sha512-6t10qk83GOG8p0vKmaCr8eiilZwO171AvbROMtvvNiwrTly62t+7XkA8RdIIVbpMhCASAsxgAzdRSwh6nw/5Dg==} engines: {node: '>=4'} @@ -18835,7 +18878,6 @@ packages: /b4a@1.6.4: resolution: {integrity: sha512-fpWrvyVHEKyeEvbKZTVOeZF3VSKKWtJxFIxX/jaVPf+cLbGUSitjb49pHLqPV2BUNNZ0LcoeEGfE/YCpyDYHIw==} - dev: false /babel-core@7.0.0-bridge.0(@babel/core@7.24.4): resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} @@ -19163,6 +19205,44 @@ packages: /balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + /bare-events@2.2.2: + resolution: {integrity: sha512-h7z00dWdG0PYOQEvChhOSWvOfkIKsdZGkWr083FgN/HyoQuebSew/cgirYqh9SCuy/hRvxc5Vy6Fw8xAmYHLkQ==} + requiresBuild: true + dev: true + optional: true + + /bare-fs@2.3.0: + resolution: {integrity: sha512-TNFqa1B4N99pds2a5NYHR15o0ZpdNKbAeKTE/+G6ED/UeOavv8RY3dr/Fu99HW3zU3pXpo2kDNO8Sjsm2esfOw==} + requiresBuild: true + dependencies: + bare-events: 2.2.2 + bare-path: 2.1.2 + bare-stream: 1.0.0 + dev: true + optional: true + + /bare-os@2.3.0: + resolution: {integrity: sha512-oPb8oMM1xZbhRQBngTgpcQ5gXw6kjOaRsSWsIeNyRxGed2w/ARyP7ScBYpWR1qfX2E5rS3gBw6OWcSQo+s+kUg==} + requiresBuild: true + dev: true + optional: true + + /bare-path@2.1.2: + resolution: {integrity: sha512-o7KSt4prEphWUHa3QUwCxUI00R86VdjiuxmJK0iNVDHYPGo+HsDaVCnqCmPbf/MiW1ok8F4p3m8RTHlWk8K2ig==} + requiresBuild: true + dependencies: + bare-os: 2.3.0 + dev: true + optional: true + + /bare-stream@1.0.0: + resolution: {integrity: sha512-KhNUoDL40iP4gFaLSsoGE479t0jHijfYdIcxRn/XtezA2BaUD0NRf/JGRpsMq6dMNM+SrCrB0YSSo/5wBY4rOQ==} + requiresBuild: true + dependencies: + streamx: 2.16.1 + dev: true + optional: true + /base-x@3.0.9: resolution: {integrity: sha512-H7JU6iBHTal1gp56aKoaa//YUxEaAOUiydvrV/pILqIHXTtqxSkATOnDA2u+jZ/61sD+L/412+7kzXRtWukhpQ==} dependencies: @@ -19192,6 +19272,11 @@ packages: dependencies: safe-buffer: 5.1.2 + /basic-ftp@5.0.5: + resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} + engines: {node: '>=10.0.0'} + dev: true + /batch@0.6.1: resolution: {integrity: sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==} dev: true @@ -19859,6 +19944,10 @@ packages: parse5-htmlparser2-tree-adapter: 7.0.0 dev: true + /child_process@1.0.2: + resolution: {integrity: sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==} + dev: true + /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -19910,7 +19999,7 @@ packages: '@testim/chrome-version': 1.1.4 axios: 1.6.8 compare-versions: 6.1.0 - extract-zip: 2.0.1 + extract-zip: 2.0.1(supports-color@8.1.1) https-proxy-agent: 5.0.1 proxy-from-env: 1.1.0 tcp-port-used: 1.0.2 @@ -19919,6 +20008,17 @@ packages: - supports-color dev: true + /chromium-bidi@0.5.19(devtools-protocol@0.0.1273771): + resolution: {integrity: sha512-UA6zL77b7RYCjJkZBsZ0wlvCTD+jTjllZ8f6wdO4buevXgTZYjV+XLB9CiEa2OuuTGGTLnI7eN9I60YxuALGQg==} + peerDependencies: + devtools-protocol: '*' + dependencies: + devtools-protocol: 0.0.1273771 + mitt: 3.0.1 + urlpattern-polyfill: 10.0.0 + zod: 3.22.4 + dev: true + /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -20453,6 +20553,22 @@ packages: typescript: 5.4.5 dev: true + /cosmiconfig@9.0.0(typescript@5.4.5): + resolution: {integrity: sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==} + engines: {node: '>=14'} + peerDependencies: + typescript: '>=4.9.5' + peerDependenciesMeta: + typescript: + optional: true + dependencies: + env-paths: 2.2.1 + import-fresh: 3.3.0 + js-yaml: 4.1.0 + parse-json: 5.2.0 + typescript: 5.4.5 + dev: true + /country-flag-icons@1.5.7: resolution: {integrity: sha512-AdvXhMcmSp7nBSkpGfW4qR/luAdRUutJqya9PuwRbsBzuoknThfultbv7Ib6fWsHXC43Es/4QJ8gzQQdBNm75A==} dev: false @@ -20856,6 +20972,11 @@ packages: assert-plus: 1.0.0 dev: true + /data-uri-to-buffer@6.0.2: + resolution: {integrity: sha512-7hvf7/GW8e86rW0ptuwS3OcBGDjIi6SZva7hCyWC0yYry2cOPmLIjXAUHI6DK2HsnwJd9ifmt57i8eV2n4YNpw==} + engines: {node: '>= 14'} + dev: true + /data-urls@3.0.2: resolution: {integrity: sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==} engines: {node: '>=12'} @@ -20938,6 +21059,7 @@ packages: dependencies: ms: 2.1.2 supports-color: 5.5.0 + dev: true /debug@4.3.4(supports-color@8.1.1): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} @@ -20950,7 +21072,6 @@ packages: dependencies: ms: 2.1.2 supports-color: 8.1.1 - dev: true /decamelize@1.2.0: resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} @@ -21126,6 +21247,15 @@ packages: resolution: {integrity: sha512-Vy2wmG3NTkmHNg/kzpuvHhkqeIx3ODWqasgCRbKtbXEN0G+HpEEv9BtJLp7ZG1CZloFaC41Ah3ZFbq7aqCqMeQ==} dev: true + /degenerator@5.0.1: + resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} + engines: {node: '>= 14'} + dependencies: + ast-types: 0.13.4 + escodegen: 2.1.0 + esprima: 4.0.1 + dev: true + /del@6.1.1: resolution: {integrity: sha512-ua8BhapfP0JUJKC/zV9yHHDW/rDoDxP4Zhn3AkA6/xT6gY7jYXJiaeyBZznYVujhZZET+UgcbZiQ7sN3WqcImg==} engines: {node: '>=10'} @@ -21173,7 +21303,7 @@ packages: hasBin: true dependencies: commander: 2.20.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) filing-cabinet: 3.3.1 precinct: 9.2.1 typescript: 4.9.5 @@ -21245,7 +21375,7 @@ packages: hasBin: true dependencies: address: 1.2.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -21306,7 +21436,7 @@ packages: resolution: {integrity: sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==} engines: {node: '>= 6.0'} dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) gonzales-pe: 4.3.0 node-source-walk: 4.3.0 transitivePeerDependencies: @@ -21317,7 +21447,7 @@ packages: resolution: {integrity: sha512-Fwc/g9VcrowODIAeKRWZfVA/EufxYL7XfuqJQFroBKGikKX83d2G7NFw6kDlSYGG3LNQIyVa+eWv1mqre+v4+A==} engines: {node: ^10 || ^12 || >=14} dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) is-url: 1.2.4 postcss: 8.4.35 postcss-values-parser: 2.0.1 @@ -21404,6 +21534,10 @@ packages: - supports-color dev: true + /devtools-protocol@0.0.1273771: + resolution: {integrity: sha512-QDbb27xcTVReQQW/GHJsdQqGKwYBE7re7gxehj467kKP2DKuYBUj6i2k5LRiAC66J1yZG/9gsxooz/s9pcm0Og==} + dev: true + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} @@ -21719,6 +21853,11 @@ packages: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} + /env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + dev: true + /envinfo@7.11.0: resolution: {integrity: sha512-G9/6xF1FPbIw0TtalAMaVPpiq2aDEuKLXM314jPVAO9r2fo2a4BLqMNkmRS7O/xPPZ+COAhGIz3ETvHEV3eUcg==} engines: {node: '>=4'} @@ -21952,7 +22091,7 @@ packages: peerDependencies: esbuild: '>=0.12 <1' dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) esbuild: 0.18.20 transitivePeerDependencies: - supports-color @@ -22211,7 +22350,7 @@ packages: eslint: '*' eslint-plugin-import: '*' dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) enhanced-resolve: 5.15.0 eslint: 8.40.0 eslint-module-utils: 2.8.0(@typescript-eslint/parser@5.62.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.40.0) @@ -22234,7 +22373,7 @@ packages: eslint: '*' eslint-plugin-import: '*' dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) enhanced-resolve: 5.15.0 eslint: 8.54.0 eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.54.0) @@ -22257,7 +22396,7 @@ packages: eslint: '*' eslint-plugin-import: '*' dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) enhanced-resolve: 5.15.0 eslint: 8.57.0 eslint-module-utils: 2.8.0(@typescript-eslint/parser@6.21.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.1)(eslint@8.57.0) @@ -23150,7 +23289,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -23200,7 +23339,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -23247,7 +23386,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -23538,20 +23677,6 @@ packages: - supports-color dev: true - /extract-zip@2.0.1: - resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} - engines: {node: '>= 10.17.0'} - hasBin: true - dependencies: - debug: 4.3.4(supports-color@5.5.0) - get-stream: 5.2.0 - yauzl: 2.10.0 - optionalDependencies: - '@types/yauzl': 2.10.3 - transitivePeerDependencies: - - supports-color - dev: true - /extract-zip@2.0.1(supports-color@8.1.1): resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -23597,7 +23722,6 @@ packages: /fast-fifo@1.3.2: resolution: {integrity: sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==} - dev: false /fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} @@ -23801,7 +23925,7 @@ packages: dependencies: app-module-path: 2.2.0 commander: 2.20.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) enhanced-resolve: 5.15.0 is-relative-path: 1.0.2 module-definition: 3.4.0 @@ -24404,6 +24528,18 @@ packages: dependencies: resolve-pkg-maps: 1.0.0 + /get-uri@6.0.3: + resolution: {integrity: sha512-BzUrJBS9EcUb4cFol8r4W3v1cPsSyajLSthNkz5BxbpDcHN5tIrM10E2eNvfnvBn3DaT3DUgx0OpsBKkaOpanw==} + engines: {node: '>= 14'} + dependencies: + basic-ftp: 5.0.5 + data-uri-to-buffer: 6.0.2 + debug: 4.3.4(supports-color@8.1.1) + fs-extra: 11.2.0 + transitivePeerDependencies: + - supports-color + dev: true + /getobject@1.0.2: resolution: {integrity: sha512-2zblDBaFcb3rB4rF77XVnuINOE2h2k/OnqXAiy0IrTxUfV1iFp3la33oAQVY9pCpWU268WFYVt2t71hlMuLsOg==} engines: {node: '>=10'} @@ -25496,7 +25632,7 @@ packages: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -25505,7 +25641,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -25515,7 +25651,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -25572,7 +25708,7 @@ packages: engines: {node: '>= 6.0.0'} dependencies: agent-base: 5.1.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -25582,7 +25718,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -25591,7 +25727,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -25601,7 +25737,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color @@ -25844,7 +25980,7 @@ packages: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -25861,7 +25997,6 @@ packages: dependencies: jsbn: 1.1.0 sprintf-js: 1.1.3 - dev: false /ip-regex@4.3.0: resolution: {integrity: sha512-B9ZWJxHHOHUhUjCPrMpLD4xEq35bUTClHM1S6CBU5ixQnkZmwipwgc96vAd7AAGM9TGHvJR+Uss+/Ak6UphK+Q==} @@ -26347,7 +26482,7 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) istanbul-lib-coverage: 3.2.0 source-map: 0.6.1 transitivePeerDependencies: @@ -27094,7 +27229,6 @@ packages: /jsbn@1.1.0: resolution: {integrity: sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==} - dev: false /jscodeshift@0.15.1(@babel/preset-env@7.24.4): resolution: {integrity: sha512-hIJfxUy8Rt4HkJn/zZPU9ChKfKZM1342waJ1QC2e2YsPcWhM+3BJ4dcfQCzArTrk1jJeNLB341H+qOcEHRxJZg==} @@ -27330,7 +27464,7 @@ packages: dependencies: '@types/express': 4.17.21 '@types/jsonwebtoken': 9.0.6 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) jose: 4.15.2 limiter: 1.1.5 lru-memoizer: 2.2.0 @@ -27417,7 +27551,7 @@ packages: dependencies: colorette: 2.0.19 commander: 10.0.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) escalade: 3.1.1 esm: 3.2.25 get-package-type: 0.1.0 @@ -27697,7 +27831,7 @@ packages: bignumber.js: 9.1.2 bolt11: 1.4.1 commander: 12.0.0 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) express: 4.19.2 lightning-backends: 1.6.3 lnurl-offline: 1.2.0 @@ -27960,7 +28094,6 @@ packages: /lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} - dev: false /lru-memoizer@2.2.0: resolution: {integrity: sha512-QfOZ6jNkxCcM/BkIPnFsqDhtrazLRsghi9mBwFAzol5GCvj4EkFT899Za3+QwikCg5sRX8JstioBDwOxEyzaNw==} @@ -27995,7 +28128,7 @@ packages: chalk: 4.1.2 commander: 7.2.0 commondir: 1.0.1 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) dependency-tree: 9.0.0 detective-amd: 4.2.0 detective-cjs: 4.1.0 @@ -28397,6 +28530,10 @@ packages: yallist: 4.0.0 dev: true + /mitt@3.0.1: + resolution: {integrity: sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==} + dev: true + /mkdirp-classic@0.5.3: resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} @@ -28441,7 +28578,7 @@ packages: hasBin: true dependencies: commander: 2.20.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) glob: 7.2.3 requirejs: 2.3.6 requirejs-config-file: 4.0.0 @@ -28569,7 +28706,7 @@ packages: resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==} engines: {node: '>=14.0.0'} dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: false @@ -28651,6 +28788,11 @@ packages: /neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + /netmask@2.0.2: + resolution: {integrity: sha512-dBpDMdxv9Irdq66304OLfEmQ9tbNRFnFTuZiLo+bD+r332bBmMJ8GBLXklIXXgxd3+v9+KUnZaUR5PJMa75Gsg==} + engines: {node: '>= 0.4.0'} + dev: true + /next-auth@4.24.5(next@14.0.4)(react-dom@18.2.0)(react@18.2.0): resolution: {integrity: sha512-3RafV3XbfIKk6rF6GlLE4/KxjTcuMCifqrmD+98ejFq73SRoj2rmzoca8u764977lH/Q7jo6Xu6yM+Re1Mz/Og==} peerDependencies: @@ -29459,6 +29601,30 @@ packages: engines: {node: '>=6'} dev: true + /pac-proxy-agent@7.0.1: + resolution: {integrity: sha512-ASV8yU4LLKBAjqIPMbrgtaKIvxQri/yh2OpI+S6hVa9JRkUI3Y3NPFbfngDtY7oFtSMD3w31Xns89mDa3Feo5A==} + engines: {node: '>= 14'} + dependencies: + '@tootallnate/quickjs-emscripten': 0.23.0 + agent-base: 7.1.0 + debug: 4.3.4(supports-color@8.1.1) + get-uri: 6.0.3 + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + pac-resolver: 7.0.1 + socks-proxy-agent: 8.0.3 + transitivePeerDependencies: + - supports-color + dev: true + + /pac-resolver@7.0.1: + resolution: {integrity: sha512-5NPgf87AT2STgwa2ntRMr45jTKrYBGkVU36yT0ig/n/GMAa3oPqhZfIQ2kMEimReg0+t9kZViDVZ83qfVUlckg==} + engines: {node: '>= 14'} + dependencies: + degenerator: 5.0.1 + netmask: 2.0.2 + dev: true + /pako@0.2.9: resolution: {integrity: sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==} dev: true @@ -30241,7 +30407,7 @@ packages: hasBin: true dependencies: commander: 2.20.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) detective-amd: 3.1.2 detective-cjs: 3.1.3 detective-es6: 2.2.2 @@ -30466,6 +30632,22 @@ packages: forwarded: 0.2.0 ipaddr.js: 1.9.1 + /proxy-agent@6.4.0: + resolution: {integrity: sha512-u0piLU+nCOHMgGjRbimiXmA9kM/L9EHh3zL81xCdp7m+Y2pHIsnmbdDoEDoAz5geaonNR6q6+yOPQs6n4T6sBQ==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.0 + debug: 4.3.4(supports-color@8.1.1) + http-proxy-agent: 7.0.2 + https-proxy-agent: 7.0.4 + lru-cache: 7.18.3 + pac-proxy-agent: 7.0.1 + proxy-from-env: 1.1.0 + socks-proxy-agent: 8.0.3 + transitivePeerDependencies: + - supports-color + dev: true + /proxy-from-env@1.0.0: resolution: {integrity: sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==} dev: true @@ -30536,7 +30718,7 @@ packages: engines: {node: '>=8.16.0'} dependencies: '@types/mime-types': 2.1.4 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) extract-zip: 1.7.0 https-proxy-agent: 4.0.0 mime: 2.6.0 @@ -30551,6 +30733,38 @@ packages: - utf-8-validate dev: true + /puppeteer-core@22.7.1: + resolution: {integrity: sha512-jD7T7yN7PWGuJmNT0TAEboA26s0VVnvbgCxqgQIF+eNQW2u71ENaV2JwzSJiCHO+e72H4Ue6AgKD9USQ8xAcOQ==} + engines: {node: '>=18'} + dependencies: + '@puppeteer/browsers': 2.2.3 + chromium-bidi: 0.5.19(devtools-protocol@0.0.1273771) + debug: 4.3.4(supports-color@8.1.1) + devtools-protocol: 0.0.1273771 + ws: 8.16.0 + transitivePeerDependencies: + - bufferutil + - supports-color + - utf-8-validate + dev: true + + /puppeteer@22.7.1(typescript@5.4.5): + resolution: {integrity: sha512-JBCBCwQ9+dyPp5haqeecgv0N0vgWFx44woUeKJaPeJT8CU3RXrd8F/tqJQbuAmcWlbMhYJSlTJkIFrwVAs6BNA==} + engines: {node: '>=18'} + hasBin: true + requiresBuild: true + dependencies: + '@puppeteer/browsers': 2.2.3 + cosmiconfig: 9.0.0(typescript@5.4.5) + devtools-protocol: 0.0.1273771 + puppeteer-core: 22.7.1 + transitivePeerDependencies: + - bufferutil + - supports-color + - typescript + - utf-8-validate + dev: true + /pure-rand@6.0.4: resolution: {integrity: sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==} dev: true @@ -30629,7 +30843,6 @@ packages: /queue-tick@1.0.1: resolution: {integrity: sha512-kJt5qhMxoszgU/62PLP1CJytzd2NKetjSRnyuj31fDd3Rlcz3fzlFdFLD1SItunPwyqEOkca6GbV612BWfaBag==} - dev: false /quick-format-unescaped@4.0.4: resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} @@ -31414,7 +31627,7 @@ packages: resolution: {integrity: sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==} engines: {node: '>=8.6.0'} dependencies: - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: @@ -32056,7 +32269,6 @@ packages: /smart-buffer@4.2.0: resolution: {integrity: sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==} engines: {node: '>= 6.0.0', npm: '>= 3.0.0'} - dev: false /snake-case@3.0.4: resolution: {integrity: sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==} @@ -32069,19 +32281,29 @@ packages: engines: {node: '>= 10'} dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) socks: 2.8.3 transitivePeerDependencies: - supports-color dev: false + /socks-proxy-agent@8.0.3: + resolution: {integrity: sha512-VNegTZKhuGq5vSD6XNKlbqWhyt/40CgoEw8XxD6dhnm8Jq9IEa3nIa4HwnM8XOqU0CdB0BwWVXusqiFXfHB3+A==} + engines: {node: '>= 14'} + dependencies: + agent-base: 7.1.1 + debug: 4.3.4(supports-color@8.1.1) + socks: 2.8.3 + transitivePeerDependencies: + - supports-color + dev: true + /socks@2.8.3: resolution: {integrity: sha512-l5x7VUUWbjVFbafGLxPWkYsHIhEvmF85tbIeFZWc8ZPtoMyybuEhL7Jye/ooC4/d48FgOjSJXgsF/AJPYCW8Zw==} engines: {node: '>= 10.0.0', npm: '>= 3.0.0'} dependencies: ip-address: 9.0.5 smart-buffer: 4.2.0 - dev: false /sonic-boom@3.7.0: resolution: {integrity: sha512-IudtNvSqA/ObjN97tfgNmOKyDOs4dNcg4cUUsHDebqsgb8wGBBwb31LIgShNO8fye0dFI52X1+tFoKKI6Rq1Gg==} @@ -32392,7 +32614,17 @@ packages: dependencies: fast-fifo: 1.3.2 queue-tick: 1.0.1 - dev: false + + /streamx@2.16.1: + resolution: {integrity: sha512-m9QYj6WygWyWa3H1YY69amr4nVgy61xfjys7xO7kviL5rfIEc2naf+ewFiOA+aEJD7y0JO3h2GoiUv4TDwEGzQ==} + requiresBuild: true + dependencies: + fast-fifo: 1.3.2 + queue-tick: 1.0.1 + optionalDependencies: + bare-events: 2.2.2 + dev: true + optional: true /strict-uri-encode@1.1.0: resolution: {integrity: sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==} @@ -32629,7 +32861,7 @@ packages: hasBin: true dependencies: commander: 2.20.3 - debug: 4.3.4(supports-color@5.5.0) + debug: 4.3.4(supports-color@8.1.1) transitivePeerDependencies: - supports-color dev: true @@ -32879,6 +33111,16 @@ packages: tar-stream: 3.1.7 dev: false + /tar-fs@3.0.5: + resolution: {integrity: sha512-JOgGAmZyMgbqpLwct7ZV8VzkEB6pxXFBVErLtb+XCOqzc6w1xiWKI9GVd6bwk68EX7eJ4DWmfXVmq8K2ziZTGg==} + dependencies: + pump: 3.0.0 + tar-stream: 3.1.7 + optionalDependencies: + bare-fs: 2.3.0 + bare-path: 2.1.2 + dev: true + /tar-stream@1.6.2: resolution: {integrity: sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==} engines: {node: '>= 0.8.0'} @@ -32908,7 +33150,6 @@ packages: b4a: 1.6.4 fast-fifo: 1.3.2 streamx: 2.15.6 - dev: false /tar@6.2.0: resolution: {integrity: sha512-/Wo7DcT0u5HUV486xg675HtjNd3BXZ6xDbzsCUZPt5iw8bTQ63bP0Raut3mvro9u+CUyq7YQd8Cx55fsZXxqLQ==} @@ -34941,7 +35182,6 @@ packages: /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} - dev: false /zod@3.23.4: resolution: {integrity: sha512-/AtWOKbBgjzEYYQRNfoGKHObgfAZag6qUJX1VbHo2PRBgS+wfWagEY2mizjfyAPcGesrJOcx/wcl0L9WnVrHFw==} From b7c50aa33176aecd4317a5ad72c9d8c2b986b8db Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Tue, 30 Apr 2024 16:46:35 -0600 Subject: [PATCH 3/6] feat: exposing delegation --- apps/consent/app/graphql/generated.ts | 10 +++++++++ apps/dashboard/services/graphql/generated.ts | 22 +++++++++++++++++++ apps/map/services/galoy/graphql/generated.ts | 10 +++++++++ apps/pay/lib/graphql/generated.ts | 10 +++++++++ bats/core/api/user.bats | 7 ++++++ bats/gql/list-sessions.gql | 6 +++++ core/api/src/app/users/list-sessions.ts | 9 ++++---- .../domain/authentication/index.types.d.ts | 2 +- core/api/src/graphql/public/schema.graphql | 10 +++++++++ .../public/types/object/deleguation.ts | 15 +++++++++++++ .../src/graphql/public/types/object/user.ts | 11 +++++++++- core/api/src/services/hydra/index.ts | 6 +++-- .../integration/app/user/consent-list.spec.ts | 5 +++-- .../apollo-federation/supergraph.graphql | 12 ++++++++++ 14 files changed, 124 insertions(+), 11 deletions(-) create mode 100644 core/api/src/graphql/public/types/object/deleguation.ts diff --git a/apps/consent/app/graphql/generated.ts b/apps/consent/app/graphql/generated.ts index e689c2696d..3958a65f86 100644 --- a/apps/consent/app/graphql/generated.ts +++ b/apps/consent/app/graphql/generated.ts @@ -449,6 +449,14 @@ export type CurrencyConversionEstimation = { readonly usdCentAmount: Scalars['CentAmount']['output']; }; +export type Delegation = { + readonly __typename: 'Delegation'; + readonly app: Scalars['String']['output']; + readonly handledAt: Scalars['Timestamp']['output']; + readonly remember: Scalars['Boolean']['output']; + readonly scope: ReadonlyArray; +}; + export type DepositFeesInformation = { readonly __typename: 'DepositFeesInformation'; readonly minBankFee: Scalars['String']['output']; @@ -1921,6 +1929,8 @@ export type User = { readonly contacts: ReadonlyArray; readonly createdAt: Scalars['Timestamp']['output']; readonly defaultAccount: Account; + /** List of Oauth2 delegations */ + readonly delegations: ReadonlyArray; /** Email address */ readonly email?: Maybe; readonly id: Scalars['ID']['output']; diff --git a/apps/dashboard/services/graphql/generated.ts b/apps/dashboard/services/graphql/generated.ts index 82fe5a8b81..97685a0279 100644 --- a/apps/dashboard/services/graphql/generated.ts +++ b/apps/dashboard/services/graphql/generated.ts @@ -489,6 +489,14 @@ export type CurrencyConversionEstimation = { readonly usdCentAmount: Scalars['CentAmount']['output']; }; +export type Delegation = { + readonly __typename: 'Delegation'; + readonly app: Scalars['String']['output']; + readonly handledAt: Scalars['Timestamp']['output']; + readonly remember: Scalars['Boolean']['output']; + readonly scope: ReadonlyArray; +}; + export type DepositFeesInformation = { readonly __typename: 'DepositFeesInformation'; readonly minBankFee: Scalars['String']['output']; @@ -2018,6 +2026,8 @@ export type User = { readonly contacts: ReadonlyArray; readonly createdAt: Scalars['Timestamp']['output']; readonly defaultAccount: Account; + /** List of Oauth2 delegations */ + readonly delegations: ReadonlyArray; /** Email address */ readonly email?: Maybe; readonly id: Scalars['ID']['output']; @@ -3471,6 +3481,7 @@ export type ResolversTypes = { CountryCode: ResolverTypeWrapper; Currency: ResolverTypeWrapper; CurrencyConversionEstimation: ResolverTypeWrapper; + Delegation: ResolverTypeWrapper; DepositFeesInformation: ResolverTypeWrapper; DeviceNotificationTokenCreateInput: DeviceNotificationTokenCreateInput; DisplayCurrency: ResolverTypeWrapper; @@ -3699,6 +3710,7 @@ export type ResolversParentTypes = { CountryCode: Scalars['CountryCode']['output']; Currency: Currency; CurrencyConversionEstimation: CurrencyConversionEstimation; + Delegation: Delegation; DepositFeesInformation: DepositFeesInformation; DeviceNotificationTokenCreateInput: DeviceNotificationTokenCreateInput; DisplayCurrency: Scalars['DisplayCurrency']['output']; @@ -4139,6 +4151,14 @@ export type CurrencyConversionEstimationResolvers; }; +export type DelegationResolvers = { + app?: Resolver; + handledAt?: Resolver; + remember?: Resolver; + scope?: Resolver, ParentType, ContextType>; + __isTypeOf?: IsTypeOfResolverFn; +}; + export type DepositFeesInformationResolvers = { minBankFee?: Resolver; minBankFeeThreshold?: Resolver; @@ -4835,6 +4855,7 @@ export type UserResolvers, ParentType, ContextType>; createdAt?: Resolver; defaultAccount?: Resolver; + delegations?: Resolver, ParentType, ContextType>; email?: Resolver, ParentType, ContextType>; id?: Resolver; language?: Resolver; @@ -4992,6 +5013,7 @@ export type Resolvers = { CountryCode?: GraphQLScalarType; Currency?: CurrencyResolvers; CurrencyConversionEstimation?: CurrencyConversionEstimationResolvers; + Delegation?: DelegationResolvers; DepositFeesInformation?: DepositFeesInformationResolvers; DisplayCurrency?: GraphQLScalarType; Email?: EmailResolvers; diff --git a/apps/map/services/galoy/graphql/generated.ts b/apps/map/services/galoy/graphql/generated.ts index 279cf2cb2a..0dce789e6d 100644 --- a/apps/map/services/galoy/graphql/generated.ts +++ b/apps/map/services/galoy/graphql/generated.ts @@ -449,6 +449,14 @@ export type CurrencyConversionEstimation = { readonly usdCentAmount: Scalars['CentAmount']['output']; }; +export type Delegation = { + readonly __typename: 'Delegation'; + readonly app: Scalars['String']['output']; + readonly handledAt: Scalars['Timestamp']['output']; + readonly remember: Scalars['Boolean']['output']; + readonly scope: ReadonlyArray; +}; + export type DepositFeesInformation = { readonly __typename: 'DepositFeesInformation'; readonly minBankFee: Scalars['String']['output']; @@ -1921,6 +1929,8 @@ export type User = { readonly contacts: ReadonlyArray; readonly createdAt: Scalars['Timestamp']['output']; readonly defaultAccount: Account; + /** List of Oauth2 delegations */ + readonly delegations: ReadonlyArray; /** Email address */ readonly email?: Maybe; readonly id: Scalars['ID']['output']; diff --git a/apps/pay/lib/graphql/generated.ts b/apps/pay/lib/graphql/generated.ts index ccd77bf613..a114aef2d8 100644 --- a/apps/pay/lib/graphql/generated.ts +++ b/apps/pay/lib/graphql/generated.ts @@ -448,6 +448,14 @@ export type CurrencyConversionEstimation = { readonly usdCentAmount: Scalars['CentAmount']; }; +export type Delegation = { + readonly __typename: 'Delegation'; + readonly app: Scalars['String']; + readonly handledAt: Scalars['Timestamp']; + readonly remember: Scalars['Boolean']; + readonly scope: ReadonlyArray; +}; + export type DepositFeesInformation = { readonly __typename: 'DepositFeesInformation'; readonly minBankFee: Scalars['String']; @@ -1920,6 +1928,8 @@ export type User = { readonly contacts: ReadonlyArray; readonly createdAt: Scalars['Timestamp']; readonly defaultAccount: Account; + /** List of Oauth2 delegations */ + readonly delegations: ReadonlyArray; /** Email address */ readonly email?: Maybe; readonly id: Scalars['ID']; diff --git a/bats/core/api/user.bats b/bats/core/api/user.bats index e8fe4ce578..6e5579e4de 100644 --- a/bats/core/api/user.bats +++ b/bats/core/api/user.bats @@ -26,3 +26,10 @@ setup_file() { language="$(graphql_output '.data.me.language')" [[ "$language" == "$new_language" ]] || exit 1 } + +@test "user: list sessions" { + exec_graphql 'alice' 'list-sessions' + sessions="$(graphql_output '.data.me.mobileSessions')" + id="$(echo "$sessions" | jq -r '.[0].id')" # Extracts the ID of the first element + [[ "$sessions" != "[]" ]] && [[ -n "$id" ]] || exit 1 +} diff --git a/bats/gql/list-sessions.gql b/bats/gql/list-sessions.gql index fa43e65b7e..5a5ee558a6 100644 --- a/bats/gql/list-sessions.gql +++ b/bats/gql/list-sessions.gql @@ -7,5 +7,11 @@ query userDetails { expiresAt issuedAt } + delegations { + app + handledAt + remember + scope + } } } diff --git a/core/api/src/app/users/list-sessions.ts b/core/api/src/app/users/list-sessions.ts index a08885cf38..a122d83006 100644 --- a/core/api/src/app/users/list-sessions.ts +++ b/core/api/src/app/users/list-sessions.ts @@ -1,11 +1,10 @@ +import { consentList } from "@/services/hydra" import { listSessions as listSessionsService } from "@/services/kratos" export const listMobileSessions = async (userId: UserId) => { - const list = await listSessionsService(userId) - console.dir(list) - return list + return listSessionsService(userId) } -export const listDeleguateSessions = async (userId: UserId) => { - +export const listDeleguations = async (userId: UserId) => { + return consentList(userId) } diff --git a/core/api/src/domain/authentication/index.types.d.ts b/core/api/src/domain/authentication/index.types.d.ts index 8863f43b20..d8a9840931 100644 --- a/core/api/src/domain/authentication/index.types.d.ts +++ b/core/api/src/domain/authentication/index.types.d.ts @@ -68,7 +68,7 @@ type MobileSession = { issuedAt: Date } -type ConsentSession = { +type Delegation = { scope: string[] handledAt: Date remember: boolean diff --git a/core/api/src/graphql/public/schema.graphql b/core/api/src/graphql/public/schema.graphql index 0e693edd93..c8b6dd7e01 100644 --- a/core/api/src/graphql/public/schema.graphql +++ b/core/api/src/graphql/public/schema.graphql @@ -354,6 +354,13 @@ type CurrencyConversionEstimation { usdCentAmount: CentAmount! } +type Delegation { + app: String! + handledAt: Timestamp! + remember: Boolean! + scope: [String!]! +} + type DepositFeesInformation { minBankFee: String! @@ -1595,6 +1602,9 @@ type User { createdAt: Timestamp! defaultAccount: Account! + """List of Oauth2 delegations""" + delegations: [Delegation!]! + """Email address""" email: Email id: ID! diff --git a/core/api/src/graphql/public/types/object/deleguation.ts b/core/api/src/graphql/public/types/object/deleguation.ts new file mode 100644 index 0000000000..2e714efe63 --- /dev/null +++ b/core/api/src/graphql/public/types/object/deleguation.ts @@ -0,0 +1,15 @@ +import Timestamp from "@/graphql/shared/types/scalar/timestamp" + +import { GT } from "@/graphql/index" + +const Delegation = GT.Object({ + name: "Delegation", + fields: () => ({ + app: { type: GT.NonNull(GT.String) }, + handledAt: { type: GT.NonNull(Timestamp) }, + remember: { type: GT.NonNull(GT.Boolean) }, + scope: { type: GT.NonNullList(GT.String) }, + }), +}) + +export default Delegation diff --git a/core/api/src/graphql/public/types/object/user.ts b/core/api/src/graphql/public/types/object/user.ts index 51b7f6772b..e75af282f9 100644 --- a/core/api/src/graphql/public/types/object/user.ts +++ b/core/api/src/graphql/public/types/object/user.ts @@ -4,6 +4,7 @@ import Account from "../abstract/account" import SupportMessage from "./support-message" import AccountContact from "./account-contact" +import Delegation from "./deleguation" import { Accounts, Users, SupportChat } from "@/app" @@ -19,7 +20,7 @@ import Language from "@/graphql/shared/types/scalar/language" import Username from "@/graphql/shared/types/scalar/username" import Timestamp from "@/graphql/shared/types/scalar/timestamp" import GraphQLEmail from "@/graphql/shared/types/object/email" -import MobileSession from "./mobile-session" +import MobileSession from "@/graphql/public/types/object/mobile-session" const GraphQLUser = GT.Object({ name: "User", @@ -84,6 +85,14 @@ const GraphQLUser = GT.Object({ }, }, + delegations: { + type: GT.NonNullList(Delegation), + description: "List of Oauth2 delegations", + resolve: async (source, args, { user }) => { + return Users.listDeleguations(user.id) + }, + }, + contacts: { deprecationReason: "will be moved to account", type: GT.NonNullList(AccountContact), // TODO: Make it a Connection Interface diff --git a/core/api/src/services/hydra/index.ts b/core/api/src/services/hydra/index.ts index cef1a89daf..3e08646bf7 100644 --- a/core/api/src/services/hydra/index.ts +++ b/core/api/src/services/hydra/index.ts @@ -2,7 +2,9 @@ import axios, { AxiosResponse } from "axios" const hydraUrl = process.env.HYDRA_ADMIN_URL || "http://localhost:4445" -export const consentList = async (userId: UserId): Promise => { +export const consentList = async (userId: UserId): Promise => { + /* eslint @typescript-eslint/ban-ts-comment: "off" */ + // @ts-ignore-next-line no-implicit-any error let res: AxiosResponse try { @@ -15,7 +17,7 @@ export const consentList = async (userId: UserId): Promise => return [] } - let sessions: ConsentSession[] + let sessions: Delegation[] try { /* eslint @typescript-eslint/ban-ts-comment: "off" */ diff --git a/core/api/test/integration/app/user/consent-list.spec.ts b/core/api/test/integration/app/user/consent-list.spec.ts index a6bbe5b83c..a88f00e15c 100644 --- a/core/api/test/integration/app/user/consent-list.spec.ts +++ b/core/api/test/integration/app/user/consent-list.spec.ts @@ -1,8 +1,9 @@ +import { exec } from "child_process" +import puppeteer from "puppeteer" + import { Admin } from "@/app" import { consentList } from "@/services/hydra" import { sleep } from "@/utils" -import { exec } from "child_process" -import puppeteer from "puppeteer" let userId: UserId const email = "test@galoy.io" as EmailAddress diff --git a/dev/config/apollo-federation/supergraph.graphql b/dev/config/apollo-federation/supergraph.graphql index 35daf5baeb..e9db449eeb 100644 --- a/dev/config/apollo-federation/supergraph.graphql +++ b/dev/config/apollo-federation/supergraph.graphql @@ -486,6 +486,15 @@ type CurrencyConversionEstimation usdCentAmount: CentAmount! } +type Delegation + @join__type(graph: PUBLIC) +{ + app: String! + handledAt: Timestamp! + remember: Boolean! + scope: [String!]! +} + type DepositFeesInformation @join__type(graph: PUBLIC) { @@ -2085,6 +2094,9 @@ type User createdAt: Timestamp! @join__field(graph: PUBLIC) defaultAccount: Account! @join__field(graph: PUBLIC) + """List of Oauth2 delegations""" + delegations: [Delegation!]! @join__field(graph: PUBLIC) + """Email address""" email: Email @join__field(graph: PUBLIC) From efb4e86aaaa5fa2184ab454cf1adac0f52e423af Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Wed, 1 May 2024 15:43:05 -0600 Subject: [PATCH 4/6] fix: remove skip --- bats/core/api/user.bats | 2 -- 1 file changed, 2 deletions(-) diff --git a/bats/core/api/user.bats b/bats/core/api/user.bats index 6e5579e4de..c16d74ab9b 100644 --- a/bats/core/api/user.bats +++ b/bats/core/api/user.bats @@ -5,8 +5,6 @@ setup_file() { } @test "account: updates language" { - "skip" - local new_language="de" exec_graphql 'alice' 'user-details' From 5e1b2904af06bb0c5f64da407b6402f86f121a5e Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Wed, 1 May 2024 15:49:05 -0600 Subject: [PATCH 5/6] chore: using object for param --- core/api/src/app/users/list-sessions.ts | 4 ++-- core/api/src/graphql/public/types/object/user.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/core/api/src/app/users/list-sessions.ts b/core/api/src/app/users/list-sessions.ts index a122d83006..ce51412502 100644 --- a/core/api/src/app/users/list-sessions.ts +++ b/core/api/src/app/users/list-sessions.ts @@ -1,10 +1,10 @@ import { consentList } from "@/services/hydra" import { listSessions as listSessionsService } from "@/services/kratos" -export const listMobileSessions = async (userId: UserId) => { +export const listMobileSessions = async ({ userId }: { userId: UserId }) => { return listSessionsService(userId) } -export const listDeleguations = async (userId: UserId) => { +export const listDeleguations = async ({ userId }: { userId: UserId }) => { return consentList(userId) } diff --git a/core/api/src/graphql/public/types/object/user.ts b/core/api/src/graphql/public/types/object/user.ts index e75af282f9..2a21c579df 100644 --- a/core/api/src/graphql/public/types/object/user.ts +++ b/core/api/src/graphql/public/types/object/user.ts @@ -81,7 +81,7 @@ const GraphQLUser = GT.Object({ type: GT.NonNullList(MobileSession), description: "List of mobile sessions", resolve: async (source, args, { user }) => { - return Users.listMobileSessions(user.id) + return Users.listMobileSessions({ userId: user.id }) }, }, @@ -89,7 +89,7 @@ const GraphQLUser = GT.Object({ type: GT.NonNullList(Delegation), description: "List of Oauth2 delegations", resolve: async (source, args, { user }) => { - return Users.listDeleguations(user.id) + return Users.listDeleguations({ userId: user.id }) }, }, From 535ee7fda0d2c4fb845df62c7bdbee8d1271fcb1 Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Wed, 1 May 2024 16:11:01 -0600 Subject: [PATCH 6/6] chore: remove child_process --- core/api/package.json | 1 - .../integration/app/user/consent-list.spec.ts | 41 ++-- pnpm-lock.yaml | 232 +++++++++++++----- 3 files changed, 198 insertions(+), 76 deletions(-) diff --git a/core/api/package.json b/core/api/package.json index 42d1d150e3..114a49ee5e 100644 --- a/core/api/package.json +++ b/core/api/package.json @@ -161,7 +161,6 @@ "@typescript-eslint/parser": "^7.7.0", "@xascode/tscpaths": "0.1.4", "axios-mock-adapter": "^1.22.0", - "child_process": "^1.0.2", "eslint": "^8.57.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-import": "^2.29.1", diff --git a/core/api/test/integration/app/user/consent-list.spec.ts b/core/api/test/integration/app/user/consent-list.spec.ts index a88f00e15c..db5b986f1f 100644 --- a/core/api/test/integration/app/user/consent-list.spec.ts +++ b/core/api/test/integration/app/user/consent-list.spec.ts @@ -1,9 +1,9 @@ -import { exec } from "child_process" import puppeteer from "puppeteer" import { Admin } from "@/app" import { consentList } from "@/services/hydra" import { sleep } from "@/utils" +import knex from "knex" let userId: UserId const email = "test@galoy.io" as EmailAddress @@ -15,26 +15,31 @@ beforeAll(async () => { userId = account.kratosUserId }) +const db = knex({ + client: "pg", + connection: "postgres://dbuser:secret@localhost:5432/default?sslmode=disable", +}) + const getOTP = (email: string): Promise => { - return new Promise((resolve, reject) => { - const query = `docker exec -i galoy-dev-kratos-pg-1 psql -U dbuser -d default -t -c "SELECT body FROM courier_messages WHERE recipient='${email}' ORDER BY created_at DESC LIMIT 1;"` - exec(query, (error, stdout, stderr) => { - if (error) { - reject(`error: ${error.message}`) - return - } - if (stderr) { - reject(`stderr: ${stderr}`) - return + return db<{ body: string }>("courier_messages") // Specifying the expected row structure + .select("body") + .where("recipient", email) + .orderBy("created_at", "desc") + .limit(1) + .then((rows) => { + if (rows.length === 0) { + throw new Error("OTP not found in the message") } - const otpMatch = stdout.match(/(\d{6})/) + const otpMatch = rows[0].body.match(/(\d{6})/) if (otpMatch && otpMatch[1]) { - resolve(otpMatch[1]) + return otpMatch[1] } else { - reject("OTP not found in the message") + throw new Error("OTP not found in the message") } }) - }) + .catch((error) => { + throw new Error(`Error retrieving OTP: ${error.message}`) + }) } async function performOAuthLogin() { @@ -60,17 +65,17 @@ async function performOAuthLogin() { ) await page.type('[data-testid="email_id_input"]', email) screenshots && (await page.screenshot({ path: "screenshot2.png" })) - await sleep(250) + await sleep(1000) await page.click("#accept") - await sleep(500) + await sleep(1000) screenshots && (await page.screenshot({ path: "screenshot3.png" })) const otp = await getOTP(email) await page.waitForSelector("#code") - await page.type("#code", otp, { delay: 100 }) + await page.type("#code", otp) screenshots && (await page.screenshot({ path: "screenshot4.png" })) await sleep(1500) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2f8c3a6b36..7b801faf58 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -1408,9 +1408,6 @@ importers: axios-mock-adapter: specifier: ^1.22.0 version: 1.22.0(axios@1.6.8) - child_process: - specifier: ^1.0.2 - version: 1.0.2 eslint: specifier: ^8.57.0 version: 8.57.0 @@ -2969,7 +2966,7 @@ packages: '@babel/traverse': 7.24.1 '@babel/types': 7.24.0 convert-source-map: 2.0.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) gensync: 1.0.0-beta.2 json5: 2.2.3 semver: 6.3.1 @@ -3227,7 +3224,7 @@ packages: '@babel/core': 7.24.4 '@babel/helper-compilation-targets': 7.23.6 '@babel/helper-plugin-utils': 7.24.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) lodash.debounce: 4.0.8 resolve: 1.22.8 transitivePeerDependencies: @@ -6979,7 +6976,7 @@ packages: '@babel/helper-split-export-declaration': 7.22.6 '@babel/parser': 7.24.4 '@babel/types': 7.24.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) globals: 11.12.0 transitivePeerDependencies: - supports-color @@ -7734,7 +7731,7 @@ packages: engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} dependencies: ajv: 6.12.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) espree: 9.6.1 globals: 13.24.0 ignore: 5.3.1 @@ -10238,7 +10235,7 @@ packages: engines: {node: '>=10.10.0'} dependencies: '@humanwhocodes/object-schema': 2.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) minimatch: 3.1.2 transitivePeerDependencies: - supports-color @@ -10302,6 +10299,49 @@ packages: slash: 3.0.0 dev: true + /@jest/core@29.7.0: + resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + node-notifier: ^8.0.1 || ^9.0.0 || ^10.0.0 + peerDependenciesMeta: + node-notifier: + optional: true + dependencies: + '@jest/console': 29.7.0 + '@jest/reporters': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.7 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@20.12.7) + jest-haste-map: 29.7.0 + jest-message-util: 29.7.0 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-resolve-dependencies: 29.7.0 + jest-runner: 29.7.0 + jest-runtime: 29.7.0 + jest-snapshot: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + jest-watcher: 29.7.0 + micromatch: 4.0.5 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + dev: true + /@jest/core@29.7.0(ts-node@10.9.2): resolution: {integrity: sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -12287,8 +12327,8 @@ packages: engines: {node: '>=18'} hasBin: true dependencies: - debug: 4.3.4(supports-color@8.1.1) - extract-zip: 2.0.1(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) + extract-zip: 2.0.1 progress: 2.0.3 proxy-agent: 6.4.0 semver: 7.6.0 @@ -16937,7 +16977,7 @@ packages: '@typescript-eslint/type-utils': 7.7.0(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/utils': 7.7.0(eslint@8.57.0)(typescript@5.4.5) '@typescript-eslint/visitor-keys': 7.7.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) eslint: 8.57.0 graphemer: 1.4.0 ignore: 5.3.1 @@ -17121,7 +17161,7 @@ packages: '@typescript-eslint/types': 7.7.0 '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.4.5) '@typescript-eslint/visitor-keys': 7.7.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) eslint: 8.57.0 typescript: 5.4.5 transitivePeerDependencies: @@ -17268,7 +17308,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 7.7.0(typescript@5.4.5) '@typescript-eslint/utils': 7.7.0(eslint@8.57.0)(typescript@5.4.5) - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.4.5) typescript: 5.4.5 @@ -17321,7 +17361,7 @@ packages: dependencies: '@typescript-eslint/types': 4.33.0 '@typescript-eslint/visitor-keys': 4.33.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 @@ -17342,7 +17382,7 @@ packages: dependencies: '@typescript-eslint/types': 5.62.0 '@typescript-eslint/visitor-keys': 5.62.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 semver: 7.6.0 @@ -17449,7 +17489,7 @@ packages: dependencies: '@typescript-eslint/types': 6.21.0 '@typescript-eslint/visitor-keys': 6.21.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.3 @@ -17537,7 +17577,7 @@ packages: dependencies: '@typescript-eslint/types': 7.7.0 '@typescript-eslint/visitor-keys': 7.7.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.4 @@ -18285,7 +18325,7 @@ packages: resolution: {integrity: sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==} engines: {node: '>= 6.0.0'} dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -18293,7 +18333,7 @@ packages: resolution: {integrity: sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==} engines: {node: '>= 14'} dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -18301,7 +18341,7 @@ packages: resolution: {integrity: sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==} engines: {node: '>= 14'} dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color dev: true @@ -19944,10 +19984,6 @@ packages: parse5-htmlparser2-tree-adapter: 7.0.0 dev: true - /child_process@1.0.2: - resolution: {integrity: sha512-Wmza/JzL0SiWz7kl6MhIKT5ceIlnFPJX+lwUGj7Clhy5MMldsSoJR0+uvRzOS5Kv45Mq7t1PoE8TsOA9bzvb6g==} - dev: true - /chokidar@3.5.3: resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} engines: {node: '>= 8.10.0'} @@ -20613,6 +20649,25 @@ packages: - ts-node dev: true + /create-jest@29.7.0(@types/node@20.12.7): + resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + hasBin: true + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@20.12.7) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + dev: true + /create-jest@29.7.0(@types/node@20.12.7)(ts-node@10.9.2): resolution: {integrity: sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -21025,6 +21080,16 @@ packages: dependencies: ms: 2.0.0 + /debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + /debug@3.2.7(supports-color@8.1.1): resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} peerDependencies: @@ -21059,7 +21124,6 @@ packages: dependencies: ms: 2.1.2 supports-color: 5.5.0 - dev: true /debug@4.3.4(supports-color@8.1.1): resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} @@ -21303,7 +21367,7 @@ packages: hasBin: true dependencies: commander: 2.20.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) filing-cabinet: 3.3.1 precinct: 9.2.1 typescript: 4.9.5 @@ -21436,7 +21500,7 @@ packages: resolution: {integrity: sha512-Rps1xDkEEBSq3kLdsdnHZL1x2S4NGDcbrjmd4q+PykK5aJwDdP5MBgrJw1Xo+kyUHuv3JEzPqxr+Dj9ryeDRTA==} engines: {node: '>= 6.0'} dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) gonzales-pe: 4.3.0 node-source-walk: 4.3.0 transitivePeerDependencies: @@ -21447,7 +21511,7 @@ packages: resolution: {integrity: sha512-Fwc/g9VcrowODIAeKRWZfVA/EufxYL7XfuqJQFroBKGikKX83d2G7NFw6kDlSYGG3LNQIyVa+eWv1mqre+v4+A==} engines: {node: ^10 || ^12 || >=14} dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) is-url: 1.2.4 postcss: 8.4.35 postcss-values-parser: 2.0.1 @@ -22337,7 +22401,7 @@ packages: /eslint-import-resolver-node@0.3.9: resolution: {integrity: sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==} dependencies: - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 is-core-module: 2.13.1 resolve: 1.22.8 transitivePeerDependencies: @@ -22611,7 +22675,7 @@ packages: optional: true dependencies: '@typescript-eslint/parser': 7.7.0(eslint@8.57.0)(typescript@5.4.5) - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 transitivePeerDependencies: @@ -22852,7 +22916,7 @@ packages: array.prototype.findlastindex: 1.2.3 array.prototype.flat: 1.3.2 array.prototype.flatmap: 1.3.2 - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 @@ -23386,7 +23450,7 @@ packages: ajv: 6.12.6 chalk: 4.1.2 cross-spawn: 7.0.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) doctrine: 3.0.0 escape-string-regexp: 4.0.0 eslint-scope: 7.2.2 @@ -23677,6 +23741,20 @@ packages: - supports-color dev: true + /extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + dependencies: + debug: 4.3.4(supports-color@5.5.0) + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + dev: true + /extract-zip@2.0.1(supports-color@8.1.1): resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} engines: {node: '>= 10.17.0'} @@ -23925,7 +24003,7 @@ packages: dependencies: app-module-path: 2.2.0 commander: 2.20.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) enhanced-resolve: 5.15.0 is-relative-path: 1.0.2 module-definition: 3.4.0 @@ -24534,7 +24612,7 @@ packages: dependencies: basic-ftp: 5.0.5 data-uri-to-buffer: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) fs-extra: 11.2.0 transitivePeerDependencies: - supports-color @@ -25632,7 +25710,7 @@ packages: dependencies: '@tootallnate/once': 2.0.0 agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -25651,7 +25729,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color dev: true @@ -25718,7 +25796,7 @@ packages: engines: {node: '>= 6'} dependencies: agent-base: 6.0.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -25737,7 +25815,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color @@ -25980,7 +26058,7 @@ packages: dependencies: '@ioredis/commands': 1.2.0 cluster-key-slot: 1.1.2 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) denque: 2.1.0 lodash.defaults: 4.2.0 lodash.isarguments: 3.1.0 @@ -26482,7 +26560,7 @@ packages: resolution: {integrity: sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==} engines: {node: '>=10'} dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) istanbul-lib-coverage: 3.2.0 source-map: 0.6.1 transitivePeerDependencies: @@ -26613,14 +26691,14 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/core': 29.7.0 '@jest/test-result': 29.7.0 '@jest/types': 29.6.3 chalk: 4.1.2 - create-jest: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2) + create-jest: 29.7.0(@types/node@20.12.7) exit: 0.1.2 import-local: 3.1.0 - jest-config: 29.7.0(@types/node@20.12.7)(ts-node@10.9.2) + jest-config: 29.7.0(@types/node@20.12.7) jest-util: 29.7.0 jest-validate: 29.7.0 yargs: 17.7.2 @@ -26699,6 +26777,46 @@ packages: - supports-color dev: true + /jest-config@29.7.0(@types/node@20.12.7): + resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + peerDependencies: + '@types/node': '*' + ts-node: '>=9.0.0' + peerDependenciesMeta: + '@types/node': + optional: true + ts-node: + optional: true + dependencies: + '@babel/core': 7.24.4 + '@jest/test-sequencer': 29.7.0 + '@jest/types': 29.6.3 + '@types/node': 20.12.7 + babel-jest: 29.7.0(@babel/core@7.24.4) + chalk: 4.1.2 + ci-info: 3.9.0 + deepmerge: 4.3.1 + glob: 7.2.3 + graceful-fs: 4.2.11 + jest-circus: 29.7.0 + jest-environment-node: 29.7.0 + jest-get-type: 29.6.3 + jest-regex-util: 29.6.3 + jest-resolve: 29.7.0 + jest-runner: 29.7.0 + jest-util: 29.7.0 + jest-validate: 29.7.0 + micromatch: 4.0.5 + parse-json: 5.2.0 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-json-comments: 3.1.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + dev: true + /jest-config@29.7.0(@types/node@20.12.7)(ts-node@10.9.2): resolution: {integrity: sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} @@ -27096,7 +27214,7 @@ packages: node-notifier: optional: true dependencies: - '@jest/core': 29.7.0(ts-node@10.9.2) + '@jest/core': 29.7.0 '@jest/types': 29.6.3 import-local: 3.1.0 jest-cli: 29.7.0(@types/node@20.12.7) @@ -27464,7 +27582,7 @@ packages: dependencies: '@types/express': 4.17.21 '@types/jsonwebtoken': 9.0.6 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) jose: 4.15.2 limiter: 1.1.5 lru-memoizer: 2.2.0 @@ -27551,7 +27669,7 @@ packages: dependencies: colorette: 2.0.19 commander: 10.0.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) escalade: 3.1.1 esm: 3.2.25 get-package-type: 0.1.0 @@ -28128,7 +28246,7 @@ packages: chalk: 4.1.2 commander: 7.2.0 commondir: 1.0.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) dependency-tree: 9.0.0 detective-amd: 4.2.0 detective-cjs: 4.1.0 @@ -28578,7 +28696,7 @@ packages: hasBin: true dependencies: commander: 2.20.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) glob: 7.2.3 requirejs: 2.3.6 requirejs-config-file: 4.0.0 @@ -28706,7 +28824,7 @@ packages: resolution: {integrity: sha512-iQMncpmEK8R8ncT8HJGsGc9Dsp8xcgYMVSbs5jgnm1lFHTZqMJTUWTDx1LBO8+mK3tPNZWFLBghQEIOULSTHZg==} engines: {node: '>=14.0.0'} dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color dev: false @@ -29607,7 +29725,7 @@ packages: dependencies: '@tootallnate/quickjs-emscripten': 0.23.0 agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) get-uri: 6.0.3 http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.4 @@ -30407,7 +30525,7 @@ packages: hasBin: true dependencies: commander: 2.20.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) detective-amd: 3.1.2 detective-cjs: 3.1.3 detective-es6: 2.2.2 @@ -30637,7 +30755,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.0 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.4 lru-cache: 7.18.3 @@ -30739,7 +30857,7 @@ packages: dependencies: '@puppeteer/browsers': 2.2.3 chromium-bidi: 0.5.19(devtools-protocol@0.0.1273771) - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) devtools-protocol: 0.0.1273771 ws: 8.16.0 transitivePeerDependencies: @@ -31627,7 +31745,7 @@ packages: resolution: {integrity: sha512-nQFEv9gRw6SJAwWD2LrL0NmQvAcO7FBwJbwmr2ttPAacfy0xuiOjE5zt+zM4xDyuyvUaxBi/9gb2SoCyNEVJcw==} engines: {node: '>=8.6.0'} dependencies: - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) module-details-from-path: 1.0.3 resolve: 1.22.8 transitivePeerDependencies: @@ -32292,7 +32410,7 @@ packages: engines: {node: '>= 14'} dependencies: agent-base: 7.1.1 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) socks: 2.8.3 transitivePeerDependencies: - supports-color @@ -32861,7 +32979,7 @@ packages: hasBin: true dependencies: commander: 2.20.3 - debug: 4.3.4(supports-color@8.1.1) + debug: 4.3.4(supports-color@5.5.0) transitivePeerDependencies: - supports-color dev: true @@ -33399,7 +33517,7 @@ packages: resolution: {integrity: sha512-44yhA3tsaRoMOjQQ+5v5mVdqef+kH6Qze9jTpqtVufgYjYt08zyZAwNwwVBj3i1rJMnR52IxOW0LK0vBzgAkuA==} dependencies: body: 5.1.0 - debug: 3.2.7(supports-color@8.1.1) + debug: 3.2.7 faye-websocket: 0.10.0 livereload-js: 2.4.0 object-assign: 4.1.1