This commit is contained in:
einhornimmond 2024-02-16 00:42:49 +01:00
parent eedd9fa3ac
commit 4e955d8d95
21 changed files with 343 additions and 111 deletions

View File

@ -16,6 +16,7 @@ module.exports = {
moduleNameMapper: {
'@/(.*)': '<rootDir>/src/$1',
'@arg/(.*)': '<rootDir>/src/graphql/arg/$1',
'@input/(.*)': '<rootDir>/src/graphql/input/$1',
'@dltConnector/(.*)': '<rootDir>/src/apis/dltConnector/$1',
'@enum/(.*)': '<rootDir>/src/graphql/enum/$1',
'@model/(.*)': '<rootDir>/src/graphql/model/$1',

View File

@ -1,14 +1,13 @@
import { IsString } from 'class-validator'
import { Field, ArgsType, InputType } from 'type-graphql'
import { IsBoolean, IsString } from 'class-validator'
import { ArgsType, Field } from 'type-graphql'
@InputType()
@ArgsType()
export class CommunityArgs {
@Field(() => String)
@Field(() => String, { nullable: true })
@IsString()
uuid: string
communityIdentifier?: string | null
@Field(() => String)
@IsString()
gmsApiKey: string
@Field(() => Boolean, { nullable: true })
@IsBoolean()
foreign?: boolean | null
}

View File

@ -1,4 +1,4 @@
import { MaxLength, MinLength, IsString } from 'class-validator'
import { MaxLength, MinLength, IsString, IsUUID } from 'class-validator'
import { Decimal } from 'decimal.js-light'
import { ArgsType, Field } from 'type-graphql'

View File

@ -0,0 +1,14 @@
import { IsString, IsUUID } from 'class-validator'
import { ArgsType, Field, InputType } from 'type-graphql'
@ArgsType()
@InputType()
export class EditCommunityInput {
@Field(() => String)
@IsUUID('4')
uuid: string
@Field(() => String)
@IsString()
gmsApiKey: string
}

View File

@ -10,6 +10,7 @@ import { Community as DbCommunity } from '@entity/Community'
import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity'
import { ApolloServerTestClient } from 'apollo-server-testing'
import { GraphQLError } from 'graphql/error/GraphQLError'
import { v4 as uuidv4 } from 'uuid'
import { cleanDB, testEnvironment } from '@test/helpers'
import { logger, i18n as localization } from '@test/testSetup'
@ -19,7 +20,7 @@ import { login, updateHomeCommunityQuery } from '@/seeds/graphql/mutations'
import { getCommunities, communitiesQuery, getCommunityByUuidQuery } from '@/seeds/graphql/queries'
import { peterLustig } from '@/seeds/users/peter-lustig'
import { getCommunityByUuid } from './util/communities'
import { getCommunity } from './util/communities'
// to do: We need a setup for the tests that closes the connection
let mutate: ApolloServerTestClient['mutate'],
@ -459,7 +460,7 @@ describe('CommunityResolver', () => {
await mutate({ mutation: login, variables: peterLoginData })
// HomeCommunity is still created in userFactory
homeCom = await getCommunityByUuid(admin.communityUuid)
homeCom = await getCommunity(admin.communityUuid)
foreignCom1 = DbCommunity.create()
foreignCom1.foreign = true
@ -478,7 +479,7 @@ describe('CommunityResolver', () => {
foreignCom2.url = 'http://stage-3.gradido.net/api'
foreignCom2.publicKey = Buffer.from('publicKey-stage-3_Community')
foreignCom2.privateKey = Buffer.from('privateKey-stage-3_Community')
foreignCom2.communityUuid = 'Stage3-Com-UUID'
foreignCom2.communityUuid = uuidv4()
foreignCom2.authenticatedAt = new Date()
foreignCom2.name = 'Stage-3_Community-name'
foreignCom2.description = 'Stage-3_Community-description'
@ -490,7 +491,7 @@ describe('CommunityResolver', () => {
await expect(
query({
query: getCommunityByUuidQuery,
variables: { communityUuid: homeCom?.communityUuid },
variables: { communityIdentifier: homeCom?.communityUuid },
}),
).resolves.toMatchObject({
data: {
@ -563,7 +564,7 @@ describe('CommunityResolver', () => {
expect(
await mutate({
mutation: updateHomeCommunityQuery,
variables: { uuid: 'unknownUuid', gmsApiKey: 'gmsApiKey' },
variables: { uuid: uuidv4(), gmsApiKey: 'gmsApiKey' },
}),
).toEqual(
expect.objectContaining({

View File

@ -1,16 +1,17 @@
import { IsNull, Not } from '@dbTools/typeorm'
import { Community as DbCommunity } from '@entity/Community'
import { FederatedCommunity as DbFederatedCommunity } from '@entity/FederatedCommunity'
import { Resolver, Query, Authorized, Arg, Mutation, Args } from 'type-graphql'
import { Resolver, Query, Authorized, Mutation, Args } from 'type-graphql'
import { CommunityArgs } from '@arg//CommunityArgs'
import { EditCommunityInput } from '@input/EditCommunityInput'
import { Community } from '@model/Community'
import { FederatedCommunity } from '@model/FederatedCommunity'
import { RIGHTS } from '@/auth/RIGHTS'
import { LogError } from '@/server/LogError'
import { getCommunityByUuid } from './util/communities'
import { getCommunity } from './util/communities'
@Resolver()
export class CommunityResolver {
@ -41,41 +42,30 @@ export class CommunityResolver {
return dbCommunities.map((dbCom: DbCommunity) => new Community(dbCom))
}
@Authorized([RIGHTS.COMMUNITY_BY_UUID])
@Authorized([RIGHTS.COMMUNITIES])
@Query(() => Community)
async community(@Arg('communityUuid') communityUuid: string): Promise<Community> {
const com: DbCommunity | null = await getCommunityByUuid(communityUuid)
if (!com) {
throw new LogError('community not found', communityUuid)
async community(@Args() { communityIdentifier, foreign }: CommunityArgs): Promise<Community> {
const community = await getCommunity(communityIdentifier, foreign)
if (!community) {
throw new LogError('community not found', communityIdentifier, foreign)
}
return new Community(com)
return new Community(community)
}
@Authorized([RIGHTS.COMMUNITY_UPDATE])
@Mutation(() => Community)
async updateHomeCommunity(@Args() { uuid, gmsApiKey }: CommunityArgs): Promise<Community> {
let homeCom: DbCommunity | null
let com: Community
if (uuid) {
let toUpdate = false
homeCom = await getCommunityByUuid(uuid)
if (!homeCom) {
throw new LogError('HomeCommunity with uuid not found: ', uuid)
}
if (homeCom.foreign) {
throw new LogError('Error: Only the HomeCommunity could be modified!')
}
if (homeCom.gmsApiKey !== gmsApiKey) {
homeCom.gmsApiKey = gmsApiKey
toUpdate = true
}
if (toUpdate) {
await DbCommunity.save(homeCom)
}
com = new Community(homeCom)
} else {
throw new LogError(`HomeCommunity without an uuid can't be modified!`)
async updateHomeCommunity(@Args() { uuid, gmsApiKey }: EditCommunityInput): Promise<Community> {
const homeCom = await getCommunity(uuid)
if (!homeCom) {
throw new LogError('HomeCommunity with uuid not found: ', uuid)
}
return com
if (homeCom.foreign) {
throw new LogError('Error: Only the HomeCommunity could be modified!')
}
if (homeCom.gmsApiKey !== gmsApiKey) {
homeCom.gmsApiKey = gmsApiKey
await DbCommunity.save(homeCom)
}
return new Community(homeCom)
}
}

View File

@ -38,7 +38,7 @@ import { calculateBalance } from '@/util/validate'
import { virtualLinkTransaction, virtualDecayTransaction } from '@/util/virtualTransactions'
import { BalanceResolver } from './BalanceResolver'
import { getCommunityByUuid, getCommunityName, isHomeCommunity } from './util/communities'
import { getCommunity, getCommunityName, isHomeCommunity } from './util/communities'
import { findUserByIdentifier } from './util/findUserByIdentifier'
import { getLastTransaction } from './util/getLastTransaction'
import { getTransactionList } from './util/getTransactionList'
@ -452,7 +452,7 @@ export class TransactionResolver {
if (!CONFIG.FEDERATION_XCOM_SENDCOINS_ENABLED) {
throw new LogError('X-Community sendCoins disabled per configuration!')
}
const recipCom = await getCommunityByUuid(recipientCommunityIdentifier)
const recipCom = await getCommunity(recipientCommunityIdentifier)
logger.debug('recipient commuity: ', recipCom)
if (recipCom === null) {
throw new LogError(

View File

@ -1,65 +1,116 @@
import { FindOptionsWhere } from '@dbTools/typeorm'
import { Community as DbCommunity } from '@entity/Community'
import { isURL } from 'class-validator'
import { LogError } from '@/server/LogError'
import { isUUID4 } from '@/util/validate'
function getCommunityFindOptions(
communityIdentifier?: string | boolean | null,
foreign?: boolean | null,
): FindOptionsWhere<DbCommunity> {
if (communityIdentifier === undefined && foreign === undefined) {
throw new LogError('one of communityIdentifier or foreign must be set')
}
const where: FindOptionsWhere<DbCommunity> = {}
// != null cover !== null and !== undefined
if (communityIdentifier != null) {
if (typeof communityIdentifier === 'boolean') {
if (typeof foreign === 'boolean') {
throw new LogError('communityIdentifier cannot be boolean if foreign is set separately ')
}
where.foreign = communityIdentifier
} else if (isURL(communityIdentifier)) {
where.url = communityIdentifier
} else if (isUUID4(communityIdentifier)) {
where.communityUuid = communityIdentifier
}
}
if (typeof foreign === 'boolean') {
where.foreign = foreign
}
return where
}
/**
* Retrieves a community from the database based on the provided identifier and foreign status.
* If communityIdentifier is a string, it can represent either the URL, UUID, or name of the community.
* If communityIdentifier is a boolean, it represents the foreign status of the community.
* If foreign is provided separately and is a boolean, it represents the foreign status of the community.
* communityIdentifier and foreign cannot both be boolean
* @param communityIdentifier The identifier (URL, UUID, or name) of the community, or a boolean representing the foreign status.
* @param foreign Optional. If provided and is a boolean, it represents the foreign status of the community.
* @returns A promise that resolves to a DbCommunity object if found, or null if not found.
*/
export async function getCommunity(
communityIdentifier?: string | boolean | null,
foreign?: boolean | null,
): Promise<DbCommunity | null> {
return DbCommunity.findOne({ where: getCommunityFindOptions(communityIdentifier, foreign) })
}
/**
* Retrieves a community from the database based on the provided identifier and foreign status.
* If communityIdentifier is a string, it can represent either the URL, UUID, or name of the community.
* If communityIdentifier is a boolean, it represents the foreign status of the community.
* If foreign is provided separately and is a boolean, it represents the foreign status of the community.
* communityIdentifier and foreign cannot both be boolean
* @param communityIdentifier The identifier (URL, UUID, or name) of the community, or a boolean representing the foreign status.
* @param foreign Optional. If provided and is a boolean, it represents the foreign status of the community.
* @returns A promise that resolves to a DbCommunity object if found, or throw if not found.
*/
export async function getCommunityOrFail(
communityIdentifier?: string | boolean | null,
foreign?: boolean | null,
): Promise<DbCommunity> {
return DbCommunity.findOneOrFail({
where: getCommunityFindOptions(communityIdentifier, foreign),
})
}
/**
* Checks if a community with the given identifier exists and is not foreign.
* @param communityIdentifier The identifier (URL, UUID, or name) of the community.
* @returns A promise that resolves to true if a non-foreign community exists with the given identifier, otherwise false.
*/
export async function isHomeCommunity(communityIdentifier: string): Promise<boolean> {
const homeCommunity = await DbCommunity.findOne({
where: [
{ foreign: false, communityUuid: communityIdentifier },
{ foreign: false, name: communityIdentifier },
{ foreign: false, url: communityIdentifier },
],
})
if (homeCommunity) {
return true
} else {
return false
}
return (await getCommunity(communityIdentifier, false)) !== null
}
/**
* Retrieves the home community, i.e., a community that is not foreign.
* @returns A promise that resolves to the home community, or throw if no home community was found
*/
export async function getHomeCommunity(): Promise<DbCommunity> {
return await DbCommunity.findOneOrFail({
where: [{ foreign: false }],
})
return getCommunityOrFail(false)
}
/**
* Retrieves the URL of the community with the given identifier.
* @param communityIdentifier The identifier (URL, UUID, or name) of the community.
* @returns A promise that resolves to the URL of the community or throw if no community with this identifier was found
*/
export async function getCommunityUrl(communityIdentifier: string): Promise<string> {
const community = await DbCommunity.findOneOrFail({
where: [
{ communityUuid: communityIdentifier },
{ name: communityIdentifier },
{ url: communityIdentifier },
],
})
return community.url
return (await getCommunityOrFail(communityIdentifier)).url
}
/**
* Checks if a community with the given identifier exists and has an authenticatedAt property set.
* @param communityIdentifier The identifier (URL, UUID, or name) of the community.
* @returns A promise that resolves to true if a community with an authenticatedAt property exists with the given identifier, otherwise false.
*/
export async function isCommunityAuthenticated(communityIdentifier: string): Promise<boolean> {
const community = await DbCommunity.findOne({
where: [
{ communityUuid: communityIdentifier },
{ name: communityIdentifier },
{ url: communityIdentifier },
],
})
if (community?.authenticatedAt) {
return true
} else {
return false
}
// The !! operator is used to convert the result to a boolean value.
return !!(await getCommunity(communityIdentifier))?.authenticatedAt
}
/**
* Retrieves the name of the community with the given identifier.
* @param communityIdentifier The identifier (URL, UUID, or name) of the community.
* @returns A promise that resolves to the name of the community. If the community does not exist or has no name, an empty string is returned.
*/
export async function getCommunityName(communityIdentifier: string): Promise<string> {
const community = await DbCommunity.findOne({
where: [{ communityUuid: communityIdentifier }, { url: communityIdentifier }],
})
if (community?.name) {
return community.name
} else {
return ''
}
}
export async function getCommunityByUuid(communityUuid: string): Promise<DbCommunity | null> {
return await DbCommunity.findOne({
where: [{ communityUuid }],
})
return (await getCommunity(communityIdentifier))?.name ?? ''
}

View File

@ -2,9 +2,11 @@ import { FindOptionsWhere } from '@dbTools/typeorm'
import { Community } from '@entity/Community'
import { User as DbUser } from '@entity/User'
import { UserContact as DbUserContact } from '@entity/UserContact'
import { isURL } from 'class-validator'
import { validate, version } from 'uuid'
import { LogError } from '@/server/LogError'
import { isEMail, isUUID4 } from '@/util/validate'
import { VALID_ALIAS_REGEX } from './validateAlias'
@ -19,10 +21,11 @@ export const findUserByIdentifier = async (
communityIdentifier: string,
): Promise<DbUser> => {
let user: DbUser | null
const communityWhere: FindOptionsWhere<Community> =
validate(communityIdentifier) && version(communityIdentifier) === 4
? { communityUuid: communityIdentifier }
: { name: communityIdentifier }
const communityWhere: FindOptionsWhere<Community> = isURL(communityIdentifier)
? { url: communityIdentifier }
: isUUID4(communityIdentifier)
? { communityUuid: communityIdentifier }
: { name: communityIdentifier }
if (validate(identifier) && version(identifier) === 4) {
user = await DbUser.findOne({
@ -32,7 +35,7 @@ export const findUserByIdentifier = async (
if (!user) {
throw new LogError('No user found to given identifier(s)', identifier, communityIdentifier)
}
} else if (/^.{2,}@.{2,}\..{2,}$/.exec(identifier)) {
} else if (isEMail(identifier)) {
const userContact = await DbUserContact.findOne({
where: {
email: identifier,

View File

@ -135,8 +135,8 @@ export const communitiesQuery = gql`
`
export const getCommunityByUuidQuery = gql`
query ($communityUuid: String!) {
community(communityUuid: $communityUuid) {
query ($communityIdentifier: String!) {
community(communityIdentifier: $communityIdentifier) {
id
foreign
name

View File

@ -1,5 +1,6 @@
import { TransactionLink as dbTransactionLink } from '@entity/TransactionLink'
import { Decimal } from 'decimal.js-light'
import { validate, version } from 'uuid'
import { Decay } from '@model/Decay'
@ -16,6 +17,14 @@ function isStringBoolean(value: string): boolean {
return false
}
function isUUID4(value: string): boolean {
return validate(value) && version(value) === 4
}
function isEMail(value: string): boolean {
return /^.{2,}@.{2,}\..{2,}$/.exec(value) !== null
}
async function calculateBalance(
userId: number,
amount: Decimal,
@ -42,4 +51,4 @@ async function calculateBalance(
return { balance, lastTransactionId: lastTransaction.id, decay }
}
export { calculateBalance, isStringBoolean }
export { calculateBalance, isStringBoolean, isUUID4, isEMail }

View File

@ -49,6 +49,7 @@
"paths": { /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
"@/*": ["src/*"],
"@arg/*": ["src/graphql/arg/*"],
"@input/*": ["src/graphql/input/*"],
"@dltConnector/*": ["src/apis/dltConnector/*"],
"@enum/*": ["src/graphql/enum/*"],
"@model/*": ["src/graphql/model/*"],

View File

@ -19,4 +19,7 @@ DB_DATABASE_TEST=gradido_dlt_test
TYPEORM_LOGGING_RELATIVE_PATH=typeorm.backend.log
# DLT-Connector
DLT_CONNECTOR_PORT=6010
DLT_CONNECTOR_PORT=6010
# Route to Backend
BACKEND_SERVER_URL=http://localhost:4000

View File

@ -15,4 +15,7 @@ DB_DATABASE_TEST=$DB_DATABASE_TEST
TYPEORM_LOGGING_RELATIVE_PATH=typeorm.backend.log
# DLT-Connector
DLT_CONNECTOR_PORT=$DLT_CONNECTOR_PORT
DLT_CONNECTOR_PORT=$DLT_CONNECTOR_PORT
# Route to Backend
BACKEND_SERVER_URL=http://localhost:4000

View File

@ -6,7 +6,7 @@ module.exports = {
collectCoverageFrom: ['src/**/*.ts', '!**/node_modules/**', '!src/seeds/**', '!build/**'],
coverageThreshold: {
global: {
lines: 66,
lines: 63,
},
},
setupFiles: ['<rootDir>/test/testSetup.ts'],

View File

@ -31,6 +31,7 @@
"express": "4.17.1",
"express-slow-down": "^2.0.1",
"graphql": "^16.7.1",
"graphql-request": "^6.1.0",
"graphql-scalars": "^1.22.2",
"helmet": "^7.1.0",
"log4js": "^6.7.1",

View File

@ -0,0 +1,88 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { gql, GraphQLClient } from 'graphql-request'
import { CONFIG } from '@/config'
import { CommunityDraft } from '@/graphql/input/CommunityDraft'
import { logger } from '@/logging/logger'
import { LogError } from '@/server/LogError'
const communityByForeign = gql`
query ($foreign: Boolean) {
community(foreign: $foreign) {
uuid
foreign
creationDate
}
}
`
interface Community {
community: {
uuid: string
foreign: boolean
creationDate: string
}
}
// Source: https://refactoring.guru/design-patterns/singleton/typescript/example
// and ../federation/client/FederationClientFactory.ts
/**
* A Singleton class defines the `getInstance` method that lets clients access
* the unique singleton instance.
*/
// eslint-disable-next-line @typescript-eslint/no-extraneous-class
export class BackendClient {
// eslint-disable-next-line no-use-before-define
private static instance: BackendClient
client: GraphQLClient
/**
* The Singleton's constructor should always be private to prevent direct
* construction calls with the `new` operator.
*/
// eslint-disable-next-line no-useless-constructor, @typescript-eslint/no-empty-function
private constructor() {}
/**
* The static method that controls the access to the singleton instance.
*
* This implementation let you subclass the Singleton class while keeping
* just one instance of each subclass around.
*/
public static getInstance(): BackendClient | undefined {
if (!BackendClient.instance) {
BackendClient.instance = new BackendClient()
}
if (!BackendClient.instance.client) {
try {
BackendClient.instance.client = new GraphQLClient(CONFIG.BACKEND_SERVER_URL, {
headers: {
'content-type': 'application/json',
},
method: 'POST',
jsonSerializer: {
parse: JSON.parse,
stringify: JSON.stringify,
},
})
} catch (e) {
logger.error("couldn't connect to backend: ", e)
return
}
}
return BackendClient.instance
}
public async homeCommunityUUid(): Promise<CommunityDraft> {
logger.info('check home community on backend')
const { data, errors } = await this.client.rawRequest<Community>(communityByForeign, {
foreign: false,
})
if (errors) {
throw new LogError('error getting home community from backend', errors)
}
const communityDraft = new CommunityDraft()
communityDraft.uuid = data.community.uuid
communityDraft.foreign = data.community.foreign
communityDraft.createdAt = data.community.creationDate
return communityDraft
}
}

View File

@ -9,7 +9,7 @@ const constants = {
LOG_LEVEL: process.env.LOG_LEVEL ?? 'info',
CONFIG_VERSION: {
DEFAULT: 'DEFAULT',
EXPECTED: 'v4.2023-09-12',
EXPECTED: 'v5.2024-02-24',
CURRENT: '',
},
}
@ -38,6 +38,10 @@ const dltConnector = {
DLT_CONNECTOR_PORT: process.env.DLT_CONNECTOR_PORT ?? 6010,
}
const backendServer = {
BACKEND_SERVER_URL: process.env.BACKEND_SERVER_URL ?? 'http://backend:4000',
}
// Check config version
constants.CONFIG_VERSION.CURRENT = process.env.CONFIG_VERSION ?? constants.CONFIG_VERSION.DEFAULT
if (
@ -56,4 +60,5 @@ export const CONFIG = {
...database,
...iota,
...dltConnector,
...backendServer,
}

View File

@ -1,13 +1,61 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import 'reflect-metadata'
import { CONFIG } from '@/config'
import { BackendClient } from './client/BackendClient'
import { CommunityRepository } from './data/Community.repository'
import { CommunityDraft } from './graphql/input/CommunityDraft'
import { AddCommunityContext } from './interactions/backendToDb/community/AddCommunity.context'
import { logger } from './logging/logger'
import createServer from './server/createServer'
import { LogError } from './server/LogError'
async function waitForServer(
backend: BackendClient,
retryIntervalMs: number,
maxRetries: number,
): Promise<CommunityDraft> {
let retries = 0
while (retries < maxRetries) {
logger.info(`Attempt ${retries + 1} for connecting to backend`)
try {
// Make a HEAD request to the server
return await backend.homeCommunityUUid()
} catch (error) {
logger.info('Server is not reachable: ', error)
}
// Server is not reachable, wait and retry
await new Promise((resolve) => setTimeout(resolve, retryIntervalMs))
retries++
}
throw new LogError('Max retries exceeded. Server did not become reachable.')
}
async function main() {
// eslint-disable-next-line no-console
console.log(`DLT_CONNECTOR_PORT=${CONFIG.DLT_CONNECTOR_PORT}`)
const { app } = await createServer()
// ask backend for home community if we haven't one
try {
await CommunityRepository.loadHomeCommunityKeyPair()
} catch (e) {
const backend = BackendClient.getInstance()
if (!backend) {
throw new LogError('cannot create backend client')
}
// wait for backend server to be ready
await waitForServer(backend, 1000, 8)
const communityDraft = await backend.homeCommunityUUid()
const addCommunityContext = new AddCommunityContext(communityDraft)
await addCommunityContext.run()
}
app.listen(CONFIG.DLT_CONNECTOR_PORT, () => {
// eslint-disable-next-line no-console
console.log(`Server is running at http://localhost:${CONFIG.DLT_CONNECTOR_PORT}`)

View File

@ -63,7 +63,7 @@
"@entity/*": ["../dlt-database/entity/*", "../../dlt-database/build/entity/*"]
},
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
"typeRoots": ["node_modules/@types"], /* List of folders to include type definitions from. */
"typeRoots": ["@types", "node_modules/@types"], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */

View File

@ -569,7 +569,7 @@
"@graphql-typed-document-node/core" "^3.1.1"
tslib "^2.4.0"
"@graphql-typed-document-node/core@^3.1.1":
"@graphql-typed-document-node/core@^3.1.1", "@graphql-typed-document-node/core@^3.2.0":
version "3.2.0"
resolved "https://registry.yarnpkg.com/@graphql-typed-document-node/core/-/core-3.2.0.tgz#5f3d96ec6b2354ad6d8a28bf216a1d97b5426861"
integrity sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==
@ -2119,6 +2119,13 @@ cross-env@^7.0.3:
dependencies:
cross-spawn "^7.0.1"
cross-fetch@^3.1.5:
version "3.1.8"
resolved "https://registry.yarnpkg.com/cross-fetch/-/cross-fetch-3.1.8.tgz#0327eba65fd68a7d119f8fb2bf9334a1a7956f82"
integrity sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==
dependencies:
node-fetch "^2.6.12"
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@ -3329,6 +3336,14 @@ graphql-query-complexity@^0.12.0:
dependencies:
lodash.get "^4.4.2"
graphql-request@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/graphql-request/-/graphql-request-6.1.0.tgz#f4eb2107967af3c7a5907eb3131c671eac89be4f"
integrity sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==
dependencies:
"@graphql-typed-document-node/core" "^3.2.0"
cross-fetch "^3.1.5"
graphql-scalars@^1.22.2:
version "1.22.2"
resolved "https://registry.yarnpkg.com/graphql-scalars/-/graphql-scalars-1.22.2.tgz#6326e6fe2d0ad4228a9fea72a977e2bf26b86362"
@ -4775,7 +4790,7 @@ node-abort-controller@^3.1.1:
resolved "https://registry.yarnpkg.com/node-abort-controller/-/node-abort-controller-3.1.1.tgz#a94377e964a9a37ac3976d848cb5c765833b8548"
integrity sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==
node-fetch@^2.6.7:
node-fetch@^2.6.12, node-fetch@^2.6.7:
version "2.7.0"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.7.0.tgz#d0f0fa6e3e2dc1d27efcd8ad99d550bda94d187d"
integrity sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==