From 0a1aa5d3c53d93850dcde6a569f7e2a7a58782af Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Tue, 21 May 2024 13:45:18 +0200 Subject: [PATCH 01/37] WIP --- .env.template | 41 +++-- Dockerfile | 1 - src/common/appSettings.ts | 26 ++- src/common/commonTypeDef.ts | 7 + src/common/dripsContracts.ts | 85 ++++++++++ src/common/provider.ts | 4 - src/common/queryableChains.ts | 12 ++ src/common/types.ts | 52 ++++-- src/dataLoaders/ProjectsDataSource.ts | 116 ++++++++++---- src/database/connectToDatabase.ts | 10 +- src/drip-list/dripListResolvers.ts | 5 +- src/environment.d.ts | 14 +- src/project/projectResolvers.ts | 221 ++++++++++++++------------ src/project/projectTypeDef.ts | 26 ++- src/project/projectUtils.ts | 113 ++++++++++--- src/resolvers.ts | 7 +- src/schema.ts | 8 +- src/server.ts | 2 +- src/user/UserDataSource.ts | 11 +- src/user/userResolvers.ts | 11 +- src/utils/getSchema.ts | 8 +- 21 files changed, 537 insertions(+), 243 deletions(-) create mode 100644 src/common/dripsContracts.ts delete mode 100644 src/common/provider.ts create mode 100644 src/common/queryableChains.ts diff --git a/.env.template b/.env.template index e384487..fb7580d 100644 --- a/.env.template +++ b/.env.template @@ -1,16 +1,25 @@ -PORT=string -NETWORK=string # See 'SupportedNetwork' type. -PUBLIC_API_KEYS=string # comma-separated list of strings -DRIPS_API_KEY=string -INFURA_API_KEY=string -POSTGRES_CONNECTION_STRING=string -REPO_DRIVER_ADDRESS=string # optional, defaults to mainnet address of latest deployment -RPC_URL=string # optional, defaults to infura mainnet -PRETEND_ALL_REPOS_EXIST=boolean # true or false. If true, app will always assume all GitHub repos exist. Used in E2E tests. Defaults to false. -NODE_ENV=string # 'development' or 'production'. -RATE_LIMIT_WINDOW_IN_MINUTES=number # optional, defaults to 2. -RATE_LIMIT_MAX_REQUESTS_PER_WINDOW=number # optional, defaults to 1000. -MAX_QUERY_DEPTH=number # optional, defaults to 4. -TIMEOUT_IN_SECONDS=number # optional, defaults to 20. -ADDRESS_DRIVER_ADDRESS=string # required, address of the `AddressDriver` contract. -IPFS_GATEWAY_URL=string # required, URL of the IPFS gateway. \ No newline at end of file +PORT=string # Optional. The API server port. Defaults to 8080. + +NETWORK=string # Required. The network to connect to. See `SupportedNetworks` in `types.ts` for supported networks. + +# You should provide at least one of the following RPC URLs: +RPC_URL_MAINNET=string # The RPC URL for the Mainnet provider. +RPC_URL_SEPOLIA=string # The RPC URL for the Sepolia provider. +RPC_URL_OPTIMISM_SEPOLIA=string # The RPC URL for the Optimism Sepolia provider. +RPC_URL_POLYGON_AMOY=string # The RPC URL for the Polygon Amoy provider. + +PUBLIC_API_KEYS=string # Required. Comma-separated list of strings API keys that rate limit is applied to. +DRIPS_API_KEY=string # Required. API key withouth rate limit. + +NODE_ENV=string # Required. 'development' or 'production'. + +POSTGRES_CONNECTION_STRING=string # Required. The connection string for the database. + +PRETEND_ALL_REPOS_EXIST=boolean # If true, app will always assume all GitHub repos exist. Used in E2E tests. Defaults to false. + +RATE_LIMIT_WINDOW_IN_MINUTES=number # Optional. defaults to 2. +RATE_LIMIT_MAX_REQUESTS_PER_WINDOW=number # Optional. defaults to 1000. +MAX_QUERY_DEPTH=number # Optional. defaults to 4. +TIMEOUT_IN_SECONDS=number # Optional. defaults to 20. + +IPFS_GATEWAY_URL=string # Optional. The IPFS gateway URL to use for fetching IPFS data. Defaults to 'https://drips.mypinata.cloud'. diff --git a/Dockerfile b/Dockerfile index f8e53fe..e8aac8f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,7 +9,6 @@ RUN npm ci ENV PORT=8080 ENV NETWORK=localtestnet ENV PUBLIC_API_KEYS=afdb8b7e-8fa7-4de9-bd95-b650b839e745 -ENV INFURA_API_KEY=ef24377ad66642b8a0dcdaa42ea95e7c ENV POSTGRES_CONNECTION_STRING=postgresql://user:admin@postgres-event-processor:5432/dripsdb ENV PRETEND_ALL_REPOS_EXIST=true ENV REPO_DRIVER_ADDRESS=0xb9C8e18E82687a564Ac4D26E22D28a4C95057CE9 diff --git a/src/common/appSettings.ts b/src/common/appSettings.ts index 7edb6e3..2707d18 100644 --- a/src/common/appSettings.ts +++ b/src/common/appSettings.ts @@ -1,24 +1,21 @@ import dotenv from 'dotenv'; -import shouldNeverHappen from '../utils/shouldNeverHappen'; dotenv.config({ path: `.env.${process.env.ENV}` }); export default { port: (process.env.PORT || 8080) as number, - network: process.env.NETWORK, - environment: process.env.ENV ?? 'local', - infuraApiKey: process.env.INFURA_API_KEY, + rpcUrls: { + mainnet: process.env.RPC_URL_MAINNET, + sepolia: process.env.RPC_URL_SEPOLIA, + optimism_sepolia: process.env.RPC_URL_OPTIMISM_SEPOLIA, + polygon_amoy: process.env.RPC_URL_POLYGON_AMOY, + }, publicApiKeys: process.env.PUBLIC_API_KEYS?.split(',') || [], dripsApiKey: process.env.DRIPS_API_KEY, postgresConnectionString: process.env.POSTGRES_CONNECTION_STRING, - rpcUrl: - process.env.RPC_URL ?? - `https://mainnet.infura.io/v3/${process.env.INFURA_API_KEY}`, - repoDriverAddress: - process.env.REPO_DRIVER_ADDRESS ?? - '0x770023d55D09A9C110694827F1a6B32D5c2b373E', pretendAllReposExist: - (process.env.PRETEND_ALL_REPOS_EXIST as unknown as string) === 'true', + (process.env.PRETEND_ALL_REPOS_EXIST as unknown as string) === 'true' || + false, rateLimitWindowInMinutes: parseInt( process.env.RATE_LIMIT_WINDOW_IN_MINUTES ?? '2', 10, @@ -29,9 +26,6 @@ export default { ), maxQueryDepth: parseInt(process.env.MAX_QUERY_DEPTH ?? '10', 10), timeoutInSeconds: parseInt(process.env.TIMEOUT_IN_SECONDS ?? '20', 10), - // TODO: Refactor when we switch to multi-chain API. - addressDriverAddress: - process.env.ADDRESS_DRIVER_ADDRESS || - shouldNeverHappen('Missing address driver address in .env file.'), - ipfsGatewayUrl: process.env.IPFS_GATEWAY_URL, + ipfsGatewayUrl: + process.env.IPFS_GATEWAY_URL || 'https://drips.mypinata.cloud', }; diff --git a/src/common/commonTypeDef.ts b/src/common/commonTypeDef.ts index 3e85a73..62d1cb6 100644 --- a/src/common/commonTypeDef.ts +++ b/src/common/commonTypeDef.ts @@ -122,6 +122,13 @@ const commonTypeDef = gql` ASC DESC } + + enum SupportedChain { + mainnet + sepolia + optimism_sepolia + polygon_amoy + } `; export default commonTypeDef; diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts new file mode 100644 index 0000000..3a91256 --- /dev/null +++ b/src/common/dripsContracts.ts @@ -0,0 +1,85 @@ +import { JsonRpcProvider, WebSocketProvider } from 'ethers'; +import appSettings from './appSettings'; +import type { AddressDriver, RepoDriver } from '../generated/contracts'; +import { + AddressDriver__factory, + RepoDriver__factory, +} from '../generated/contracts'; +import shouldNeverHappen from '../utils/shouldNeverHappen'; +import { SupportedChain } from '../generated/graphql'; + +const chainConfigs: Record< + SupportedChain, + { + addressDriverAddress: string; + repoDriverAddress: string; + } +> = { + mainnet: { + addressDriverAddress: '0x1455d9bD6B98f95dd8FEB2b3D60ed825fcef0610', + repoDriverAddress: '0x770023d55D09A9C110694827F1a6B32D5c2b373E', + }, + sepolia: { + addressDriverAddress: '0x70E1E1437AeFe8024B6780C94490662b45C3B567', + repoDriverAddress: '0xa71bdf410D48d4AA9aE1517A69D7E1Ef0c179b2B', + }, + optimism_sepolia: { + addressDriverAddress: '0x70E1E1437AeFe8024B6780C94490662b45C3B567', + repoDriverAddress: '0xa71bdf410D48d4AA9aE1517A69D7E1Ef0c179b2B', + }, + polygon_amoy: { + addressDriverAddress: '0x004310a6d47893Dd6e443cbE471c24aDA1e6c619', + repoDriverAddress: '0x54372850Db72915Fd9C5EC745683EB607b4a8642', + }, +}; + +const { rpcUrls } = appSettings; + +const providers: { + [network in SupportedChain]?: JsonRpcProvider | WebSocketProvider; +} = {}; + +for (const network of Object.keys(SupportedChain)) { + if (rpcUrls[network as SupportedChain]) { + const rpcUrl = rpcUrls[network as SupportedChain] as string; + + // eslint-disable-next-line no-nested-ternary + const provider = rpcUrl.startsWith('http') + ? new JsonRpcProvider(rpcUrl) + : rpcUrl.startsWith('wss') + ? new WebSocketProvider(rpcUrl) + : shouldNeverHappen(`Invalid RPC URL: ${rpcUrl}`); + + providers[network as SupportedChain] = provider; + } +} + +let dripsContracts: { + addressDriver: AddressDriver; + repoDriver: RepoDriver; +} = {} as any; + +Object.entries(providers).forEach(([network, provider]) => { + if (!chainConfigs[network as SupportedChain]) { + throw new Error(`Missing chain config for network '${network}'.`); + } + + const { addressDriverAddress, repoDriverAddress } = + chainConfigs[network as SupportedChain]; + + const addressDriver = AddressDriver__factory.connect( + addressDriverAddress, + provider, + ); + + const repoDriver = RepoDriver__factory.connect(repoDriverAddress, provider); + + dripsContracts = { + addressDriver, + repoDriver, + }; +}); + +export default { + contracts: dripsContracts, +}; diff --git a/src/common/provider.ts b/src/common/provider.ts deleted file mode 100644 index a3ea01b..0000000 --- a/src/common/provider.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { JsonRpcProvider } from 'ethers'; -import appSettings from './appSettings'; - -export default new JsonRpcProvider(appSettings.rpcUrl); diff --git a/src/common/queryableChains.ts b/src/common/queryableChains.ts new file mode 100644 index 0000000..52eb3a9 --- /dev/null +++ b/src/common/queryableChains.ts @@ -0,0 +1,12 @@ +import { SupportedChain } from '../generated/graphql'; +import appSettings from './appSettings'; + +const queryableChains: SupportedChain[] = []; + +for (const network of Object.keys(SupportedChain)) { + if (appSettings.rpcUrls[network as SupportedChain]) { + queryableChains.push(network as SupportedChain); + } +} + +export default queryableChains; diff --git a/src/common/types.ts b/src/common/types.ts index fb3d7f8..5713473 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -1,9 +1,15 @@ import type { AnyVersion } from '@efstajas/versioned-parser'; -import type { ProjectVerificationStatus } from '../generated/graphql'; +import type { + ClaimedProjectData, + Project, + SupportedChain, + UnClaimedProjectData, +} from '../generated/graphql'; import type StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; -import type { FORGES_MAP, SUPPORTED_NETWORKS } from './constants'; +import type { FORGES_MAP } from './constants'; import type { addressDriverAccountMetadataParser } from '../schemas'; import type StreamsSetEventModel from '../models/StreamsSetEventModel'; +import type ProjectModel from '../project/ProjectModel'; export type KnownAny = any; export type ValuesOf = T[keyof T]; @@ -22,22 +28,13 @@ export type Address = string & { __brand: 'Address' }; export type BigIntString = string & { __brand: 'BigIntString' }; export type Forge = ValuesOf; -export type DbSchema = SupportedNetwork & { __brand: 'dbSchema' }; -export type SupportedNetwork = (typeof SUPPORTED_NETWORKS)[number]; +export type DbSchema = SupportedChain; export enum DependencyType { ProjectDependency = 'ProjectDependency', DripListDependency = 'DripListDependency', } -export type FakeUnclaimedProject = { - id: ProjectId; - name: string; - forge: Forge; - url: string; - verificationStatus: ProjectVerificationStatus; -}; - export interface IEventModel { logIndex: number; blockNumber: number; @@ -69,3 +66,34 @@ export type AssetConfigMetadata = AccountMetadata['assetConfigs'][number]; export type StreamHistoryHashes = string & { __type: 'StreamHistoryHashes'; }; + +export type ProjectDataValues = ProjectModel['dataValues'] & { + createdAt: Date; + updatedAt: Date; + chain: SupportedChain; +}; + +export type ResolverProject = Project & { + chainData: ( + | ResolverClaimedChainProjectData + | ResolverUnClaimedChainProjectData + )[]; +}; + +export type ResolverClaimedProjectData = ClaimedProjectData & { + projectId: ProjectId; +}; + +export type ResolverClaimedChainProjectData = { + chain: SupportedChain; + data: ResolverClaimedProjectData; +}; + +export type ResolverUnClaimedProjectData = UnClaimedProjectData & { + projectId: ProjectId; +}; + +export type ResolverUnClaimedChainProjectData = { + chain: SupportedChain; + data: ResolverUnClaimedProjectData; +}; diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 3d5cb7b..b0966e4 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -1,21 +1,25 @@ -import type { Order, WhereOptions } from 'sequelize'; -import { Op } from 'sequelize'; +import { Op, QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; import ProjectModel from '../project/ProjectModel'; -import type { FakeUnclaimedProject, ProjectId } from '../common/types'; +import type { ProjectDataValues, ProjectId } from '../common/types'; import { doesRepoExists, - isValidateProjectName, + isValidProjectName, toApiProject, toFakeUnclaimedProjectFromUrl, } from '../project/projectUtils'; -import type { ProjectSortInput, ProjectWhereInput } from '../generated/graphql'; +import type { + ProjectSortInput, + ProjectWhereInput, + SupportedChain, +} from '../generated/graphql'; import SplitEventModel from '../models/SplitEventModel'; import GivenEventModel from '../given-event/GivenEventModel'; +import { dbConnection } from '../database/connectToDatabase'; export default class ProjectsDataSource { private readonly _batchProjectsByIds = new DataLoader( - async (projectIds: readonly ProjectId[]): Promise => { + async (projectIds: readonly ProjectId[]): Promise => { const projects = await ProjectModel.findAll({ where: { id: { @@ -25,14 +29,14 @@ export default class ProjectsDataSource { }, }).then((projectModels) => projectModels.filter((p) => - p.name ? isValidateProjectName(p.name) : true, + p.name ? isValidProjectName(p.name) : true, ), ); const projectIdToProjectMap = projects.reduce< - Record + Record >((mapping, project) => { - mapping[project.id] = project; // eslint-disable-line no-param-reassign + mapping[project.id] = project.dataValues as ProjectDataValues; // eslint-disable-line no-param-reassign return mapping; }, {}); @@ -43,14 +47,13 @@ export default class ProjectsDataSource { public async getProjectById( id: ProjectId, - ): Promise { + ): Promise { return toApiProject(await this._batchProjectsByIds.load(id)); } - public async getProjectByUrl( - url: string, - ): Promise { - const project = await ProjectModel.findOne({ where: { url } }); + public async getProjectByUrl(url: string): Promise { + const project = (await ProjectModel.findOne({ where: { url } })) + ?.dataValues as ProjectDataValues; if (project) { return toApiProject(project); @@ -62,26 +65,79 @@ export default class ProjectsDataSource { } public async getProjectsByFilter( + chains: SupportedChain[], where: ProjectWhereInput, sort?: ProjectSortInput, - ): Promise<(ProjectModel | FakeUnclaimedProject)[]> { - const order: Order = sort ? [[sort.field, sort.direction || 'DESC']] : []; - - const projects = - (await ProjectModel.findAll({ - where: (where as WhereOptions) || {}, - order, - })) || []; - - return projects - .filter((p) => p.isValid) - .filter((p) => (p.name ? isValidateProjectName(p.name) : true)) - .map(toApiProject) - .filter(Boolean) as (ProjectModel | FakeUnclaimedProject)[]; + ): Promise { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GitProjects" + `; + + // Initialize the WHERE clause parts. + const conditions: string[] = []; + const parameters: { [key: string]: any } = {}; + + // Build the WHERE clause based on input filters. + if (where?.id) { + conditions.push(`"id" = :id`); + parameters.id = where.id; + } + if (where?.ownerAddress) { + conditions.push(`"ownerAddress" = :ownerAddress`); + parameters.ownerAddress = where.ownerAddress; + } + if (where?.url) { + conditions.push(`"url" = :url`); + parameters.url = where.url; + } + if (where?.verificationStatus) { + conditions.push(`"verificationStatus" = :verificationStatus`); + parameters.verificationStatus = where.verificationStatus; + } + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Define the order. + const orderClause = sort + ? ` ORDER BY "${sort.field}" ${sort.direction || 'DESC'}` + : ''; + + // Build the SQL for each specified schema. + const queries = chains.map( + (chain) => baseSQL(chain) + whereClause + orderClause, + ); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const projectsDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: ProjectModel, + }) + ).map((p) => p.dataValues as ProjectDataValues); + + return Promise.all( + projectsDataValues + .filter((p) => p.isValid) + .filter((p) => (p.name ? isValidProjectName(p.name) : true)) + .map(toApiProject) + .filter(Boolean) as ProjectDataValues[], + ); } - public async getProjectsByIds(ids: ProjectId[]): Promise { - return this._batchProjectsByIds.loadMany(ids) as Promise; + public async getProjectsByIds( + ids: ProjectId[], + ): Promise { + return this._batchProjectsByIds.loadMany(ids) as Promise< + ProjectDataValues[] + >; } public async getEarnedFunds(projectId: ProjectId): Promise< diff --git a/src/database/connectToDatabase.ts b/src/database/connectToDatabase.ts index 30b5430..493fdce 100644 --- a/src/database/connectToDatabase.ts +++ b/src/database/connectToDatabase.ts @@ -13,12 +13,12 @@ import StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel import AccountMetadataEmittedEventModel from '../models/AccountMetadataEmittedEventModel'; import SqueezedStreamsEventModel from '../models/SqueezedStreamsEventModel'; -export default async function connectToDatabase() { - const dbConnection = new Sequelize( - `${appSettings.postgresConnectionString}`, - {}, - ); +export const dbConnection = new Sequelize( + `${appSettings.postgresConnectionString}`, + {}, +); +export async function connectToDatabase() { await dbConnection.authenticate(); ProjectModel.initialize(dbConnection); diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index fba1ae7..71d3f19 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -1,5 +1,5 @@ import { isAddress } from 'ethers'; -import type { Address, DripListId } from '../common/types'; +import type { Address, DripListId, ProjectDataValues } from '../common/types'; import type DripListModel from './DripListModel'; import type { AddressDriverAccount, @@ -13,7 +13,6 @@ import type { import { Driver } from '../generated/graphql'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { Context } from '../server'; -import type GitProjectModel from '../project/ProjectModel'; import assert, { isDripListId } from '../utils/assert'; const dripListResolvers = { @@ -118,7 +117,7 @@ const dripListResolvers = { project: (splitsOfTypeProjectModels .filter( - (p): p is GitProjectModel => p && (p as any).id !== undefined, + (p): p is ProjectDataValues => p && (p as any).id !== undefined, ) .find( (p) => (p as any).id === receiver.fundeeProjectId, diff --git a/src/environment.d.ts b/src/environment.d.ts index dfc5579..c1d28b4 100644 --- a/src/environment.d.ts +++ b/src/environment.d.ts @@ -1,23 +1,23 @@ -import type { SupportedNetwork } from './common/types'; +import type { SupportedChain } from './common/types'; declare global { namespace NodeJS { interface ProcessEnv { PORT: string; + RPC_URL_MAINNET: string; + RPC_URL_SEPOLIA: string; + RPC_URL_OPTIMISM_SEPOLIA: string; + RPC_URL_POLYGON_AMOY: string; PUBLIC_API_KEYS: string; DRIPS_API_KEY: string; - INFURA_API_KEY: string; - NETWORK: SupportedNetwork; - ENV: 'local' | SupportedNetwork; + NODE_ENV: 'development' | 'production'; + ENV: 'local' | SupportedChain; POSTGRES_CONNECTION_STRING: string; - RPC_URL: string | undefined; - REPO_DRIVER_ADDRESS: string | undefined; PRETEND_ALL_REPOS_EXIST: boolean; RATE_LIMIT_WINDOW_IN_MINUTES: string; RATE_LIMIT_MAX_REQUESTS_PER_WINDOW: string; MAX_QUERY_DEPTH: string; TIMEOUT_IN_SECONDS: string; - ADDRESS_DRIVER_ADDRESS: string; IPFS_GATEWAY_URL: string; } } diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 178c1e2..215f6ee 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -1,10 +1,16 @@ import { isAddress } from 'ethers'; -import type { FakeUnclaimedProject, ProjectId } from '../common/types'; -import type ProjectModel from './ProjectModel'; -import { ProjectVerificationStatus } from './ProjectModel'; -import { splitProjectName } from './projectUtils'; +import type { + ProjectDataValues, + ProjectId, + ResolverClaimedChainProjectData, + ResolverClaimedProjectData, + ResolverProject, + ResolverUnClaimedChainProjectData, + ResolverUnClaimedProjectData, +} from '../common/types'; +import { toResolverProjects } from './projectUtils'; import shouldNeverHappen from '../utils/shouldNeverHappen'; -import { Driver } from '../generated/graphql'; +import { Driver, SupportedChain } from '../generated/graphql'; import type { SplitsReceiver, Source, @@ -13,10 +19,11 @@ import type { Splits, Project, AddressReceiver, - Forge, DripList, ProjectWhereInput, ProjectSortInput, + ProjectChainData, + Avatar, } from '../generated/graphql'; import type { Context } from '../server'; import { AddressDriverSplitReceiverType } from '../models/AddressDriverSplitReceiverModel'; @@ -28,6 +35,7 @@ import assert, { isProjectId, isSortableProjectField, } from '../utils/assert'; +import queryableChains from '../common/queryableChains'; const projectResolvers = { Query: { @@ -35,7 +43,7 @@ const projectResolvers = { _: any, { id }: { id: ProjectId }, { dataSources }: Context, - ): Promise => { + ): Promise => { assert(isProjectId(id)); return dataSources.projectsDb.getProjectById(id); @@ -44,16 +52,24 @@ const projectResolvers = { _: any, { url }: { url: string }, { dataSources }: Context, - ): Promise => { + ): Promise => { assert(isGitHubUrl(url)); return dataSources.projectsDb.getProjectByUrl(url); }, projects: async ( _: any, - { where, sort }: { where: ProjectWhereInput; sort: ProjectSortInput }, + { + chains, + where, + sort, + }: { + chains: SupportedChain[]; + where: ProjectWhereInput; + sort: ProjectSortInput; + }, { dataSources }: Context, - ): Promise<(ProjectModel | FakeUnclaimedProject)[]> => { + ): Promise => { if (where?.id) { assert(isProjectId(where.id)); } @@ -74,7 +90,22 @@ const projectResolvers = { assert(isSortableProjectField(sort.field)); } - return dataSources.projectsDb.getProjectsByFilter(where, sort); + if (chains) { + chains.forEach((chain) => { + assert(chain in SupportedChain); + }); + } + + const chainsToQuery = chains?.length ? chains : queryableChains; + + const projectsDataValues = + await dataSources.projectsDb.getProjectsByFilter( + chainsToQuery, + where, + sort, + ); + + return toResolverProjects(chainsToQuery, projectsDataValues); }, earnedFunds: async ( _: any, @@ -87,61 +118,47 @@ const projectResolvers = { }, }, Project: { - __resolveType(parent: ProjectModel) { - if (parent.verificationStatus === ProjectVerificationStatus.Claimed) { - return 'ClaimedProject'; - } - - return 'UnclaimedProject'; - }, + account: (project: ResolverProject): RepoDriverAccount => project.account, + source: (project: ResolverProject): Source => project.source, }, - Avatar: { - __resolveType(parent: { cid: string } | { emoji: string }) { - if ('cid' in parent) { - return 'ImageAvatar'; + ProjectChainData: { + __resolveType(parent: ProjectChainData) { + if ('claimedAt' in parent.data) { + return 'ClaimedChainProjectData'; } - return 'EmojiAvatar'; + return 'UnClaimedChainProjectData'; }, }, - ClaimedProject: { - color: (project: ProjectModel): string => - project.color || shouldNeverHappen(), - description: (project: ProjectModel): string | null => project.description, - emoji: (project: ProjectModel): string => project.emoji || '💧', - avatar: (project: ProjectModel): any => { - if (project.avatarCid) { - return { - cid: project.avatarCid, - }; - } - - return { - emoji: project.emoji || '💧', - }; - }, - owner: (project: ProjectModel): AddressDriverAccount => ({ - driver: Driver.ADDRESS, - accountId: project.ownerAccountId || shouldNeverHappen(), - address: (project.ownerAddress as string) || shouldNeverHappen(), - }), - account: (project: ProjectModel): RepoDriverAccount => ({ - driver: Driver.REPO, - accountId: project.id, - }), - source: (project: ProjectModel): Source => ({ - url: project.url || shouldNeverHappen(), - repoName: splitProjectName(project.name || shouldNeverHappen()).repoName, - ownerName: splitProjectName(project.name || shouldNeverHappen()) - .ownerName, - forge: (project.forge as Forge) || shouldNeverHappen(), - }), - verificationStatus: (project: ProjectModel): ProjectVerificationStatus => - project.verificationStatus === ProjectVerificationStatus.Claimed - ? project.verificationStatus - : shouldNeverHappen(), + ClaimedChainProjectData: { + chain: ( + chainProjectData: ResolverClaimedChainProjectData, + ): SupportedChain => chainProjectData.chain, + data: (chainProjectData: ResolverClaimedChainProjectData) => + chainProjectData.data, + }, + UnClaimedChainProjectData: { + chain: ( + chainProjectData: ResolverUnClaimedChainProjectData, + ): SupportedChain => chainProjectData.chain, + data: (chainProjectData: ResolverUnClaimedChainProjectData) => + chainProjectData.data, + }, + ClaimedProjectData: { + verificationStatus: (projectData: ResolverClaimedProjectData) => + projectData.verificationStatus, + color: (projectData: ResolverClaimedProjectData): string => + projectData.color, + description: (projectData: ResolverClaimedProjectData) => + projectData.description, + emoji: (projectData: ResolverClaimedProjectData): string => + projectData.emoji || '💧', + avatar: (projectData: ResolverClaimedProjectData): Avatar => + projectData.avatar, + owner: (projectData: ResolverClaimedProjectData): AddressDriverAccount => + projectData.owner, splits: async ( - project: ProjectModel, + project: ResolverClaimedProjectData, _: any, context: Context, ): Promise => { @@ -157,7 +174,7 @@ const projectResolvers = { const receiversOfTypeAddressModels = await receiversOfTypeAddressDb.getReceiversOfTypeAddressByProjectId( - project.id, + project.projectId, ); const maintainersAndAddressDependencies = groupBy( @@ -186,7 +203,7 @@ const projectResolvers = { const receiversOfTypeProjectModels = await receiversOfTypeProjectDb.getReceiversOfTypeProjectByProjectId( - project.id, + project.projectId, ); const splitsOfTypeProjectModels = await projectsDb.getProjectsByIds( @@ -205,7 +222,7 @@ const projectResolvers = { project: (splitsOfTypeProjectModels .filter( - (p): p is ProjectModel => p && (p as any).id !== undefined, + (p): p is ProjectDataValues => p && (p as any).id !== undefined, ) .find( (p) => (p as any).id === receiver.fundeeProjectId, @@ -215,7 +232,7 @@ const projectResolvers = { const receiversOfTypeDripListModels = await receiversOfTypeDripListDb.getReceiversOfTypeDripListByProjectId( - project.id, + project.projectId, ); const splitsOfTypeDripListModels = await dripListsDb.getDripListsByIds( @@ -250,19 +267,48 @@ const projectResolvers = { ], }; }, - support: async (project: ProjectModel, _: any, context: Context) => { + support: async ( + project: ResolverClaimedProjectData, + _: any, + context: Context, + ) => { const { dataSources: { projectAndDripListSupportDb }, } = context; const projectAndDripListSupport = await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( - project.id, + project.projectId, ); const oneTimeDonationSupport = await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( - project.id, + project.projectId, + ); + + return [...projectAndDripListSupport, ...oneTimeDonationSupport]; + }, + }, + UnClaimedProjectData: { + verificationStatus: (projectData: ResolverUnClaimedProjectData) => + projectData.verificationStatus, + support: async ( + projectData: ResolverUnClaimedProjectData, + _: any, + context: Context, + ) => { + const { + dataSources: { projectAndDripListSupportDb }, + } = context; + + const projectAndDripListSupport = + await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( + projectData.projectId, + ); + + const oneTimeDonationSupport = + await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( + projectData.projectId, ); return [...projectAndDripListSupport, ...oneTimeDonationSupport]; @@ -285,42 +331,13 @@ const projectResolvers = { return shouldNeverHappen(); }, }, - UnclaimedProject: { - account(project: ProjectModel): RepoDriverAccount { - return { - driver: Driver.REPO, - accountId: project.id, - }; - }, - source(project: ProjectModel): Source { - return { - url: project.url || shouldNeverHappen(), - repoName: splitProjectName(project.name || shouldNeverHappen()) - .repoName, - ownerName: splitProjectName(project.name || shouldNeverHappen()) - .ownerName, - forge: (project.forge as Forge) || shouldNeverHappen(), - }; - }, - verificationStatus(project: ProjectModel): ProjectVerificationStatus { - return project.verificationStatus; - }, - support: async (project: ProjectModel, _: any, context: Context) => { - const { - dataSources: { projectAndDripListSupportDb }, - } = context; - - const projectAndDripListSupport = - await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( - project.id, - ); - - const oneTimeDonationSupport = - await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( - project.id, - ); + Avatar: { + __resolveType(parent: { cid: string } | { emoji: string }) { + if ('cid' in parent) { + return 'ImageAvatar'; + } - return [...projectAndDripListSupport, ...oneTimeDonationSupport]; + return 'EmojiAvatar'; }, }, }; diff --git a/src/project/projectTypeDef.ts b/src/project/projectTypeDef.ts index fa30335..45470b0 100644 --- a/src/project/projectTypeDef.ts +++ b/src/project/projectTypeDef.ts @@ -25,23 +25,37 @@ const projectTypeDef = gql` union Avatar = EmojiAvatar | ImageAvatar - type ClaimedProject { + type Project { source: Source! + account: RepoDriverAccount! + chainData: [ProjectChainData!]! + } + + union ProjectChainData = ClaimedChainProjectData | UnClaimedChainProjectData + + type ClaimedChainProjectData { + chain: SupportedChain! + data: ClaimedProjectData! + } + + type ClaimedProjectData { color: String! emoji: String! @deprecated(reason: "Use avatar instead") avatar: Avatar! splits: Splits! description: String owner: AddressDriverAccount! - account: RepoDriverAccount! verificationStatus: ProjectVerificationStatus! support: [SupportItem!]! claimedAt: Date! } - type UnclaimedProject { - source: Source! - account: RepoDriverAccount! + type UnClaimedChainProjectData { + chain: SupportedChain! + data: UnClaimedProjectData! + } + + type UnClaimedProjectData { verificationStatus: ProjectVerificationStatus! support: [SupportItem!]! } @@ -61,8 +75,6 @@ const projectTypeDef = gql` enum ProjectSortField { claimedAt } - - union Project = ClaimedProject | UnclaimedProject `; export default projectTypeDef; diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 0382f4e..0a74a60 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -1,12 +1,21 @@ import { ethers } from 'ethers'; -import type { FakeUnclaimedProject, Forge, ProjectId } from '../common/types'; +import type { + Forge, + ProjectDataValues, + ProjectId, + ResolverProject, +} from '../common/types'; import shouldNeverHappen from '../utils/shouldNeverHappen'; -import type ProjectModel from './ProjectModel'; import { ProjectVerificationStatus } from './ProjectModel'; -import { RepoDriver__factory } from '../generated/contracts'; import assert from '../utils/assert'; import appSettings from '../common/appSettings'; -import provider from '../common/provider'; +import dripsContracts from '../common/dripsContracts'; +import { Driver } from '../generated/graphql'; +import type { + Forge as GraphQlForge, + SupportedChain, + Splits, +} from '../generated/graphql'; export function splitProjectName(projectName: string): { ownerName: string; @@ -21,7 +30,7 @@ export function splitProjectName(projectName: string): { return { ownerName: components[0], repoName: components[1] }; } -export function isValidateProjectName(name: string): boolean { +export function isValidProjectName(name: string): boolean { const components = name.split('/'); if (components.length !== 2) { @@ -62,7 +71,7 @@ export async function doesRepoExists(url: string) { return res.status === 200; } -export function toApiProject(project: ProjectModel) { +export function toApiProject(project: ProjectDataValues) { if (!project) { return null; } @@ -107,10 +116,9 @@ export async function toFakeUnclaimedProjectFromUrl(url: string) { const ownerName = match[2]; const repoName = match[3]; - const repoDriver = RepoDriver__factory.connect( - appSettings.repoDriverAddress, - provider, - ); + const { + contracts: { repoDriver }, + } = dripsContracts; const nameAsBytesLike = ethers.toUtf8Bytes(`${ownerName}/${repoName}`); @@ -122,7 +130,7 @@ export async function toFakeUnclaimedProjectFromUrl(url: string) { forge, url, verificationStatus: ProjectVerificationStatus.Unclaimed, - }; + } as ProjectDataValues; } function toUrl(forge: Forge, projectName: string): string { @@ -135,18 +143,17 @@ function toUrl(forge: Forge, projectName: string): string { } export async function toFakeUnclaimedProject( - project: ProjectModel, -): Promise { + project: ProjectDataValues, +): Promise { const { name, forge } = project; assert(name && forge, 'Project name and forge must be defined.'); const { ownerName, repoName } = splitProjectName(name); - const repoDriver = RepoDriver__factory.connect( - appSettings.repoDriverAddress, - provider, - ); + const { + contracts: { repoDriver }, + } = dripsContracts; const nameAsBytesLike = ethers.toUtf8Bytes(`${ownerName}/${repoName}`); @@ -157,7 +164,73 @@ export async function toFakeUnclaimedProject( name: `${ownerName}/${repoName}`, forge, url: toUrl(forge, name), - verificationStatus: - project.verificationStatus ?? ProjectVerificationStatus.Unclaimed, - }; + verificationStatus: ProjectVerificationStatus.Unclaimed, + } as ProjectDataValues; +} + +export async function toResolverProjects( + chains: SupportedChain[], + projects: ProjectDataValues[], +): Promise { + return Promise.all( + projects.map(async (project) => { + const chainData = await Promise.all( + chains.map(async (chain) => { + if (project.chain === chain) { + return { + chain, + data: { + projectId: project.id, + color: project.color, + emoji: project.emoji, + avatar: project.avatarCid + ? { + cid: project.avatarCid, + } + : { + emoji: project.emoji || '💧', + }, + splits: {} as Splits, // Will be populated by the resolver. + description: project.description, + owner: { + driver: Driver.ADDRESS, + accountId: project.ownerAccountId, + address: project.ownerAddress as string, + }, + verificationStatus: project.verificationStatus, + support: [], // Will be populated by the resolver. + claimedAt: project.claimedAt, + }, + }; + } + const fakeUnclaimedProject = await toFakeUnclaimedProject(project); + + return { + chain, + data: { + projectId: fakeUnclaimedProject.id, + verificationStatus: fakeUnclaimedProject.verificationStatus, + support: [], // Will be populated by the resolver. + }, + }; + }), + ); + + return { + account: { + accountId: project.id, + driver: Driver.REPO, + }, + source: { + url: project.url || shouldNeverHappen(), + repoName: splitProjectName(project.name || shouldNeverHappen()) + .repoName, + ownerName: splitProjectName(project.name || shouldNeverHappen()) + .ownerName, + forge: (project.forge as GraphQlForge) || shouldNeverHappen(), + }, + chainData, + } as ResolverProject; + }), + ); } diff --git a/src/resolvers.ts b/src/resolvers.ts index f8b1069..186cf5b 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -15,10 +15,13 @@ const resolvers = { ...estimatesResolvers.Query, }, Project: projectResolvers.Project, + ProjectChainData: projectResolvers.ProjectChainData, + ClaimedProjectData: projectResolvers.ClaimedProjectData, + ClaimedChainProjectData: projectResolvers.ClaimedChainProjectData, + UnClaimedProjectData: projectResolvers.UnClaimedProjectData, + UnClaimedChainProjectData: projectResolvers.UnClaimedChainProjectData, DripList: dripListResolvers.DripList, SplitsReceiver: projectResolvers.SplitsReceiver, - ClaimedProject: projectResolvers.ClaimedProject, - UnclaimedProject: projectResolvers.UnclaimedProject, SupportItem: commonResolvers.SupportItem, Avatar: projectResolvers.Avatar, ProjectSupport: commonResolvers.ProjectSupport, diff --git a/src/schema.ts b/src/schema.ts index e111850..eb7e53d 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -9,9 +9,13 @@ import estimatesTypeDef from './balances/estimatesTypeDef'; const rootTypeDef = gql` type Query { - projectById(id: ID!): Project + projects( + chains: [SupportedChain!]! + where: ProjectWhereInput + sort: ProjectSortInput + ): [Project!]! + projectById(id: ID!, chain: SupportedChain!): Project projectByUrl(url: String!): Project - projects(where: ProjectWhereInput, sort: ProjectSortInput): [Project!]! dripList(id: ID!): DripList dripLists(where: DripListWhereInput): [DripList!]! gives(where: GiveWhereInput): [Give!]! diff --git a/src/server.ts b/src/server.ts index 56d5661..7e382fe 100644 --- a/src/server.ts +++ b/src/server.ts @@ -21,7 +21,7 @@ import resolvers from './resolvers'; import typeDefs from './schema'; import appSettings from './common/appSettings'; import ProjectsDataSource from './dataLoaders/ProjectsDataSource'; -import connectToDatabase from './database/connectToDatabase'; +import { connectToDatabase } from './database/connectToDatabase'; import ReceiversOfTypeProjectDataSource from './dataLoaders/ReceiversOfTypeProjectDataSource'; import ReceiversOfTypeAddressDataSource from './dataLoaders/ReceiversOfTypeAddressDataSource'; import DripListsDataSource from './dataLoaders/DripListsDataSource'; diff --git a/src/user/UserDataSource.ts b/src/user/UserDataSource.ts index a4459e6..f00b42a 100644 --- a/src/user/UserDataSource.ts +++ b/src/user/UserDataSource.ts @@ -1,11 +1,9 @@ -import appSettings from '../common/appSettings'; -import provider from '../common/provider'; import type { Address, AddressDriverId } from '../common/types'; -import { AddressDriver__factory } from '../generated/contracts'; import { Driver } from '../generated/graphql'; import type { User, UserAccount } from '../generated/graphql'; import getUserAddress from '../utils/getUserAddress'; import getUserAccount from '../utils/getUserAccount'; +import dripsContracts from '../common/dripsContracts'; export default class UsersDataSource { public async getUserAccount( @@ -32,10 +30,9 @@ export default class UsersDataSource { } public async getUserByAddress(address: Address): Promise { - const addressDriver = AddressDriver__factory.connect( - appSettings.addressDriverAddress, - provider, - ); + const { + contracts: { addressDriver }, + } = dripsContracts; const accountId = (await addressDriver.calcAccountId(address)).toString(); diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index 8e32fdf..951cdef 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -1,6 +1,6 @@ import { assetOutgoingBalanceTimeline } from '../balances/estimate-reloaded'; import type { Address, AddressDriverId } from '../common/types'; -import { Driver } from '../generated/graphql'; +import { Driver, SupportedChain } from '../generated/graphql'; import type { AddressDriverAccount, User } from '../generated/graphql'; import type { Context } from '../server'; import assert, { isAddressDriverId } from '../utils/assert'; @@ -57,9 +57,12 @@ const userResolvers = { const { accountId } = parent.account; assert(isAddressDriverId(accountId)); - return dataSources.projectsDb.getProjectsByFilter({ - ownerAddress: getUserAddress(accountId), - }); + return dataSources.projectsDb.getProjectsByFilter( + [SupportedChain.sepolia], // TODO: Temporary for compiling. + { + ownerAddress: getUserAddress(accountId), + }, + ); }, dripLists: (parent: User, _: any, { dataSources }: Context) => { const { accountId } = parent.account; diff --git a/src/utils/getSchema.ts b/src/utils/getSchema.ts index 6c6fd5c..11f8327 100644 --- a/src/utils/getSchema.ts +++ b/src/utils/getSchema.ts @@ -1,6 +1,6 @@ -import type { DbSchema } from '../common/types'; -import appSettings from '../common/appSettings'; +import { SupportedChain } from '../generated/graphql'; -export default function getSchema(): DbSchema { - return appSettings.network as DbSchema; +// TODO: This should be removed once multi-chain support is implemented. For we return sepolia for anything that still relies on the "network". +export default function getSchema(): SupportedChain { + return SupportedChain.sepolia; } From 3c4eb5f860a5a3359d627367656cc45f5568eadf Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 24 May 2024 16:27:12 +0200 Subject: [PATCH 02/37] WIP --- src/common/commonResolvers.ts | 40 +++-- src/common/types.ts | 32 ++-- .../ProjectAndDripListSupportDataSource.ts | 144 +++++++++++++----- src/dataLoaders/ProjectsDataSource.ts | 83 +++++++--- src/drip-list/dripListResolvers.ts | 7 +- src/given-event/GivenEventModel.ts | 17 ++- src/models/RepoDriverSplitReceiverModel.ts | 8 + src/project/ProjectModel.ts | 7 + src/project/projectResolvers.ts | 39 +++-- src/project/projectUtils.ts | 18 ++- src/utils/parseMultiChainKeys.ts | 33 ++++ 11 files changed, 317 insertions(+), 111 deletions(-) create mode 100644 src/utils/parseMultiChainKeys.ts diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index 599c5f1..8629f7f 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -3,43 +3,43 @@ import type { Amount, NftDriverAccount, RepoDriverAccount, + SupportedChain, } from '../generated/graphql'; import { Driver } from '../generated/graphql'; -import GivenEventModel from '../given-event/GivenEventModel'; -import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; +import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; +import type GivenEventModel from '../given-event/GivenEventModel'; +import type DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import type { Context } from '../server'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { DripListId, ProjectId } from './types'; import { DependencyType } from './types'; import getUserAddress from '../utils/getUserAddress'; -import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import type { ProtoStream } from '../utils/buildAssetConfigs'; +import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; const commonResolvers = { SupportItem: { __resolveType( parent: | DripListSplitReceiverModel - | RepoDriverSplitReceiverModel - | GivenEventModel + | RepoDriverSplitReceiverModelDataValues + | GivenEventModelDataValues | ProtoStream, ) { - if ( - parent instanceof DripListSplitReceiverModel || - parent instanceof RepoDriverSplitReceiverModel - ) { - if (parent.type === DependencyType.ProjectDependency) { + if ('funderDripListId' in parent || 'funderProjectId' in parent) { + // TODO: Fix these type assertions. + if ((parent as any).type === DependencyType.ProjectDependency) { return 'ProjectSupport'; } - if (parent.type === DependencyType.DripListDependency) { + if ((parent as any).type === DependencyType.DripListDependency) { return 'DripListSupport'; } return shouldNeverHappen('Invalid SupportItem type'); } - if (parent instanceof GivenEventModel) { + if ('receiver' in parent) { return 'OneTimeDonationSupport'; } @@ -48,7 +48,11 @@ const commonResolvers = { }, ProjectSupport: { account: async ( - parent: { funderProjectId: ProjectId; weight: number }, + parent: { + funderProjectId: ProjectId; + weight: number; + chain: SupportedChain; + }, _: any, context: Context, ): Promise => { @@ -56,7 +60,9 @@ const commonResolvers = { dataSources: { projectsDb }, } = context; - const project = await projectsDb.getProjectById(parent.funderProjectId); + const { funderProjectId, chain } = parent; + + const project = await projectsDb.getProjectById(funderProjectId, chain); return { driver: Driver.REPO, @@ -66,7 +72,7 @@ const commonResolvers = { date: (parent: { blockTimestamp: Date }): Date => parent.blockTimestamp, weight: (parent: { weight: number }): number => parent.weight, project: ( - parent: { funderProjectId: ProjectId }, + parent: { funderProjectId: ProjectId; chain: SupportedChain }, _: any, context: Context, ) => { @@ -74,7 +80,9 @@ const commonResolvers = { dataSources: { projectsDb }, } = context; - return projectsDb.getProjectById(parent.funderProjectId); + const { funderProjectId, chain } = parent; + + return projectsDb.getProjectById(funderProjectId, chain); }, }, DripListSupport: { diff --git a/src/common/types.ts b/src/common/types.ts index 5713473..5b1a366 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -9,7 +9,6 @@ import type StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEvent import type { FORGES_MAP } from './constants'; import type { addressDriverAccountMetadataParser } from '../schemas'; import type StreamsSetEventModel from '../models/StreamsSetEventModel'; -import type ProjectModel from '../project/ProjectModel'; export type KnownAny = any; export type ValuesOf = T[keyof T]; @@ -67,12 +66,6 @@ export type StreamHistoryHashes = string & { __type: 'StreamHistoryHashes'; }; -export type ProjectDataValues = ProjectModel['dataValues'] & { - createdAt: Date; - updatedAt: Date; - chain: SupportedChain; -}; - export type ResolverProject = Project & { chainData: ( | ResolverClaimedChainProjectData @@ -80,20 +73,35 @@ export type ResolverProject = Project & { )[]; }; -export type ResolverClaimedProjectData = ClaimedProjectData & { - projectId: ProjectId; +type ProjectDataParentProjectInfo = { + parentProject: { + projectId: ProjectId; + queriedChains: SupportedChain[]; + }; }; +export type ResolverClaimedProjectData = ClaimedProjectData & + ProjectDataParentProjectInfo; + export type ResolverClaimedChainProjectData = { chain: SupportedChain; data: ResolverClaimedProjectData; }; -export type ResolverUnClaimedProjectData = UnClaimedProjectData & { - projectId: ProjectId; -}; +export type ResolverUnClaimedProjectData = UnClaimedProjectData & + ProjectDataParentProjectInfo; export type ResolverUnClaimedChainProjectData = { chain: SupportedChain; data: ResolverUnClaimedProjectData; }; + +export interface DripListMultiChainKey { + dripListId: DripListId; + chains: SupportedChain[]; +} + +export interface ProjectMultiChainKey { + projectId: ProjectId; + chains: SupportedChain[]; +} diff --git a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts index 8e504f0..340c8a2 100644 --- a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts +++ b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts @@ -1,11 +1,24 @@ import DataLoader from 'dataloader'; -import { Op } from 'sequelize'; -import type { AccountId, DripListId, ProjectId } from '../common/types'; +import { Op, QueryTypes } from 'sequelize'; +import type { + AccountId, + DripListId, + DripListMultiChainKey, + ProjectId, + ProjectMultiChainKey, +} from '../common/types'; import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; +import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import GivenEventModel from '../given-event/GivenEventModel'; +import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import streams from '../utils/streams'; import type { ProtoStream } from '../utils/buildAssetConfigs'; +import parseMultiChainKeys from '../utils/parseMultiChainKeys'; +import type { SupportedChain } from '../generated/graphql'; +import { dbConnection } from '../database/connectToDatabase'; +import { isDripListId, isProjectId } from '../utils/assert'; +import shouldNeverHappen from '../utils/shouldNeverHappen'; export default class ProjectAndDripListSupportDataSource { private readonly _batchProjectAndDripListSupportByDripListIds = @@ -38,19 +51,43 @@ export default class ProjectAndDripListSupportDataSource { }); private readonly _batchProjectAndDripListSupportByProjectIds = new DataLoader( - async (projectIds: readonly ProjectId[]) => { - const projectAndDripListSupport = - await RepoDriverSplitReceiverModel.findAll({ - where: { - fundeeProjectId: { - [Op.in]: projectIds, - }, - }, - }); + async (projectKeys: readonly ProjectMultiChainKey[]) => { + const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); + + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."RepoDriverSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [`"fundeeProjectId" IN (:fundeeProjectIds)`]; + const parameters: { [key: string]: any } = { + fundeeProjectIds: projectIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const repoDriverSplitReceiverModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: RepoDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); const projectAndDripListSupportToProjectMapping = - projectAndDripListSupport.reduce< - Record + repoDriverSplitReceiverModelDataValues.reduce< + Record >((mapping, receiver) => { if (!mapping[receiver.fundeeProjectId]) { mapping[receiver.fundeeProjectId] = []; // eslint-disable-line no-param-reassign @@ -94,32 +131,51 @@ export default class ProjectAndDripListSupportDataSource { ); private readonly _batchOneTimeDonationSupportByAccountIds = new DataLoader( - async (dripListIds: readonly (DripListId | ProjectId)[]) => { - const oneTimeDonationSupport = await GivenEventModel.findAll({ - where: { - receiver: { - [Op.in]: dripListIds, - }, - }, - }); + async (keys: readonly (DripListMultiChainKey | ProjectMultiChainKey)[]) => { + const { chains, ids } = parseMultiChainKeys(keys); + + const baseSQL = (schema: SupportedChain) => ` + SELECT "accountId", "receiver", "erc20", "amt", "blockTimestamp", "logIndex", "blockTimestamp", "transactionHash", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."GivenEvents" + `; + + // Build the WHERE clause. + const conditions: string[] = [`"receiver" IN (:ids)`]; + const parameters: { [key: string]: any } = { ids }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const oneTimeDonationSupport = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); const oneTimeDonationSupportToDripListMapping = - oneTimeDonationSupport.reduce>( - (mapping, givenEvent) => { - if (!mapping[givenEvent.receiver]) { - mapping[givenEvent.receiver] = []; // eslint-disable-line no-param-reassign - } + oneTimeDonationSupport.reduce< + Record + >((mapping, givenEvent) => { + if (!mapping[givenEvent.receiver]) { + mapping[givenEvent.receiver] = []; // eslint-disable-line no-param-reassign + } - mapping[givenEvent.receiver].push(givenEvent); + mapping[givenEvent.receiver].push(givenEvent); - return mapping; - }, - {}, - ); + return mapping; + }, {}); - return dripListIds.map( - (id) => oneTimeDonationSupportToDripListMapping[id] || [], - ); + return ids.map((id) => oneTimeDonationSupportToDripListMapping[id] || []); }, ); @@ -131,14 +187,26 @@ export default class ProjectAndDripListSupportDataSource { public async getProjectAndDripListSupportByProjectId( id: ProjectId, - ): Promise { - return this._batchProjectAndDripListSupportByProjectIds.load(id); + chains: SupportedChain[], + ): Promise { + return this._batchProjectAndDripListSupportByProjectIds.load({ + projectId: id, + chains, + }); } public async getOneTimeDonationSupportByAccountId( id: DripListId | ProjectId, - ): Promise { - return this._batchOneTimeDonationSupportByAccountIds.load(id); + chains: SupportedChain[], + ): Promise { + // eslint-disable-next-line no-nested-ternary + const key = isDripListId(id) + ? { dripListId: id, chains } + : isProjectId(id) + ? { projectId: id, chains } + : shouldNeverHappen(); + + return this._batchOneTimeDonationSupportByAccountIds.load(key); } public async getStreamSupportByAccountId( diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index b0966e4..50795b7 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -1,7 +1,8 @@ -import { Op, QueryTypes } from 'sequelize'; +import { QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; +import type { ProjectDataValues } from '../project/ProjectModel'; import ProjectModel from '../project/ProjectModel'; -import type { ProjectDataValues, ProjectId } from '../common/types'; +import type { ProjectId, ProjectMultiChainKey } from '../common/types'; import { doesRepoExists, isValidProjectName, @@ -16,27 +17,59 @@ import type { import SplitEventModel from '../models/SplitEventModel'; import GivenEventModel from '../given-event/GivenEventModel'; import { dbConnection } from '../database/connectToDatabase'; +import parseMultiChainKeys from '../utils/parseMultiChainKeys'; export default class ProjectsDataSource { private readonly _batchProjectsByIds = new DataLoader( - async (projectIds: readonly ProjectId[]): Promise => { - const projects = await ProjectModel.findAll({ - where: { - id: { - [Op.in]: projectIds, - }, - isValid: true, - }, - }).then((projectModels) => - projectModels.filter((p) => - p.name ? isValidProjectName(p.name) : true, - ), + async ( + projectKeys: readonly ProjectMultiChainKey[], + ): Promise => { + const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); + + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GitProjects" + `; + + // Initialize the WHERE clause parts. + const conditions: string[] = ['"id" IN (:projectIds)']; + const parameters: { [key: string]: any } = { projectIds }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const projectsDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: ProjectModel, + }) + ) + .map((p) => p.dataValues as ProjectDataValues) + .filter((p) => p.isValid) + .filter((p) => (p.name ? isValidProjectName(p.name) : true)); + + const projectsDataValuesWithApi = await Promise.all( + projectsDataValues.map(toApiProject), ); - const projectIdToProjectMap = projects.reduce< + const filteredProjectsDataValues = projectsDataValuesWithApi.filter( + Boolean, + ) as ProjectDataValues[]; + + const projectIdToProjectMap = filteredProjectsDataValues.reduce< Record >((mapping, project) => { - mapping[project.id] = project.dataValues as ProjectDataValues; // eslint-disable-line no-param-reassign + mapping[project.id] = project; // eslint-disable-line no-param-reassign return mapping; }, {}); @@ -47,8 +80,14 @@ export default class ProjectsDataSource { public async getProjectById( id: ProjectId, + chain: SupportedChain, ): Promise { - return toApiProject(await this._batchProjectsByIds.load(id)); + return toApiProject( + await this._batchProjectsByIds.load({ + projectId: id, + chains: [chain], + }), + ); } public async getProjectByUrl(url: string): Promise { @@ -134,10 +173,14 @@ export default class ProjectsDataSource { public async getProjectsByIds( ids: ProjectId[], + chains: SupportedChain[], ): Promise { - return this._batchProjectsByIds.loadMany(ids) as Promise< - ProjectDataValues[] - >; + return this._batchProjectsByIds.loadMany( + ids.map((id) => ({ + projectId: id, + chains, + })), + ) as Promise; } public async getEarnedFunds(projectId: ProjectId): Promise< diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index 71d3f19..f924140 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -1,5 +1,5 @@ import { isAddress } from 'ethers'; -import type { Address, DripListId, ProjectDataValues } from '../common/types'; +import type { Address, DripListId } from '../common/types'; import type DripListModel from './DripListModel'; import type { AddressDriverAccount, @@ -10,10 +10,11 @@ import type { Project, SplitsReceiver, } from '../generated/graphql'; -import { Driver } from '../generated/graphql'; +import { Driver, SupportedChain } from '../generated/graphql'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { Context } from '../server'; import assert, { isDripListId } from '../utils/assert'; +import type { ProjectDataValues } from '../project/ProjectModel'; const dripListResolvers = { Query: { @@ -104,6 +105,7 @@ const dripListResolvers = { const splitsOfTypeProjectModels = await projectsDb.getProjectsByIds( receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), + [SupportedChain.sepolia], // TODO: Hardcoded until multiple chains are supported. Fix. ); const projectReceivers = receiversOfTypeProjectModels.map((receiver) => ({ @@ -167,6 +169,7 @@ const dripListResolvers = { const oneTimeDonationSupport = await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( dripList.id, + [], // TODO: Only for compilation. Fix. ); const streamSupport = diff --git a/src/given-event/GivenEventModel.ts b/src/given-event/GivenEventModel.ts index ac43a9d..6fb517d 100644 --- a/src/given-event/GivenEventModel.ts +++ b/src/given-event/GivenEventModel.ts @@ -6,13 +6,18 @@ import type { import { DataTypes, Model } from 'sequelize'; import type { AccountId, Address, BigIntString } from '../common/types'; import getSchema from '../utils/getSchema'; +import type { SupportedChain } from '../generated/graphql'; -export default class GivenEventModel - extends Model< - InferAttributes, - InferCreationAttributes - > -{ +export type GivenEventModelDataValues = GivenEventModel['dataValues'] & { + createdAt: Date; + updatedAt: Date; + chain: SupportedChain; +}; + +export default class GivenEventModel extends Model< + InferAttributes, + InferCreationAttributes +> { public declare accountId: AccountId; // Sender of the Give public declare receiver: AccountId; public declare erc20: Address; diff --git a/src/models/RepoDriverSplitReceiverModel.ts b/src/models/RepoDriverSplitReceiverModel.ts index ad30417..725fe48 100644 --- a/src/models/RepoDriverSplitReceiverModel.ts +++ b/src/models/RepoDriverSplitReceiverModel.ts @@ -10,6 +10,14 @@ import type { DripListId, ProjectId } from '../common/types'; import { DependencyType } from '../common/types'; import ProjectModel from '../project/ProjectModel'; import DripListModel from '../drip-list/DripListModel'; +import type { SupportedChain } from '../generated/graphql'; + +export type RepoDriverSplitReceiverModelDataValues = + RepoDriverSplitReceiverModel['dataValues'] & { + createdAt: Date; + updatedAt: Date; + chain: SupportedChain; + }; export default class RepoDriverSplitReceiverModel extends Model< InferAttributes, diff --git a/src/project/ProjectModel.ts b/src/project/ProjectModel.ts index a58e4a1..506d00c 100644 --- a/src/project/ProjectModel.ts +++ b/src/project/ProjectModel.ts @@ -8,6 +8,13 @@ import type { AddressLike } from 'ethers'; import getSchema from '../utils/getSchema'; import type { AccountId, Forge, ProjectId } from '../common/types'; import { FORGES_MAP } from '../common/constants'; +import type { SupportedChain } from '../generated/graphql'; + +export type ProjectDataValues = ProjectModel['dataValues'] & { + createdAt: Date; + updatedAt: Date; + chain: SupportedChain; +}; export enum ProjectVerificationStatus { Claimed = 'Claimed', diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 215f6ee..9950b36 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -1,6 +1,5 @@ import { isAddress } from 'ethers'; import type { - ProjectDataValues, ProjectId, ResolverClaimedChainProjectData, ResolverClaimedProjectData, @@ -36,17 +35,19 @@ import assert, { isSortableProjectField, } from '../utils/assert'; import queryableChains from '../common/queryableChains'; +import type { ProjectDataValues } from './ProjectModel'; const projectResolvers = { Query: { projectById: async ( _: any, - { id }: { id: ProjectId }, + { id, chain }: { id: ProjectId; chain: SupportedChain }, { dataSources }: Context, ): Promise => { assert(isProjectId(id)); + assert(chain in SupportedChain); - return dataSources.projectsDb.getProjectById(id); + return dataSources.projectsDb.getProjectById(id, chain); }, projectByUrl: async ( _: any, @@ -158,7 +159,7 @@ const projectResolvers = { owner: (projectData: ResolverClaimedProjectData): AddressDriverAccount => projectData.owner, splits: async ( - project: ResolverClaimedProjectData, + projectData: ResolverClaimedProjectData, _: any, context: Context, ): Promise => { @@ -172,9 +173,11 @@ const projectResolvers = { }, } = context; + const { parentProject } = projectData; + const receiversOfTypeAddressModels = await receiversOfTypeAddressDb.getReceiversOfTypeAddressByProjectId( - project.projectId, + parentProject.projectId, ); const maintainersAndAddressDependencies = groupBy( @@ -203,11 +206,12 @@ const projectResolvers = { const receiversOfTypeProjectModels = await receiversOfTypeProjectDb.getReceiversOfTypeProjectByProjectId( - project.projectId, + parentProject.projectId, ); const splitsOfTypeProjectModels = await projectsDb.getProjectsByIds( receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), + [SupportedChain.sepolia], // TODO: Hardcoded until multiple chains are supported. Fix. ); const dependenciesOfTypeProject = receiversOfTypeProjectModels.map( @@ -232,7 +236,7 @@ const projectResolvers = { const receiversOfTypeDripListModels = await receiversOfTypeDripListDb.getReceiversOfTypeDripListByProjectId( - project.projectId, + parentProject.projectId, ); const splitsOfTypeDripListModels = await dripListsDb.getDripListsByIds( @@ -268,22 +272,27 @@ const projectResolvers = { }; }, support: async ( - project: ResolverClaimedProjectData, + projectData: ResolverClaimedProjectData, _: any, context: Context, ) => { + const { + parentProject: { projectId, queriedChains }, + } = projectData; const { dataSources: { projectAndDripListSupportDb }, } = context; const projectAndDripListSupport = await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( - project.projectId, + projectId, + queriedChains, ); const oneTimeDonationSupport = await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( - project.projectId, + projectId, + queriedChains, ); return [...projectAndDripListSupport, ...oneTimeDonationSupport]; @@ -301,14 +310,20 @@ const projectResolvers = { dataSources: { projectAndDripListSupportDb }, } = context; + const { + parentProject: { projectId, queriedChains }, + } = projectData; + const projectAndDripListSupport = await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( - projectData.projectId, + projectId, + queriedChains, ); const oneTimeDonationSupport = await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( - projectData.projectId, + projectId, + queriedChains, ); return [...projectAndDripListSupport, ...oneTimeDonationSupport]; diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 0a74a60..425af00 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -1,11 +1,13 @@ import { ethers } from 'ethers'; import type { Forge, - ProjectDataValues, ProjectId, + ResolverClaimedChainProjectData, ResolverProject, + ResolverUnClaimedChainProjectData, } from '../common/types'; import shouldNeverHappen from '../utils/shouldNeverHappen'; +import type { ProjectDataValues } from './ProjectModel'; import { ProjectVerificationStatus } from './ProjectModel'; import assert from '../utils/assert'; import appSettings from '../common/appSettings'; @@ -180,7 +182,10 @@ export async function toResolverProjects( return { chain, data: { - projectId: project.id, + parentProject: { + projectId: project.id, + queriedChains: chains, + }, color: project.color, emoji: project.emoji, avatar: project.avatarCid @@ -201,18 +206,21 @@ export async function toResolverProjects( support: [], // Will be populated by the resolver. claimedAt: project.claimedAt, }, - }; + } as ResolverClaimedChainProjectData; } const fakeUnclaimedProject = await toFakeUnclaimedProject(project); return { chain, data: { - projectId: fakeUnclaimedProject.id, + parentProject: { + queriedChains: chains, + projectId: fakeUnclaimedProject.id, + }, verificationStatus: fakeUnclaimedProject.verificationStatus, support: [], // Will be populated by the resolver. }, - }; + } as ResolverUnClaimedChainProjectData; }), ); diff --git a/src/utils/parseMultiChainKeys.ts b/src/utils/parseMultiChainKeys.ts new file mode 100644 index 0000000..e6c8f07 --- /dev/null +++ b/src/utils/parseMultiChainKeys.ts @@ -0,0 +1,33 @@ +import type { SupportedChain } from '../generated/graphql'; +import shouldNeverHappen from './shouldNeverHappen'; + +type MultiChainKey = { chains: SupportedChain[] }; + +type ExtractedValues = { + ids: (T extends { projectId: infer P } + ? P + : T extends { dripListId: infer D } + ? D + : never)[]; + chains: SupportedChain[]; +}; + +export default function parseMultiChainKeys< + T extends MultiChainKey & { [key: string]: any }, +>(keys: ReadonlyArray): ExtractedValues { + const ids = keys.map((key) => key.projectId ?? key.dripListId); + const chainsToQuery = keys.map((key) => key.chains); + + if ( + chainsToQuery.some( + (chain) => JSON.stringify(chain) !== JSON.stringify(chainsToQuery[0]), + ) + ) { + shouldNeverHappen('Chains are not the same within a batch.'); + } + + return { + ids, + chains: chainsToQuery[0], + }; +} From 7bd92d0e9a38f46516ba87497fcea3ec55e6c905 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Wed, 29 May 2024 15:45:01 +0200 Subject: [PATCH 03/37] WIP --- src/common/commonResolvers.ts | 53 +++++- src/common/types.ts | 44 ++++- src/dataLoaders/DripListsDataSource.ts | 134 +++++++++++--- .../ProjectAndDripListSupportDataSource.ts | 61 ++++-- .../ReceiversOfTypeAddressDataSource.ts | 175 ++++++++++++------ .../ReceiversOfTypeDripListDataSource.ts | 170 ++++++++++++----- .../ReceiversOfTypeProjectDataSource.ts | 170 ++++++++++++----- src/drip-list/DripListModel.ts | 4 +- src/drip-list/dripListResolvers.ts | 130 ++++++++----- src/drip-list/dripListTypeDef.ts | 11 +- src/drip-list/dripListUtils.ts | 57 ++++++ src/drip-list/dripListValidators.ts | 24 +++ src/given-event/GivenEventModel.ts | 15 +- src/models/AddressDriverSplitReceiverModel.ts | 10 +- src/models/DripListSplitReceiverModel.ts | 5 +- src/models/RepoDriverSplitReceiverModel.ts | 9 +- src/project/ProjectModel.ts | 14 +- src/project/projectResolvers.ts | 149 +++++++-------- src/project/projectTypeDef.ts | 6 +- src/project/projectUtils.ts | 14 +- src/project/projectValidators.ts | 46 +++++ src/resolvers.ts | 6 +- src/schema.ts | 7 +- src/stream/streamResolvers.ts | 12 +- src/user/userResolvers.ts | 9 +- src/utils/assert.ts | 4 - src/utils/parseMultiChainKeys.ts | 13 +- 27 files changed, 954 insertions(+), 398 deletions(-) create mode 100644 src/drip-list/dripListUtils.ts create mode 100644 src/drip-list/dripListValidators.ts create mode 100644 src/project/projectValidators.ts diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index 8629f7f..a27cf51 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -16,6 +16,8 @@ import { DependencyType } from './types'; import getUserAddress from '../utils/getUserAddress'; import type { ProtoStream } from '../utils/buildAssetConfigs'; import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; +import { toResolverProjects } from '../project/projectUtils'; +import toResolverDripLists from '../drip-list/dripListUtils'; const commonResolvers = { SupportItem: { @@ -50,7 +52,6 @@ const commonResolvers = { account: async ( parent: { funderProjectId: ProjectId; - weight: number; chain: SupportedChain; }, _: any, @@ -71,8 +72,12 @@ const commonResolvers = { }, date: (parent: { blockTimestamp: Date }): Date => parent.blockTimestamp, weight: (parent: { weight: number }): number => parent.weight, - project: ( - parent: { funderProjectId: ProjectId; chain: SupportedChain }, + project: async ( + parent: { + funderProjectId: ProjectId; + chain: SupportedChain; + queriedChains: SupportedChain[]; + }, _: any, context: Context, ) => { @@ -82,12 +87,26 @@ const commonResolvers = { const { funderProjectId, chain } = parent; - return projectsDb.getProjectById(funderProjectId, chain); + const projectDataValues = + (await projectsDb.getProjectById(funderProjectId, chain)) || + shouldNeverHappen(); + + const resolverProjects = await toResolverProjects( + [chain], + [projectDataValues], + ); + + const [project] = resolverProjects; + + return project; }, }, DripListSupport: { account: async ( - parent: { funderDripListId: DripListId; weight: number }, + parent: { + funderDripListId: DripListId; + chain: SupportedChain; + }, _: any, context: Context, ): Promise => { @@ -95,8 +114,11 @@ const commonResolvers = { dataSources: { dripListsDb }, } = context; + const { funderDripListId, chain } = parent; + const dripList = await dripListsDb.getDripListById( - parent.funderDripListId, + funderDripListId, + chain, ); return { @@ -106,8 +128,8 @@ const commonResolvers = { }, date: (parent: { blockTimestamp: Date }): Date => parent.blockTimestamp, weight: (parent: { weight: number }): number => parent.weight, - dripList: ( - parent: { funderDripListId: DripListId }, + dripList: async ( + parent: { funderDripListId: DripListId; chain: SupportedChain }, _: any, context: Context, ) => { @@ -115,7 +137,20 @@ const commonResolvers = { dataSources: { dripListsDb }, } = context; - return dripListsDb.getDripListById(parent.funderDripListId); + const { funderDripListId, chain } = parent; + + const dripListDataValues = + (await dripListsDb.getDripListById(funderDripListId, chain)) || + shouldNeverHappen(); + + const resolverDripLists = await toResolverDripLists( + [chain], + [dripListDataValues], + ); + + const [dripLists] = resolverDripLists; + + return dripLists; }, }, OneTimeDonationSupport: { diff --git a/src/common/types.ts b/src/common/types.ts index 5b1a366..6c6def2 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -1,6 +1,8 @@ import type { AnyVersion } from '@efstajas/versioned-parser'; import type { ClaimedProjectData, + DripList, + DripListData, Project, SupportedChain, UnClaimedProjectData, @@ -68,14 +70,15 @@ export type StreamHistoryHashes = string & { export type ResolverProject = Project & { chainData: ( - | ResolverClaimedChainProjectData - | ResolverUnClaimedChainProjectData + | ResolverClaimedProjectChainData + | ResolverUnClaimedProjectChainData )[]; }; type ProjectDataParentProjectInfo = { - parentProject: { + parentProjectInfo: { projectId: ProjectId; + projectChain: SupportedChain; queriedChains: SupportedChain[]; }; }; @@ -83,7 +86,7 @@ type ProjectDataParentProjectInfo = { export type ResolverClaimedProjectData = ClaimedProjectData & ProjectDataParentProjectInfo; -export type ResolverClaimedChainProjectData = { +export type ResolverClaimedProjectChainData = { chain: SupportedChain; data: ResolverClaimedProjectData; }; @@ -91,7 +94,7 @@ export type ResolverClaimedChainProjectData = { export type ResolverUnClaimedProjectData = UnClaimedProjectData & ProjectDataParentProjectInfo; -export type ResolverUnClaimedChainProjectData = { +export type ResolverUnClaimedProjectChainData = { chain: SupportedChain; data: ResolverUnClaimedProjectData; }; @@ -101,7 +104,38 @@ export interface DripListMultiChainKey { chains: SupportedChain[]; } +export interface StreamMultiChainKey { + accountId: AccountId; + chains: SupportedChain[]; +} + export interface ProjectMultiChainKey { projectId: ProjectId; chains: SupportedChain[]; } + +export type ResolverDripList = DripList & { + chainData: ResolverDripListChainData[]; +}; + +export type ResolverDripListChainData = { + chain: SupportedChain; + data: ResolverDripListData | null; +}; + +type DripListDataParentDripListInfo = { + parentDripListInfo: { + dripListId: DripListId; + dripListChain: SupportedChain; + queriedChains: SupportedChain[]; + }; +}; + +export type ResolverDripListData = DripListData & + DripListDataParentDripListInfo; + +export type CommonDataValues = { + createdAt: Date; + updatedAt: Date; + chain: SupportedChain; +}; diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index d0d9a57..3c145b3 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -1,25 +1,58 @@ -import type { WhereOptions } from 'sequelize'; -import { Op } from 'sequelize'; +import { QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; -import type { Address, DripListId } from '../common/types'; -import type { DripListWhereInput } from '../generated/graphql'; +import type { + Address, + DripListId, + DripListMultiChainKey, +} from '../common/types'; +import type { DripListWhereInput, SupportedChain } from '../generated/graphql'; +import type { DripListDataValues } from '../drip-list/DripListModel'; import DripListModel from '../drip-list/DripListModel'; import TransferEventModel from '../drip-list/TransferEventModel'; +import { dbConnection } from '../database/connectToDatabase'; +import parseMultiChainKeys from '../utils/parseMultiChainKeys'; export default class DripListsDataSource { private readonly _batchDripListsByIds = new DataLoader( - async (dripListIds: readonly DripListId[]): Promise => { - const dripLists = await DripListModel.findAll({ - where: { - id: { - [Op.in]: dripListIds, - }, - isValid: true, - }, - }); - - const dripListIdToDripListMap = dripLists.reduce< - Record + async ( + dripListKeys: readonly DripListMultiChainKey[], + ): Promise => { + const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); + + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "ownerAddress", "ownerAccountId", "name", "latestVotingRoundId", "description", "creator", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."DripLists" + `; + + // Initialize the WHERE clause parts. + const conditions: string[] = [ + '"id" IN (:dripListIds)', + '"isValid" = true', + ]; + const parameters: { [key: string]: any } = { dripListIds }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const dripListDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListModel, + }) + ).map((p) => p.dataValues as DripListDataValues); + + const dripListIdToDripListMap = dripListDataValues.reduce< + Record >((mapping, dripList) => { mapping[dripList.id] = dripList; // eslint-disable-line no-param-reassign @@ -30,23 +63,72 @@ export default class DripListsDataSource { }, ); - public async getDripListById(id: DripListId): Promise { - return this._batchDripListsByIds.load(id); + public async getDripListById( + id: DripListId, + chains: SupportedChain, + ): Promise { + return this._batchDripListsByIds.load({ + dripListId: id, + chains: [chains], + }); } public async getDripListsByFilter( + chains: SupportedChain[], where: DripListWhereInput, - ): Promise { - const dripLists = - (await DripListModel.findAll({ - where: (where as WhereOptions) || {}, - })) || []; + ): Promise { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "name", "creator", "description", "ownerAddress", "ownerAccountId", "latestVotingRoundId", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."DripLists" + `; + + // Initialize the WHERE clause parts. + const conditions: string[] = []; + const parameters: { [key: string]: any } = {}; + + // Build the WHERE clause based on input filters. + if (where?.id) { + conditions.push(`"id" = :id`); + parameters.id = where.id; + } + if (where?.ownerAddress) { + conditions.push(`"ownerAddress" = :ownerAddress`); + parameters.ownerAddress = where.ownerAddress; + } + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const dripListsDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListModel, + }) + ).map((p) => p.dataValues as DripListDataValues); - return dripLists.filter((p) => p.isValid && p.name); + return dripListsDataValues.filter((p) => p.isValid && p.name); } - public async getDripListsByIds(ids: DripListId[]): Promise { - return this._batchDripListsByIds.loadMany(ids) as Promise; + public async getDripListsByIds( + ids: DripListId[], + chains: SupportedChain[], + ): Promise { + return this._batchDripListsByIds.loadMany( + ids.map((id) => ({ + dripListId: id, + chains, + })), + ) as Promise; } public async getMintedTokensCountByAccountId( diff --git a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts index 340c8a2..86c879d 100644 --- a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts +++ b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts @@ -1,5 +1,5 @@ import DataLoader from 'dataloader'; -import { Op, QueryTypes } from 'sequelize'; +import { QueryTypes } from 'sequelize'; import type { AccountId, DripListId, @@ -7,6 +7,7 @@ import type { ProjectId, ProjectMultiChainKey, } from '../common/types'; +import type { DripListSplitReceiverModelDataValues } from '../models/DripListSplitReceiverModel'; import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import GivenEventModel from '../given-event/GivenEventModel'; @@ -22,19 +23,45 @@ import shouldNeverHappen from '../utils/shouldNeverHappen'; export default class ProjectAndDripListSupportDataSource { private readonly _batchProjectAndDripListSupportByDripListIds = - new DataLoader(async (dripListIds: readonly DripListId[]) => { - const projectAndDripListSupport = - await DripListSplitReceiverModel.findAll({ - where: { - fundeeDripListId: { - [Op.in]: dripListIds, - }, - }, - }); + new DataLoader(async (dripListKeys: readonly DripListMultiChainKey[]) => { + const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); + + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."DripListSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [ + `"fundeeDripListId" IN (:fundeeDripListIds)`, + ]; + const parameters: { [key: string]: any } = { + fundeeDripListIds: dripListIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const dripListSplitReceiverModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListSplitReceiverModel, + }) + ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); const projectAndDripListSupportToDripListMapping = - projectAndDripListSupport.reduce< - Record + dripListSplitReceiverModelDataValues.reduce< + Record >((mapping, receiver) => { if (!mapping[receiver.fundeeDripListId]) { mapping[receiver.fundeeDripListId] = []; // eslint-disable-line no-param-reassign @@ -135,7 +162,7 @@ export default class ProjectAndDripListSupportDataSource { const { chains, ids } = parseMultiChainKeys(keys); const baseSQL = (schema: SupportedChain) => ` - SELECT "accountId", "receiver", "erc20", "amt", "blockTimestamp", "logIndex", "blockTimestamp", "transactionHash", "createdAt", "updatedAt",'${schema}' AS chain + SELECT "accountId", "receiver", "erc20", "amt", "blockTimestamp", "logIndex", "transactionHash", "createdAt", "updatedAt",'${schema}' AS chain FROM "${schema}"."GivenEvents" `; @@ -181,8 +208,12 @@ export default class ProjectAndDripListSupportDataSource { public async getProjectAndDripListSupportByDripListId( id: DripListId, - ): Promise { - return this._batchProjectAndDripListSupportByDripListIds.load(id); + chains: SupportedChain[], + ): Promise { + return this._batchProjectAndDripListSupportByDripListIds.load({ + dripListId: id, + chains, + }); } public async getProjectAndDripListSupportByProjectId( diff --git a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts index a0ba81b..6b6215d 100644 --- a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts @@ -1,38 +1,69 @@ import DataLoader from 'dataloader'; -import { Op } from 'sequelize'; -import type { DripListId, ProjectId } from '../common/types'; +import { QueryTypes } from 'sequelize'; +import type { + DripListId, + DripListMultiChainKey, + ProjectId, + ProjectMultiChainKey, +} from '../common/types'; +import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; import AddressDriverSplitReceiverModel, { AddressDriverSplitReceiverType, } from '../models/AddressDriverSplitReceiverModel'; +import type { SupportedChain } from '../generated/graphql'; +import parseMultiChainKeys from '../utils/parseMultiChainKeys'; +import { dbConnection } from '../database/connectToDatabase'; export default class ReceiversOfTypeAddressDataSource { private readonly _batchReceiversOfTypeAddressByProjectIds = new DataLoader( - async (projectIds: readonly ProjectId[]) => { - const receivers = await AddressDriverSplitReceiverModel.findAll({ - where: { - funderProjectId: { - [Op.in]: projectIds, - }, - type: { - [Op.in]: [ - AddressDriverSplitReceiverType.ProjectMaintainer, - AddressDriverSplitReceiverType.ProjectDependency, - ], - }, - }, - }); - - const receiversOfTypeAddressToProjectMapping = receivers.reduce< - Record - >((mapping, receiver) => { - if (!mapping[receiver.funderProjectId as ProjectId]) { - mapping[receiver.funderProjectId as ProjectId] = []; // eslint-disable-line no-param-reassign - } - - mapping[receiver.funderProjectId as ProjectId].push(receiver); - - return mapping; - }, {}); + async (projectKeys: readonly ProjectMultiChainKey[]) => { + const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); + + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."AddressDriverSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [ + `"funderDripListId" IN (:funderProjectIds)`, + `type IN ('${AddressDriverSplitReceiverType.ProjectMaintainer}', '${AddressDriverSplitReceiverType.ProjectDependency}')`, + ]; + const parameters: { [key: string]: any } = { + funderProjectIds: projectIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const addressDriverSplitReceiverModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: AddressDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); + + const receiversOfTypeAddressToProjectMapping = + addressDriverSplitReceiverModelDataValues.reduce< + Record + >((mapping, receiver) => { + if (!mapping[receiver.funderProjectId as ProjectId]) { + mapping[receiver.funderProjectId as ProjectId] = []; // eslint-disable-line no-param-reassign + } + + mapping[receiver.funderProjectId as ProjectId].push(receiver); + + return mapping; + }, {}); return projectIds.map( (id) => receiversOfTypeAddressToProjectMapping[id] || [], @@ -42,34 +73,64 @@ export default class ReceiversOfTypeAddressDataSource { public async getReceiversOfTypeAddressByProjectId( id: ProjectId, - ): Promise { - return this._batchReceiversOfTypeAddressByProjectIds.load(id); + chains: SupportedChain[], + ): Promise { + return this._batchReceiversOfTypeAddressByProjectIds.load({ + projectId: id, + chains, + }); } private readonly _batchReceiversOfTypeAddressByDripListIds = new DataLoader( - async (dripListIds: readonly DripListId[]) => { - const receivers = await AddressDriverSplitReceiverModel.findAll({ - where: { - funderDripListId: { - [Op.in]: dripListIds, - }, - type: { - [Op.in]: [AddressDriverSplitReceiverType.DripListDependency], - }, - }, - }); - - const receiversOfTypeAddressToDripListMapping = receivers.reduce< - Record - >((mapping, receiver) => { - if (!mapping[receiver.funderDripListId as DripListId]) { - mapping[receiver.funderDripListId as DripListId] = []; // eslint-disable-line no-param-reassign - } - - mapping[receiver.funderDripListId as DripListId].push(receiver); - - return mapping; - }, {}); + async (dripListKeys: readonly DripListMultiChainKey[]) => { + const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); + + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."AddressDriverSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [ + `"funderDripListId" IN (:funderDripListIds)`, + `"type" IN ('${AddressDriverSplitReceiverType.DripListDependency}')`, + ]; + const parameters: { [key: string]: any } = { + funderDripListIds: dripListIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const addressDriverSplitReceiverModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: AddressDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); + + const receiversOfTypeAddressToDripListMapping = + addressDriverSplitReceiverModelDataValues.reduce< + Record + >((mapping, receiver) => { + if (!mapping[receiver.funderDripListId as DripListId]) { + mapping[receiver.funderDripListId as DripListId] = []; // eslint-disable-line no-param-reassign + } + + mapping[receiver.funderDripListId as DripListId].push(receiver); + + return mapping; + }, {}); return dripListIds.map( (id) => receiversOfTypeAddressToDripListMapping[id] || [], @@ -79,7 +140,11 @@ export default class ReceiversOfTypeAddressDataSource { public async getReceiversOfTypeAddressByDripListId( id: DripListId, - ): Promise { - return this._batchReceiversOfTypeAddressByDripListIds.load(id); + chains: SupportedChain[], + ): Promise { + return this._batchReceiversOfTypeAddressByDripListIds.load({ + dripListId: id, + chains, + }); } } diff --git a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts index 3da2c14..4129c4f 100644 --- a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts @@ -1,35 +1,68 @@ import DataLoader from 'dataloader'; -import { Op } from 'sequelize'; -import { - DependencyType, - type DripListId, - type ProjectId, +import { QueryTypes } from 'sequelize'; +import { DependencyType } from '../common/types'; +import type { + ProjectMultiChainKey, + DripListId, + ProjectId, + DripListMultiChainKey, } from '../common/types'; +import type { DripListSplitReceiverModelDataValues } from '../models/DripListSplitReceiverModel'; import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; +import { dbConnection } from '../database/connectToDatabase'; +import type { SupportedChain } from '../generated/graphql'; +import parseMultiChainKeys from '../utils/parseMultiChainKeys'; export default class ReceiversOfTypeDripListDataSource { private readonly _batchReceiversOfTypeDripListByProjectIds = new DataLoader( - async (projectIds: readonly ProjectId[]) => { - const receivers = await DripListSplitReceiverModel.findAll({ - where: { - funderProjectId: { - [Op.in]: projectIds, - }, - type: DependencyType.ProjectDependency, - }, - }); - - const receiversOfTypeDripListToProjectListMapping = receivers.reduce< - Record - >((mapping, receiver) => { - if (!mapping[receiver.funderProjectId as ProjectId]) { - mapping[receiver.funderProjectId as ProjectId] = []; // eslint-disable-line no-param-reassign - } - - mapping[receiver.funderProjectId as ProjectId].push(receiver); - - return mapping; - }, {}); + async (projectKeys: readonly ProjectMultiChainKey[]) => { + const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); + + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."DripListSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [ + `"funderDripListId" IN (:funderProjectIds)`, + `type = '${DependencyType.ProjectDependency}'`, + ]; + const parameters: { [key: string]: any } = { + funderProjectIds: projectIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const dripListSplitReceiverModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListSplitReceiverModel, + }) + ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); + + const receiversOfTypeDripListToProjectListMapping = + dripListSplitReceiverModelDataValues.reduce< + Record + >((mapping, receiver) => { + if (!mapping[receiver.funderProjectId as ProjectId]) { + mapping[receiver.funderProjectId as ProjectId] = []; // eslint-disable-line no-param-reassign + } + + mapping[receiver.funderProjectId as ProjectId].push(receiver); + + return mapping; + }, {}); return projectIds.map( (id) => receiversOfTypeDripListToProjectListMapping[id] || [], @@ -39,32 +72,63 @@ export default class ReceiversOfTypeDripListDataSource { public async getReceiversOfTypeDripListByProjectId( id: ProjectId, - ): Promise { - return this._batchReceiversOfTypeDripListByProjectIds.load(id); + chains: SupportedChain[], + ): Promise { + return this._batchReceiversOfTypeDripListByProjectIds.load({ + projectId: id, + chains, + }); } private readonly _batchReceiversOfTypeDripListByDripListIds = new DataLoader( - async (dripListIds: readonly DripListId[]) => { - const receivers = await DripListSplitReceiverModel.findAll({ - where: { - funderDripListId: { - [Op.in]: dripListIds, - }, - type: DependencyType.DripListDependency, - }, - }); - - const receiversOfTypeDripListToDripListMapping = receivers.reduce< - Record - >((mapping, receiver) => { - if (!mapping[receiver.funderDripListId as DripListId]) { - mapping[receiver.funderDripListId as DripListId] = []; // eslint-disable-line no-param-reassign - } - - mapping[receiver.funderDripListId as DripListId].push(receiver); - - return mapping; - }, {}); + async (dripListKeys: readonly DripListMultiChainKey[]) => { + const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); + + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."DripListSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [ + `"funderDripListId" IN (:funderDripListIds)`, + `type = '${DependencyType.DripListDependency}'`, + ]; + const parameters: { [key: string]: any } = { + funderDripListIds: dripListIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const dripListSplitReceiverModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListSplitReceiverModel, + }) + ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); + + const receiversOfTypeDripListToDripListMapping = + dripListSplitReceiverModelDataValues.reduce< + Record + >((mapping, receiver) => { + if (!mapping[receiver.funderDripListId as DripListId]) { + mapping[receiver.funderDripListId as DripListId] = []; // eslint-disable-line no-param-reassign + } + + mapping[receiver.funderDripListId as DripListId].push(receiver); + + return mapping; + }, {}); return dripListIds.map( (id) => receiversOfTypeDripListToDripListMapping[id] || [], @@ -74,7 +138,11 @@ export default class ReceiversOfTypeDripListDataSource { public async getReceiversOfTypeDripListByDripListId( id: DripListId, - ): Promise { - return this._batchReceiversOfTypeDripListByDripListIds.load(id); + chains: SupportedChain[], + ): Promise { + return this._batchReceiversOfTypeDripListByDripListIds.load({ + dripListId: id, + chains, + }); } } diff --git a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts index 4ab4fa7..0549442 100644 --- a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts @@ -1,35 +1,68 @@ import DataLoader from 'dataloader'; -import { Op } from 'sequelize'; -import { - DependencyType, - type DripListId, - type ProjectId, +import { QueryTypes } from 'sequelize'; +import { DependencyType } from '../common/types'; +import type { + DripListMultiChainKey, + DripListId, + ProjectId, + ProjectMultiChainKey, } from '../common/types'; +import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; +import type { SupportedChain } from '../generated/graphql'; +import parseMultiChainKeys from '../utils/parseMultiChainKeys'; +import { dbConnection } from '../database/connectToDatabase'; export default class ReceiversOfTypeProjectDataSource { private readonly _batchReceiversOfTypeProjectByProjectIds = new DataLoader( - async (projectIds: readonly ProjectId[]) => { - const receivers = await RepoDriverSplitReceiverModel.findAll({ - where: { - funderProjectId: { - [Op.in]: projectIds, - }, - type: DependencyType.ProjectDependency, - }, - }); - - const receiversOfTypeProjectToProjectMapping = receivers.reduce< - Record - >((mapping, receiver) => { - if (!mapping[receiver.funderProjectId as ProjectId]) { - mapping[receiver.funderProjectId as ProjectId] = []; // eslint-disable-line no-param-reassign - } - - mapping[receiver.funderProjectId as ProjectId].push(receiver); - - return mapping; - }, {}); + async (projectKeys: readonly ProjectMultiChainKey[]) => { + const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); + + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."RepoDriverSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [ + `"funderProjectId" IN (:funderProjectIds)`, + `type = '${DependencyType.ProjectDependency}'`, + ]; + const parameters: { [key: string]: any } = { + funderProjectIds: projectIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const repoDriverSplitReceiverModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: RepoDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); + + const receiversOfTypeProjectToProjectMapping = + repoDriverSplitReceiverModelDataValues.reduce< + Record + >((mapping, receiver) => { + if (!mapping[receiver.funderProjectId as ProjectId]) { + mapping[receiver.funderProjectId as ProjectId] = []; // eslint-disable-line no-param-reassign + } + + mapping[receiver.funderProjectId as ProjectId].push(receiver); + + return mapping; + }, {}); return projectIds.map( (id) => receiversOfTypeProjectToProjectMapping[id] || [], @@ -39,32 +72,63 @@ export default class ReceiversOfTypeProjectDataSource { public async getReceiversOfTypeProjectByProjectId( id: ProjectId, - ): Promise { - return this._batchReceiversOfTypeProjectByProjectIds.load(id); + chains: SupportedChain[], + ): Promise { + return this._batchReceiversOfTypeProjectByProjectIds.load({ + projectId: id, + chains, + }); } private readonly _batchReceiversOfTypeProjectByDripListIds = new DataLoader( - async (dripListIds: readonly DripListId[]) => { - const receivers = await RepoDriverSplitReceiverModel.findAll({ - where: { - funderDripListId: { - [Op.in]: dripListIds, - }, - type: DependencyType.DripListDependency, - }, - }); - - const receiversOfTypeProjectToDripListMapping = receivers.reduce< - Record - >((mapping, receiver) => { - if (!mapping[receiver.funderDripListId as DripListId]) { - mapping[receiver.funderDripListId as DripListId] = []; // eslint-disable-line no-param-reassign - } - - mapping[receiver.funderDripListId as DripListId].push(receiver); - - return mapping; - }, {}); + async (dripListKeys: readonly DripListMultiChainKey[]) => { + const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); + + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."RepoDriverSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [ + `"funderDripListId" IN (:funderDripListIds)`, + `type = '${DependencyType.DripListDependency}'`, + ]; + const parameters: { [key: string]: any } = { + funderDripListIds: dripListIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const repoDriverSplitReceiverModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: RepoDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); + + const receiversOfTypeProjectToDripListMapping = + repoDriverSplitReceiverModelDataValues.reduce< + Record + >((mapping, receiver) => { + if (!mapping[receiver.funderDripListId as DripListId]) { + mapping[receiver.funderDripListId as DripListId] = []; // eslint-disable-line no-param-reassign + } + + mapping[receiver.funderDripListId as DripListId].push(receiver); + + return mapping; + }, {}); return dripListIds.map( (id) => receiversOfTypeProjectToDripListMapping[id] || [], @@ -74,7 +138,11 @@ export default class ReceiversOfTypeProjectDataSource { public async getReceiversOfTypeProjectByDripListId( id: DripListId, - ): Promise { - return this._batchReceiversOfTypeProjectByDripListIds.load(id); + chains: SupportedChain[], + ): Promise { + return this._batchReceiversOfTypeProjectByDripListIds.load({ + dripListId: id, + chains, + }); } } diff --git a/src/drip-list/DripListModel.ts b/src/drip-list/DripListModel.ts index 1b2d74c..ea0fd7e 100644 --- a/src/drip-list/DripListModel.ts +++ b/src/drip-list/DripListModel.ts @@ -7,7 +7,9 @@ import { DataTypes, Model } from 'sequelize'; import type { AddressLike } from 'ethers'; import type { UUID } from 'crypto'; import getSchema from '../utils/getSchema'; -import type { AccountId, DripListId } from '../common/types'; +import type { AccountId, CommonDataValues, DripListId } from '../common/types'; + +export type DripListDataValues = DripListModel['dataValues'] & CommonDataValues; export default class DripListModel extends Model< InferAttributes, diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index f924140..f14ed3d 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -1,5 +1,11 @@ import { isAddress } from 'ethers'; -import type { Address, DripListId } from '../common/types'; +import type { + Address, + DripListId, + ResolverDripList, + ResolverDripListChainData, + ResolverDripListData, +} from '../common/types'; import type DripListModel from './DripListModel'; import type { AddressDriverAccount, @@ -10,36 +16,47 @@ import type { Project, SplitsReceiver, } from '../generated/graphql'; -import { Driver, SupportedChain } from '../generated/graphql'; +import { SupportedChain, Driver } from '../generated/graphql'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { Context } from '../server'; import assert, { isDripListId } from '../utils/assert'; import type { ProjectDataValues } from '../project/ProjectModel'; +import queryableChains from '../common/queryableChains'; +import toResolverDripLists from './dripListUtils'; +import verifyDripListsInput from './dripListValidators'; +import type { DripListDataValues } from './DripListModel'; const dripListResolvers = { Query: { - dripList: async ( + dripLists: async ( _: any, - { id }: { id: DripListId }, + { + chains, + where, + }: { chains: SupportedChain[]; where: DripListWhereInput }, { dataSources }: Context, - ): Promise => { - assert(isDripListId(id)); + ): Promise => { + verifyDripListsInput({ chains, where }); + + const chainsToQuery = chains?.length ? chains : queryableChains; + + const dripListDataValues = + await dataSources.dripListsDb.getDripListsByFilter( + chainsToQuery, + where, + ); - return dataSources.dripListsDb.getDripListById(id); + return toResolverDripLists(chainsToQuery, dripListDataValues); }, - dripLists: async ( + dripList: async ( _: any, - { where }: { where: DripListWhereInput }, + { id, chain }: { id: DripListId; chain: SupportedChain }, { dataSources }: Context, - ): Promise => { - if (where?.id) { - assert(isDripListId(where.id)); - } - if (where?.ownerAddress) { - assert(isAddress(where.ownerAddress)); - } - - return dataSources.dripListsDb.getDripListsByFilter(where); + ): Promise => { + assert(isDripListId(id)); + assert(chain in SupportedChain); + + return dataSources.dripListsDb.getDripListById(id, chain); }, mintedTokensCountByOwnerAddress: async ( _: any, @@ -54,22 +71,28 @@ const dripListResolvers = { }, }, DripList: { - name: (dripList: DripListModel) => dripList.name ?? 'Unnamed Drip List', - creator: (dripList: DripListModel) => dripList.creator, - description: (dripList: DripListModel) => dripList.description, - previousOwnerAddress: (dripList: DripListModel) => - dripList.previousOwnerAddress, - owner: (dripList: DripListModel): AddressDriverAccount => ({ - driver: Driver.ADDRESS, - accountId: dripList.ownerAccountId || shouldNeverHappen(), - address: (dripList.ownerAddress as string) || shouldNeverHappen(), - }), - account: (dripList: DripListModel): NftDriverAccount => ({ - driver: Driver.NFT, - accountId: dripList.id, - }), + account: (dripList: ResolverDripList): NftDriverAccount => dripList.account, + }, + DripListChainData: { + chain: (chainDripListData: ResolverDripListChainData): SupportedChain => + chainDripListData.chain, + data: (chainDripListData: ResolverDripListChainData) => + chainDripListData.data, + }, + DripListData: { + name: (dripListData: ResolverDripListData) => + dripListData.name ?? 'Unnamed Drip List', + creator: (dripListData: ResolverDripListData) => dripListData.creator, + description: (dripListData: ResolverDripListData) => + dripListData.description, + previousOwnerAddress: (dripListData: ResolverDripListData) => + dripListData.previousOwnerAddress, + latestVotingRoundId: (dripList: DripListModel) => + dripList.latestVotingRoundId, + owner: (dripListData: ResolverDripListData): AddressDriverAccount => + dripListData.owner, splits: async ( - dripList: DripListModel, + dripListData: ResolverDripListData, _: any, context: Context, ): Promise => { @@ -83,10 +106,16 @@ const dripListResolvers = { }, } = context; + const { + parentDripListInfo: { dripListId, dripListChain }, + } = dripListData; + const receiversOfTypeAddressModels = await receiversOfTypeAddressDb.getReceiversOfTypeAddressByDripListId( - dripList.id, + dripListId, + [dripListChain], ); + const addressSplits = receiversOfTypeAddressModels.map((receiver) => ({ driver: Driver.ADDRESS, weight: receiver.weight, @@ -100,12 +129,13 @@ const dripListResolvers = { const receiversOfTypeProjectModels = await receiversOfTypeProjectDb.getReceiversOfTypeProjectByDripListId( - dripList.id, + dripListId, + [dripListChain], ); const splitsOfTypeProjectModels = await projectsDb.getProjectsByIds( receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), - [SupportedChain.sepolia], // TODO: Hardcoded until multiple chains are supported. Fix. + [dripListChain], ); const projectReceivers = receiversOfTypeProjectModels.map((receiver) => ({ @@ -128,11 +158,13 @@ const dripListResolvers = { const receiversOfTypeDripListModels = await receiversOfTypeDripListDb.getReceiversOfTypeDripListByDripListId( - dripList.id, + dripListId, + [dripListChain], ); const splitsOfTypeDripListModels = await dripListsDb.getDripListsByIds( receiversOfTypeDripListModels.map((r) => r.fundeeDripListId), + [dripListChain], ); const dripListReceivers = receiversOfTypeDripListModels.map( @@ -146,7 +178,8 @@ const dripListResolvers = { dripList: (splitsOfTypeDripListModels .filter( - (l): l is DripListModel => l && (l as any).id !== undefined, + (l): l is DripListDataValues => + l && (l as any).id !== undefined, ) .find( (p) => (p as any).id === receiver.fundeeDripListId, @@ -156,25 +189,34 @@ const dripListResolvers = { return [...addressSplits, ...projectReceivers, ...dripListReceivers]; }, - support: async (dripList: DripListModel, _: any, context: Context) => { + support: async ( + dripListData: ResolverDripListData, + _: any, + context: Context, + ) => { + const { + parentDripListInfo: { dripListId, dripListChain }, + } = dripListData; + const { dataSources: { projectAndDripListSupportDb }, } = context; const projectAndDripListSupport = await projectAndDripListSupportDb.getProjectAndDripListSupportByDripListId( - dripList.id, + dripListId, + [dripListChain], ); const oneTimeDonationSupport = await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( - dripList.id, - [], // TODO: Only for compilation. Fix. + dripListId, + [dripListChain], ); const streamSupport = await projectAndDripListSupportDb.getStreamSupportByAccountId( - dripList.id, + dripListId, ); return [ @@ -183,8 +225,6 @@ const dripListResolvers = { ...oneTimeDonationSupport, ]; }, - latestVotingRoundId: (dripList: DripListModel) => - dripList.latestVotingRoundId, }, }; diff --git a/src/drip-list/dripListTypeDef.ts b/src/drip-list/dripListTypeDef.ts index 38e6d53..52eda0d 100644 --- a/src/drip-list/dripListTypeDef.ts +++ b/src/drip-list/dripListTypeDef.ts @@ -2,11 +2,20 @@ import gql from 'graphql-tag'; const dripListTypeDef = gql` type DripList { + account: NftDriverAccount! + chainData: [DripListChainData!]! + } + + type DripListChainData { + chain: SupportedChain! + data: DripListData + } + + type DripListData { name: String! creator: String! description: String splits: [SplitsReceiver!]! - account: NftDriverAccount! owner: AddressDriverAccount! previousOwnerAddress: String! support: [SupportItem!]! diff --git a/src/drip-list/dripListUtils.ts b/src/drip-list/dripListUtils.ts new file mode 100644 index 0000000..e6f34b6 --- /dev/null +++ b/src/drip-list/dripListUtils.ts @@ -0,0 +1,57 @@ +import type { + ResolverDripList, + ResolverDripListChainData, +} from '../common/types'; +import { Driver, type SupportedChain } from '../generated/graphql'; +import type { DripListDataValues } from './DripListModel'; + +export default async function toResolverDripLists( + chains: SupportedChain[], + dripLists: DripListDataValues[], +): Promise { + return Promise.all( + dripLists.map(async (dripList) => { + const chainData = await Promise.all( + chains.map(async (chain) => { + if (dripList.chain === chain) { + return { + chain, + data: { + parentDripListInfo: { + dripListId: dripList.id, + dripListChain: chain, + queriedChains: chains, + }, + name: dripList.name, + creator: dripList.creator, + description: dripList.description, + owner: { + driver: Driver.ADDRESS, + accountId: dripList.ownerAccountId, + address: dripList.ownerAddress as string, + }, + previousOwnerAddress: dripList.previousOwnerAddress, + support: [], // Will be populated by the resolver. + splits: [], // Will be populated by the resolver. + latestVotingRoundId: dripList.latestVotingRoundId, + }, + } as ResolverDripListChainData; + } + + return { + chain, + data: null, + }; + }), + ); + + return { + account: { + accountId: dripList.id, + driver: Driver.NFT, + }, + chainData, + } as ResolverDripList; + }), + ); +} diff --git a/src/drip-list/dripListValidators.ts b/src/drip-list/dripListValidators.ts new file mode 100644 index 0000000..2be3e50 --- /dev/null +++ b/src/drip-list/dripListValidators.ts @@ -0,0 +1,24 @@ +import { isAddress } from 'ethers'; +import { SupportedChain } from '../generated/graphql'; +import type { DripListWhereInput } from '../generated/graphql'; +import assert, { isDripListId } from '../utils/assert'; + +export default function verifyDripListsInput(input: { + chains: SupportedChain[]; + where: DripListWhereInput; +}) { + const { where, chains } = input; + + if (where?.id) { + assert(isDripListId(where.id)); + } + if (where?.ownerAddress) { + assert(isAddress(where.ownerAddress)); + } + + if (chains) { + chains.forEach((chain) => { + assert(chain in SupportedChain); + }); + } +} diff --git a/src/given-event/GivenEventModel.ts b/src/given-event/GivenEventModel.ts index 6fb517d..5d2e9f4 100644 --- a/src/given-event/GivenEventModel.ts +++ b/src/given-event/GivenEventModel.ts @@ -4,15 +4,16 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import type { AccountId, Address, BigIntString } from '../common/types'; +import type { + AccountId, + Address, + BigIntString, + CommonDataValues, +} from '../common/types'; import getSchema from '../utils/getSchema'; -import type { SupportedChain } from '../generated/graphql'; -export type GivenEventModelDataValues = GivenEventModel['dataValues'] & { - createdAt: Date; - updatedAt: Date; - chain: SupportedChain; -}; +export type GivenEventModelDataValues = GivenEventModel['dataValues'] & + CommonDataValues; export default class GivenEventModel extends Model< InferAttributes, diff --git a/src/models/AddressDriverSplitReceiverModel.ts b/src/models/AddressDriverSplitReceiverModel.ts index 903a416..adb9e65 100644 --- a/src/models/AddressDriverSplitReceiverModel.ts +++ b/src/models/AddressDriverSplitReceiverModel.ts @@ -7,10 +7,18 @@ import type { import { DataTypes, Model } from 'sequelize'; import type { AddressLike } from 'ethers'; import getSchema from '../utils/getSchema'; -import type { AddressDriverId, DripListId, ProjectId } from '../common/types'; +import type { + AddressDriverId, + CommonDataValues, + DripListId, + ProjectId, +} from '../common/types'; import DripListModel from '../drip-list/DripListModel'; import ProjectModel from '../project/ProjectModel'; +export type AddressDriverSplitReceiverModelDataValues = + AddressDriverSplitReceiverModel['dataValues'] & CommonDataValues; + export enum AddressDriverSplitReceiverType { ProjectMaintainer = 'ProjectMaintainer', ProjectDependency = 'ProjectDependency', diff --git a/src/models/DripListSplitReceiverModel.ts b/src/models/DripListSplitReceiverModel.ts index 6a6ac19..66e0f1a 100644 --- a/src/models/DripListSplitReceiverModel.ts +++ b/src/models/DripListSplitReceiverModel.ts @@ -7,10 +7,13 @@ import type { import { DataTypes, Model } from 'sequelize'; import getSchema from '../utils/getSchema'; import { DependencyType } from '../common/types'; -import type { DripListId, ProjectId } from '../common/types'; +import type { CommonDataValues, DripListId, ProjectId } from '../common/types'; import DripListModel from '../drip-list/DripListModel'; import ProjectModel from '../project/ProjectModel'; +export type DripListSplitReceiverModelDataValues = + DripListSplitReceiverModel['dataValues'] & CommonDataValues; + export default class DripListSplitReceiverModel extends Model< InferAttributes, InferCreationAttributes diff --git a/src/models/RepoDriverSplitReceiverModel.ts b/src/models/RepoDriverSplitReceiverModel.ts index 725fe48..d7b19c3 100644 --- a/src/models/RepoDriverSplitReceiverModel.ts +++ b/src/models/RepoDriverSplitReceiverModel.ts @@ -6,18 +6,13 @@ import type { } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; import getSchema from '../utils/getSchema'; -import type { DripListId, ProjectId } from '../common/types'; +import type { CommonDataValues, DripListId, ProjectId } from '../common/types'; import { DependencyType } from '../common/types'; import ProjectModel from '../project/ProjectModel'; import DripListModel from '../drip-list/DripListModel'; -import type { SupportedChain } from '../generated/graphql'; export type RepoDriverSplitReceiverModelDataValues = - RepoDriverSplitReceiverModel['dataValues'] & { - createdAt: Date; - updatedAt: Date; - chain: SupportedChain; - }; + RepoDriverSplitReceiverModel['dataValues'] & CommonDataValues; export default class RepoDriverSplitReceiverModel extends Model< InferAttributes, diff --git a/src/project/ProjectModel.ts b/src/project/ProjectModel.ts index 506d00c..a98f10a 100644 --- a/src/project/ProjectModel.ts +++ b/src/project/ProjectModel.ts @@ -6,15 +6,15 @@ import type { import { DataTypes, Model } from 'sequelize'; import type { AddressLike } from 'ethers'; import getSchema from '../utils/getSchema'; -import type { AccountId, Forge, ProjectId } from '../common/types'; +import type { + AccountId, + CommonDataValues, + Forge, + ProjectId, +} from '../common/types'; import { FORGES_MAP } from '../common/constants'; -import type { SupportedChain } from '../generated/graphql'; -export type ProjectDataValues = ProjectModel['dataValues'] & { - createdAt: Date; - updatedAt: Date; - chain: SupportedChain; -}; +export type ProjectDataValues = ProjectModel['dataValues'] & CommonDataValues; export enum ProjectVerificationStatus { Claimed = 'Claimed', diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 9950b36..c9f1ed3 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -1,10 +1,9 @@ -import { isAddress } from 'ethers'; import type { ProjectId, - ResolverClaimedChainProjectData, + ResolverClaimedProjectChainData, ResolverClaimedProjectData, ResolverProject, - ResolverUnClaimedChainProjectData, + ResolverUnClaimedProjectChainData, ResolverUnClaimedProjectData, } from '../common/types'; import { toResolverProjects } from './projectUtils'; @@ -27,37 +26,14 @@ import type { import type { Context } from '../server'; import { AddressDriverSplitReceiverType } from '../models/AddressDriverSplitReceiverModel'; import groupBy from '../utils/linq'; -import type DripListModel from '../drip-list/DripListModel'; -import assert, { - isGitHubUrl, - isProjectVerificationStatus, - isProjectId, - isSortableProjectField, -} from '../utils/assert'; +import assert, { isGitHubUrl, isProjectId } from '../utils/assert'; import queryableChains from '../common/queryableChains'; import type { ProjectDataValues } from './ProjectModel'; +import verifyProjectsInput from './projectValidators'; +import type { DripListDataValues } from '../drip-list/DripListModel'; const projectResolvers = { Query: { - projectById: async ( - _: any, - { id, chain }: { id: ProjectId; chain: SupportedChain }, - { dataSources }: Context, - ): Promise => { - assert(isProjectId(id)); - assert(chain in SupportedChain); - - return dataSources.projectsDb.getProjectById(id, chain); - }, - projectByUrl: async ( - _: any, - { url }: { url: string }, - { dataSources }: Context, - ): Promise => { - assert(isGitHubUrl(url)); - - return dataSources.projectsDb.getProjectByUrl(url); - }, projects: async ( _: any, { @@ -71,31 +47,7 @@ const projectResolvers = { }, { dataSources }: Context, ): Promise => { - if (where?.id) { - assert(isProjectId(where.id)); - } - - if (where?.ownerAddress) { - assert(isAddress(where.ownerAddress)); - } - - if (where?.url) { - assert(isGitHubUrl(where.url)); - } - - if (where?.verificationStatus) { - assert(isProjectVerificationStatus(where.verificationStatus)); - } - - if (sort?.field === 'claimedAt') { - assert(isSortableProjectField(sort.field)); - } - - if (chains) { - chains.forEach((chain) => { - assert(chain in SupportedChain); - }); - } + verifyProjectsInput({ chains, where, sort }); const chainsToQuery = chains?.length ? chains : queryableChains; @@ -108,6 +60,25 @@ const projectResolvers = { return toResolverProjects(chainsToQuery, projectsDataValues); }, + projectById: async ( + _: any, + { id, chain }: { id: ProjectId; chain: SupportedChain }, + { dataSources }: Context, + ): Promise => { + assert(isProjectId(id)); + assert(chain in SupportedChain); + + return dataSources.projectsDb.getProjectById(id, chain); + }, + projectByUrl: async ( + _: any, + { url }: { url: string }, + { dataSources }: Context, + ): Promise => { + assert(isGitHubUrl(url)); + + return dataSources.projectsDb.getProjectByUrl(url); + }, earnedFunds: async ( _: any, { projectId }: { projectId: ProjectId }, @@ -119,30 +90,30 @@ const projectResolvers = { }, }, Project: { - account: (project: ResolverProject): RepoDriverAccount => project.account, source: (project: ResolverProject): Source => project.source, + account: (project: ResolverProject): RepoDriverAccount => project.account, }, ProjectChainData: { __resolveType(parent: ProjectChainData) { if ('claimedAt' in parent.data) { - return 'ClaimedChainProjectData'; + return 'ClaimedProjectChainData'; } - return 'UnClaimedChainProjectData'; + return 'UnClaimedProjectChainData'; }, }, - ClaimedChainProjectData: { + ClaimedProjectChainData: { chain: ( - chainProjectData: ResolverClaimedChainProjectData, + chainProjectData: ResolverClaimedProjectChainData, ): SupportedChain => chainProjectData.chain, - data: (chainProjectData: ResolverClaimedChainProjectData) => + data: (chainProjectData: ResolverClaimedProjectChainData) => chainProjectData.data, }, - UnClaimedChainProjectData: { + UnClaimedProjectChainData: { chain: ( - chainProjectData: ResolverUnClaimedChainProjectData, + chainProjectData: ResolverUnClaimedProjectChainData, ): SupportedChain => chainProjectData.chain, - data: (chainProjectData: ResolverUnClaimedChainProjectData) => + data: (chainProjectData: ResolverUnClaimedProjectChainData) => chainProjectData.data, }, ClaimedProjectData: { @@ -173,11 +144,14 @@ const projectResolvers = { }, } = context; - const { parentProject } = projectData; + const { + parentProjectInfo: { projectId, projectChain }, + } = projectData; const receiversOfTypeAddressModels = await receiversOfTypeAddressDb.getReceiversOfTypeAddressByProjectId( - parentProject.projectId, + projectId, + [projectChain], ); const maintainersAndAddressDependencies = groupBy( @@ -206,12 +180,13 @@ const projectResolvers = { const receiversOfTypeProjectModels = await receiversOfTypeProjectDb.getReceiversOfTypeProjectByProjectId( - parentProject.projectId, + projectId, + [projectChain], ); const splitsOfTypeProjectModels = await projectsDb.getProjectsByIds( receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), - [SupportedChain.sepolia], // TODO: Hardcoded until multiple chains are supported. Fix. + [projectChain], ); const dependenciesOfTypeProject = receiversOfTypeProjectModels.map( @@ -236,11 +211,13 @@ const projectResolvers = { const receiversOfTypeDripListModels = await receiversOfTypeDripListDb.getReceiversOfTypeDripListByProjectId( - parentProject.projectId, + projectId, + [projectChain], ); const splitsOfTypeDripListModels = await dripListsDb.getDripListsByIds( receiversOfTypeDripListModels.map((r) => r.fundeeDripListId), + [projectChain], ); const dripListReceivers = receiversOfTypeDripListModels.map( @@ -254,7 +231,8 @@ const projectResolvers = { dripList: (splitsOfTypeDripListModels .filter( - (l): l is DripListModel => l && (l as any).id !== undefined, + (l): l is DripListDataValues => + l && (l as any).id !== undefined, ) .find( (p) => (p as any).id === receiver.fundeeDripListId, @@ -277,23 +255,26 @@ const projectResolvers = { context: Context, ) => { const { - parentProject: { projectId, queriedChains }, + parentProjectInfo: { projectId, projectChain }, } = projectData; + const { dataSources: { projectAndDripListSupportDb }, } = context; - const projectAndDripListSupport = + const projectAndDripListSupport = ( await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( projectId, - queriedChains, - ); + [projectChain], + ) + ).filter((s) => s.chain === projectChain); - const oneTimeDonationSupport = + const oneTimeDonationSupport = ( await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( projectId, - queriedChains, - ); + [projectChain], + ) + ).filter((s) => s.chain === projectChain); return [...projectAndDripListSupport, ...oneTimeDonationSupport]; }, @@ -311,20 +292,22 @@ const projectResolvers = { } = context; const { - parentProject: { projectId, queriedChains }, + parentProjectInfo: { projectId, projectChain }, } = projectData; - const projectAndDripListSupport = + const projectAndDripListSupport = ( await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( projectId, - queriedChains, - ); + [projectChain], + ) + ).filter((s) => s.chain === projectChain); - const oneTimeDonationSupport = + const oneTimeDonationSupport = ( await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( projectId, - queriedChains, - ); + [projectChain], + ) + ).filter((s) => s.chain === projectChain); return [...projectAndDripListSupport, ...oneTimeDonationSupport]; }, diff --git a/src/project/projectTypeDef.ts b/src/project/projectTypeDef.ts index 45470b0..0d9f34f 100644 --- a/src/project/projectTypeDef.ts +++ b/src/project/projectTypeDef.ts @@ -31,9 +31,9 @@ const projectTypeDef = gql` chainData: [ProjectChainData!]! } - union ProjectChainData = ClaimedChainProjectData | UnClaimedChainProjectData + union ProjectChainData = ClaimedProjectChainData | UnClaimedProjectChainData - type ClaimedChainProjectData { + type ClaimedProjectChainData { chain: SupportedChain! data: ClaimedProjectData! } @@ -50,7 +50,7 @@ const projectTypeDef = gql` claimedAt: Date! } - type UnClaimedChainProjectData { + type UnClaimedProjectChainData { chain: SupportedChain! data: UnClaimedProjectData! } diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 425af00..e3bc42e 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -2,9 +2,9 @@ import { ethers } from 'ethers'; import type { Forge, ProjectId, - ResolverClaimedChainProjectData, + ResolverClaimedProjectChainData, ResolverProject, - ResolverUnClaimedChainProjectData, + ResolverUnClaimedProjectChainData, } from '../common/types'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { ProjectDataValues } from './ProjectModel'; @@ -182,9 +182,10 @@ export async function toResolverProjects( return { chain, data: { - parentProject: { + parentProjectInfo: { projectId: project.id, queriedChains: chains, + projectChain: chain, }, color: project.color, emoji: project.emoji, @@ -206,21 +207,22 @@ export async function toResolverProjects( support: [], // Will be populated by the resolver. claimedAt: project.claimedAt, }, - } as ResolverClaimedChainProjectData; + } as ResolverClaimedProjectChainData; } const fakeUnclaimedProject = await toFakeUnclaimedProject(project); return { chain, data: { - parentProject: { + parentProjectInfo: { queriedChains: chains, projectId: fakeUnclaimedProject.id, + projectChain: chain, }, verificationStatus: fakeUnclaimedProject.verificationStatus, support: [], // Will be populated by the resolver. }, - } as ResolverUnClaimedChainProjectData; + } as ResolverUnClaimedProjectChainData; }), ); diff --git a/src/project/projectValidators.ts b/src/project/projectValidators.ts new file mode 100644 index 0000000..6ff0c31 --- /dev/null +++ b/src/project/projectValidators.ts @@ -0,0 +1,46 @@ +import { isAddress } from 'ethers'; +import { SupportedChain } from '../generated/graphql'; +import type { ProjectSortInput, ProjectWhereInput } from '../generated/graphql'; +import assert, { + isGitHubUrl, + isProjectId, + isProjectVerificationStatus, +} from '../utils/assert'; + +function isSortableProjectField(field: string): boolean { + return ['claimedAt'].includes(field); +} + +export default function verifyProjectsInput(input: { + chains: SupportedChain[]; + where: ProjectWhereInput; + sort: ProjectSortInput; +}) { + const { where, sort, chains } = input; + + if (where?.id) { + assert(isProjectId(where.id)); + } + + if (where?.ownerAddress) { + assert(isAddress(where.ownerAddress)); + } + + if (where?.url) { + assert(isGitHubUrl(where.url)); + } + + if (where?.verificationStatus) { + assert(isProjectVerificationStatus(where.verificationStatus)); + } + + if (sort?.field === 'claimedAt') { + assert(isSortableProjectField(sort.field)); + } + + if (chains) { + chains.forEach((chain) => { + assert(chain in SupportedChain); + }); + } +} diff --git a/src/resolvers.ts b/src/resolvers.ts index a6e3e3f..02d9a84 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -15,10 +15,12 @@ const resolvers = { Project: projectResolvers.Project, ProjectChainData: projectResolvers.ProjectChainData, ClaimedProjectData: projectResolvers.ClaimedProjectData, - ClaimedChainProjectData: projectResolvers.ClaimedChainProjectData, + ClaimedProjectChainData: projectResolvers.ClaimedProjectChainData, UnClaimedProjectData: projectResolvers.UnClaimedProjectData, - UnClaimedChainProjectData: projectResolvers.UnClaimedChainProjectData, + UnClaimedProjectChainData: projectResolvers.UnClaimedProjectChainData, DripList: dripListResolvers.DripList, + DripListChainData: dripListResolvers.DripListChainData, + DripListData: dripListResolvers.DripListData, SplitsReceiver: projectResolvers.SplitsReceiver, SupportItem: commonResolvers.SupportItem, Avatar: projectResolvers.Avatar, diff --git a/src/schema.ts b/src/schema.ts index bf81afc..fc58e2d 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -15,8 +15,11 @@ const rootTypeDef = gql` ): [Project!]! projectById(id: ID!, chain: SupportedChain!): Project projectByUrl(url: String!): Project - dripList(id: ID!): DripList - dripLists(where: DripListWhereInput): [DripList!]! + dripLists( + chains: [SupportedChain!]! + where: DripListWhereInput + ): [DripList!]! + dripList(id: ID!, chain: SupportedChain!): DripList gives(where: GiveWhereInput): [Give!]! mintedTokensCountByOwnerAddress(ownerAddress: String!): Int! earnedFunds(projectId: String!): [Amount!]! diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index c85f82f..026423a 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -1,4 +1,8 @@ -import { Driver, type StreamWhereInput } from '../generated/graphql'; +import { + Driver, + SupportedChain, + type StreamWhereInput, +} from '../generated/graphql'; import type { Context } from '../server'; import shouldNeverHappen from '../utils/shouldNeverHappen'; @@ -21,6 +25,7 @@ const streamResolvers = { if (parent.receiver.driver === Driver.NFT) { return dataSources.dripListsDb.getDripListById( parent.receiver.accountId, + SupportedChain.sepolia, // TODO: Temporary for compiling. ); } @@ -32,7 +37,10 @@ const streamResolvers = { } if (parent.sender.driver === Driver.NFT) { - return dataSources.dripListsDb.getDripListById(parent.sender.accountId); + return dataSources.dripListsDb.getDripListById( + parent.sender.accountId, + SupportedChain.sepolia, // TODO: Temporary for compiling. + ); } throw shouldNeverHappen(); diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index 5934557..e436500 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -62,9 +62,12 @@ const userResolvers = { const { accountId } = parent.account; assert(isAddressDriverId(accountId)); - return dataSources.dripListsDb.getDripListsByFilter({ - ownerAddress: getUserAddress(accountId), - }); + return dataSources.dripListsDb.getDripListsByFilter( + [SupportedChain.sepolia], // TODO: Temporary for compiling. + { + ownerAddress: getUserAddress(accountId), + }, + ); }, }, UserStreams: { diff --git a/src/utils/assert.ts b/src/utils/assert.ts index b852f73..88feac1 100644 --- a/src/utils/assert.ts +++ b/src/utils/assert.ts @@ -72,7 +72,3 @@ export function isProjectVerificationStatus( export function isAccountId(id: string): boolean { return isAddressDriverId(id) || isDripListId(id) || isProjectId(id); } - -export function isSortableProjectField(field: string): boolean { - return ['claimedAt'].includes(field); -} diff --git a/src/utils/parseMultiChainKeys.ts b/src/utils/parseMultiChainKeys.ts index e6c8f07..791e54f 100644 --- a/src/utils/parseMultiChainKeys.ts +++ b/src/utils/parseMultiChainKeys.ts @@ -1,5 +1,4 @@ import type { SupportedChain } from '../generated/graphql'; -import shouldNeverHappen from './shouldNeverHappen'; type MultiChainKey = { chains: SupportedChain[] }; @@ -16,18 +15,10 @@ export default function parseMultiChainKeys< T extends MultiChainKey & { [key: string]: any }, >(keys: ReadonlyArray): ExtractedValues { const ids = keys.map((key) => key.projectId ?? key.dripListId); - const chainsToQuery = keys.map((key) => key.chains); - - if ( - chainsToQuery.some( - (chain) => JSON.stringify(chain) !== JSON.stringify(chainsToQuery[0]), - ) - ) { - shouldNeverHappen('Chains are not the same within a batch.'); - } + const chains = new Set(keys.flatMap((key) => key.chains)); return { ids, - chains: chainsToQuery[0], + chains: [...chains], }; } From d5c83d52f06576b89d447658f893f0356ba0c47d Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 30 May 2024 15:46:12 +0200 Subject: [PATCH 04/37] add multi chain totalEarded queries --- src/common/commonResolverLogic.ts | 87 ++++++++++++++++ src/common/commonResolvers.ts | 44 +-------- src/dataLoaders/TotalEarnedDataSource.ts | 120 +++++++++++++++++++++++ src/drip-list/dripListResolvers.ts | 33 ++----- src/models/SplitEventModel.ts | 10 +- src/project/projectResolvers.ts | 43 +++----- src/server.ts | 3 + src/utils/mergeAmounts.ts | 19 +++- 8 files changed, 253 insertions(+), 106 deletions(-) create mode 100644 src/common/commonResolverLogic.ts create mode 100644 src/dataLoaders/TotalEarnedDataSource.ts diff --git a/src/common/commonResolverLogic.ts b/src/common/commonResolverLogic.ts new file mode 100644 index 0000000..12c9cd3 --- /dev/null +++ b/src/common/commonResolverLogic.ts @@ -0,0 +1,87 @@ +import type { + DripListId, + ProjectId, + ResolverDripListData, + ResolverUnClaimedProjectData, +} from './types'; +import type { Context } from '../server'; +import mergeAmounts from '../utils/mergeAmounts'; +import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; +import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; +import shouldNeverHappen from '../utils/shouldNeverHappen'; +import SplitEventModel from '../models/SplitEventModel'; +import { SupportedChain } from '../generated/graphql'; + +export async function resolveTotalSplit( + parent: DripListSplitReceiverModel | RepoDriverSplitReceiverModel, +) { + let incomingAccountId: DripListId | ProjectId; + let recipientAccountId: DripListId | ProjectId; + + if (parent instanceof DripListSplitReceiverModel) { + const { fundeeDripListId, funderDripListId, funderProjectId } = parent; + recipientAccountId = fundeeDripListId; + incomingAccountId = + funderDripListId || funderProjectId || shouldNeverHappen(); + } else if (parent instanceof RepoDriverSplitReceiverModel) { + const { fundeeProjectId, funderDripListId, funderProjectId } = parent; + recipientAccountId = fundeeProjectId; + incomingAccountId = + funderDripListId || funderProjectId || shouldNeverHappen(); + } else { + shouldNeverHappen('Invalid SupportItem type'); + } + + const splitEvents = await SplitEventModel.findAll({ + where: { + accountId: incomingAccountId, + receiver: recipientAccountId, + }, + }); + + return mergeAmounts( + splitEvents.map((splitEvent) => ({ + tokenAddress: splitEvent.erc20, + amount: BigInt(splitEvent.amt), + chain: SupportedChain.sepolia, // TODO: Only for compilation. + })), + ).map((amount) => ({ + ...amount, + amount: amount.amount.toString(), + })); +} + +export async function resolveTotalEarned( + projectOrDripListData: ResolverUnClaimedProjectData | ResolverDripListData, + _: any, + context: Context, +) { + let accountId: ProjectId | DripListId; + let chain: SupportedChain; + if ('parentProjectInfo' in projectOrDripListData) { + accountId = projectOrDripListData.parentProjectInfo.projectId; + chain = projectOrDripListData.parentProjectInfo.projectChain; + } else { + accountId = projectOrDripListData.parentDripListInfo.dripListId; + chain = projectOrDripListData.parentDripListInfo.dripListChain; + } + + const { totalEarnedDb } = context.dataSources; + + const { splitEventsForDripListDataValues, givenEventsForDripListDataValues } = + await totalEarnedDb.getTotalEarnedByProjectIds(accountId, [chain]); + + return mergeAmounts( + [ + ...splitEventsForDripListDataValues.filter((e) => e.chain === chain), + ...givenEventsForDripListDataValues.filter((e) => e.chain === chain), + ].map((event) => ({ + tokenAddress: event.erc20, + amount: BigInt(event.amt), + chain: event.chain, + })), + ).map((amount) => ({ + ...amount, + amount: amount.amount.toString(), + })); +} diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index a7eece7..6c8d3b9 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -8,7 +8,7 @@ import type { import { Driver } from '../generated/graphql'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import type GivenEventModel from '../given-event/GivenEventModel'; -import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; +import type DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import type { Context } from '../server'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { DripListId, ProjectId } from './types'; @@ -18,47 +18,7 @@ import type { ProtoStream } from '../utils/buildAssetConfigs'; import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; import { toResolverProjects } from '../project/projectUtils'; import toResolverDripLists from '../drip-list/dripListUtils'; -import SplitEventModel from '../models/SplitEventModel'; -import mergeAmounts from '../utils/mergeAmounts'; -import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; - -async function resolveTotalSplit( - parent: DripListSplitReceiverModel | RepoDriverSplitReceiverModel, -) { - let incomingAccountId: DripListId | ProjectId; - let recipientAccountId: DripListId | ProjectId; - - if (parent instanceof DripListSplitReceiverModel) { - const { fundeeDripListId, funderDripListId, funderProjectId } = parent; - recipientAccountId = fundeeDripListId; - incomingAccountId = - funderDripListId || funderProjectId || shouldNeverHappen(); - } else if (parent instanceof RepoDriverSplitReceiverModel) { - const { fundeeProjectId, funderDripListId, funderProjectId } = parent; - recipientAccountId = fundeeProjectId; - incomingAccountId = - funderDripListId || funderProjectId || shouldNeverHappen(); - } else { - shouldNeverHappen('Invalid SupportItem type'); - } - - const splitEvents = await SplitEventModel.findAll({ - where: { - accountId: incomingAccountId, - receiver: recipientAccountId, - }, - }); - - return mergeAmounts( - splitEvents.map((splitEvent) => ({ - tokenAddress: splitEvent.erc20, - amount: BigInt(splitEvent.amt), - })), - ).map((amount) => ({ - ...amount, - amount: amount.amount.toString(), - })); -} +import { resolveTotalSplit } from './commonResolverLogic'; const commonResolvers = { SupportItem: { diff --git a/src/dataLoaders/TotalEarnedDataSource.ts b/src/dataLoaders/TotalEarnedDataSource.ts new file mode 100644 index 0000000..09a89c3 --- /dev/null +++ b/src/dataLoaders/TotalEarnedDataSource.ts @@ -0,0 +1,120 @@ +/* eslint-disable no-param-reassign */ +import DataLoader from 'dataloader'; +import { QueryTypes } from 'sequelize'; +import type { + AccountId, + DripListId, + DripListMultiChainKey, + ProjectId, + ProjectMultiChainKey, +} from '../common/types'; +import parseMultiChainKeys from '../utils/parseMultiChainKeys'; +import type { SupportedChain } from '../generated/graphql'; +import { dbConnection } from '../database/connectToDatabase'; +import type { SplitEventModelDataValues } from '../models/SplitEventModel'; +import SplitEventModel from '../models/SplitEventModel'; +import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; +import GivenEventModel from '../given-event/GivenEventModel'; +import { isDripListId, isProjectId } from '../utils/assert'; +import shouldNeverHappen from '../utils/shouldNeverHappen'; + +export default class TotalEarnedDataSource { + private readonly _batchTotalEarnedByProjectIds = new DataLoader( + async (keys: readonly (DripListMultiChainKey | ProjectMultiChainKey)[]) => { + const { chains, ids: projectIds } = parseMultiChainKeys(keys); + + // Define base SQL to query from multiple chains (schemas). + const baseSplitEventsSQL = (schema: SupportedChain) => + `SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; + + const baseGivenEventsSplitsSQL = (schema: SupportedChain) => + `SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + // Build the WHERE clause. + const conditions: string[] = [`"receiver" IN (:receivers)`]; + const parameters: { [key: string]: any } = { + receivers: projectIds, + }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const splitsQueries = chains.map( + (chain) => baseSplitEventsSQL(chain) + whereClause, + ); + const givenQueries = chains.map( + (chain) => baseGivenEventsSplitsSQL(chain) + whereClause, + ); + + // Combine all schema queries with UNION. + const fullSplitsQuery = `${splitsQueries.join(' UNION ')} LIMIT 1000`; + const fullGivenQuery = `${givenQueries.join(' UNION ')} LIMIT 1000`; + + const splitEventModelDataValues = ( + await dbConnection.query(fullSplitsQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: SplitEventModel, + }) + ).map((p) => p.dataValues as SplitEventModelDataValues); + + const givenEventModelDataValues = ( + await dbConnection.query(fullGivenQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); + + const splitEventsByDripListId = splitEventModelDataValues.reduce< + Record + >((mapping, event) => { + if (!mapping[event.receiver]) { + mapping[event.receiver] = []; + } + + mapping[event.receiver].push(event); + + return mapping; + }, {}); + + const givenEventsByDripListId = givenEventModelDataValues.reduce< + Record + >((mapping, event) => { + if (!mapping[event.receiver]) { + mapping[event.receiver] = []; + } + + mapping[event.receiver].push(event); + + return mapping; + }, {}); + + return projectIds.map((id) => ({ + splitEventsForDripListDataValues: splitEventsByDripListId[id] || [], + givenEventsForDripListDataValues: givenEventsByDripListId[id] || [], + })); + }, + ); + + public async getTotalEarnedByProjectIds( + id: DripListId | ProjectId, + chains: SupportedChain[], + ): Promise<{ + splitEventsForDripListDataValues: SplitEventModelDataValues[]; + givenEventsForDripListDataValues: GivenEventModelDataValues[]; + }> { + // eslint-disable-next-line no-nested-ternary + const key = isDripListId(id) + ? { dripListId: id, chains } + : isProjectId(id) + ? { projectId: id, chains } + : shouldNeverHappen(); + + return this._batchTotalEarnedByProjectIds.load(key); + } +} diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index dd09c07..30a3432 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -25,9 +25,7 @@ import queryableChains from '../common/queryableChains'; import toResolverDripLists from './dripListUtils'; import verifyDripListsInput from './dripListValidators'; import type { DripListDataValues } from './DripListModel'; -import SplitEventModel from '../models/SplitEventModel'; -import mergeAmounts from '../utils/mergeAmounts'; -import GivenEventModel from '../given-event/GivenEventModel'; +import { resolveTotalEarned } from '../common/commonResolverLogic'; const dripListResolvers = { Query: { @@ -228,30 +226,11 @@ const dripListResolvers = { ...oneTimeDonationSupport, ]; }, - totalEarned: async (dripList: DripListModel) => { - const [splitEvents, givenEvents] = await Promise.all([ - SplitEventModel.findAll({ - where: { - receiver: dripList.id, - }, - }), - GivenEventModel.findAll({ - where: { - receiver: dripList.id, - }, - }), - ]); - - return mergeAmounts( - [...splitEvents, ...givenEvents].map((event) => ({ - tokenAddress: event.erc20, - amount: BigInt(event.amt), - })), - ).map((amount) => ({ - ...amount, - amount: amount.amount.toString(), - })); - }, + totalEarned: async ( + dripListData: ResolverDripListData, + _: any, + context: Context, + ) => resolveTotalEarned(dripListData, _, context), }, }; diff --git a/src/models/SplitEventModel.ts b/src/models/SplitEventModel.ts index 05b1ca9..1e8bd83 100644 --- a/src/models/SplitEventModel.ts +++ b/src/models/SplitEventModel.ts @@ -5,9 +5,17 @@ import type { } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; import getSchema from '../utils/getSchema'; -import type { AccountId, Address, BigIntString } from '../common/types'; +import type { + AccountId, + Address, + BigIntString, + CommonDataValues, +} from '../common/types'; import { COMMON_EVENT_INIT_ATTRIBUTES } from '../common/constants'; +export type SplitEventModelDataValues = SplitEventModel['dataValues'] & + CommonDataValues; + export default class SplitEventModel extends Model< InferAttributes, InferCreationAttributes diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index a7baca3..ca94247 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -30,11 +30,8 @@ import queryableChains from '../common/queryableChains'; import type { ProjectDataValues } from './ProjectModel'; import verifyProjectsInput from './projectValidators'; import type { DripListDataValues } from '../drip-list/DripListModel'; -import SplitEventModel from '../models/SplitEventModel'; -import GivenEventModel from '../given-event/GivenEventModel'; -import mergeAmounts from '../utils/mergeAmounts'; import assert, { isGitHubUrl, isProjectId } from '../utils/assert'; -import type ProjectModel from './ProjectModel'; +import { resolveTotalEarned } from '../common/commonResolverLogic'; const projectResolvers = { Query: { @@ -282,6 +279,11 @@ const projectResolvers = { return [...projectAndDripListSupport, ...oneTimeDonationSupport]; }, + totalEarned: async ( + projectData: ResolverUnClaimedProjectData, + _: any, + context: Context, + ) => resolveTotalEarned(projectData, _, context), }, UnClaimedProjectData: { verificationStatus: (projectData: ResolverUnClaimedProjectData) => @@ -291,9 +293,7 @@ const projectResolvers = { _: any, context: Context, ) => { - const { - dataSources: { projectAndDripListSupportDb }, - } = context; + const { projectAndDripListSupportDb } = context.dataSources; const { parentProjectInfo: { projectId, projectChain }, @@ -315,30 +315,11 @@ const projectResolvers = { return [...projectAndDripListSupport, ...oneTimeDonationSupport]; }, - totalEarned: async (project: ProjectModel) => { - const [splitEvents, givenEvents] = await Promise.all([ - SplitEventModel.findAll({ - where: { - receiver: project.id, - }, - }), - GivenEventModel.findAll({ - where: { - receiver: project.id, - }, - }), - ]); - - return mergeAmounts( - [...splitEvents, ...givenEvents].map((event) => ({ - tokenAddress: event.erc20, - amount: BigInt(event.amt), - })), - ).map((amount) => ({ - ...amount, - amount: amount.amount.toString(), - })); - }, + totalEarned: async ( + projectData: ResolverUnClaimedProjectData, + _: any, + context: Context, + ) => resolveTotalEarned(projectData, _, context), }, SplitsReceiver: { __resolveType(receiver: SplitsReceiver) { diff --git a/src/server.ts b/src/server.ts index 7e382fe..dd032f0 100644 --- a/src/server.ts +++ b/src/server.ts @@ -30,6 +30,7 @@ import GivenEventsDataSource from './dataLoaders/GivenEventsDataSource'; import ProjectAndDripListSupportDataSource from './dataLoaders/ProjectAndDripListSupportDataSource'; import UsersDataSource from './user/UserDataSource'; import StreamsDataSource from './stream/StreamsDataSource'; +import TotalEarnedDataSource from './dataLoaders/TotalEarnedDataSource'; export interface Context { dataSources: { @@ -43,6 +44,7 @@ export interface Context { givesDb: GivenEventsDataSource; usersDb: UsersDataSource; streamsDb: StreamsDataSource; + totalEarnedDb: TotalEarnedDataSource; }; } @@ -148,6 +150,7 @@ const startServer = async () => { givesDb: new GivenEventsDataSource(), usersDb: new UsersDataSource(), streamsDb: new StreamsDataSource(), + totalEarnedDb: new TotalEarnedDataSource(), }, }; }, diff --git a/src/utils/mergeAmounts.ts b/src/utils/mergeAmounts.ts index a25a5dc..0fbe1bc 100644 --- a/src/utils/mergeAmounts.ts +++ b/src/utils/mergeAmounts.ts @@ -1,3 +1,5 @@ +import type { SupportedChain } from '../generated/graphql'; + type Amount = { amount: bigint; tokenAddress: string; @@ -8,19 +10,26 @@ type Amount = { * where each particular tokenAddress appears once. * @param args The arrays of amounts to add together. */ -export default function mergeAmounts(...args: Amount[][]) { +export default function mergeAmounts( + ...args: (Amount & { chain: SupportedChain })[][] +) { const amounts = new Map(); args.forEach((amountsArray) => { amountsArray.forEach((amount) => { - const existingAmount = amounts.get(amount.tokenAddress); + // Create a unique key using both tokenAddress and chain + const key = `${amount.tokenAddress}-${amount.chain}`; + const existingAmount = amounts.get(key); + if (existingAmount) { - amounts.set(amount.tokenAddress, { + // If there is already an entry, add the new amount to the existing one + amounts.set(key, { + ...existingAmount, amount: existingAmount.amount + amount.amount, - tokenAddress: amount.tokenAddress, }); } else { - amounts.set(amount.tokenAddress, amount); + // Otherwise, add the new amount to the map + amounts.set(key, amount); } }); }); From 381fa86e2c8bb04f548a74c4d6954f48f7bdd20b Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 30 May 2024 16:41:48 +0200 Subject: [PATCH 05/37] refactor: add multi chain support for projects and drip list by IDs queries --- src/common/types.ts | 11 +++++ src/dataLoaders/DripListsDataSource.ts | 2 + src/dataLoaders/GivenEventsDataSource.ts | 58 ++++++++++++++++++++---- src/dataLoaders/ProjectsDataSource.ts | 36 +++++++++++++-- src/drip-list/dripListResolvers.ts | 13 +++++- src/given-event/givenEventResolvers.ts | 30 ++++++++---- src/given-event/givenEventTypeDef.ts | 8 ++++ src/given-event/givesUtils.ts | 43 ++++++++++++++++++ src/project/projectResolvers.ts | 29 ++++++++++-- src/schema.ts | 7 ++- 10 files changed, 205 insertions(+), 32 deletions(-) create mode 100644 src/given-event/givesUtils.ts diff --git a/src/common/types.ts b/src/common/types.ts index 6c6def2..3f86052 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -3,6 +3,7 @@ import type { ClaimedProjectData, DripList, DripListData, + Give, Project, SupportedChain, UnClaimedProjectData, @@ -11,6 +12,7 @@ import type StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEvent import type { FORGES_MAP } from './constants'; import type { addressDriverAccountMetadataParser } from '../schemas'; import type StreamsSetEventModel from '../models/StreamsSetEventModel'; +import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; export type KnownAny = any; export type ValuesOf = T[keyof T]; @@ -139,3 +141,12 @@ export type CommonDataValues = { updatedAt: Date; chain: SupportedChain; }; + +export type ResolverGive = Give & { + chainData: ResolverGiveChainData[]; +}; + +export type ResolverGiveChainData = { + chain: SupportedChain; + data: GivenEventModelDataValues | null; +}; diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index 3c145b3..797ef82 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -77,6 +77,8 @@ export default class DripListsDataSource { chains: SupportedChain[], where: DripListWhereInput, ): Promise { + // TODO: For all data sources, extract the SQL query building logic into a separate function/file. + // Define base SQL to query from multiple chains (schemas). const baseSQL = (schema: SupportedChain) => ` SELECT "id", "isValid", "name", "creator", "description", "ownerAddress", "ownerAccountId", "latestVotingRoundId", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain diff --git a/src/dataLoaders/GivenEventsDataSource.ts b/src/dataLoaders/GivenEventsDataSource.ts index 54658ca..3ac77d6 100644 --- a/src/dataLoaders/GivenEventsDataSource.ts +++ b/src/dataLoaders/GivenEventsDataSource.ts @@ -1,8 +1,9 @@ -import type { WhereOptions } from 'sequelize'; -import { Op } from 'sequelize'; +import { Op, QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; -import type { GiveWhereInput } from '../generated/graphql'; +import type { GiveWhereInput, SupportedChain } from '../generated/graphql'; +import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import GivenEventModel from '../given-event/GivenEventModel'; +import { dbConnection } from '../database/connectToDatabase'; type TransactionHash = string; type LogIndex = number; @@ -44,13 +45,52 @@ export default class GivenEventsDataSource { } public async getGivenEventsByFilter( + chains: SupportedChain[], where: GiveWhereInput, - ): Promise { - const givenEvents = - (await GivenEventModel.findAll({ - where: (where as WhereOptions) || {}, - })) || []; + ): Promise { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GivenEvents" + `; - return givenEvents; + // Initialize the WHERE clause parts. + const conditions: string[] = []; + const parameters: { [key: string]: any } = {}; + + // Build the WHERE clause based on input filters. + if (where?.receiverAccountId) { + conditions.push(`"receiver" = :receiver`); + parameters.receiver = where.receiverAccountId; + } + if (where?.senderAccountId) { + conditions.push(`"accountId" = :accountId`); + parameters.accountId = where.senderAccountId; + } + if (where?.tokenAddress) { + conditions.push(`"erc20" = :erc20`); + parameters.erc20 = where.tokenAddress; + } + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const givenEventsDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); + + return givenEventsDataValues; } } diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 50795b7..7860a16 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -90,11 +90,39 @@ export default class ProjectsDataSource { ); } - public async getProjectByUrl(url: string): Promise { - const project = (await ProjectModel.findOne({ where: { url } })) - ?.dataValues as ProjectDataValues; + public async getProjectByUrl( + url: string, + chain: SupportedChain, + ): Promise { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GitProjects" + `; + + // Initialize the WHERE clause parts. + const conditions: string[] = ['"url" = :url']; + const parameters: { [key: string]: any } = { url }; + + // Join conditions into a single WHERE clause. + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + // Build the SQL for each specified schema. + const query = `${baseSQL(chain) + whereClause} LIMIT 1`; + + const projectDataValues = ( + await dbConnection.query(query, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: ProjectModel, + }) + ).map((p) => p.dataValues as ProjectDataValues); + + const [project] = projectDataValues || []; - if (project) { + if (projectDataValues) { return toApiProject(project); } diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index 30a3432..b983603 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -53,11 +53,20 @@ const dripListResolvers = { _: any, { id, chain }: { id: DripListId; chain: SupportedChain }, { dataSources }: Context, - ): Promise => { + ): Promise => { assert(isDripListId(id)); assert(chain in SupportedChain); - return dataSources.dripListsDb.getDripListById(id, chain); + const dripListDataValues = await dataSources.dripListsDb.getDripListById( + id, + chain, + ); + + if (!dripListDataValues) { + return null; + } + + return (await toResolverDripLists([chain], [dripListDataValues]))[0]; }, mintedTokensCountByOwnerAddress: async ( _: any, diff --git a/src/given-event/givenEventResolvers.ts b/src/given-event/givenEventResolvers.ts index b1f1229..d139967 100644 --- a/src/given-event/givenEventResolvers.ts +++ b/src/given-event/givenEventResolvers.ts @@ -1,16 +1,19 @@ import { isAddress } from 'ethers'; -import type { GiveWhereInput } from '../generated/graphql'; +import type { Account, GiveWhereInput } from '../generated/graphql'; +import { SupportedChain } from '../generated/graphql'; import type { Context } from '../server'; import assert, { isAccountId } from '../utils/assert'; -import type GivenEventModel from './GivenEventModel'; +import queryableChains from '../common/queryableChains'; +import type { GivenEventModelDataValues } from './GivenEventModel'; +import type { ResolverGive } from '../common/types'; const givenEventResolvers = { Query: { gives: async ( _: any, - { where }: { where: GiveWhereInput }, + { chains, where }: { chains: SupportedChain[]; where: GiveWhereInput }, { dataSources }: Context, - ): Promise => { + ): Promise => { if (where?.receiverAccountId) { assert(isAccountId(where.receiverAccountId)); } @@ -23,14 +26,25 @@ const givenEventResolvers = { assert(isAddress(where.tokenAddress)); } - return dataSources.givenEventsDb.getGivenEventsByFilter(where); + if (chains) { + chains.forEach((chain) => { + assert(chain in SupportedChain); + }); + } + + const chainsToQuery = chains?.length ? chains : queryableChains; + + return dataSources.givenEventsDb.getGivenEventsByFilter( + chainsToQuery, + where, + ); }, }, Give: { - sender: () => { - // TODO: implement. - }, + sender: (give: ResolverGive): Account => give.sender, + receiver: (give: ResolverGive): Account => give.receiver, }, + // TODO: add the remaining resolvers }; export default givenEventResolvers; diff --git a/src/given-event/givenEventTypeDef.ts b/src/given-event/givenEventTypeDef.ts index 9d3310e..aedf9d1 100644 --- a/src/given-event/givenEventTypeDef.ts +++ b/src/given-event/givenEventTypeDef.ts @@ -4,6 +4,14 @@ const givenEventTypeDef = gql` type Give { sender: Account! receiver: Account! + } + + type GiveChainData { + chain: SupportedChain! + data: GiveData + } + + type GiveData { amount: Amount! blockTimestamp: String! } diff --git a/src/given-event/givesUtils.ts b/src/given-event/givesUtils.ts new file mode 100644 index 0000000..16b5f88 --- /dev/null +++ b/src/given-event/givesUtils.ts @@ -0,0 +1,43 @@ +import type { ResolverGive, ResolverGiveChainData } from '../common/types'; +import { type SupportedChain } from '../generated/graphql'; +import type { GivenEventModelDataValues } from './GivenEventModel'; + +export default async function toResolverGives( + chains: SupportedChain[], + givenEventsDataValues: GivenEventModelDataValues[], +): Promise { + return Promise.all( + givenEventsDataValues.map(async (givenEventDataValues) => { + const chainData = await Promise.all( + chains.map(async (chain) => { + if (givenEventDataValues.chain === chain) { + return { + chain, + data: { + ...givenEventDataValues, + }, + } as ResolverGiveChainData; + } + + return { + chain, + data: null, + }; + }), + ); + + // TODO: Implement the driver for the sender and receiver. Currently, it is an empty object, as we don't use this now. + return { + sender: { + accountId: givenEventDataValues.accountId, + driver: {} as any, + }, + receiver: { + accountId: givenEventDataValues.receiver, + driver: {} as any, + }, + chainData, + } as ResolverGive; + }), + ); +} diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index ca94247..121733c 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -65,20 +65,39 @@ const projectResolvers = { _: any, { id, chain }: { id: ProjectId; chain: SupportedChain }, { dataSources }: Context, - ): Promise => { + ): Promise => { assert(isProjectId(id)); assert(chain in SupportedChain); - return dataSources.projectsDb.getProjectById(id, chain); + const projectDataValues = await dataSources.projectsDb.getProjectById( + id, + chain, + ); + + if (!projectDataValues) { + return null; + } + + return (await toResolverProjects([chain], [projectDataValues]))[0]; }, projectByUrl: async ( _: any, - { url }: { url: string }, + { url, chain }: { url: string; chain: SupportedChain }, { dataSources }: Context, - ): Promise => { + ): Promise => { assert(isGitHubUrl(url)); + assert(chain in SupportedChain); + + const projectDataValues = await dataSources.projectsDb.getProjectByUrl( + url, + chain, + ); + + if (!projectDataValues) { + return null; + } - return dataSources.projectsDb.getProjectByUrl(url); + return (await toResolverProjects([chain], [projectDataValues]))[0]; }, earnedFunds: async ( _: any, diff --git a/src/schema.ts b/src/schema.ts index fc58e2d..463b74d 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -9,18 +9,17 @@ import streamTypeDef from './stream/streamTypeDef'; const rootTypeDef = gql` type Query { projects( - chains: [SupportedChain!]! + chains: [SupportedChain!] where: ProjectWhereInput sort: ProjectSortInput ): [Project!]! projectById(id: ID!, chain: SupportedChain!): Project - projectByUrl(url: String!): Project + projectByUrl(url: String!, chain: SupportedChain!): Project dripLists( - chains: [SupportedChain!]! + chains: [SupportedChain!] where: DripListWhereInput ): [DripList!]! dripList(id: ID!, chain: SupportedChain!): DripList - gives(where: GiveWhereInput): [Give!]! mintedTokensCountByOwnerAddress(ownerAddress: String!): Int! earnedFunds(projectId: String!): [Amount!]! userById(accountId: ID!): User! From d12c485bfb8890b58315f2138cf2105e66639ccb Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 31 May 2024 10:20:07 +0200 Subject: [PATCH 06/37] refactor: add multi chain support for total minted and earned funds queries --- src/common/commonTypeDef.ts | 6 ++ src/dataLoaders/DripListsDataSource.ts | 13 ++- src/dataLoaders/ProjectsDataSource.ts | 128 ++++++++++++++++++++----- src/drip-list/TransferEventModel.ts | 5 +- src/drip-list/dripListResolvers.ts | 6 +- src/drip-list/dripListTypeDef.ts | 5 + src/project/projectResolvers.ts | 12 ++- src/schema.ts | 7 +- 8 files changed, 150 insertions(+), 32 deletions(-) diff --git a/src/common/commonTypeDef.ts b/src/common/commonTypeDef.ts index 14e68cc..ad17681 100644 --- a/src/common/commonTypeDef.ts +++ b/src/common/commonTypeDef.ts @@ -103,6 +103,12 @@ const commonTypeDef = gql` amount: String! } + type ChainAmount { + tokenAddress: String! + amount: String! + chain: SupportedChain! + } + type SupportGroup { items: [Support!] } diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index 797ef82..125b74e 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -134,15 +134,22 @@ export default class DripListsDataSource { } public async getMintedTokensCountByAccountId( + chain: SupportedChain, ownerAddress: Address, - ): Promise { + ): Promise<{ + chain: SupportedChain; + total: number; + }> { // TODO: Fix edge case. This will not count tokens minted by the owner but immediately transferred to another address. - const total = await TransferEventModel.count({ + const total = await TransferEventModel.schema(chain).count({ where: { to: ownerAddress, }, }); - return total; + return { + chain, + total, + }; } } diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 7860a16..58c7107 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -14,7 +14,9 @@ import type { ProjectWhereInput, SupportedChain, } from '../generated/graphql'; +import type { SplitEventModelDataValues } from '../models/SplitEventModel'; import SplitEventModel from '../models/SplitEventModel'; +import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import GivenEventModel from '../given-event/GivenEventModel'; import { dbConnection } from '../database/connectToDatabase'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; @@ -211,31 +213,71 @@ export default class ProjectsDataSource { ) as Promise; } - public async getEarnedFunds(projectId: ProjectId): Promise< + public async getEarnedFunds( + projectId: ProjectId, + chains: SupportedChain[], + ): Promise< { tokenAddress: string; amount: string; + chain: SupportedChain; }[] > { const amounts = await Promise.all([ - this._getIncomingSplitTotal(projectId), - this._getIncomingGivesTotal(projectId), + this._getIncomingSplitTotal(projectId, chains), + this._getIncomingGivesTotal(projectId, chains), ]); return this._mergeAmounts(...amounts); } - private async _getIncomingSplitTotal(accountId: string) { - const incomingSplitEvents = await SplitEventModel.findAll({ - where: { - receiver: accountId, - }, - }); + private async _getIncomingSplitTotal( + accountId: string, + chains: SupportedChain[], + ) { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => + `SELECT + "accountId", + "receiver", + "erc20", + "amt", + "transactionHash", + "logIndex", + "blockTimestamp", + "blockNumber", + "createdAt", + "updatedAt", + '${schema}' AS chain + FROM "${schema}"."SplitEvents"`; + + // Initialize the WHERE clause parts. + const conditions: string[] = ['"receiver" = :receiver']; + const parameters: { [receiver: string]: any } = { receiver: accountId }; + + // Create the WHERE clause. + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); - return incomingSplitEvents.reduce< + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const incomingSplitEventModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: SplitEventModel, + }) + ).map((p) => p.dataValues as SplitEventModelDataValues); + + return incomingSplitEventModelDataValues.reduce< { tokenAddress: string; amount: bigint; + chain: SupportedChain; }[] >((acc, curr) => { const existing = acc.find((e) => e.tokenAddress === curr.erc20); @@ -248,6 +290,7 @@ export default class ProjectsDataSource { acc.push({ tokenAddress: curr.erc20, amount, + chain: curr.chain, }); } @@ -255,17 +298,53 @@ export default class ProjectsDataSource { }, []); } - private async _getIncomingGivesTotal(accountId: string) { - const incomingGiveEvents = await GivenEventModel.findAll({ - where: { - receiver: accountId, - }, - }); + private async _getIncomingGivesTotal( + accountId: string, + chains: SupportedChain[], + ) { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => + `SELECT + "accountId", + "receiver", + "erc20", + "amt", + "transactionHash", + "logIndex", + "blockTimestamp", + "blockNumber", + "createdAt", + "updatedAt", + '${schema}' AS chain + FROM "${schema}"."GivenEvents"`; + + // Initialize the WHERE clause parts. + const conditions: string[] = ['"receiver" = :receiver']; + const parameters: { [receiver: string]: any } = { receiver: accountId }; - return incomingGiveEvents.reduce< + // Create the WHERE clause. + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const incomingGivenEventModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); + + return incomingGivenEventModelDataValues.reduce< { tokenAddress: string; amount: bigint; + chain: SupportedChain; }[] >((acc, curr) => { const existing = acc.find((e) => e.tokenAddress === curr.erc20); @@ -277,6 +356,7 @@ export default class ProjectsDataSource { acc.push({ tokenAddress: curr.erc20, amount, + chain: curr.chain, }); } @@ -288,6 +368,7 @@ export default class ProjectsDataSource { ...args: { tokenAddress: string; amount: bigint; + chain: SupportedChain; }[][] ) { const amounts = new Map< @@ -295,26 +376,29 @@ export default class ProjectsDataSource { { tokenAddress: string; amount: bigint; + chain: SupportedChain; } >(); args.forEach((amountsArray) => { amountsArray.forEach((amount) => { - const existingAmount = amounts.get(amount.tokenAddress); + const key = `${amount.chain}-${amount.tokenAddress}`; + const existingAmount = amounts.get(key); if (existingAmount) { - amounts.set(amount.tokenAddress, { + amounts.set(key, { + ...existingAmount, amount: existingAmount.amount + amount.amount, - tokenAddress: amount.tokenAddress, }); } else { - amounts.set(amount.tokenAddress, amount); + amounts.set(key, amount); } }); }); return Array.from(amounts.values()).map((x) => ({ - amount: x.amount.toString(), tokenAddress: x.tokenAddress, + amount: x.amount.toString(), + chain: x.chain, })); } } diff --git a/src/drip-list/TransferEventModel.ts b/src/drip-list/TransferEventModel.ts index aa45cb4..22bb77d 100644 --- a/src/drip-list/TransferEventModel.ts +++ b/src/drip-list/TransferEventModel.ts @@ -6,9 +6,12 @@ import type { } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; import getSchema from '../utils/getSchema'; -import type { DripListId } from '../common/types'; +import type { CommonDataValues, DripListId } from '../common/types'; import { COMMON_EVENT_INIT_ATTRIBUTES } from '../common/constants'; +export type TransferEventModelDataValues = TransferEventModel['dataValues'] & + CommonDataValues; + export default class TransferEventModel extends Model< InferAttributes, InferCreationAttributes diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index b983603..b5d14f4 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -70,12 +70,14 @@ const dripListResolvers = { }, mintedTokensCountByOwnerAddress: async ( _: any, - { ownerAddress }: { ownerAddress: Address }, + { ownerAddress, chain }: { ownerAddress: Address; chain: SupportedChain }, { dataSources }: Context, - ): Promise => { + ): Promise<{ chain: SupportedChain; total: number }> => { assert(isAddress(ownerAddress)); + assert(chain in SupportedChain); return dataSources.dripListsDb.getMintedTokensCountByAccountId( + chain, ownerAddress, ); }, diff --git a/src/drip-list/dripListTypeDef.ts b/src/drip-list/dripListTypeDef.ts index 2b8069b..558b472 100644 --- a/src/drip-list/dripListTypeDef.ts +++ b/src/drip-list/dripListTypeDef.ts @@ -27,6 +27,11 @@ const dripListTypeDef = gql` id: String ownerAddress: String } + + type MintedTokens { + chain: SupportedChain! + total: Int! + } `; export default dripListTypeDef; diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 121733c..0116fb0 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -101,12 +101,20 @@ const projectResolvers = { }, earnedFunds: async ( _: any, - { projectId }: { projectId: ProjectId }, + { projectId, chains }: { projectId: ProjectId; chains: SupportedChain[] }, { dataSources }: Context, ) => { assert(isProjectId(projectId)); - return dataSources.projectsDb.getEarnedFunds(projectId); + if (chains) { + chains.forEach((chain) => { + assert(chain in SupportedChain); + }); + } + + const chainsToQuery = chains?.length ? chains : queryableChains; + + return dataSources.projectsDb.getEarnedFunds(projectId, chainsToQuery); }, }, Project: { diff --git a/src/schema.ts b/src/schema.ts index 463b74d..c17e245 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -20,8 +20,11 @@ const rootTypeDef = gql` where: DripListWhereInput ): [DripList!]! dripList(id: ID!, chain: SupportedChain!): DripList - mintedTokensCountByOwnerAddress(ownerAddress: String!): Int! - earnedFunds(projectId: String!): [Amount!]! + mintedTokensCountByOwnerAddress( + ownerAddress: String! + chain: SupportedChain! + ): MintedTokens! + earnedFunds(projectId: String!, chains: [SupportedChain!]): [ChainAmount!]! userById(accountId: ID!): User! userByAddress(address: String!): User! streams(where: StreamWhereInput): [Stream!]! From 40765e91c88b4746c9ba80844da2444afad39300 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Mon, 3 Jun 2024 09:46:17 +0200 Subject: [PATCH 07/37] refactor: support multi chain one time donation support queries --- src/common/commonResolvers.ts | 9 ++- src/dataLoaders/GivenEventsDataSource.ts | 75 ++++++++++++++++++------ 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index 6c8d3b9..feb5850 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -158,7 +158,11 @@ const commonResolvers = { }, OneTimeDonationSupport: { account: async ( - parent: { transactionHash: string; logIndex: number }, + parent: { + transactionHash: string; + logIndex: number; + chain: SupportedChain; + }, _: any, context: Context, ): Promise => { @@ -166,9 +170,10 @@ const commonResolvers = { dataSources: { givesDb }, } = context; - const { transactionHash, logIndex } = parent; + const { transactionHash, logIndex, chain } = parent; const givenEvent = await givesDb.getGivenEventById( + [chain], transactionHash, logIndex, ); diff --git a/src/dataLoaders/GivenEventsDataSource.ts b/src/dataLoaders/GivenEventsDataSource.ts index 3ac77d6..28789c7 100644 --- a/src/dataLoaders/GivenEventsDataSource.ts +++ b/src/dataLoaders/GivenEventsDataSource.ts @@ -1,4 +1,6 @@ -import { Op, QueryTypes } from 'sequelize'; +/* eslint-disable no-param-reassign */ + +import { QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; import type { GiveWhereInput, SupportedChain } from '../generated/graphql'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; @@ -12,23 +14,58 @@ type CompositePrimaryKey = readonly [TransactionHash, LogIndex]; export default class GivenEventsDataSource { private readonly _batchGivenEventsByIds = new DataLoader( async ( - givenEventIds: readonly CompositePrimaryKey[], - ): Promise => { - const givenEvents = await GivenEventModel.findAll({ - where: { - [Op.or]: givenEventIds.map(([transactionHash, logIndex]) => ({ - transactionHash, - logIndex, - })), - }, - }); - - const idToEventMap = givenEvents.reduce< - Record<`${string}-${string}`, GivenEventModel> + keys: readonly { + chains: SupportedChain[]; + key: CompositePrimaryKey; + }[], + ): Promise => { + const chains = [...new Set(keys.flatMap((key) => key.chains))]; + const givenEventIds = keys.map(({ key }) => key); + const transactionHashes = givenEventIds.map( + ([transactionHash]) => transactionHash, + ); + const logIndexes = givenEventIds.map(([, logIndex]) => logIndex); + + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GivenEvents" + `; + + // Initialize the WHERE clause parts. + const conditions: string[] = [ + '"transactionHash" IN (:transactionHashes)', + '"logIndex" IN (:logIndexes)', + ]; + const parameters: { [key: string]: any } = { + transactionHashes, + logIndexes, + }; + + // Build the where clause. + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const givenEventsDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); + + const idToEventMap = givenEventsDataValues.reduce< + Record<`${string}-${string}`, GivenEventModelDataValues> >((mapping, givenEvent) => { const key: `${string}-${string}` = `${givenEvent.transactionHash}-${givenEvent.logIndex}`; - mapping[key] = givenEvent; // eslint-disable-line no-param-reassign + mapping[key] = givenEvent; return mapping; }, {}); @@ -38,10 +75,14 @@ export default class GivenEventsDataSource { ); public async getGivenEventById( + chains: SupportedChain[], transactionHash: TransactionHash, logIndex: LogIndex, - ): Promise { - return this._batchGivenEventsByIds.load([transactionHash, logIndex]); + ): Promise { + return this._batchGivenEventsByIds.load({ + chains, + key: [transactionHash, logIndex], + }); } public async getGivenEventsByFilter( From 6fdbd3a2f6866f3b8823287db35ab2680338d303 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Mon, 3 Jun 2024 14:08:33 +0200 Subject: [PATCH 08/37] refactor: add user and streams multi chain query support --- src/common/commonResolverLogic.ts | 42 +++- src/common/commonResolvers.ts | 4 +- src/common/dripsContracts.ts | 70 +++++-- src/common/types.ts | 37 ++-- src/dataLoaders/DripListsDataSource.ts | 8 +- .../ProjectAndDripListSupportDataSource.ts | 36 +++- src/dataLoaders/ProjectsDataSource.ts | 32 +-- .../ReceiversOfTypeAddressDataSource.ts | 4 +- .../ReceiversOfTypeDripListDataSource.ts | 4 +- .../ReceiversOfTypeProjectDataSource.ts | 4 +- src/dataLoaders/TotalEarnedDataSource.ts | 4 +- src/drip-list/dripListResolvers.ts | 3 +- src/given-event/givenEventTypeDef.ts | 1 + .../AccountMetadataEmittedEventModel.ts | 5 +- src/models/StreamReceiverSeenEventModel.ts | 10 +- src/models/StreamsSetEventModel.ts | 10 +- src/project/projectResolvers.ts | 20 +- src/project/projectUtils.ts | 42 +--- src/resolvers.ts | 3 +- src/schema.ts | 5 +- src/stream/StreamsDataSource.ts | 47 +++-- src/stream/streamResolvers.ts | 23 +-- src/user/UserDataSource.ts | 50 ++--- src/user/userResolvers.ts | 163 +++++++++++----- src/user/userTypeDef.ts | 9 + src/user/userUtils.ts | 33 ++++ src/utils/getAssetConfigs.ts | 40 ++-- src/utils/getLatestAccountMetadata.ts | 82 +++++--- src/utils/getStreamsSetEventsWithReceivers.ts | 183 ++++++++++++------ src/utils/getUserAccount.ts | 72 +++++-- src/utils/parseMultiChainKeys.ts | 13 +- src/utils/streams.ts | 108 +++++++---- 32 files changed, 762 insertions(+), 405 deletions(-) create mode 100644 src/user/userUtils.ts diff --git a/src/common/commonResolverLogic.ts b/src/common/commonResolverLogic.ts index 12c9cd3..19208e9 100644 --- a/src/common/commonResolverLogic.ts +++ b/src/common/commonResolverLogic.ts @@ -1,3 +1,4 @@ +import { QueryTypes } from 'sequelize'; import type { DripListId, ProjectId, @@ -9,10 +10,13 @@ import mergeAmounts from '../utils/mergeAmounts'; import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import shouldNeverHappen from '../utils/shouldNeverHappen'; +import type { SplitEventModelDataValues } from '../models/SplitEventModel'; import SplitEventModel from '../models/SplitEventModel'; import { SupportedChain } from '../generated/graphql'; +import { dbConnection } from '../database/connectToDatabase'; export async function resolveTotalSplit( + chains: SupportedChain[], parent: DripListSplitReceiverModel | RepoDriverSplitReceiverModel, ) { let incomingAccountId: DripListId | ProjectId; @@ -32,15 +36,39 @@ export async function resolveTotalSplit( shouldNeverHappen('Invalid SupportItem type'); } - const splitEvents = await SplitEventModel.findAll({ - where: { - accountId: incomingAccountId, - receiver: recipientAccountId, - }, - }); + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."SplitEvents"`; + + // Initialize the WHERE clause parts. + const conditions: string[] = [ + '"accountId" = :accountId', + '"receiver" = :receiver', + ]; + const parameters: { [receiver: string]: any } = { + accountId: incomingAccountId, + receiver: recipientAccountId, + }; + + // Create the WHERE clause. + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + // Build the SQL for each specified schema. + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const splitEventModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: SplitEventModel, + }) + ).map((p) => p.dataValues as SplitEventModelDataValues); return mergeAmounts( - splitEvents.map((splitEvent) => ({ + splitEventModelDataValues.map((splitEvent) => ({ tokenAddress: splitEvent.erc20, amount: BigInt(splitEvent.amt), chain: SupportedChain.sepolia, // TODO: Only for compilation. diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index feb5850..76f0897 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -119,8 +119,8 @@ const commonResolvers = { const { funderDripListId, chain } = parent; const dripList = await dripListsDb.getDripListById( + [chain], funderDripListId, - chain, ); return { @@ -142,7 +142,7 @@ const commonResolvers = { const { funderDripListId, chain } = parent; const dripListDataValues = - (await dripListsDb.getDripListById(funderDripListId, chain)) || + (await dripListsDb.getDripListById([chain], funderDripListId)) || shouldNeverHappen(); const resolverDripLists = await toResolverDripLists( diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts index 3a91256..17b644e 100644 --- a/src/common/dripsContracts.ts +++ b/src/common/dripsContracts.ts @@ -1,4 +1,4 @@ -import { JsonRpcProvider, WebSocketProvider } from 'ethers'; +import { JsonRpcProvider, WebSocketProvider, ethers } from 'ethers'; import appSettings from './appSettings'; import type { AddressDriver, RepoDriver } from '../generated/contracts'; import { @@ -7,6 +7,8 @@ import { } from '../generated/contracts'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import { SupportedChain } from '../generated/graphql'; +import type { AccountId, Address, Forge, ProjectId } from './types'; +import queryableChains from './queryableChains'; const chainConfigs: Record< SupportedChain, @@ -39,25 +41,25 @@ const providers: { [network in SupportedChain]?: JsonRpcProvider | WebSocketProvider; } = {}; -for (const network of Object.keys(SupportedChain)) { - if (rpcUrls[network as SupportedChain]) { - const rpcUrl = rpcUrls[network as SupportedChain] as string; - +Object.values(SupportedChain).forEach((network) => { + const rpcUrl = rpcUrls[network]; + if (rpcUrl) { // eslint-disable-next-line no-nested-ternary const provider = rpcUrl.startsWith('http') ? new JsonRpcProvider(rpcUrl) : rpcUrl.startsWith('wss') ? new WebSocketProvider(rpcUrl) : shouldNeverHappen(`Invalid RPC URL: ${rpcUrl}`); - - providers[network as SupportedChain] = provider; + providers[network] = provider; } -} +}); -let dripsContracts: { - addressDriver: AddressDriver; - repoDriver: RepoDriver; -} = {} as any; +const dripsContracts: { + [network in SupportedChain]?: { + addressDriver: AddressDriver; + repoDriver: RepoDriver; + }; +} = {}; Object.entries(providers).forEach(([network, provider]) => { if (!chainConfigs[network as SupportedChain]) { @@ -71,15 +73,49 @@ Object.entries(providers).forEach(([network, provider]) => { addressDriverAddress, provider, ); - const repoDriver = RepoDriver__factory.connect(repoDriverAddress, provider); - dripsContracts = { + dripsContracts[network as SupportedChain] = { addressDriver, repoDriver, }; }); -export default { - contracts: dripsContracts, -}; +export default dripsContracts; + +export async function getCrossChainAddressDriverAccountIdByAddress( + address: Address, +): Promise { + // AddressDriver account IDs are the same across all chains. + const { addressDriver } = dripsContracts[queryableChains[0]]!; + + const accountId = (await addressDriver.calcAccountId(address)).toString(); + + return accountId as AccountId; +} + +export async function getCrossChainRepoDriverAccountIdByAddress( + forge: Forge, + project: string, +): Promise { + // RepoDriver account IDs are the same across all chains. + const { repoDriver } = dripsContracts[queryableChains[0]]!; + + const nameAsBytesLike = ethers.toUtf8Bytes(project); + + let forgeAsNum: 0 | 1 | undefined; + + if (forge === 'GitHub') { + forgeAsNum = 0; + } else if (forge === 'GitLab') { + forgeAsNum = 1; + } else { + return shouldNeverHappen(`Forge ${forge} not supported.`); + } + + const accountId = ( + await repoDriver.calcAccountId(forgeAsNum, nameAsBytesLike) + ).toString(); + + return accountId as ProjectId; +} diff --git a/src/common/types.ts b/src/common/types.ts index 3f86052..4760571 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -7,6 +7,8 @@ import type { Project, SupportedChain, UnClaimedProjectData, + User, + UserData, } from '../generated/graphql'; import type StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; import type { FORGES_MAP } from './constants'; @@ -101,20 +103,12 @@ export type ResolverUnClaimedProjectChainData = { data: ResolverUnClaimedProjectData; }; -export interface DripListMultiChainKey { - dripListId: DripListId; - chains: SupportedChain[]; -} - -export interface StreamMultiChainKey { - accountId: AccountId; - chains: SupportedChain[]; -} - -export interface ProjectMultiChainKey { - projectId: ProjectId; +export interface MultiChainKey { + id: T; chains: SupportedChain[]; } +export type ProjectMultiChainKey = MultiChainKey; +export type DripListMultiChainKey = MultiChainKey; export type ResolverDripList = DripList & { chainData: ResolverDripListChainData[]; @@ -150,3 +144,22 @@ export type ResolverGiveChainData = { chain: SupportedChain; data: GivenEventModelDataValues | null; }; + +export type ResolverUser = User & { + chainData: ResolverUserChainData[]; +}; + +export type ResolverUserChainData = { + chain: SupportedChain; + data: ResolverUserData | null; +}; + +export type ResolverUserData = UserData & UserDataParentDripListInfo; + +export type UserDataParentDripListInfo = { + parentUserInfo: { + accountId: AccountId; + userChain: SupportedChain; + queriedChains: SupportedChain[]; + }; +}; diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index 125b74e..d95e6a1 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -64,12 +64,12 @@ export default class DripListsDataSource { ); public async getDripListById( + chains: SupportedChain[], id: DripListId, - chains: SupportedChain, ): Promise { return this._batchDripListsByIds.load({ - dripListId: id, - chains: [chains], + id, + chains, }); } @@ -127,7 +127,7 @@ export default class DripListsDataSource { ): Promise { return this._batchDripListsByIds.loadMany( ids.map((id) => ({ - dripListId: id, + id, chains, })), ) as Promise; diff --git a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts index 7563625..9306dc4 100644 --- a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts +++ b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts @@ -4,6 +4,7 @@ import type { AccountId, DripListId, DripListMultiChainKey, + MultiChainKey, ProjectId, ProjectMultiChainKey, } from '../common/types'; @@ -132,14 +133,25 @@ export default class ProjectAndDripListSupportDataSource { ); private readonly _batchStreamSupportByAccountIds = new DataLoader( - async (accountIds: readonly AccountId[]) => { + async (accountKeys: readonly MultiChainKey[]) => { + const { chains, ids: accountIds } = parseMultiChainKeys(accountKeys); + const streamsToList = ( await Promise.all( accountIds.map((accountId) => - streams.getUserIncomingStreams(accountId), + streams.getUserIncomingStreams(chains, accountId), + ), + ) + ) + .flatMap((s) => + Object.entries(s).map(([chain, protoStreamsForChain]) => + protoStreamsForChain.map((protoStream) => ({ + ...protoStream, + chain: chain as SupportedChain, + })), ), ) - ).flat(); + .flat(); const streamSupportToAccountMapping = streamsToList.reduce< Record @@ -152,7 +164,7 @@ export default class ProjectAndDripListSupportDataSource { ], }), {}, - ); + ) as Record; return accountIds.map((id) => streamSupportToAccountMapping[id] || []); }, @@ -212,7 +224,7 @@ export default class ProjectAndDripListSupportDataSource { chains: SupportedChain[], ): Promise { return this._batchProjectAndDripListSupportByDripListIds.load({ - dripListId: id, + id, chains, }); } @@ -222,7 +234,7 @@ export default class ProjectAndDripListSupportDataSource { chains: SupportedChain[], ): Promise { return this._batchProjectAndDripListSupportByProjectIds.load({ - projectId: id, + id, chains, }); } @@ -233,9 +245,9 @@ export default class ProjectAndDripListSupportDataSource { ): Promise { // eslint-disable-next-line no-nested-ternary const key = isDripListId(id) - ? { dripListId: id, chains } + ? { id, chains } : isProjectId(id) - ? { projectId: id, chains } + ? { id, chains } : shouldNeverHappen(); return this._batchOneTimeDonationSupportByAccountIds.load(key); @@ -243,7 +255,11 @@ export default class ProjectAndDripListSupportDataSource { public async getStreamSupportByAccountId( id: AccountId, - ): Promise { - return this._batchStreamSupportByAccountIds.load(id); + chains: SupportedChain[], + ) { + return this._batchStreamSupportByAccountIds.load({ + id, + chains, + }); } } diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 58c7107..76bcef3 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -86,7 +86,7 @@ export default class ProjectsDataSource { ): Promise { return toApiProject( await this._batchProjectsByIds.load({ - projectId: id, + id, chains: [chain], }), ); @@ -207,7 +207,7 @@ export default class ProjectsDataSource { ): Promise { return this._batchProjectsByIds.loadMany( ids.map((id) => ({ - projectId: id, + id, chains, })), ) as Promise; @@ -237,19 +237,7 @@ export default class ProjectsDataSource { ) { // Define base SQL to query from multiple chains (schemas). const baseSQL = (schema: SupportedChain) => - `SELECT - "accountId", - "receiver", - "erc20", - "amt", - "transactionHash", - "logIndex", - "blockTimestamp", - "blockNumber", - "createdAt", - "updatedAt", - '${schema}' AS chain - FROM "${schema}"."SplitEvents"`; + `SELECT *, '${schema}' AS chain FROM "${schema}"."SplitEvents"`; // Initialize the WHERE clause parts. const conditions: string[] = ['"receiver" = :receiver']; @@ -304,19 +292,7 @@ export default class ProjectsDataSource { ) { // Define base SQL to query from multiple chains (schemas). const baseSQL = (schema: SupportedChain) => - `SELECT - "accountId", - "receiver", - "erc20", - "amt", - "transactionHash", - "logIndex", - "blockTimestamp", - "blockNumber", - "createdAt", - "updatedAt", - '${schema}' AS chain - FROM "${schema}"."GivenEvents"`; + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; // Initialize the WHERE clause parts. const conditions: string[] = ['"receiver" = :receiver']; diff --git a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts index 6b6215d..f74f069 100644 --- a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts @@ -76,7 +76,7 @@ export default class ReceiversOfTypeAddressDataSource { chains: SupportedChain[], ): Promise { return this._batchReceiversOfTypeAddressByProjectIds.load({ - projectId: id, + id, chains, }); } @@ -143,7 +143,7 @@ export default class ReceiversOfTypeAddressDataSource { chains: SupportedChain[], ): Promise { return this._batchReceiversOfTypeAddressByDripListIds.load({ - dripListId: id, + id, chains, }); } diff --git a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts index 4129c4f..749665a 100644 --- a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts @@ -75,7 +75,7 @@ export default class ReceiversOfTypeDripListDataSource { chains: SupportedChain[], ): Promise { return this._batchReceiversOfTypeDripListByProjectIds.load({ - projectId: id, + id, chains, }); } @@ -141,7 +141,7 @@ export default class ReceiversOfTypeDripListDataSource { chains: SupportedChain[], ): Promise { return this._batchReceiversOfTypeDripListByDripListIds.load({ - dripListId: id, + id, chains, }); } diff --git a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts index 0549442..e8cb08a 100644 --- a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts @@ -75,7 +75,7 @@ export default class ReceiversOfTypeProjectDataSource { chains: SupportedChain[], ): Promise { return this._batchReceiversOfTypeProjectByProjectIds.load({ - projectId: id, + id, chains, }); } @@ -141,7 +141,7 @@ export default class ReceiversOfTypeProjectDataSource { chains: SupportedChain[], ): Promise { return this._batchReceiversOfTypeProjectByDripListIds.load({ - dripListId: id, + id, chains, }); } diff --git a/src/dataLoaders/TotalEarnedDataSource.ts b/src/dataLoaders/TotalEarnedDataSource.ts index 09a89c3..73efbaa 100644 --- a/src/dataLoaders/TotalEarnedDataSource.ts +++ b/src/dataLoaders/TotalEarnedDataSource.ts @@ -110,9 +110,9 @@ export default class TotalEarnedDataSource { }> { // eslint-disable-next-line no-nested-ternary const key = isDripListId(id) - ? { dripListId: id, chains } + ? { id, chains } : isProjectId(id) - ? { projectId: id, chains } + ? { id, chains } : shouldNeverHappen(); return this._batchTotalEarnedByProjectIds.load(key); diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index b5d14f4..a824a6b 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -58,8 +58,8 @@ const dripListResolvers = { assert(chain in SupportedChain); const dripListDataValues = await dataSources.dripListsDb.getDripListById( + [chain], id, - chain, ); if (!dripListDataValues) { @@ -229,6 +229,7 @@ const dripListResolvers = { const streamSupport = await projectAndDripListSupportDb.getStreamSupportByAccountId( dripListId, + [dripListChain], ); return [ diff --git a/src/given-event/givenEventTypeDef.ts b/src/given-event/givenEventTypeDef.ts index aedf9d1..2a2289b 100644 --- a/src/given-event/givenEventTypeDef.ts +++ b/src/given-event/givenEventTypeDef.ts @@ -4,6 +4,7 @@ const givenEventTypeDef = gql` type Give { sender: Account! receiver: Account! + chainData: [GiveChainData!]! } type GiveChainData { diff --git a/src/models/AccountMetadataEmittedEventModel.ts b/src/models/AccountMetadataEmittedEventModel.ts index 899adcb..8c309d3 100644 --- a/src/models/AccountMetadataEmittedEventModel.ts +++ b/src/models/AccountMetadataEmittedEventModel.ts @@ -5,9 +5,12 @@ import type { } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; import getSchema from '../utils/getSchema'; -import type { IEventModel } from '../common/types'; +import type { CommonDataValues, IEventModel } from '../common/types'; import getCommonEventAttributes from '../utils/getCommonEventAttributes'; +export type AccountMetadataEmittedEventModelDataValues = + AccountMetadataEmittedEventModel['dataValues'] & CommonDataValues; + export default class AccountMetadataEmittedEventModel extends Model< InferAttributes, diff --git a/src/models/StreamReceiverSeenEventModel.ts b/src/models/StreamReceiverSeenEventModel.ts index b9a4e7d..d749576 100644 --- a/src/models/StreamReceiverSeenEventModel.ts +++ b/src/models/StreamReceiverSeenEventModel.ts @@ -5,9 +5,17 @@ import type { } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; import getSchema from '../utils/getSchema'; -import type { AccountId, BigIntString, IEventModel } from '../common/types'; +import type { + AccountId, + BigIntString, + CommonDataValues, + IEventModel, +} from '../common/types'; import getCommonEventAttributes from '../utils/getCommonEventAttributes'; +export type StreamReceiverSeenEventModelDataValues = + StreamReceiverSeenEventModel['dataValues'] & CommonDataValues; + export default class StreamReceiverSeenEventModel extends Model< InferAttributes, diff --git a/src/models/StreamsSetEventModel.ts b/src/models/StreamsSetEventModel.ts index a823045..ae8a441 100644 --- a/src/models/StreamsSetEventModel.ts +++ b/src/models/StreamsSetEventModel.ts @@ -5,9 +5,17 @@ import type { } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; import getSchema from '../utils/getSchema'; -import type { AccountId, BigIntString, IEventModel } from '../common/types'; +import type { + AccountId, + BigIntString, + CommonDataValues, + IEventModel, +} from '../common/types'; import getCommonEventAttributes from '../utils/getCommonEventAttributes'; +export type StreamsSetEventModelDataValues = + StreamsSetEventModel['dataValues'] & CommonDataValues; + export default class StreamsSetEventModel extends Model< InferAttributes, diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 0116fb0..9954c3e 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -290,19 +290,17 @@ const projectResolvers = { dataSources: { projectAndDripListSupportDb }, } = context; - const projectAndDripListSupport = ( + const projectAndDripListSupport = await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( projectId, [projectChain], - ) - ).filter((s) => s.chain === projectChain); + ); - const oneTimeDonationSupport = ( + const oneTimeDonationSupport = await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( projectId, [projectChain], - ) - ).filter((s) => s.chain === projectChain); + ); return [...projectAndDripListSupport, ...oneTimeDonationSupport]; }, @@ -326,19 +324,17 @@ const projectResolvers = { parentProjectInfo: { projectId, projectChain }, } = projectData; - const projectAndDripListSupport = ( + const projectAndDripListSupport = await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( projectId, [projectChain], - ) - ).filter((s) => s.chain === projectChain); + ); - const oneTimeDonationSupport = ( + const oneTimeDonationSupport = await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( projectId, [projectChain], - ) - ).filter((s) => s.chain === projectChain); + ); return [...projectAndDripListSupport, ...oneTimeDonationSupport]; }, diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 6f8b2da..67d2c28 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -1,7 +1,5 @@ -import { ethers } from 'ethers'; import type { Forge, - ProjectId, ResolverClaimedProjectChainData, ResolverProject, ResolverUnClaimedProjectChainData, @@ -11,7 +9,7 @@ import type { ProjectDataValues } from './ProjectModel'; import { ProjectVerificationStatus } from './ProjectModel'; import assert from '../utils/assert'; import appSettings from '../common/appSettings'; -import dripsContracts from '../common/dripsContracts'; +import { getCrossChainRepoDriverAccountIdByAddress } from '../common/dripsContracts'; import { Driver } from '../generated/graphql'; import type { Forge as GraphQlForge, @@ -54,17 +52,6 @@ export function isValidProjectName(name: string): boolean { return true; } -function toContractForge(forge: Forge): 0 | 1 { - switch (forge) { - case `GitHub`: - return 0; - case `GitLab`: - return 1; - default: - return shouldNeverHappen(`Forge ${forge} not supported.`); - } -} - export async function doesRepoExists(url: string) { if (appSettings.pretendAllReposExist) return true; @@ -118,16 +105,11 @@ export async function toFakeUnclaimedProjectFromUrl(url: string) { const ownerName = match[2]; const repoName = match[3]; - const { - contracts: { repoDriver }, - } = dripsContracts; - - const nameAsBytesLike = ethers.toUtf8Bytes(`${ownerName}/${repoName}`); - return { - id: ( - await repoDriver.calcAccountId(toContractForge(forge), nameAsBytesLike) - ).toString() as ProjectId, + id: await getCrossChainRepoDriverAccountIdByAddress( + forge, + `${ownerName}/${repoName}`, + ), name: `${ownerName}/${repoName}`, forge, url, @@ -151,19 +133,9 @@ export async function toFakeUnclaimedProject( assert(name && forge, 'Project name and forge must be defined.'); - const { ownerName, repoName } = splitProjectName(name); - - const { - contracts: { repoDriver }, - } = dripsContracts; - - const nameAsBytesLike = ethers.toUtf8Bytes(`${ownerName}/${repoName}`); - return { - id: ( - await repoDriver.calcAccountId(toContractForge(forge), nameAsBytesLike) - ).toString() as ProjectId, - name: `${ownerName}/${repoName}`, + id: await getCrossChainRepoDriverAccountIdByAddress(forge, name), + name, forge, url: toUrl(forge, name), verificationStatus: ProjectVerificationStatus.Unclaimed, diff --git a/src/resolvers.ts b/src/resolvers.ts index 02d9a84..a516987 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -10,7 +10,6 @@ const resolvers = { ...projectResolvers.Query, ...dripListResolvers.Query, ...userResolvers.Query, - ...streamResolvers.Query, }, Project: projectResolvers.Project, ProjectChainData: projectResolvers.ProjectChainData, @@ -30,6 +29,8 @@ const resolvers = { OneTimeDonationSupport: commonResolvers.OneTimeDonationSupport, Date: dateScalar, User: userResolvers.User, + UserChainData: userResolvers.UserChainData, + UserData: userResolvers.UserData, UserStreams: userResolvers.UserStreams, Stream: streamResolvers.Stream, StreamReceiver: userResolvers.StreamReceiver, diff --git a/src/schema.ts b/src/schema.ts index c17e245..c8d348c 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -25,9 +25,8 @@ const rootTypeDef = gql` chain: SupportedChain! ): MintedTokens! earnedFunds(projectId: String!, chains: [SupportedChain!]): [ChainAmount!]! - userById(accountId: ID!): User! - userByAddress(address: String!): User! - streams(where: StreamWhereInput): [Stream!]! + userById(accountId: ID!, chains: [SupportedChain!]): User! + userByAddress(address: String!, chains: [SupportedChain!]): User! } `; diff --git a/src/stream/StreamsDataSource.ts b/src/stream/StreamsDataSource.ts index b8b7486..405f6ff 100644 --- a/src/stream/StreamsDataSource.ts +++ b/src/stream/StreamsDataSource.ts @@ -1,25 +1,40 @@ import type { AddressDriverId } from '../common/types'; -import type { StreamWhereInput } from '../generated/graphql'; +import type { StreamWhereInput, SupportedChain } from '../generated/graphql'; import assert, { isAddressDriverId } from '../utils/assert'; import type { ProtoStream } from '../utils/buildAssetConfigs'; import getUserAccount from '../utils/getUserAccount'; import streamsUtils from '../utils/streams'; export default class StreamsDataSource { - public async getUserOutgoingStreams(accountId: AddressDriverId) { - const userAccount = await getUserAccount(accountId); + public async getUserOutgoingStreams( + chains: SupportedChain[], + accountId: AddressDriverId, + ) { + const userAccount = await getUserAccount(chains, accountId); - return userAccount.assetConfigs.flatMap( - (assetConfig) => assetConfig.streams, - ); + const response = {} as Record; + + chains.forEach((chain) => { + response[chain] = userAccount[chain].assetConfigs.flatMap( + (assetConfig) => assetConfig.streams, + ); + }); + + return response; } - public async getUserIncomingStreams(accountId: AddressDriverId) { - return streamsUtils.getUserIncomingStreams(accountId); + public async getUserIncomingStreams( + chains: SupportedChain[], + accountId: AddressDriverId, + ) { + return streamsUtils.getUserIncomingStreams(chains, accountId); } - public async getStreamsByFilter(where: StreamWhereInput) { - const streams: ProtoStream[] = []; + public async getStreamsByFilter( + chains: SupportedChain[], + where: StreamWhereInput, + ) { + const streams = {} as Record; if (!where.senderId && !where.receiverId) { throw new Error( @@ -31,20 +46,28 @@ export default class StreamsDataSource { assert(isAddressDriverId(where.senderId)); const senderOutgoingStreams = await this.getUserOutgoingStreams( + chains, where.senderId, ); - streams.push(...senderOutgoingStreams); + Object.entries(senderOutgoingStreams).forEach(([chain, chainStreams]) => { + streams[chain as SupportedChain].push(...chainStreams); + }); } if (where.receiverId) { assert(isAddressDriverId(where.receiverId)); const receiverIncomingStreams = await this.getUserIncomingStreams( + chains, where.receiverId, ); - streams.push(...receiverIncomingStreams); + Object.entries(receiverIncomingStreams).forEach( + ([chain, chainStreams]) => { + streams[chain as SupportedChain].push(...chainStreams); + }, + ); } return streams; diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index 026423a..5a77550 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -1,31 +1,21 @@ -import { - Driver, - SupportedChain, - type StreamWhereInput, -} from '../generated/graphql'; +import { Driver, SupportedChain } from '../generated/graphql'; import type { Context } from '../server'; import shouldNeverHappen from '../utils/shouldNeverHappen'; const streamResolvers = { - Query: { - streams: async ( - _: any, - { where }: { where: StreamWhereInput }, - { dataSources }: Context, - ) => dataSources.streamsDb.getStreamsByFilter(where), - }, Stream: { receiver: (parent: any, _: any, { dataSources }: Context) => { if (parent.receiver.driver === Driver.ADDRESS) { return dataSources.usersDb.getUserByAccountId( + [SupportedChain.sepolia], // TODO: Temporary for compiling. parent.receiver.accountId, ); } if (parent.receiver.driver === Driver.NFT) { return dataSources.dripListsDb.getDripListById( + [SupportedChain.sepolia], // TODO: Temporary for compiling. parent.receiver.accountId, - SupportedChain.sepolia, // TODO: Temporary for compiling. ); } @@ -33,13 +23,16 @@ const streamResolvers = { }, sender: (parent: any, _: any, { dataSources }: Context) => { if (parent.sender.driver === Driver.ADDRESS) { - return dataSources.usersDb.getUserByAccountId(parent.sender.accountId); + return dataSources.usersDb.getUserByAccountId( + [SupportedChain.sepolia], // TODO: Temporary for compiling. + parent.sender.accountId, + ); } if (parent.sender.driver === Driver.NFT) { return dataSources.dripListsDb.getDripListById( + [SupportedChain.sepolia], // TODO: Temporary for compiling. parent.sender.accountId, - SupportedChain.sepolia, // TODO: Temporary for compiling. ); } diff --git a/src/user/UserDataSource.ts b/src/user/UserDataSource.ts index 63f9c8c..6e101dc 100644 --- a/src/user/UserDataSource.ts +++ b/src/user/UserDataSource.ts @@ -1,39 +1,31 @@ -import type { Address, AddressDriverId } from '../common/types'; -import { Driver } from '../generated/graphql'; -import type { User } from '../generated/graphql'; -import getUserAddress from '../utils/getUserAddress'; +import type { Address, AddressDriverId, ResolverUser } from '../common/types'; +import type { SupportedChain } from '../generated/graphql'; import getUserAccount from '../utils/getUserAccount'; -import dripsContracts from '../common/dripsContracts'; +import { getCrossChainAddressDriverAccountIdByAddress } from '../common/dripsContracts'; +import toResolverUsers from './userUtils'; export default class UsersDataSource { - public async getUserAccount(accountId: AddressDriverId) { - return getUserAccount(accountId); + public async getUserAccount( + chains: SupportedChain[], + accountId: AddressDriverId, + ) { + return getUserAccount(chains, accountId); } - public async getUserByAccountId(accountId: AddressDriverId): Promise { - return { - account: { - accountId, - address: getUserAddress(accountId), - driver: Driver.ADDRESS, - }, - projects: [], - dripLists: [], - streams: { - outgoing: [], - incoming: [], - }, - balances: [], - }; + public async getUserByAccountId( + chains: SupportedChain[], + accountId: AddressDriverId, + ): Promise { + return toResolverUsers(chains, accountId); } - public async getUserByAddress(address: Address): Promise { - const { - contracts: { addressDriver }, - } = dripsContracts; + public async getUserByAddress( + chains: SupportedChain[], + address: Address, + ): Promise { + const accountId = + await getCrossChainAddressDriverAccountIdByAddress(address); - const accountId = (await addressDriver.calcAccountId(address)).toString(); - - return this.getUserByAccountId(accountId as AddressDriverId); + return this.getUserByAccountId(chains, accountId as AddressDriverId); } } diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index e436500..17b0f5c 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -1,95 +1,166 @@ import { assetOutgoingBalanceTimeline } from '../balances/estimate-reloaded'; -import type { Address, AddressDriverId } from '../common/types'; -import { Driver, SupportedChain } from '../generated/graphql'; +import type { + Address, + AddressDriverId, + ResolverUser, + ResolverUserChainData, + ResolverUserData, +} from '../common/types'; import DripListModel from '../drip-list/DripListModel'; -import type { User } from '../generated/graphql'; +import { SupportedChain } from '../generated/graphql'; +import type { AddressDriverAccount, User } from '../generated/graphql'; import type { Context } from '../server'; import assert, { isAddressDriverId } from '../utils/assert'; import getAssetConfigs from '../utils/getAssetConfigs'; -import getLatestAccountMetadata from '../utils/getLatestAccountMetadata'; import getUserAddress from '../utils/getUserAddress'; +import queryableChains from '../common/queryableChains'; +import { toResolverProjects } from '../project/projectUtils'; +import toResolverDripLists from '../drip-list/dripListUtils'; +import getLatestAccountMetadataByChain from '../utils/getLatestAccountMetadata'; const userResolvers = { Query: { userById: async ( _: any, - { accountId }: { accountId: AddressDriverId }, + { + chains, + accountId, + }: { chains: SupportedChain[]; accountId: AddressDriverId }, { dataSources }: Context, - ): Promise => dataSources.usersDb.getUserByAccountId(accountId), + ): Promise => { + if (chains) { + chains.forEach((chain) => { + assert(chain in SupportedChain); + }); + } + + const chainsToQuery = chains?.length ? chains : queryableChains; + + return dataSources.usersDb.getUserByAccountId(chainsToQuery, accountId); + }, userByAddress: async ( _: any, - { address }: { address: Address }, + { chains, address }: { chains: SupportedChain[]; address: Address }, { dataSources }: Context, - ): Promise => dataSources.usersDb.getUserByAddress(address), + ): Promise => { + if (chains) { + chains.forEach((chain) => { + assert(chain in SupportedChain); + }); + } + + const chainsToQuery = chains?.length ? chains : queryableChains; + + return dataSources.usersDb.getUserByAddress(chainsToQuery, address); + }, }, User: { - account: (parent: User) => ({ - accountId: parent.account.accountId, - driver: Driver.ADDRESS, - address: getUserAddress(parent.account.accountId as AddressDriverId), - }), - streams: async (parent: User) => ({ - accountId: parent.account.accountId, - }), - balances: async (parent: User) => { - const { metadata } = - (await getLatestAccountMetadata( - parent.account.accountId as AddressDriverId, - )) ?? {}; + account: (user: ResolverUser): AddressDriverAccount => user.account, + }, + UserChainData: { + chain: (chainUserData: ResolverUserChainData): SupportedChain => + chainUserData.chain, + data: (chainUserData: ResolverUserChainData) => chainUserData.data, + }, + UserData: { + streams: async (userData: ResolverUserData) => { + const { parentUserInfo, streams } = userData; + + return { + incoming: streams.incoming, + outgoing: streams.outgoing, + parentUserInfo, + }; + }, + balances: async (userData: ResolverUserData) => { + const { + parentUserInfo: { accountId, userChain }, + } = userData; + assert(isAddressDriverId(accountId)); + + const chainMetadata = await getLatestAccountMetadataByChain( + [userChain], + accountId as AddressDriverId, + ); + + const metadata = chainMetadata[userChain]?.metadata ?? {}; + const assetConfigs = await getAssetConfigs( - parent.account.accountId as AddressDriverId, + accountId as AddressDriverId, metadata, ); - return assetConfigs.map((ac) => ({ - tokenAddress: ac.tokenAddress, - incoming: [], - outgoing: assetOutgoingBalanceTimeline(ac.history), + return Object.entries(assetConfigs).map(([chain, chainAssetConfigs]) => ({ + chain: chain as SupportedChain, + + assetConfigs: chainAssetConfigs.map((ac) => ({ + tokenAddress: ac.tokenAddress, + incoming: [], + outgoing: assetOutgoingBalanceTimeline(ac.history), + })), })); }, - projects: (parent: User, _: any, { dataSources }: Context) => { - const { accountId } = parent.account; + projects: async ( + userData: ResolverUserData, + _: any, + { dataSources }: Context, + ) => { + const { accountId, userChain } = userData.parentUserInfo; assert(isAddressDriverId(accountId)); - return dataSources.projectsDb.getProjectsByFilter( - [SupportedChain.sepolia], // TODO: Temporary for compiling. - { + const projectDataValues = + await dataSources.projectsDb.getProjectsByFilter([userChain], { ownerAddress: getUserAddress(accountId), - }, - ); + }); + + return toResolverProjects([userChain], projectDataValues); }, - dripLists: (parent: User, _: any, { dataSources }: Context) => { - const { accountId } = parent.account; + dripLists: async ( + userData: ResolverUserData, + _: any, + { dataSources }: Context, + ) => { + const { accountId, userChain } = userData.parentUserInfo; assert(isAddressDriverId(accountId)); - return dataSources.dripListsDb.getDripListsByFilter( - [SupportedChain.sepolia], // TODO: Temporary for compiling. - { + const dripListDataValues = + await dataSources.dripListsDb.getDripListsByFilter([userChain], { ownerAddress: getUserAddress(accountId), - }, - ); + }); + + return toResolverDripLists([userChain], dripListDataValues); }, }, UserStreams: { outgoing: async ( - parent: { accountId: AddressDriverId }, + userData: { parentUserInfo: { accountId: any; userChain: any } }, _: any, { dataSources }: Context, ) => { - const { accountId } = parent; + const { accountId, userChain } = userData.parentUserInfo; assert(isAddressDriverId(accountId)); - return dataSources.streamsDb.getUserOutgoingStreams(accountId); + return ( + await dataSources.streamsDb.getUserOutgoingStreams( + [userChain], + accountId, + ) + )[userChain as SupportedChain]; }, incoming: async ( - parent: { accountId: AddressDriverId }, + userData: { parentUserInfo: { accountId: any; userChain: any } }, _: any, { dataSources }: Context, ) => { - const { accountId } = parent; + const { accountId, userChain } = userData.parentUserInfo; assert(isAddressDriverId(accountId)); - return dataSources.streamsDb.getUserIncomingStreams(accountId); + return ( + await dataSources.streamsDb.getUserIncomingStreams( + [userChain], + accountId, + ) + )[userChain as SupportedChain]; }, }, StreamReceiver: { diff --git a/src/user/userTypeDef.ts b/src/user/userTypeDef.ts index bb2c9be..3f65da8 100644 --- a/src/user/userTypeDef.ts +++ b/src/user/userTypeDef.ts @@ -20,6 +20,15 @@ const userTypeDef = gql` type User { account: AddressDriverAccount! + chainData: [UserChainData!]! + } + + type UserChainData { + chain: SupportedChain! + data: UserData + } + + type UserData { streams: UserStreams! projects: [Project]! dripLists: [DripList]! diff --git a/src/user/userUtils.ts b/src/user/userUtils.ts new file mode 100644 index 0000000..e307148 --- /dev/null +++ b/src/user/userUtils.ts @@ -0,0 +1,33 @@ +import type { AccountId, ResolverUser } from '../common/types'; +import { Driver, type SupportedChain } from '../generated/graphql'; +import getUserAddress from '../utils/getUserAddress'; + +export default function toResolverUsers( + chains: SupportedChain[], + accountId: AccountId, +): ResolverUser { + return { + account: { + accountId, + address: getUserAddress(accountId), + driver: Driver.ADDRESS, + }, + chainData: chains.map((chain) => ({ + chain, + data: { + parentUserInfo: { + accountId, + queriedChains: chains, + userChain: chain, + }, + balances: [], // Will be populated by the resolver. + dripLists: [], // Will be populated by the resolver. + projects: [], // Will be populated by the resolver. + streams: { + incoming: [], // Will be populated by the resolver. + outgoing: [], // Will be populated by the resolver. + }, + }, + })), + }; +} diff --git a/src/utils/getAssetConfigs.ts b/src/utils/getAssetConfigs.ts index b0991b4..a4706fb 100644 --- a/src/utils/getAssetConfigs.ts +++ b/src/utils/getAssetConfigs.ts @@ -1,28 +1,42 @@ import type { AddressDriverId } from '../common/types'; +import type { SupportedChain } from '../generated/graphql'; import buildAssetConfigs from './buildAssetConfigs'; -import type getLatestAccountMetadata from './getLatestAccountMetadata'; +import type getLatestAccountMetadataByChain from './getLatestAccountMetadata'; import getStreamsSetEventsWithReceivers from './getStreamsSetEventsWithReceivers'; import groupBy from './linq'; export default async function getAssetConfigs( accountId: AddressDriverId, - accountMetadata: - | NonNullable< - Awaited> - >['metadata'] - | undefined, -): Promise> { + accountMetadata: NonNullable< + Awaited> + >, +): Promise>> { + const chainsToQuery = Object.keys(accountMetadata) as SupportedChain[]; + + if (!chainsToQuery.length) { + return {} as Record>; + } + const accountStreamsSetEventsWithReceivers = - await getStreamsSetEventsWithReceivers(accountId); + await getStreamsSetEventsWithReceivers(chainsToQuery, accountId); const accountStreamsSetEventsWithReceiversByErc20 = groupBy( accountStreamsSetEventsWithReceivers, (event) => event.erc20, ); - return buildAssetConfigs( - accountId, - accountMetadata, - accountStreamsSetEventsWithReceiversByErc20, - ); + const response = {} as Record< + SupportedChain, + ReturnType + >; + + chainsToQuery.forEach((chain) => { + response[chain] = buildAssetConfigs( + accountId, + accountMetadata[chain]?.metadata, + accountStreamsSetEventsWithReceiversByErc20, + ); + }); + + return response; } diff --git a/src/utils/getLatestAccountMetadata.ts b/src/utils/getLatestAccountMetadata.ts index 9690c3e..bae06c4 100644 --- a/src/utils/getLatestAccountMetadata.ts +++ b/src/utils/getLatestAccountMetadata.ts @@ -1,9 +1,13 @@ import type { AnyVersion } from '@efstajas/versioned-parser'; import { ethers } from 'ethers'; +import { QueryTypes } from 'sequelize'; import { addressDriverAccountMetadataParser } from '../schemas'; import type { AddressDriverId, IpfsHash } from '../common/types'; import appSettings from '../common/appSettings'; +import type { AccountMetadataEmittedEventModelDataValues } from '../models/AccountMetadataEmittedEventModel'; import AccountMetadataEmittedEventModel from '../models/AccountMetadataEmittedEventModel'; +import type { SupportedChain } from '../generated/graphql'; +import { dbConnection } from '../database/connectToDatabase'; function toIpfsHash(str: string): IpfsHash { const ipfsHash = ethers.toUtf8String(str); @@ -21,33 +25,65 @@ async function getIpfsFile(hash: IpfsHash): Promise { return fetch(`${appSettings.ipfsGatewayUrl}/ipfs/${hash}`); } -export default async function getLatestAccountMetadata( +export default async function getLatestAccountMetadataByChain( + chains: SupportedChain[], accountId: AddressDriverId, -): Promise< - | { +) { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => + `SELECT *,'${schema}' AS chain FROM "${schema}"."AccountMetadataEmittedEvents"`; + + // Initialize the WHERE clause parts. + const conditions: string[] = ['"accountId" = :accountId']; + const parameters: { [key: string]: any } = { accountId }; + + // Build the where clause. + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + // Define the order. + const orderClause = ' ORDER BY "blockNumber" DESC, "logIndex" DESC'; + + // Build the SQL for each specified schema. + const queries = chains.map( + (chain) => baseSQL(chain) + whereClause + orderClause, + ); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + const accountMetadataEmittedEventModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: AccountMetadataEmittedEventModel, + }) + ).map((p) => p.dataValues as AccountMetadataEmittedEventModelDataValues); + + const response: { + [chain in SupportedChain]?: { metadata: AnyVersion; ipfsHash: IpfsHash; - } - | undefined -> { - const latestAccountMetadataEmittedEvent = - await AccountMetadataEmittedEventModel.findAll({ - where: { accountId }, - order: [ - ['blockNumber', 'DESC'], - ['logIndex', 'DESC'], - ], - limit: 1, - }); - - if (!latestAccountMetadataEmittedEvent.length) { - return undefined; - } + } | null; + } = {}; - const ipfsHash = toIpfsHash(latestAccountMetadataEmittedEvent[0].value); + for (const metadataDataValues of accountMetadataEmittedEventModelDataValues) { + if (!accountMetadataEmittedEventModelDataValues.length) { + response[metadataDataValues.chain as SupportedChain] = null; + } else { + const ipfsHash = toIpfsHash( + accountMetadataEmittedEventModelDataValues[0].value, + ); - const ipfsFile = await (await getIpfsFile(ipfsHash)).json(); - const metadata = addressDriverAccountMetadataParser.parseAny(ipfsFile); + const ipfsFile = await (await getIpfsFile(ipfsHash)).json(); + const metadata = addressDriverAccountMetadataParser.parseAny(ipfsFile); + + response[metadataDataValues.chain as SupportedChain] = { + metadata, + ipfsHash, + }; + } + } - return { metadata, ipfsHash }; + return response; } diff --git a/src/utils/getStreamsSetEventsWithReceivers.ts b/src/utils/getStreamsSetEventsWithReceivers.ts index 3ff4000..122c0b4 100644 --- a/src/utils/getStreamsSetEventsWithReceivers.ts +++ b/src/utils/getStreamsSetEventsWithReceivers.ts @@ -1,83 +1,140 @@ -import { Op } from 'sequelize'; +import { QueryTypes } from 'sequelize'; import type { AddressDriverId, StreamsSetEventWithReceivers, } from '../common/types'; +import type { StreamReceiverSeenEventModelDataValues } from '../models/StreamReceiverSeenEventModel'; import StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; +import type { StreamsSetEventModelDataValues } from '../models/StreamsSetEventModel'; import StreamsSetEventModel from '../models/StreamsSetEventModel'; +import type { SupportedChain } from '../generated/graphql'; +import { dbConnection } from '../database/connectToDatabase'; export default async function getStreamsSetEventsWithReceivers( + chains: SupportedChain[], accountId: AddressDriverId, ): Promise { - const sortedAccountStreamSetEvents = await StreamsSetEventModel.findAll({ - where: { accountId }, - order: [ - // Oldest first - ['blockNumber', 'ASC'], - ['logIndex', 'ASC'], - ], - }); + const baseStreamsSetEventsSQL = (schema: SupportedChain) => ` + SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; + + // Initialize the WHERE clause parts. + const streamsSetEventModelConditions: string[] = ['"accountId" = :accountId']; + const streamsSetEventModelParameters: { [key: string]: any } = { accountId }; + + // Build the where clause. + const whereClause = ` WHERE ${streamsSetEventModelConditions.join(' AND ')}`; + + // Define the order. + const orderClause = ' ORDER BY "blockNumber" ASC, "logIndex" ASC'; + + // Build the SQL for each specified schema. + const streamsSetEventModelDataValuesQueries = chains.map( + (chain) => `${baseStreamsSetEventsSQL(chain) + whereClause + orderClause}`, + ); + + // Combine all schema queries with UNION. + const fullQueryStreamsSetEventModelQuery = `${streamsSetEventModelDataValuesQueries.join( + ' UNION ', + )} LIMIT 1000`; + + const sortedAccountStreamSetEventModelDataValues = ( + await dbConnection.query(fullQueryStreamsSetEventModelQuery, { + type: QueryTypes.SELECT, + replacements: streamsSetEventModelParameters, + mapToModel: true, + model: StreamsSetEventModel, + }) + ).map((p) => p.dataValues as StreamsSetEventModelDataValues); const uniqueReceiversHashes = [ ...new Set( - sortedAccountStreamSetEvents.map((event) => event.receiversHash), + sortedAccountStreamSetEventModelDataValues.map( + (event) => event.receiversHash, + ), ), ]; - const streamReceiverSeenEventsByReceiversHash = - await StreamReceiverSeenEventModel.findAll({ - where: { - receiversHash: { - [Op.in]: uniqueReceiversHashes, - }, - }, - }).then((events) => { - // Group receivers by their hash - const receiversGroupedByHash = events.reduce<{ - [receiversHash: string]: StreamReceiverSeenEventModel[]; - }>((acc, receiver) => { - if (!acc[receiver.receiversHash]) { - acc[receiver.receiversHash] = []; - } - acc[receiver.receiversHash].push(receiver); - return acc; - }, {}); - - Object.keys(receiversGroupedByHash).forEach((hash) => { - receiversGroupedByHash[hash] = [ - ...new Map( - receiversGroupedByHash[hash].map((receiver) => [ - receiver.config, - receiver, - ]), - ).values(), - ]; - }); - - return receiversGroupedByHash; - }); - - const streamsSetEventsWithReceivers = sortedAccountStreamSetEvents.reduce< - StreamsSetEventWithReceivers[] - >( - (acc, streamsSetEvent) => [ - ...acc, - { - accountId: streamsSetEvent.accountId, - erc20: streamsSetEvent.erc20, - receiversHash: streamsSetEvent.receiversHash, - streamsHistoryHash: streamsSetEvent.streamsHistoryHash, - balance: streamsSetEvent.balance, - maxEnd: streamsSetEvent.maxEnd, - blockTimestamp: streamsSetEvent.blockTimestamp, - receivers: - streamReceiverSeenEventsByReceiversHash[ - streamsSetEvent.receiversHash - ] || [], - }, - ], - [], + // Define base SQL to query from multiple chains (schemas). + const baseStreamReceiverSeenEventModelSQL = (schema: SupportedChain) => ` + SELECT *, '${schema}' AS chain FROM "${schema}"."StreamReceiverSeenEvents"`; + + // Initialize the WHERE clause parts. + const streamReceiverSeenEventModelConditions: string[] = [ + '"receiversHash" IN (:uniqueReceiversHashes)', + ]; + const streamReceiverSeenEventModelParameters: { [key: string]: any } = { + uniqueReceiversHashes, + }; + + // Build the where clause. + const streamReceiverSeenEventModelWhereClause = ` WHERE ${streamReceiverSeenEventModelConditions.join( + ' AND ', + )}`; + + // Build the SQL for each specified schema. + const streamReceiverSeenEventModelQueries = chains.map( + (chain) => + `${ + baseStreamReceiverSeenEventModelSQL(chain) + + streamReceiverSeenEventModelWhereClause + }`, ); + // Combine all schema queries with UNION. + const fullQueryStreamReceiverSeenEventModelQuery = `${streamReceiverSeenEventModelQueries.join( + ' UNION ', + )} LIMIT 1000`; + + const streamReceiverSeenEventModelDataValues = ( + await dbConnection.query(fullQueryStreamReceiverSeenEventModelQuery, { + type: QueryTypes.SELECT, + replacements: streamReceiverSeenEventModelParameters, + mapToModel: true, + model: StreamReceiverSeenEventModel, + }) + ).map((p) => p.dataValues as StreamReceiverSeenEventModelDataValues); + + const receiversGroupedByHash = streamReceiverSeenEventModelDataValues.reduce<{ + [receiversHash: string]: StreamReceiverSeenEventModelDataValues[]; + }>((acc, receiver) => { + if (!acc[receiver.receiversHash]) { + acc[receiver.receiversHash] = []; + } + acc[receiver.receiversHash].push(receiver); + return acc; + }, {}); + + Object.keys(receiversGroupedByHash).forEach((hash) => { + receiversGroupedByHash[hash] = [ + ...new Map( + receiversGroupedByHash[hash].map((receiver) => [ + receiver.config, + receiver, + ]), + ).values(), + ]; + }); + + const streamsSetEventsWithReceivers = + sortedAccountStreamSetEventModelDataValues.reduce< + StreamsSetEventWithReceivers[] + >( + (acc, streamsSetEvent) => [ + ...acc, + { + accountId: streamsSetEvent.accountId, + erc20: streamsSetEvent.erc20, + receiversHash: streamsSetEvent.receiversHash, + streamsHistoryHash: streamsSetEvent.streamsHistoryHash, + balance: streamsSetEvent.balance, + maxEnd: streamsSetEvent.maxEnd, + blockTimestamp: streamsSetEvent.blockTimestamp, + receivers: + receiversGroupedByHash[streamsSetEvent.receiversHash] || [], + }, + ], + [], + ); + return streamsSetEventsWithReceivers; } diff --git a/src/utils/getUserAccount.ts b/src/utils/getUserAccount.ts index 43b9e0e..a416e02 100644 --- a/src/utils/getUserAccount.ts +++ b/src/utils/getUserAccount.ts @@ -1,27 +1,61 @@ import type { AddressDriverId } from '../common/types'; +import type { SupportedChain } from '../generated/graphql'; import { Driver } from '../generated/graphql'; import getUserAddress from './getUserAddress'; -import getLatestAccountMetadata from './getLatestAccountMetadata'; import getAssetConfigs from './getAssetConfigs'; +import getLatestAccountMetadataByChain from './getLatestAccountMetadata'; -export default async function getUserAccount(accountId: AddressDriverId) { - const { metadata, ipfsHash } = - (await getLatestAccountMetadata(accountId)) ?? {}; +export default async function getUserAccount( + chains: SupportedChain[], + accountId: AddressDriverId, +) { + const latestAccountMetadataByChain = + (await getLatestAccountMetadataByChain(chains, accountId)) ?? {}; - const assetConfigs = await getAssetConfigs(accountId, metadata); + const assetConfigsByChain = await getAssetConfigs( + accountId, + latestAccountMetadataByChain, + ); - return { - user: { - accountId, - driver: Driver.ADDRESS, - address: getUserAddress(accountId), - }, - name: metadata?.name, - description: metadata?.description, - emoji: metadata?.emoji, - assetConfigs: assetConfigs ?? [], - lastUpdated: metadata ? new Date(metadata.timestamp * 1000) : undefined, - lastUpdatedByAddress: metadata?.writtenByAddress, - lastIpfsHash: ipfsHash, - }; + const response = {} as Record< + SupportedChain, + { + user: { + accountId: AddressDriverId; + driver: Driver; + address: string; + }; + name: string | undefined; + description: string | undefined; + emoji: string | undefined; + assetConfigs: Awaited>[SupportedChain]; + lastUpdated: Date | undefined; + lastUpdatedByAddress: string | undefined; + lastIpfsHash: string | undefined; + } + >; + + Object.entries(assetConfigsByChain).forEach(([chain, assetConfigs]) => { + const metadata = + latestAccountMetadataByChain[chain as SupportedChain]?.metadata; + const ipfsHash = + latestAccountMetadataByChain[chain as SupportedChain]?.ipfsHash; + + response[chain as SupportedChain] = { + user: { + accountId, + driver: Driver.ADDRESS, + address: getUserAddress(accountId), + }, + name: metadata?.name, + description: metadata?.description, + emoji: metadata?.emoji, + assetConfigs: assetConfigs ?? [], + lastUpdated: metadata ? new Date(metadata.timestamp * 1000) : undefined, + lastUpdatedByAddress: metadata?.writtenByAddress, + lastIpfsHash: ipfsHash, + }; + }); + + return response; } diff --git a/src/utils/parseMultiChainKeys.ts b/src/utils/parseMultiChainKeys.ts index 791e54f..a0eaa00 100644 --- a/src/utils/parseMultiChainKeys.ts +++ b/src/utils/parseMultiChainKeys.ts @@ -1,7 +1,6 @@ +import type { MultiChainKey } from '../common/types'; import type { SupportedChain } from '../generated/graphql'; -type MultiChainKey = { chains: SupportedChain[] }; - type ExtractedValues = { ids: (T extends { projectId: infer P } ? P @@ -11,14 +10,14 @@ type ExtractedValues = { chains: SupportedChain[]; }; -export default function parseMultiChainKeys< - T extends MultiChainKey & { [key: string]: any }, ->(keys: ReadonlyArray): ExtractedValues { - const ids = keys.map((key) => key.projectId ?? key.dripListId); +export default function parseMultiChainKeys( + keys: ReadonlyArray, +): ExtractedValues { + const ids = keys.map((key) => key.id); const chains = new Set(keys.flatMap((key) => key.chains)); return { - ids, + ids: ids as ExtractedValues['ids'], chains: [...chains], }; } diff --git a/src/utils/streams.ts b/src/utils/streams.ts index b93d044..063e8f2 100644 --- a/src/utils/streams.ts +++ b/src/utils/streams.ts @@ -1,37 +1,67 @@ -import { Op } from 'sequelize'; - +import { QueryTypes } from 'sequelize'; +import type { StreamReceiverSeenEventModelDataValues } from '../models/StreamReceiverSeenEventModel'; import StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; +import type { StreamsSetEventModelDataValues } from '../models/StreamsSetEventModel'; import StreamsSetEventModel from '../models/StreamsSetEventModel'; import assert, { isAddressDriverId } from './assert'; import getUserAccount from './getUserAccount'; import type { AddressDriverAccount, NftDriverAccount, + SupportedChain, } from '../generated/graphql'; import type { AccountId } from '../common/types'; import type { ProtoStream } from './buildAssetConfigs'; +import { dbConnection } from '../database/connectToDatabase'; async function getUserIncomingStreams( + chains: SupportedChain[], accountId: AccountId, -): Promise { - const streamReceiverSeenEventsForUser = - await StreamReceiverSeenEventModel.findAll({ - where: { - accountId, - }, - }); - - const streamsSetEventsWithMatchingHistoryHash = - await StreamsSetEventModel.findAll({ - where: { - receiversHash: { - [Op.in]: streamReceiverSeenEventsForUser.map( - (event) => event.receiversHash, - ), - }, +) { + const baseStreamReceiverSeenEventsSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamReceiverSeenEvents" WHERE "accountId" = :accountId`; + + const streamReceiverSeenEventsSqlQueries = `${chains + .map((chain) => `${baseStreamReceiverSeenEventsSQL(chain)}`) + .join(' UNION ')} LIMIT 1000`; + + const streamReceiverSeenEventModelDataValuesForUser = ( + await dbConnection.query(streamReceiverSeenEventsSqlQueries, { + type: QueryTypes.SELECT, + replacements: { accountId }, + mapToModel: true, + model: StreamReceiverSeenEventModel, + }) + ).map((p) => p.dataValues as StreamReceiverSeenEventModelDataValues); + + const baseStreamsSetEventsSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; + + const whereClause = streamReceiverSeenEventModelDataValuesForUser.length + ? ` WHERE "receiversHash" IN (:receiversHash)` + : ''; + + const streamsSetEventsSqlQueries = chains.map( + (chain) => baseStreamsSetEventsSQL(chain) + whereClause, + ); + + const fullStreamsSetEventsQuery = `${streamsSetEventsSqlQueries.join( + ' UNION ', + )} LIMIT 1000`; + + const streamsSetEventsWithMatchingHistoryHash = ( + await dbConnection.query(fullStreamsSetEventsQuery, { + type: QueryTypes.SELECT, + replacements: { + receiversHash: streamReceiverSeenEventModelDataValuesForUser.map( + (event) => event.receiversHash, + ), }, - }); + mapToModel: true, + model: StreamsSetEventModel, + }) + ).map((p) => p.dataValues as StreamsSetEventModelDataValues); const accountIdsStreamingToUser = streamsSetEventsWithMatchingHistoryHash .map((event) => event.accountId) @@ -40,26 +70,34 @@ async function getUserIncomingStreams( const accountsStreamingToUser = await Promise.all( accountIdsStreamingToUser.map((id) => { assert(isAddressDriverId(id)); - return getUserAccount(id); + return getUserAccount(chains, id); }), ); - const incomingStreams = accountsStreamingToUser.reduce( - (acc, account) => { - const streams = account.assetConfigs - .flatMap((assetConfig) => assetConfig.streams) - .filter( - (stream) => - (stream.receiver as any as AddressDriverAccount | NftDriverAccount) - .accountId === accountId, - ); - - return [...acc, ...streams]; - }, - [], - ); + const response = {} as Record; + + chains.forEach((chain) => { + response[chain] = accountsStreamingToUser.reduce( + (acc, account) => { + const streams = + account[chain]?.assetConfigs + .flatMap((assetConfig) => assetConfig?.streams) + .filter( + (stream) => + ( + stream.receiver as any as + | AddressDriverAccount + | NftDriverAccount + ).accountId === accountId, + ) || []; + + return [...acc, ...streams]; + }, + [], + ); + }); - return incomingStreams; + return response; } export default { From f4b1d2273c41cebe60af71dd84600e1b37dfc925 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Wed, 5 Jun 2024 12:26:33 +0200 Subject: [PATCH 09/37] refactor: remove hardcoded chains in stream queries and schema property from all models --- src/common/commonResolverLogic.ts | 4 +- src/common/queryableChains.ts | 11 +-- src/dataLoaders/ProjectsDataSource.ts | 59 ++-------------- src/drip-list/DripListModel.ts | 2 - src/drip-list/TransferEventModel.ts | 2 - src/given-event/GivenEventModel.ts | 2 - .../AccountMetadataEmittedEventModel.ts | 2 - src/models/AddressDriverSplitReceiverModel.ts | 2 - src/models/DripListSplitReceiverModel.ts | 2 - src/models/RepoDriverSplitReceiverModel.ts | 2 - src/models/SplitEventModel.ts | 2 - src/models/SqueezedStreamsEventModel.ts | 2 - src/models/StreamReceiverSeenEventModel.ts | 2 - src/models/StreamsSetEventModel.ts | 2 - src/project/ProjectModel.ts | 2 - src/project/projectResolvers.ts | 55 ++++++--------- src/project/projectUtils.ts | 7 ++ src/project/projectValidators.ts | 24 ++++--- src/stream/streamResolvers.ts | 40 +++++++---- src/user/userResolvers.ts | 9 ++- src/utils/buildAssetConfigs.ts | 8 +++ src/utils/getAssetConfigs.ts | 1 + src/utils/getSchema.ts | 6 -- src/utils/inputValidators.ts | 14 ++++ src/utils/sqlQueries.ts | 68 +++++++++++++++++++ src/utils/streamUtils.ts | 3 + 26 files changed, 183 insertions(+), 150 deletions(-) delete mode 100644 src/utils/getSchema.ts create mode 100644 src/utils/inputValidators.ts create mode 100644 src/utils/sqlQueries.ts diff --git a/src/common/commonResolverLogic.ts b/src/common/commonResolverLogic.ts index 19208e9..c1183ca 100644 --- a/src/common/commonResolverLogic.ts +++ b/src/common/commonResolverLogic.ts @@ -12,7 +12,7 @@ import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { SplitEventModelDataValues } from '../models/SplitEventModel'; import SplitEventModel from '../models/SplitEventModel'; -import { SupportedChain } from '../generated/graphql'; +import type { SupportedChain } from '../generated/graphql'; import { dbConnection } from '../database/connectToDatabase'; export async function resolveTotalSplit( @@ -71,7 +71,7 @@ export async function resolveTotalSplit( splitEventModelDataValues.map((splitEvent) => ({ tokenAddress: splitEvent.erc20, amount: BigInt(splitEvent.amt), - chain: SupportedChain.sepolia, // TODO: Only for compilation. + chain: splitEvent.chain, })), ).map((amount) => ({ ...amount, diff --git a/src/common/queryableChains.ts b/src/common/queryableChains.ts index 52eb3a9..e8ae9cb 100644 --- a/src/common/queryableChains.ts +++ b/src/common/queryableChains.ts @@ -1,12 +1,15 @@ import { SupportedChain } from '../generated/graphql'; import appSettings from './appSettings'; +/** + * Chains that have a defined RPC URL in the `.env` file. + */ const queryableChains: SupportedChain[] = []; -for (const network of Object.keys(SupportedChain)) { - if (appSettings.rpcUrls[network as SupportedChain]) { - queryableChains.push(network as SupportedChain); +Object.keys(SupportedChain).forEach((chain) => { + if (appSettings.rpcUrls[chain as SupportedChain]) { + queryableChains.push(chain as SupportedChain); } -} +}); export default queryableChains; diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 76bcef3..4f632fb 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -20,6 +20,7 @@ import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import GivenEventModel from '../given-event/GivenEventModel'; import { dbConnection } from '../database/connectToDatabase'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; +import sqlQueries from '../utils/sqlQueries'; export default class ProjectsDataSource { private readonly _batchProjectsByIds = new DataLoader( @@ -135,63 +136,15 @@ export default class ProjectsDataSource { public async getProjectsByFilter( chains: SupportedChain[], - where: ProjectWhereInput, + where?: ProjectWhereInput, sort?: ProjectSortInput, ): Promise { - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."GitProjects" - `; - - // Initialize the WHERE clause parts. - const conditions: string[] = []; - const parameters: { [key: string]: any } = {}; - - // Build the WHERE clause based on input filters. - if (where?.id) { - conditions.push(`"id" = :id`); - parameters.id = where.id; - } - if (where?.ownerAddress) { - conditions.push(`"ownerAddress" = :ownerAddress`); - parameters.ownerAddress = where.ownerAddress; - } - if (where?.url) { - conditions.push(`"url" = :url`); - parameters.url = where.url; - } - if (where?.verificationStatus) { - conditions.push(`"verificationStatus" = :verificationStatus`); - parameters.verificationStatus = where.verificationStatus; - } - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Define the order. - const orderClause = sort - ? ` ORDER BY "${sort.field}" ${sort.direction || 'DESC'}` - : ''; - - // Build the SQL for each specified schema. - const queries = chains.map( - (chain) => baseSQL(chain) + whereClause + orderClause, + const projectsDataValues = await sqlQueries.projects.getProjectsByFilter( + chains, + where, + sort, ); - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const projectsDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: ProjectModel, - }) - ).map((p) => p.dataValues as ProjectDataValues); - return Promise.all( projectsDataValues .filter((p) => p.isValid) diff --git a/src/drip-list/DripListModel.ts b/src/drip-list/DripListModel.ts index ea0fd7e..9b4f3f3 100644 --- a/src/drip-list/DripListModel.ts +++ b/src/drip-list/DripListModel.ts @@ -6,7 +6,6 @@ import type { import { DataTypes, Model } from 'sequelize'; import type { AddressLike } from 'ethers'; import type { UUID } from 'crypto'; -import getSchema from '../utils/getSchema'; import type { AccountId, CommonDataValues, DripListId } from '../common/types'; export type DripListDataValues = DripListModel['dataValues'] & CommonDataValues; @@ -67,7 +66,6 @@ export default class DripListModel extends Model< }, { sequelize, - schema: getSchema(), tableName: 'DripLists', }, ); diff --git a/src/drip-list/TransferEventModel.ts b/src/drip-list/TransferEventModel.ts index 22bb77d..0d0d647 100644 --- a/src/drip-list/TransferEventModel.ts +++ b/src/drip-list/TransferEventModel.ts @@ -5,7 +5,6 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; import type { CommonDataValues, DripListId } from '../common/types'; import { COMMON_EVENT_INIT_ATTRIBUTES } from '../common/constants'; @@ -45,7 +44,6 @@ export default class TransferEventModel extends Model< }, { sequelize, - schema: getSchema(), tableName: 'TransferEvents', }, ); diff --git a/src/given-event/GivenEventModel.ts b/src/given-event/GivenEventModel.ts index 5d2e9f4..9438fdd 100644 --- a/src/given-event/GivenEventModel.ts +++ b/src/given-event/GivenEventModel.ts @@ -10,7 +10,6 @@ import type { BigIntString, CommonDataValues, } from '../common/types'; -import getSchema from '../utils/getSchema'; export type GivenEventModelDataValues = GivenEventModel['dataValues'] & CommonDataValues; @@ -70,7 +69,6 @@ export default class GivenEventModel extends Model< }, { sequelize, - schema: getSchema(), tableName: 'GivenEvents', }, ); diff --git a/src/models/AccountMetadataEmittedEventModel.ts b/src/models/AccountMetadataEmittedEventModel.ts index 8c309d3..f505385 100644 --- a/src/models/AccountMetadataEmittedEventModel.ts +++ b/src/models/AccountMetadataEmittedEventModel.ts @@ -4,7 +4,6 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; import type { CommonDataValues, IEventModel } from '../common/types'; import getCommonEventAttributes from '../utils/getCommonEventAttributes'; @@ -48,7 +47,6 @@ export default class AccountMetadataEmittedEventModel }, { sequelize, - schema: getSchema(), tableName: 'AccountMetadataEmittedEvents', }, ); diff --git a/src/models/AddressDriverSplitReceiverModel.ts b/src/models/AddressDriverSplitReceiverModel.ts index adb9e65..c6bea31 100644 --- a/src/models/AddressDriverSplitReceiverModel.ts +++ b/src/models/AddressDriverSplitReceiverModel.ts @@ -6,7 +6,6 @@ import type { } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; import type { AddressLike } from 'ethers'; -import getSchema from '../utils/getSchema'; import type { AddressDriverId, CommonDataValues, @@ -85,7 +84,6 @@ export default class AddressDriverSplitReceiverModel extends Model< }, { sequelize, - schema: getSchema(), tableName: 'AddressDriverSplitReceivers', }, ); diff --git a/src/models/DripListSplitReceiverModel.ts b/src/models/DripListSplitReceiverModel.ts index 66e0f1a..d598f89 100644 --- a/src/models/DripListSplitReceiverModel.ts +++ b/src/models/DripListSplitReceiverModel.ts @@ -5,7 +5,6 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; import { DependencyType } from '../common/types'; import type { CommonDataValues, DripListId, ProjectId } from '../common/types'; import DripListModel from '../drip-list/DripListModel'; @@ -77,7 +76,6 @@ export default class DripListSplitReceiverModel extends Model< }, { sequelize, - schema: getSchema(), tableName: 'DripListSplitReceivers', }, ); diff --git a/src/models/RepoDriverSplitReceiverModel.ts b/src/models/RepoDriverSplitReceiverModel.ts index d7b19c3..3e4eb39 100644 --- a/src/models/RepoDriverSplitReceiverModel.ts +++ b/src/models/RepoDriverSplitReceiverModel.ts @@ -5,7 +5,6 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; import type { CommonDataValues, DripListId, ProjectId } from '../common/types'; import { DependencyType } from '../common/types'; import ProjectModel from '../project/ProjectModel'; @@ -77,7 +76,6 @@ export default class RepoDriverSplitReceiverModel extends Model< }, { sequelize, - schema: getSchema(), tableName: 'RepoDriverSplitReceivers', }, ); diff --git a/src/models/SplitEventModel.ts b/src/models/SplitEventModel.ts index 1e8bd83..117601d 100644 --- a/src/models/SplitEventModel.ts +++ b/src/models/SplitEventModel.ts @@ -4,7 +4,6 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; import type { AccountId, Address, @@ -54,7 +53,6 @@ export default class SplitEventModel extends Model< }, { sequelize, - schema: getSchema(), tableName: 'SplitEvents', }, ); diff --git a/src/models/SqueezedStreamsEventModel.ts b/src/models/SqueezedStreamsEventModel.ts index 7720c18..2635727 100644 --- a/src/models/SqueezedStreamsEventModel.ts +++ b/src/models/SqueezedStreamsEventModel.ts @@ -4,7 +4,6 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; import type { AccountId, Address, @@ -67,7 +66,6 @@ export default class SqueezedStreamsEventModel }, { sequelize, - schema: getSchema(), tableName: 'SqueezedStreamsEvents', }, ); diff --git a/src/models/StreamReceiverSeenEventModel.ts b/src/models/StreamReceiverSeenEventModel.ts index d749576..ab96682 100644 --- a/src/models/StreamReceiverSeenEventModel.ts +++ b/src/models/StreamReceiverSeenEventModel.ts @@ -4,7 +4,6 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; import type { AccountId, BigIntString, @@ -52,7 +51,6 @@ export default class StreamReceiverSeenEventModel }, { sequelize, - schema: getSchema(), tableName: 'StreamReceiverSeenEvents', }, ); diff --git a/src/models/StreamsSetEventModel.ts b/src/models/StreamsSetEventModel.ts index ae8a441..41cce93 100644 --- a/src/models/StreamsSetEventModel.ts +++ b/src/models/StreamsSetEventModel.ts @@ -4,7 +4,6 @@ import type { Sequelize, } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; -import getSchema from '../utils/getSchema'; import type { AccountId, BigIntString, @@ -67,7 +66,6 @@ export default class StreamsSetEventModel }, { sequelize, - schema: getSchema(), tableName: 'StreamsSetEvents', }, ); diff --git a/src/project/ProjectModel.ts b/src/project/ProjectModel.ts index a98f10a..0ec9216 100644 --- a/src/project/ProjectModel.ts +++ b/src/project/ProjectModel.ts @@ -5,7 +5,6 @@ import type { } from 'sequelize'; import { DataTypes, Model } from 'sequelize'; import type { AddressLike } from 'ethers'; -import getSchema from '../utils/getSchema'; import type { AccountId, CommonDataValues, @@ -103,7 +102,6 @@ export default class ProjectModel extends Model< }, { sequelize, - schema: getSchema(), tableName: 'GitProjects', }, ); diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 9954c3e..b4417d6 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -6,7 +6,7 @@ import type { ResolverUnClaimedProjectChainData, ResolverUnClaimedProjectData, } from '../common/types'; -import { toResolverProjects } from './projectUtils'; +import { toResolverProject, toResolverProjects } from './projectUtils'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import { Driver, SupportedChain } from '../generated/graphql'; import type { @@ -28,10 +28,11 @@ import { AddressDriverSplitReceiverType } from '../models/AddressDriverSplitRece import groupBy from '../utils/linq'; import queryableChains from '../common/queryableChains'; import type { ProjectDataValues } from './ProjectModel'; -import verifyProjectsInput from './projectValidators'; +import validateProjectsInput from './projectValidators'; import type { DripListDataValues } from '../drip-list/DripListModel'; import assert, { isGitHubUrl, isProjectId } from '../utils/assert'; import { resolveTotalEarned } from '../common/commonResolverLogic'; +import { validateChainsInput } from '../utils/inputValidators'; const projectResolvers = { Query: { @@ -46,75 +47,63 @@ const projectResolvers = { where: ProjectWhereInput; sort: ProjectSortInput; }, - { dataSources }: Context, + { dataSources: { projectsDb } }: Context, ): Promise => { - verifyProjectsInput({ chains, where, sort }); + validateProjectsInput({ chains, where, sort }); const chainsToQuery = chains?.length ? chains : queryableChains; - const projectsDataValues = - await dataSources.projectsDb.getProjectsByFilter( - chainsToQuery, - where, - sort, - ); + const dbProjects = await projectsDb.getProjectsByFilter( + chainsToQuery, + where, + sort, + ); - return toResolverProjects(chainsToQuery, projectsDataValues); + return toResolverProjects(chainsToQuery, dbProjects); }, projectById: async ( _: any, { id, chain }: { id: ProjectId; chain: SupportedChain }, - { dataSources }: Context, + { dataSources: { projectsDb } }: Context, ): Promise => { assert(isProjectId(id)); assert(chain in SupportedChain); - const projectDataValues = await dataSources.projectsDb.getProjectById( - id, - chain, - ); + const dbProjects = await projectsDb.getProjectById(id, chain); - if (!projectDataValues) { + if (!dbProjects) { return null; } - return (await toResolverProjects([chain], [projectDataValues]))[0]; + return toResolverProject(chain, dbProjects); }, projectByUrl: async ( _: any, { url, chain }: { url: string; chain: SupportedChain }, - { dataSources }: Context, + { dataSources: { projectsDb } }: Context, ): Promise => { assert(isGitHubUrl(url)); assert(chain in SupportedChain); - const projectDataValues = await dataSources.projectsDb.getProjectByUrl( - url, - chain, - ); + const dbProjects = await projectsDb.getProjectByUrl(url, chain); - if (!projectDataValues) { + if (!dbProjects) { return null; } - return (await toResolverProjects([chain], [projectDataValues]))[0]; + return toResolverProject(chain, dbProjects); }, earnedFunds: async ( _: any, { projectId, chains }: { projectId: ProjectId; chains: SupportedChain[] }, - { dataSources }: Context, + { dataSources: { projectsDb } }: Context, ) => { assert(isProjectId(projectId)); - - if (chains) { - chains.forEach((chain) => { - assert(chain in SupportedChain); - }); - } + validateChainsInput(chains); const chainsToQuery = chains?.length ? chains : queryableChains; - return dataSources.projectsDb.getEarnedFunds(projectId, chainsToQuery); + return projectsDb.getEarnedFunds(projectId, chainsToQuery); }, }, Project: { diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 67d2c28..8d469c3 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -142,6 +142,13 @@ export async function toFakeUnclaimedProject( } as ProjectDataValues; } +export async function toResolverProject( + chain: SupportedChain, + project: ProjectDataValues, +) { + return (await toResolverProjects([chain], [project]))[0]; +} + export async function toResolverProjects( chains: SupportedChain[], projects: ProjectDataValues[], diff --git a/src/project/projectValidators.ts b/src/project/projectValidators.ts index 6ff0c31..a202ffd 100644 --- a/src/project/projectValidators.ts +++ b/src/project/projectValidators.ts @@ -1,20 +1,24 @@ import { isAddress } from 'ethers'; -import { SupportedChain } from '../generated/graphql'; -import type { ProjectSortInput, ProjectWhereInput } from '../generated/graphql'; +import type { + SupportedChain, + ProjectSortInput, + ProjectWhereInput, +} from '../generated/graphql'; import assert, { isGitHubUrl, isProjectId, isProjectVerificationStatus, } from '../utils/assert'; +import { validateChainsInput } from '../utils/inputValidators'; function isSortableProjectField(field: string): boolean { return ['claimedAt'].includes(field); } -export default function verifyProjectsInput(input: { - chains: SupportedChain[]; - where: ProjectWhereInput; - sort: ProjectSortInput; +export default function validateProjectsInput(input: { + chains?: SupportedChain[]; + where?: ProjectWhereInput; + sort?: ProjectSortInput; }) { const { where, sort, chains } = input; @@ -34,13 +38,11 @@ export default function verifyProjectsInput(input: { assert(isProjectVerificationStatus(where.verificationStatus)); } - if (sort?.field === 'claimedAt') { + if (sort?.field) { assert(isSortableProjectField(sort.field)); } - if (chains) { - chains.forEach((chain) => { - assert(chain in SupportedChain); - }); + if (chains?.length) { + validateChainsInput(chains); } } diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index 5a77550..67b4ebf 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -1,38 +1,48 @@ -import { Driver, SupportedChain } from '../generated/graphql'; +import type { AddressDriverId, DripListId } from '../common/types'; +import { Driver } from '../generated/graphql'; import type { Context } from '../server'; +import type { ProtoStream } from '../utils/buildAssetConfigs'; import shouldNeverHappen from '../utils/shouldNeverHappen'; const streamResolvers = { Stream: { - receiver: (parent: any, _: any, { dataSources }: Context) => { - if (parent.receiver.driver === Driver.ADDRESS) { + receiver: ( + { chain, receiver }: ProtoStream, + _: any, + { dataSources }: Context, + ) => { + if (receiver.driver === Driver.ADDRESS) { return dataSources.usersDb.getUserByAccountId( - [SupportedChain.sepolia], // TODO: Temporary for compiling. - parent.receiver.accountId, + [chain], + receiver.accountId as AddressDriverId, ); } - if (parent.receiver.driver === Driver.NFT) { + if (receiver.driver === Driver.NFT) { return dataSources.dripListsDb.getDripListById( - [SupportedChain.sepolia], // TODO: Temporary for compiling. - parent.receiver.accountId, + [chain], + receiver.accountId as DripListId, ); } throw shouldNeverHappen(); }, - sender: (parent: any, _: any, { dataSources }: Context) => { - if (parent.sender.driver === Driver.ADDRESS) { + sender: ( + { chain, sender }: ProtoStream, + _: any, + { dataSources }: Context, + ) => { + if (sender.driver === Driver.ADDRESS) { return dataSources.usersDb.getUserByAccountId( - [SupportedChain.sepolia], // TODO: Temporary for compiling. - parent.sender.accountId, + [chain], + sender.accountId as AddressDriverId, ); } - if (parent.sender.driver === Driver.NFT) { + if (sender.driver === Driver.NFT) { return dataSources.dripListsDb.getDripListById( - [SupportedChain.sepolia], // TODO: Temporary for compiling. - parent.sender.accountId, + [chain], + sender.accountId as DripListId, ); } diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index 17b0f5c..ce63635 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -1,5 +1,6 @@ import { assetOutgoingBalanceTimeline } from '../balances/estimate-reloaded'; import type { + AccountId, Address, AddressDriverId, ResolverUser, @@ -133,7 +134,9 @@ const userResolvers = { }, UserStreams: { outgoing: async ( - userData: { parentUserInfo: { accountId: any; userChain: any } }, + userData: { + parentUserInfo: { accountId: AccountId; userChain: SupportedChain }; + }, _: any, { dataSources }: Context, ) => { @@ -148,7 +151,9 @@ const userResolvers = { )[userChain as SupportedChain]; }, incoming: async ( - userData: { parentUserInfo: { accountId: any; userChain: any } }, + userData: { + parentUserInfo: { accountId: AccountId; userChain: SupportedChain }; + }, _: any, { dataSources }: Context, ) => { diff --git a/src/utils/buildAssetConfigs.ts b/src/utils/buildAssetConfigs.ts index 4347512..d139caa 100644 --- a/src/utils/buildAssetConfigs.ts +++ b/src/utils/buildAssetConfigs.ts @@ -8,6 +8,7 @@ import buildStreamReceiver, { import type { AddressDriverAccount, NftDriverAccount, + SupportedChain, } from '../generated/graphql'; import getUserAddress from './getUserAddress'; import type { @@ -27,6 +28,7 @@ export interface AssetConfig { } export interface AssetConfigHistoryItem { + chain: SupportedChain; timestamp: Date; balance: { tokenAddress: string; @@ -39,6 +41,7 @@ export interface AssetConfigHistoryItem { } export interface ProtoStream { + chain: SupportedChain; streamId: string; config: | { @@ -63,6 +66,7 @@ export default function buildAssetConfigs( accountId: AddressDriverId, accountMetadata: AccountMetadata | undefined, accountStreamsSetEvents: Map, + chain: SupportedChain, ) { const firstAppearanceMap = new Map(); @@ -137,6 +141,7 @@ export default function buildAssetConfigs( } assetConfigHistoryItemStreams.push({ + chain, streamId, config: { raw: streamReceiverSeenEvent.config, @@ -187,6 +192,7 @@ export default function buildAssetConfigs( if (streamExistedBefore) { assetConfigHistoryItemStreams.push({ + chain, streamId: remainingStreamId, // Undefined streamConfig == stream was paused config: undefined, @@ -223,6 +229,7 @@ export default function buildAssetConfigs( } assetConfigHistoryItems.push({ + chain, timestamp: new Date(Number(streamsSetEvent.blockTimestamp)), balance: { tokenAddress, @@ -244,6 +251,7 @@ export default function buildAssetConfigs( tokenAddress, streams: currentStreams.map((receiver) => mapReceiverToStream( + chain, receiver, accountId, tokenAddress, diff --git a/src/utils/getAssetConfigs.ts b/src/utils/getAssetConfigs.ts index a4706fb..4a537a1 100644 --- a/src/utils/getAssetConfigs.ts +++ b/src/utils/getAssetConfigs.ts @@ -35,6 +35,7 @@ export default async function getAssetConfigs( accountId, accountMetadata[chain]?.metadata, accountStreamsSetEventsWithReceiversByErc20, + chain, ); }); diff --git a/src/utils/getSchema.ts b/src/utils/getSchema.ts deleted file mode 100644 index 11f8327..0000000 --- a/src/utils/getSchema.ts +++ /dev/null @@ -1,6 +0,0 @@ -import { SupportedChain } from '../generated/graphql'; - -// TODO: This should be removed once multi-chain support is implemented. For we return sepolia for anything that still relies on the "network". -export default function getSchema(): SupportedChain { - return SupportedChain.sepolia; -} diff --git a/src/utils/inputValidators.ts b/src/utils/inputValidators.ts new file mode 100644 index 0000000..53635c4 --- /dev/null +++ b/src/utils/inputValidators.ts @@ -0,0 +1,14 @@ +import queryableChains from '../common/queryableChains'; +import { SupportedChain } from '../generated/graphql'; +import assert from './assert'; + +// eslint-disable-next-line import/prefer-default-export +export function validateChainsInput(chains: SupportedChain[]) { + chains.forEach((chain) => { + assert(chain in SupportedChain); + + if (!queryableChains.includes(chain)) { + throw new Error(`Chain '${chain}' is missing RPC URL in the .env file.`); + } + }); +} diff --git a/src/utils/sqlQueries.ts b/src/utils/sqlQueries.ts new file mode 100644 index 0000000..23f7fea --- /dev/null +++ b/src/utils/sqlQueries.ts @@ -0,0 +1,68 @@ +import { QueryTypes } from 'sequelize'; +import { dbConnection } from '../database/connectToDatabase'; +import type { + ProjectSortInput, + ProjectWhereInput, + SupportedChain, +} from '../generated/graphql'; +import type { ProjectDataValues } from '../project/ProjectModel'; +import ProjectModel from '../project/ProjectModel'; + +async function getProjectsByFilter( + chains: SupportedChain[], + where?: ProjectWhereInput, + sort?: ProjectSortInput, +) { + const baseSQL = (schema: SupportedChain) => + `SELECT + "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GitProjects" `; + + const conditions: string[] = []; + const parameters: { [key: string]: any } = {}; + + if (where?.id) { + conditions.push(`"id" = :id`); + parameters.id = where.id; + } + if (where?.ownerAddress) { + conditions.push(`"ownerAddress" = :ownerAddress`); + parameters.ownerAddress = where.ownerAddress; + } + if (where?.url) { + conditions.push(`"url" = :url`); + parameters.url = where.url; + } + if (where?.verificationStatus) { + conditions.push(`"verificationStatus" = :verificationStatus`); + parameters.verificationStatus = where.verificationStatus; + } + + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + const orderClause = sort + ? ` ORDER BY "${sort.field}" ${sort.direction || 'DESC'}` + : ''; + + const chainQueries = chains.map( + (chain) => baseSQL(chain) + whereClause + orderClause, + ); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: ProjectModel, + }) + ).map((p) => p.dataValues as ProjectDataValues); +} + +export default { + projects: { + getProjectsByFilter, + }, +}; diff --git a/src/utils/streamUtils.ts b/src/utils/streamUtils.ts index 58dd849..da37227 100644 --- a/src/utils/streamUtils.ts +++ b/src/utils/streamUtils.ts @@ -13,6 +13,7 @@ import type { NftDriverAccount, AddressDriverAccount, StreamConfig, + SupportedChain, } from '../generated/graphql'; import getContractNameByAccountId from './getContractNameByAccountId'; import getUserAddress from './getUserAddress'; @@ -114,6 +115,7 @@ export default function buildStreamReceiver( } export function mapReceiverToStream( + chain: SupportedChain, receiver: ProtoStream, senderAccountId: string, tokenAddress: string, @@ -151,6 +153,7 @@ export function mapReceiverToStream( ); return { + chain, id: receiver.streamId, sender: { driver: Driver.ADDRESS, From 90220b8e58f2cb1a5fbd8f6d3d7fbc9fc2374e7f Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Wed, 5 Jun 2024 15:58:40 +0200 Subject: [PATCH 10/37] refactor: abstract Given event queries logic --- src/common/commonResolverLogic.ts | 4 +- src/common/commonResolvers.ts | 13 +- src/dataLoaders/GivenEventsDataSource.ts | 88 ++---------- .../ProjectAndDripListSupportDataSource.ts | 32 +---- src/dataLoaders/ProjectsDataSource.ts | 39 ++--- src/dataLoaders/TotalEarnedDataSource.ts | 19 +-- src/{utils => dataLoaders}/sqlQueries.ts | 136 +++++++++++++++++- 7 files changed, 166 insertions(+), 165 deletions(-) rename src/{utils => dataLoaders}/sqlQueries.ts (52%) diff --git a/src/common/commonResolverLogic.ts b/src/common/commonResolverLogic.ts index 32d4324..868e303 100644 --- a/src/common/commonResolverLogic.ts +++ b/src/common/commonResolverLogic.ts @@ -10,7 +10,7 @@ import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { SupportedChain } from '../generated/graphql'; -import sqlQueries from '../utils/sqlQueries'; +import sqlQueries from '../dataLoaders/sqlQueries'; export async function resolveTotalSplit( chains: SupportedChain[], @@ -34,7 +34,7 @@ export async function resolveTotalSplit( } const splitEventModelDataValues = - await sqlQueries.events.getSplitEventsByAccountIdAndReceiver( + await sqlQueries.events.slit.getByAccountIdAndReceiver( chains, incomingAccountId, recipientAccountId, diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index e59be23..5d82e04 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -21,7 +21,7 @@ import mergeAmounts from '../utils/mergeAmounts'; import AddressDriverSplitReceiverModel, { AddressDriverSplitReceiverType, } from '../models/AddressDriverSplitReceiverModel'; -import sqlQueries from '../utils/sqlQueries'; +import sqlQueries from '../dataLoaders/sqlQueries'; async function resolveTotalSplit( chains: SupportedChain[], @@ -53,12 +53,11 @@ async function resolveTotalSplit( shouldNeverHappen('Invalid SupportItem type'); } - const splitEvents = - await sqlQueries.events.getSplitEventsByAccountIdAndReceiver( - chains, - incomingAccountId, - recipientAccountId, - ); + const splitEvents = await sqlQueries.events.slit.getByAccountIdAndReceiver( + chains, + incomingAccountId, + recipientAccountId, + ); return mergeAmounts( splitEvents.map((splitEvent) => ({ diff --git a/src/dataLoaders/GivenEventsDataSource.ts b/src/dataLoaders/GivenEventsDataSource.ts index 28789c7..90e42ba 100644 --- a/src/dataLoaders/GivenEventsDataSource.ts +++ b/src/dataLoaders/GivenEventsDataSource.ts @@ -1,11 +1,9 @@ /* eslint-disable no-param-reassign */ -import { QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; import type { GiveWhereInput, SupportedChain } from '../generated/graphql'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; -import GivenEventModel from '../given-event/GivenEventModel'; -import { dbConnection } from '../database/connectToDatabase'; +import sqlQueries from './sqlQueries'; type TransactionHash = string; type LogIndex = number; @@ -26,39 +24,12 @@ export default class GivenEventsDataSource { ); const logIndexes = givenEventIds.map(([, logIndex]) => logIndex); - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."GivenEvents" - `; - - // Initialize the WHERE clause parts. - const conditions: string[] = [ - '"transactionHash" IN (:transactionHashes)', - '"logIndex" IN (:logIndexes)', - ]; - const parameters: { [key: string]: any } = { - transactionHashes, - logIndexes, - }; - - // Build the where clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const givenEventsDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); + const givenEventsDataValues = + await sqlQueries.events.given.getByTxHashesAndLogIndex( + chains, + transactionHashes, + logIndexes, + ); const idToEventMap = givenEventsDataValues.reduce< Record<`${string}-${string}`, GivenEventModelDataValues> @@ -89,49 +60,6 @@ export default class GivenEventsDataSource { chains: SupportedChain[], where: GiveWhereInput, ): Promise { - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."GivenEvents" - `; - - // Initialize the WHERE clause parts. - const conditions: string[] = []; - const parameters: { [key: string]: any } = {}; - - // Build the WHERE clause based on input filters. - if (where?.receiverAccountId) { - conditions.push(`"receiver" = :receiver`); - parameters.receiver = where.receiverAccountId; - } - if (where?.senderAccountId) { - conditions.push(`"accountId" = :accountId`); - parameters.accountId = where.senderAccountId; - } - if (where?.tokenAddress) { - conditions.push(`"erc20" = :erc20`); - parameters.erc20 = where.tokenAddress; - } - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const givenEventsDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); - - return givenEventsDataValues; + return sqlQueries.events.given.getByFilter(chains, where); } } diff --git a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts index 04cdc1e..5424b51 100644 --- a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts +++ b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts @@ -12,7 +12,6 @@ import type { } from '../common/types'; import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; -import GivenEventModel from '../given-event/GivenEventModel'; import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import streams from '../utils/streams'; @@ -20,7 +19,7 @@ import type { ProtoStream } from '../utils/buildAssetConfigs'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import type { SupportedChain } from '../generated/graphql'; import { dbConnection } from '../database/connectToDatabase'; -import sqlQueries from '../utils/sqlQueries'; +import sqlQueries from './sqlQueries'; import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; export default class ProjectAndDripListSupportDataSource { @@ -204,33 +203,8 @@ export default class ProjectAndDripListSupportDataSource { async (keys: readonly MultiChainKey[]) => { const { chains, ids } = parseMultiChainKeys(keys); - const baseSQL = (schema: SupportedChain) => ` - SELECT "accountId", "receiver", "erc20", "amt", "blockTimestamp", "logIndex", "transactionHash", "createdAt", "updatedAt",'${schema}' AS chain - FROM "${schema}"."GivenEvents" - `; - - // Build the WHERE clause. - const conditions: string[] = [`"receiver" IN (:ids)`]; - const parameters: { [key: string]: any } = { ids }; - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const oneTimeDonationSupport = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); + const oneTimeDonationSupport = + await sqlQueries.events.given.getByReceivers(chains, ids); const oneTimeDonationSupportToDripListMapping = oneTimeDonationSupport.reduce< diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 4f632fb..774cf3b 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -2,7 +2,11 @@ import { QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; import type { ProjectDataValues } from '../project/ProjectModel'; import ProjectModel from '../project/ProjectModel'; -import type { ProjectId, ProjectMultiChainKey } from '../common/types'; +import type { + AccountId, + ProjectId, + ProjectMultiChainKey, +} from '../common/types'; import { doesRepoExists, isValidProjectName, @@ -16,11 +20,9 @@ import type { } from '../generated/graphql'; import type { SplitEventModelDataValues } from '../models/SplitEventModel'; import SplitEventModel from '../models/SplitEventModel'; -import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; -import GivenEventModel from '../given-event/GivenEventModel'; import { dbConnection } from '../database/connectToDatabase'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; -import sqlQueries from '../utils/sqlQueries'; +import sqlQueries from './sqlQueries'; export default class ProjectsDataSource { private readonly _batchProjectsByIds = new DataLoader( @@ -240,34 +242,11 @@ export default class ProjectsDataSource { } private async _getIncomingGivesTotal( - accountId: string, + accountId: AccountId, chains: SupportedChain[], ) { - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; - - // Initialize the WHERE clause parts. - const conditions: string[] = ['"receiver" = :receiver']; - const parameters: { [receiver: string]: any } = { receiver: accountId }; - - // Create the WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const incomingGivenEventModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); + const incomingGivenEventModelDataValues = + await sqlQueries.events.given.getByReceiver(chains, accountId); return incomingGivenEventModelDataValues.reduce< { diff --git a/src/dataLoaders/TotalEarnedDataSource.ts b/src/dataLoaders/TotalEarnedDataSource.ts index 73efbaa..5ea20c3 100644 --- a/src/dataLoaders/TotalEarnedDataSource.ts +++ b/src/dataLoaders/TotalEarnedDataSource.ts @@ -14,9 +14,9 @@ import { dbConnection } from '../database/connectToDatabase'; import type { SplitEventModelDataValues } from '../models/SplitEventModel'; import SplitEventModel from '../models/SplitEventModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; -import GivenEventModel from '../given-event/GivenEventModel'; import { isDripListId, isProjectId } from '../utils/assert'; import shouldNeverHappen from '../utils/shouldNeverHappen'; +import sqlQueries from './sqlQueries'; export default class TotalEarnedDataSource { private readonly _batchTotalEarnedByProjectIds = new DataLoader( @@ -27,9 +27,6 @@ export default class TotalEarnedDataSource { const baseSplitEventsSQL = (schema: SupportedChain) => `SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; - const baseGivenEventsSplitsSQL = (schema: SupportedChain) => - `SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."GivenEvents"`; - // Build the WHERE clause. const conditions: string[] = [`"receiver" IN (:receivers)`]; const parameters: { [key: string]: any } = { @@ -44,13 +41,9 @@ export default class TotalEarnedDataSource { const splitsQueries = chains.map( (chain) => baseSplitEventsSQL(chain) + whereClause, ); - const givenQueries = chains.map( - (chain) => baseGivenEventsSplitsSQL(chain) + whereClause, - ); // Combine all schema queries with UNION. const fullSplitsQuery = `${splitsQueries.join(' UNION ')} LIMIT 1000`; - const fullGivenQuery = `${givenQueries.join(' UNION ')} LIMIT 1000`; const splitEventModelDataValues = ( await dbConnection.query(fullSplitsQuery, { @@ -61,14 +54,8 @@ export default class TotalEarnedDataSource { }) ).map((p) => p.dataValues as SplitEventModelDataValues); - const givenEventModelDataValues = ( - await dbConnection.query(fullGivenQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); + const givenEventModelDataValues = + await sqlQueries.events.given.getByReceivers(chains, projectIds); const splitEventsByDripListId = splitEventModelDataValues.reduce< Record diff --git a/src/utils/sqlQueries.ts b/src/dataLoaders/sqlQueries.ts similarity index 52% rename from src/utils/sqlQueries.ts rename to src/dataLoaders/sqlQueries.ts index b118ede..751f862 100644 --- a/src/utils/sqlQueries.ts +++ b/src/dataLoaders/sqlQueries.ts @@ -1,6 +1,7 @@ import { QueryTypes } from 'sequelize'; import { dbConnection } from '../database/connectToDatabase'; import type { + GiveWhereInput, ProjectSortInput, ProjectWhereInput, SupportedChain, @@ -12,6 +13,8 @@ import type { SplitEventModelDataValues } from '../models/SplitEventModel'; import SplitEventModel from '../models/SplitEventModel'; import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; import AddressDriverSplitReceiverModel from '../models/AddressDriverSplitReceiverModel'; +import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; +import GivenEventModel from '../given-event/GivenEventModel'; async function getProjectsByFilter( chains: SupportedChain[], @@ -129,12 +132,143 @@ async function getAddressDriverSplitReceiversByFundeeAccountIds( ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); } +async function getGivenEventsByFilter( + chains: SupportedChain[], + where: GiveWhereInput, +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + const conditions: string[] = []; + const parameters: { [key: string]: any } = {}; + + if (where?.receiverAccountId) { + conditions.push(`"receiver" = :receiver`); + parameters.receiver = where.receiverAccountId; + } + if (where?.senderAccountId) { + conditions.push(`"accountId" = :accountId`); + parameters.accountId = where.senderAccountId; + } + if (where?.tokenAddress) { + conditions.push(`"erc20" = :erc20`); + parameters.erc20 = where.tokenAddress; + } + + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); +} + +async function getGivenEventsByReceivers( + chains: SupportedChain[], + receivers: AccountId[], +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + const parameters: { [key: string]: any } = { receivers }; + + const whereClause = ` WHERE "receiver" IN (:receivers)`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); +} + +async function getGivenEventsByTxHashesAndLogIndex( + chains: SupportedChain[], + transactionHashes: string[], + logIndexes: number[], +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + const conditions: string[] = [ + '"transactionHash" IN (:transactionHashes)', + '"logIndex" IN (:logIndexes)', + ]; + const parameters: { [key: string]: any } = { + transactionHashes, + logIndexes, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); +} + +async function getGivenEventsByReceiver( + chains: SupportedChain[], + receiver: AccountId, +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + const parameters: { [receiver: string]: any } = { receiver }; + + const whereClause = ` WHERE "receiver" = :receiver`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); +} + export default { projects: { getProjectsByFilter, }, events: { - getSplitEventsByAccountIdAndReceiver, + given: { + getByFilter: getGivenEventsByFilter, + getByTxHashesAndLogIndex: getGivenEventsByTxHashesAndLogIndex, + getByReceivers: getGivenEventsByReceivers, + getByReceiver: getGivenEventsByReceiver, + }, + slit: { + getByAccountIdAndReceiver: getSplitEventsByAccountIdAndReceiver, + }, }, receivers: { getAddressDriverSplitReceiversByFundeeAccountIds, From a7d692f6fbb4f587658da0d851f97de66622447a Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 6 Jun 2024 10:45:50 +0200 Subject: [PATCH 11/37] refactor: abstract queries --- src/common/commonResolverLogic.ts | 4 +- src/common/commonResolvers.ts | 4 +- src/dataLoaders/DripListsDataSource.ts | 83 +----- src/dataLoaders/GivenEventsDataSource.ts | 6 +- .../ProjectAndDripListSupportDataSource.ts | 21 +- src/dataLoaders/ProjectsDataSource.ts | 73 +---- .../ReceiversOfTypeAddressDataSource.ts | 81 +---- .../ReceiversOfTypeDripListDataSource.ts | 6 +- .../ReceiversOfTypeProjectDataSource.ts | 6 +- src/dataLoaders/TotalEarnedDataSource.ts | 11 +- src/dataLoaders/sqlQueries.ts | 276 ------------------ .../addressDriverSplitReceiversQueries.ts | 112 +++++++ .../sqlQueries/dripListsQueries.ts | 81 +++++ .../sqlQueries/givenEventsQueries.ts | 136 +++++++++ src/dataLoaders/sqlQueries/projectsQueries.ts | 130 +++++++++ .../sqlQueries/splitEventsQueries.ts | 43 +++ src/utils/parseMultiChainKeys.ts | 6 +- 17 files changed, 562 insertions(+), 517 deletions(-) delete mode 100644 src/dataLoaders/sqlQueries.ts create mode 100644 src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts create mode 100644 src/dataLoaders/sqlQueries/dripListsQueries.ts create mode 100644 src/dataLoaders/sqlQueries/givenEventsQueries.ts create mode 100644 src/dataLoaders/sqlQueries/projectsQueries.ts create mode 100644 src/dataLoaders/sqlQueries/splitEventsQueries.ts diff --git a/src/common/commonResolverLogic.ts b/src/common/commonResolverLogic.ts index 868e303..bcb609c 100644 --- a/src/common/commonResolverLogic.ts +++ b/src/common/commonResolverLogic.ts @@ -10,7 +10,7 @@ import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { SupportedChain } from '../generated/graphql'; -import sqlQueries from '../dataLoaders/sqlQueries'; +import splitEventsQueries from '../dataLoaders/sqlQueries/splitEventsQueries'; export async function resolveTotalSplit( chains: SupportedChain[], @@ -34,7 +34,7 @@ export async function resolveTotalSplit( } const splitEventModelDataValues = - await sqlQueries.events.slit.getByAccountIdAndReceiver( + await splitEventsQueries.getByAccountIdAndReceiver( chains, incomingAccountId, recipientAccountId, diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index 5d82e04..ea592bc 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -21,7 +21,7 @@ import mergeAmounts from '../utils/mergeAmounts'; import AddressDriverSplitReceiverModel, { AddressDriverSplitReceiverType, } from '../models/AddressDriverSplitReceiverModel'; -import sqlQueries from '../dataLoaders/sqlQueries'; +import splitEventsQueries from '../dataLoaders/sqlQueries/splitEventsQueries'; async function resolveTotalSplit( chains: SupportedChain[], @@ -53,7 +53,7 @@ async function resolveTotalSplit( shouldNeverHappen('Invalid SupportItem type'); } - const splitEvents = await sqlQueries.events.slit.getByAccountIdAndReceiver( + const splitEvents = await splitEventsQueries.getByAccountIdAndReceiver( chains, incomingAccountId, recipientAccountId, diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index d95e6a1..c20cfb6 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -1,4 +1,3 @@ -import { QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; import type { Address, @@ -7,10 +6,9 @@ import type { } from '../common/types'; import type { DripListWhereInput, SupportedChain } from '../generated/graphql'; import type { DripListDataValues } from '../drip-list/DripListModel'; -import DripListModel from '../drip-list/DripListModel'; import TransferEventModel from '../drip-list/TransferEventModel'; -import { dbConnection } from '../database/connectToDatabase'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; +import dripListsQueries from './sqlQueries/dripListsQueries'; export default class DripListsDataSource { private readonly _batchDripListsByIds = new DataLoader( @@ -19,37 +17,10 @@ export default class DripListsDataSource { ): Promise => { const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "isValid", "ownerAddress", "ownerAccountId", "name", "latestVotingRoundId", "description", "creator", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."DripLists" - `; - - // Initialize the WHERE clause parts. - const conditions: string[] = [ - '"id" IN (:dripListIds)', - '"isValid" = true', - ]; - const parameters: { [key: string]: any } = { dripListIds }; - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const dripListDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: DripListModel, - }) - ).map((p) => p.dataValues as DripListDataValues); + const dripListDataValues = await dripListsQueries.getByIds( + chains, + dripListIds, + ); const dripListIdToDripListMap = dripListDataValues.reduce< Record @@ -77,46 +48,10 @@ export default class DripListsDataSource { chains: SupportedChain[], where: DripListWhereInput, ): Promise { - // TODO: For all data sources, extract the SQL query building logic into a separate function/file. - - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "isValid", "name", "creator", "description", "ownerAddress", "ownerAccountId", "latestVotingRoundId", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."DripLists" - `; - - // Initialize the WHERE clause parts. - const conditions: string[] = []; - const parameters: { [key: string]: any } = {}; - - // Build the WHERE clause based on input filters. - if (where?.id) { - conditions.push(`"id" = :id`); - parameters.id = where.id; - } - if (where?.ownerAddress) { - conditions.push(`"ownerAddress" = :ownerAddress`); - parameters.ownerAddress = where.ownerAddress; - } - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const dripListsDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: DripListModel, - }) - ).map((p) => p.dataValues as DripListDataValues); + const dripListsDataValues = await dripListsQueries.getByFilter( + chains, + where, + ); return dripListsDataValues.filter((p) => p.isValid && p.name); } diff --git a/src/dataLoaders/GivenEventsDataSource.ts b/src/dataLoaders/GivenEventsDataSource.ts index 90e42ba..2dd7309 100644 --- a/src/dataLoaders/GivenEventsDataSource.ts +++ b/src/dataLoaders/GivenEventsDataSource.ts @@ -3,7 +3,7 @@ import DataLoader from 'dataloader'; import type { GiveWhereInput, SupportedChain } from '../generated/graphql'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; -import sqlQueries from './sqlQueries'; +import givenEventsQueries from './sqlQueries/givenEventsQueries'; type TransactionHash = string; type LogIndex = number; @@ -25,7 +25,7 @@ export default class GivenEventsDataSource { const logIndexes = givenEventIds.map(([, logIndex]) => logIndex); const givenEventsDataValues = - await sqlQueries.events.given.getByTxHashesAndLogIndex( + await givenEventsQueries.getByTxHashesAndLogIndex( chains, transactionHashes, logIndexes, @@ -60,6 +60,6 @@ export default class GivenEventsDataSource { chains: SupportedChain[], where: GiveWhereInput, ): Promise { - return sqlQueries.events.given.getByFilter(chains, where); + return givenEventsQueries.getByFilter(chains, where); } } diff --git a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts index 5424b51..1616c1d 100644 --- a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts +++ b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts @@ -19,8 +19,9 @@ import type { ProtoStream } from '../utils/buildAssetConfigs'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import type { SupportedChain } from '../generated/graphql'; import { dbConnection } from '../database/connectToDatabase'; -import sqlQueries from './sqlQueries'; import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; +import addressDriverSplitReceiversQueries from './sqlQueries/addressDriverSplitReceiversQueries'; +import givenEventsQueries from './sqlQueries/givenEventsQueries'; export default class ProjectAndDripListSupportDataSource { private readonly _batchProjectAndDripListSupportByDripListIds = @@ -42,8 +43,7 @@ export default class ProjectAndDripListSupportDataSource { }; // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; // Build the SQL for each specified schema. const queries = chains.map((chain) => baseSQL(chain) + whereClause); @@ -95,8 +95,7 @@ export default class ProjectAndDripListSupportDataSource { }; // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; // Build the SQL for each specified schema. const queries = chains.map((chain) => baseSQL(chain) + whereClause); @@ -138,7 +137,7 @@ export default class ProjectAndDripListSupportDataSource { parseMultiChainKeys(addressDriverKeys); const projectAndDripListSupport = - await sqlQueries.receivers.getAddressDriverSplitReceiversByFundeeAccountIds( + await addressDriverSplitReceiversQueries.getByFundeeAccountIds( chains, addressDriverIds, ); @@ -157,7 +156,9 @@ export default class ProjectAndDripListSupportDataSource { }, {}); return addressDriverIds.map( - (id) => projectAndDripListSupportToProjectMapping[id] || [], + (id) => + projectAndDripListSupportToProjectMapping[id as AddressDriverId] || + [], ); }); @@ -203,8 +204,10 @@ export default class ProjectAndDripListSupportDataSource { async (keys: readonly MultiChainKey[]) => { const { chains, ids } = parseMultiChainKeys(keys); - const oneTimeDonationSupport = - await sqlQueries.events.given.getByReceivers(chains, ids); + const oneTimeDonationSupport = await givenEventsQueries.getByReceivers( + chains, + ids, + ); const oneTimeDonationSupportToDripListMapping = oneTimeDonationSupport.reduce< diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 774cf3b..4798906 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -1,7 +1,6 @@ import { QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; import type { ProjectDataValues } from '../project/ProjectModel'; -import ProjectModel from '../project/ProjectModel'; import type { AccountId, ProjectId, @@ -22,7 +21,8 @@ import type { SplitEventModelDataValues } from '../models/SplitEventModel'; import SplitEventModel from '../models/SplitEventModel'; import { dbConnection } from '../database/connectToDatabase'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; -import sqlQueries from './sqlQueries'; +import projectsQueries from './sqlQueries/projectsQueries'; +import givenEventsQueries from './sqlQueries/givenEventsQueries'; export default class ProjectsDataSource { private readonly _batchProjectsByIds = new DataLoader( @@ -31,37 +31,10 @@ export default class ProjectsDataSource { ): Promise => { const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."GitProjects" - `; - - // Initialize the WHERE clause parts. - const conditions: string[] = ['"id" IN (:projectIds)']; - const parameters: { [key: string]: any } = { projectIds }; - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const projectsDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: ProjectModel, - }) - ) - .map((p) => p.dataValues as ProjectDataValues) - .filter((p) => p.isValid) - .filter((p) => (p.name ? isValidProjectName(p.name) : true)); + const projectsDataValues = await projectsQueries.getByIds( + chains, + projectIds, + ); const projectsDataValuesWithApi = await Promise.all( projectsDataValues.map(toApiProject), @@ -99,35 +72,9 @@ export default class ProjectsDataSource { url: string, chain: SupportedChain, ): Promise { - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."GitProjects" - `; - - // Initialize the WHERE clause parts. - const conditions: string[] = ['"url" = :url']; - const parameters: { [key: string]: any } = { url }; - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Build the SQL for each specified schema. - const query = `${baseSQL(chain) + whereClause} LIMIT 1`; - - const projectDataValues = ( - await dbConnection.query(query, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: ProjectModel, - }) - ).map((p) => p.dataValues as ProjectDataValues); - - const [project] = projectDataValues || []; + const project = await projectsQueries.getByUrl(chain, url); - if (projectDataValues) { + if (project) { return toApiProject(project); } @@ -141,7 +88,7 @@ export default class ProjectsDataSource { where?: ProjectWhereInput, sort?: ProjectSortInput, ): Promise { - const projectsDataValues = await sqlQueries.projects.getProjectsByFilter( + const projectsDataValues = await projectsQueries.getByFilter( chains, where, sort, @@ -246,7 +193,7 @@ export default class ProjectsDataSource { chains: SupportedChain[], ) { const incomingGivenEventModelDataValues = - await sqlQueries.events.given.getByReceiver(chains, accountId); + await givenEventsQueries.getByReceiver(chains, accountId); return incomingGivenEventModelDataValues.reduce< { diff --git a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts index f74f069..1ff1797 100644 --- a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts @@ -1,5 +1,4 @@ import DataLoader from 'dataloader'; -import { QueryTypes } from 'sequelize'; import type { DripListId, DripListMultiChainKey, @@ -7,50 +6,20 @@ import type { ProjectMultiChainKey, } from '../common/types'; import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; -import AddressDriverSplitReceiverModel, { - AddressDriverSplitReceiverType, -} from '../models/AddressDriverSplitReceiverModel'; import type { SupportedChain } from '../generated/graphql'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; -import { dbConnection } from '../database/connectToDatabase'; +import addressDriverSplitReceiversQueries from './sqlQueries/addressDriverSplitReceiversQueries'; export default class ReceiversOfTypeAddressDataSource { private readonly _batchReceiversOfTypeAddressByProjectIds = new DataLoader( async (projectKeys: readonly ProjectMultiChainKey[]) => { const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "createdAt", "updatedAt",'${schema}' AS chain - FROM "${schema}"."AddressDriverSplitReceivers" - `; - - // Build the WHERE clause. - const conditions: string[] = [ - `"funderDripListId" IN (:funderProjectIds)`, - `type IN ('${AddressDriverSplitReceiverType.ProjectMaintainer}', '${AddressDriverSplitReceiverType.ProjectDependency}')`, - ]; - const parameters: { [key: string]: any } = { - funderProjectIds: projectIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const addressDriverSplitReceiverModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: AddressDriverSplitReceiverModel, - }) - ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); + const addressDriverSplitReceiverModelDataValues = + await addressDriverSplitReceiversQueries.getProjectDependenciesByFunders( + chains, + projectIds, + ); const receiversOfTypeAddressToProjectMapping = addressDriverSplitReceiverModelDataValues.reduce< @@ -85,39 +54,11 @@ export default class ReceiversOfTypeAddressDataSource { async (dripListKeys: readonly DripListMultiChainKey[]) => { const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."AddressDriverSplitReceivers" - `; - - // Build the WHERE clause. - const conditions: string[] = [ - `"funderDripListId" IN (:funderDripListIds)`, - `"type" IN ('${AddressDriverSplitReceiverType.DripListDependency}')`, - ]; - const parameters: { [key: string]: any } = { - funderDripListIds: dripListIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const addressDriverSplitReceiverModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: AddressDriverSplitReceiverModel, - }) - ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); + const addressDriverSplitReceiverModelDataValues = + await addressDriverSplitReceiversQueries.getDripListDependenciesByFunders( + chains, + dripListIds, + ); const receiversOfTypeAddressToDripListMapping = addressDriverSplitReceiverModelDataValues.reduce< diff --git a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts index 749665a..cbe1b15 100644 --- a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts @@ -33,8 +33,7 @@ export default class ReceiversOfTypeDripListDataSource { }; // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; // Build the SQL for each specified schema. const queries = chains.map((chain) => baseSQL(chain) + whereClause); @@ -99,8 +98,7 @@ export default class ReceiversOfTypeDripListDataSource { }; // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; // Build the SQL for each specified schema. const queries = chains.map((chain) => baseSQL(chain) + whereClause); diff --git a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts index e8cb08a..1d743fb 100644 --- a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts @@ -33,8 +33,7 @@ export default class ReceiversOfTypeProjectDataSource { }; // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; // Build the SQL for each specified schema. const queries = chains.map((chain) => baseSQL(chain) + whereClause); @@ -99,8 +98,7 @@ export default class ReceiversOfTypeProjectDataSource { }; // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; // Build the SQL for each specified schema. const queries = chains.map((chain) => baseSQL(chain) + whereClause); diff --git a/src/dataLoaders/TotalEarnedDataSource.ts b/src/dataLoaders/TotalEarnedDataSource.ts index 5ea20c3..d17de91 100644 --- a/src/dataLoaders/TotalEarnedDataSource.ts +++ b/src/dataLoaders/TotalEarnedDataSource.ts @@ -16,7 +16,7 @@ import SplitEventModel from '../models/SplitEventModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import { isDripListId, isProjectId } from '../utils/assert'; import shouldNeverHappen from '../utils/shouldNeverHappen'; -import sqlQueries from './sqlQueries'; +import givenEventsQueries from './sqlQueries/givenEventsQueries'; export default class TotalEarnedDataSource { private readonly _batchTotalEarnedByProjectIds = new DataLoader( @@ -34,8 +34,7 @@ export default class TotalEarnedDataSource { }; // Join conditions into a single WHERE clause. - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; // Build the SQL for each specified schema. const splitsQueries = chains.map( @@ -54,8 +53,10 @@ export default class TotalEarnedDataSource { }) ).map((p) => p.dataValues as SplitEventModelDataValues); - const givenEventModelDataValues = - await sqlQueries.events.given.getByReceivers(chains, projectIds); + const givenEventModelDataValues = await givenEventsQueries.getByReceivers( + chains, + projectIds, + ); const splitEventsByDripListId = splitEventModelDataValues.reduce< Record diff --git a/src/dataLoaders/sqlQueries.ts b/src/dataLoaders/sqlQueries.ts deleted file mode 100644 index 751f862..0000000 --- a/src/dataLoaders/sqlQueries.ts +++ /dev/null @@ -1,276 +0,0 @@ -import { QueryTypes } from 'sequelize'; -import { dbConnection } from '../database/connectToDatabase'; -import type { - GiveWhereInput, - ProjectSortInput, - ProjectWhereInput, - SupportedChain, -} from '../generated/graphql'; -import type { ProjectDataValues } from '../project/ProjectModel'; -import ProjectModel from '../project/ProjectModel'; -import type { AccountId } from '../common/types'; -import type { SplitEventModelDataValues } from '../models/SplitEventModel'; -import SplitEventModel from '../models/SplitEventModel'; -import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; -import AddressDriverSplitReceiverModel from '../models/AddressDriverSplitReceiverModel'; -import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; -import GivenEventModel from '../given-event/GivenEventModel'; - -async function getProjectsByFilter( - chains: SupportedChain[], - where?: ProjectWhereInput, - sort?: ProjectSortInput, -): Promise { - const baseSQL = (schema: SupportedChain) => - `SELECT - "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."GitProjects" `; - - const conditions: string[] = []; - const parameters: { [key: string]: any } = {}; - - if (where?.id) { - conditions.push(`"id" = :id`); - parameters.id = where.id; - } - if (where?.ownerAddress) { - conditions.push(`"ownerAddress" = :ownerAddress`); - parameters.ownerAddress = where.ownerAddress; - } - if (where?.url) { - conditions.push(`"url" = :url`); - parameters.url = where.url; - } - if (where?.verificationStatus) { - conditions.push(`"verificationStatus" = :verificationStatus`); - parameters.verificationStatus = where.verificationStatus; - } - - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - const orderClause = sort - ? ` ORDER BY "${sort.field}" ${sort.direction || 'DESC'}` - : ''; - - const chainQueries = chains.map( - (chain) => baseSQL(chain) + whereClause + orderClause, - ); - - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; - - return ( - await dbConnection.query(multiChainQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: ProjectModel, - }) - ).map((p) => p.dataValues as ProjectDataValues); -} - -async function getSplitEventsByAccountIdAndReceiver( - chains: SupportedChain[], - accountId: AccountId, - receiver: AccountId, -): Promise { - const baseSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."SplitEvents"`; - - const conditions: string[] = [ - '"accountId" = :accountId', - '"receiver" = :receiver', - ]; - const parameters: { [receiver: string]: any } = { - accountId, - receiver, - }; - - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; - - return ( - await dbConnection.query(multiChainQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: SplitEventModel, - }) - ).map((p) => p.dataValues as SplitEventModelDataValues); -} - -async function getAddressDriverSplitReceiversByFundeeAccountIds( - chains: SupportedChain[], - fundeeAccountIds: AccountId[], -) { - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."AddressDriverSplitReceivers" -`; - - const parameters: { [key: string]: any } = { - fundeeAccountIds, - }; - - const whereClause = ` WHERE "fundeeAccountId" IN (:fundeeAccountIds)`; - - const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; - - return ( - await dbConnection.query(multiChainQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: AddressDriverSplitReceiverModel, - }) - ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); -} - -async function getGivenEventsByFilter( - chains: SupportedChain[], - where: GiveWhereInput, -) { - const baseSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; - - const conditions: string[] = []; - const parameters: { [key: string]: any } = {}; - - if (where?.receiverAccountId) { - conditions.push(`"receiver" = :receiver`); - parameters.receiver = where.receiverAccountId; - } - if (where?.senderAccountId) { - conditions.push(`"accountId" = :accountId`); - parameters.accountId = where.senderAccountId; - } - if (where?.tokenAddress) { - conditions.push(`"erc20" = :erc20`); - parameters.erc20 = where.tokenAddress; - } - - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; - - const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; - - return ( - await dbConnection.query(multiChainQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); -} - -async function getGivenEventsByReceivers( - chains: SupportedChain[], - receivers: AccountId[], -) { - const baseSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; - - const parameters: { [key: string]: any } = { receivers }; - - const whereClause = ` WHERE "receiver" IN (:receivers)`; - - const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; - - return ( - await dbConnection.query(multiChainQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); -} - -async function getGivenEventsByTxHashesAndLogIndex( - chains: SupportedChain[], - transactionHashes: string[], - logIndexes: number[], -) { - const baseSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; - - const conditions: string[] = [ - '"transactionHash" IN (:transactionHashes)', - '"logIndex" IN (:logIndexes)', - ]; - const parameters: { [key: string]: any } = { - transactionHashes, - logIndexes, - }; - - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; - - return ( - await dbConnection.query(multiChainQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); -} - -async function getGivenEventsByReceiver( - chains: SupportedChain[], - receiver: AccountId, -) { - const baseSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; - - const parameters: { [receiver: string]: any } = { receiver }; - - const whereClause = ` WHERE "receiver" = :receiver`; - - const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; - - return ( - await dbConnection.query(multiChainQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: GivenEventModel, - }) - ).map((p) => p.dataValues as GivenEventModelDataValues); -} - -export default { - projects: { - getProjectsByFilter, - }, - events: { - given: { - getByFilter: getGivenEventsByFilter, - getByTxHashesAndLogIndex: getGivenEventsByTxHashesAndLogIndex, - getByReceivers: getGivenEventsByReceivers, - getByReceiver: getGivenEventsByReceiver, - }, - slit: { - getByAccountIdAndReceiver: getSplitEventsByAccountIdAndReceiver, - }, - }, - receivers: { - getAddressDriverSplitReceiversByFundeeAccountIds, - }, -}; diff --git a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts new file mode 100644 index 0000000..130f072 --- /dev/null +++ b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts @@ -0,0 +1,112 @@ +import { QueryTypes } from 'sequelize'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { SupportedChain } from '../../generated/graphql'; +import type { AccountId, DripListId } from '../../common/types'; +import type { AddressDriverSplitReceiverModelDataValues } from '../../models/AddressDriverSplitReceiverModel'; +import AddressDriverSplitReceiverModel, { + AddressDriverSplitReceiverType, +} from '../../models/AddressDriverSplitReceiverModel'; + +async function getAddressDriverSplitReceiversDripListDependenciesByFunders( + chains: SupportedChain[], + funderDripListIds: DripListId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."AddressDriverSplitReceivers" +`; + + const conditions: string[] = [ + `"funderDripListId" IN (:funderDripListIds)`, + `"type" IN ('${AddressDriverSplitReceiverType.DripListDependency}')`, + ]; + const parameters: { [key: string]: any } = { + funderDripListIds, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: AddressDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); +} + +async function getAddressDriverSplitReceiversProjectDependenciesByFunders( + chains: SupportedChain[], + funderProjectIds: AccountId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."AddressDriverSplitReceivers" + `; + + const conditions: string[] = [ + `"funderDripListId" IN (:funderProjectIds)`, + `type IN ('${AddressDriverSplitReceiverType.ProjectMaintainer}', '${AddressDriverSplitReceiverType.ProjectDependency}')`, + ]; + const parameters: { [key: string]: any } = { + funderProjectIds, + }; + + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: AddressDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); +} + +async function getAddressDriverSplitReceiversByFundeeAccountIds( + chains: SupportedChain[], + fundeeAccountIds: AccountId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."AddressDriverSplitReceivers" + `; + + const parameters: { [key: string]: any } = { + fundeeAccountIds, + }; + + const whereClause = ` WHERE "fundeeAccountId" IN (:fundeeAccountIds)`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: AddressDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as AddressDriverSplitReceiverModelDataValues); +} + +export default { + getDripListDependenciesByFunders: + getAddressDriverSplitReceiversDripListDependenciesByFunders, + getProjectDependenciesByFunders: + getAddressDriverSplitReceiversProjectDependenciesByFunders, + getByFundeeAccountIds: getAddressDriverSplitReceiversByFundeeAccountIds, +}; diff --git a/src/dataLoaders/sqlQueries/dripListsQueries.ts b/src/dataLoaders/sqlQueries/dripListsQueries.ts new file mode 100644 index 0000000..57ef65a --- /dev/null +++ b/src/dataLoaders/sqlQueries/dripListsQueries.ts @@ -0,0 +1,81 @@ +import { QueryTypes } from 'sequelize'; +import type { DripListId } from '../../common/types'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { DripListDataValues } from '../../drip-list/DripListModel'; +import DripListModel from '../../drip-list/DripListModel'; +import type { + DripListWhereInput, + SupportedChain, +} from '../../generated/graphql'; + +async function getDripListsByFilter( + chains: SupportedChain[], + where: DripListWhereInput, +) { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "name", "creator", "description", "ownerAddress", "ownerAccountId", "latestVotingRoundId", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."DripLists" + `; + + const conditions: string[] = []; + const parameters: { [key: string]: any } = {}; + + if (where?.id) { + conditions.push(`"id" = :id`); + parameters.id = where.id; + } + if (where?.ownerAddress) { + conditions.push(`"ownerAddress" = :ownerAddress`); + parameters.ownerAddress = where.ownerAddress; + } + + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListModel, + }) + ).map((p) => p.dataValues as DripListDataValues); +} + +async function getDripListsByIds( + chains: SupportedChain[], + dripListIds: DripListId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "ownerAddress", "ownerAccountId", "name", "latestVotingRoundId", "description", "creator", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."DripLists" + `; + + const conditions: string[] = ['"id" IN (:dripListIds)', '"isValid" = true']; + const parameters: { [key: string]: any } = { dripListIds }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListModel, + }) + ).map((p) => p.dataValues as DripListDataValues); +} + +export default { + getByIds: getDripListsByIds, + getByFilter: getDripListsByFilter, +}; diff --git a/src/dataLoaders/sqlQueries/givenEventsQueries.ts b/src/dataLoaders/sqlQueries/givenEventsQueries.ts new file mode 100644 index 0000000..f47ee46 --- /dev/null +++ b/src/dataLoaders/sqlQueries/givenEventsQueries.ts @@ -0,0 +1,136 @@ +import { QueryTypes } from 'sequelize'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { GiveWhereInput, SupportedChain } from '../../generated/graphql'; +import type { AccountId } from '../../common/types'; +import type { GivenEventModelDataValues } from '../../given-event/GivenEventModel'; +import GivenEventModel from '../../given-event/GivenEventModel'; + +async function getGivenEventsByFilter( + chains: SupportedChain[], + where: GiveWhereInput, +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + const conditions: string[] = []; + const parameters: { [key: string]: any } = {}; + + if (where?.receiverAccountId) { + conditions.push(`"receiver" = :receiver`); + parameters.receiver = where.receiverAccountId; + } + if (where?.senderAccountId) { + conditions.push(`"accountId" = :accountId`); + parameters.accountId = where.senderAccountId; + } + if (where?.tokenAddress) { + conditions.push(`"erc20" = :erc20`); + parameters.erc20 = where.tokenAddress; + } + + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); +} + +async function getGivenEventsByReceivers( + chains: SupportedChain[], + receivers: AccountId[], +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + const parameters: { [key: string]: any } = { receivers }; + + const whereClause = ` WHERE "receiver" IN (:receivers)`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); +} + +async function getGivenEventsByTxHashesAndLogIndex( + chains: SupportedChain[], + transactionHashes: string[], + logIndexes: number[], +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + const conditions: string[] = [ + '"transactionHash" IN (:transactionHashes)', + '"logIndex" IN (:logIndexes)', + ]; + const parameters: { [key: string]: any } = { + transactionHashes, + logIndexes, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); +} + +async function getGivenEventsByReceiver( + chains: SupportedChain[], + receiver: AccountId, +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + + const parameters: { [receiver: string]: any } = { receiver }; + + const whereClause = ` WHERE "receiver" = :receiver`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: GivenEventModel, + }) + ).map((p) => p.dataValues as GivenEventModelDataValues); +} + +export default { + getByFilter: getGivenEventsByFilter, + getByTxHashesAndLogIndex: getGivenEventsByTxHashesAndLogIndex, + getByReceivers: getGivenEventsByReceivers, + getByReceiver: getGivenEventsByReceiver, +}; diff --git a/src/dataLoaders/sqlQueries/projectsQueries.ts b/src/dataLoaders/sqlQueries/projectsQueries.ts new file mode 100644 index 0000000..174ea1f --- /dev/null +++ b/src/dataLoaders/sqlQueries/projectsQueries.ts @@ -0,0 +1,130 @@ +import { QueryTypes } from 'sequelize'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { + ProjectSortInput, + ProjectWhereInput, + SupportedChain, +} from '../../generated/graphql'; +import type { ProjectDataValues } from '../../project/ProjectModel'; +import ProjectModel from '../../project/ProjectModel'; +import { isValidProjectName } from '../../project/projectUtils'; +import type { ProjectId } from '../../common/types'; + +async function getProjectByUrl( + chain: SupportedChain, + url: string, +): Promise { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GitProjects" + `; + + const conditions: string[] = ['"url" = :url']; + const parameters: { [key: string]: any } = { url }; + + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + const query = `${baseSQL(chain) + whereClause} LIMIT 1`; + + const dbProject = ( + await dbConnection.query(query, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: ProjectModel, + }) + ).map((p) => p.dataValues as ProjectDataValues)[0]; + + return dbProject || null; +} + +async function getProjectsByIds( + chains: SupportedChain[], + projectIds: ProjectId[], +): Promise { + // Define base SQL to query from multiple chains (schemas). + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GitProjects" +`; + + const parameters: { [key: string]: any } = { projectIds }; + + const whereClause = ` WHERE "id" IN (:projectIds)`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: ProjectModel, + }) + ) + .map((p) => p.dataValues as ProjectDataValues) + .filter((p) => p.isValid) + .filter((p) => (p.name ? isValidProjectName(p.name) : true)); +} + +async function getProjectsByFilter( + chains: SupportedChain[], + where?: ProjectWhereInput, + sort?: ProjectSortInput, +): Promise { + const baseSQL = (schema: SupportedChain) => + `SELECT + "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GitProjects" `; + + const conditions: string[] = []; + const parameters: { [key: string]: any } = {}; + + if (where?.id) { + conditions.push(`"id" = :id`); + parameters.id = where.id; + } + if (where?.ownerAddress) { + conditions.push(`"ownerAddress" = :ownerAddress`); + parameters.ownerAddress = where.ownerAddress; + } + if (where?.url) { + conditions.push(`"url" = :url`); + parameters.url = where.url; + } + if (where?.verificationStatus) { + conditions.push(`"verificationStatus" = :verificationStatus`); + parameters.verificationStatus = where.verificationStatus; + } + + const whereClause = + conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + + const orderClause = sort + ? ` ORDER BY "${sort.field}" ${sort.direction || 'DESC'}` + : ''; + + const chainQueries = chains.map( + (chain) => baseSQL(chain) + whereClause + orderClause, + ); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: ProjectModel, + }) + ).map((p) => p.dataValues as ProjectDataValues); +} + +export default { + getByUrl: getProjectByUrl, + getByIds: getProjectsByIds, + getByFilter: getProjectsByFilter, +}; diff --git a/src/dataLoaders/sqlQueries/splitEventsQueries.ts b/src/dataLoaders/sqlQueries/splitEventsQueries.ts new file mode 100644 index 0000000..086108f --- /dev/null +++ b/src/dataLoaders/sqlQueries/splitEventsQueries.ts @@ -0,0 +1,43 @@ +import { QueryTypes } from 'sequelize'; +import type { AccountId } from '../../common/types'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { SupportedChain } from '../../generated/graphql'; +import type { SplitEventModelDataValues } from '../../models/SplitEventModel'; +import SplitEventModel from '../../models/SplitEventModel'; + +async function getSplitEventsByAccountIdAndReceiver( + chains: SupportedChain[], + accountId: AccountId, + receiver: AccountId, +): Promise { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."SplitEvents"`; + + const conditions: string[] = [ + '"accountId" = :accountId', + '"receiver" = :receiver', + ]; + const parameters: { [receiver: string]: any } = { + accountId, + receiver, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: SplitEventModel, + }) + ).map((p) => p.dataValues as SplitEventModelDataValues); +} + +export default { + getByAccountIdAndReceiver: getSplitEventsByAccountIdAndReceiver, +}; diff --git a/src/utils/parseMultiChainKeys.ts b/src/utils/parseMultiChainKeys.ts index a0eaa00..785f2d8 100644 --- a/src/utils/parseMultiChainKeys.ts +++ b/src/utils/parseMultiChainKeys.ts @@ -2,11 +2,7 @@ import type { MultiChainKey } from '../common/types'; import type { SupportedChain } from '../generated/graphql'; type ExtractedValues = { - ids: (T extends { projectId: infer P } - ? P - : T extends { dripListId: infer D } - ? D - : never)[]; + ids: (T extends { id: infer ID } ? ID : never)[]; chains: SupportedChain[]; }; From e00f5ef15fee83a793296cabd86363ca1231d60d Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 6 Jun 2024 11:02:55 +0200 Subject: [PATCH 12/37] fix: runtime error --- src/user/userUtils.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/user/userUtils.ts b/src/user/userUtils.ts index e307148..a1d1432 100644 --- a/src/user/userUtils.ts +++ b/src/user/userUtils.ts @@ -27,6 +27,7 @@ export default function toResolverUsers( incoming: [], // Will be populated by the resolver. outgoing: [], // Will be populated by the resolver. }, + support: [], // Will be populated by the resolver. }, })), }; From ea247d5e745de5f75c11859890f78e5617d6b160 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 6 Jun 2024 17:15:14 +0200 Subject: [PATCH 13/37] refactor: abstract SQL queries --- src/common/commonResolverLogic.ts | 5 +- src/common/commonResolvers.ts | 29 +-- src/dataLoaders/DripListsDataSource.ts | 9 +- .../ProjectAndDripListSupportDataSource.ts | 76 ++------ src/dataLoaders/ProjectsDataSource.ts | 37 +--- .../ReceiversOfTypeDripListDataSource.ts | 77 ++------ .../ReceiversOfTypeProjectDataSource.ts | 77 ++------ src/dataLoaders/TotalEarnedDataSource.ts | 37 +--- .../accountMetadataEmittedEventsQueries.ts | 40 ++++ .../addressDriverSplitReceiversQueries.ts | 3 +- .../dripListSplitReceiversQueries.ts | 113 +++++++++++ .../sqlQueries/dripListsQueries.ts | 8 +- src/dataLoaders/sqlQueries/projectsQueries.ts | 22 +-- .../repoDriverSplitReceiversQueries.ts | 110 +++++++++++ .../sqlQueries/splitEventsQueries.ts | 58 ++++++ .../streamReceiverSeenEventQueries.ts | 31 ++++ .../sqlQueries/streamsSetEventsQueries.ts | 70 +++++++ src/drip-list/dripListResolvers.ts | 118 +++++------- src/drip-list/dripListUtils.ts | 9 +- src/drip-list/dripListValidators.ts | 30 ++- src/given-event/givenEventResolvers.ts | 2 +- src/project/projectResolvers.ts | 175 ++++++++---------- src/project/projectUtils.ts | 22 --- src/project/projectValidators.ts | 50 ++--- src/schema.ts | 2 +- src/server.ts | 44 ++--- src/stream/streamResolvers.ts | 8 +- src/user/userResolvers.ts | 140 +++++++------- ...Validators.ts => commonInputValidators.ts} | 7 +- src/utils/getLatestAccountMetadata.ts | 37 +--- src/utils/getStreamsSetEventsWithReceivers.ts | 36 +--- src/utils/streams.ts | 54 +----- 32 files changed, 791 insertions(+), 745 deletions(-) create mode 100644 src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts create mode 100644 src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts create mode 100644 src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts create mode 100644 src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts create mode 100644 src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts rename src/utils/{inputValidators.ts => commonInputValidators.ts} (66%) diff --git a/src/common/commonResolverLogic.ts b/src/common/commonResolverLogic.ts index bcb609c..1a769a9 100644 --- a/src/common/commonResolverLogic.ts +++ b/src/common/commonResolverLogic.ts @@ -54,7 +54,6 @@ export async function resolveTotalSplit( export async function resolveTotalEarned( projectOrDripListData: ResolverUnClaimedProjectData | ResolverDripListData, - _: any, context: Context, ) { let accountId: ProjectId | DripListId; @@ -67,10 +66,10 @@ export async function resolveTotalEarned( chain = projectOrDripListData.parentDripListInfo.dripListChain; } - const { totalEarnedDb } = context.dataSources; + const { totalEarnedDataSource } = context.dataSources; const { splitEventsForDripListDataValues, givenEventsForDripListDataValues } = - await totalEarnedDb.getTotalEarnedByProjectIds(accountId, [chain]); + await totalEarnedDataSource.getTotalEarnedByProjectIds(accountId, [chain]); return mergeAmounts( [ diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index ea592bc..104792f 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -15,7 +15,7 @@ import { DependencyType } from './types'; import getUserAddress from '../utils/getUserAddress'; import type { ProtoStream } from '../utils/buildAssetConfigs'; import { toResolverProjects } from '../project/projectUtils'; -import toResolverDripLists from '../drip-list/dripListUtils'; +import { toResolverDripLists } from '../drip-list/dripListUtils'; import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import mergeAmounts from '../utils/mergeAmounts'; import AddressDriverSplitReceiverModel, { @@ -119,12 +119,15 @@ const commonResolvers = { context: Context, ): Promise => { const { - dataSources: { projectsDb }, + dataSources: { projectsDataSource }, } = context; const { funderProjectId, chain } = parent; - const project = await projectsDb.getProjectById(funderProjectId, chain); + const project = await projectsDataSource.getProjectById( + funderProjectId, + chain, + ); return { driver: Driver.REPO, @@ -143,13 +146,13 @@ const commonResolvers = { context: Context, ) => { const { - dataSources: { projectsDb }, + dataSources: { projectsDataSource }, } = context; const { funderProjectId, chain } = parent; const projectDataValues = - (await projectsDb.getProjectById(funderProjectId, chain)) || + (await projectsDataSource.getProjectById(funderProjectId, chain)) || shouldNeverHappen(); const resolverProjects = await toResolverProjects( @@ -173,12 +176,12 @@ const commonResolvers = { context: Context, ): Promise => { const { - dataSources: { dripListsDb }, + dataSources: { dripListsDataSource }, } = context; const { funderDripListId, chain } = parent; - const dripList = await dripListsDb.getDripListById( + const dripList = await dripListsDataSource.getDripListById( [chain], funderDripListId, ); @@ -196,14 +199,16 @@ const commonResolvers = { context: Context, ) => { const { - dataSources: { dripListsDb }, + dataSources: { dripListsDataSource }, } = context; const { funderDripListId, chain } = parent; const dripListDataValues = - (await dripListsDb.getDripListById([chain], funderDripListId)) || - shouldNeverHappen(); + (await dripListsDataSource.getDripListById( + [chain], + funderDripListId, + )) || shouldNeverHappen(); const resolverDripLists = await toResolverDripLists( [chain], @@ -227,12 +232,12 @@ const commonResolvers = { context: Context, ): Promise => { const { - dataSources: { givesDb }, + dataSources: { givenEventsDataSource }, } = context; const { transactionHash, logIndex, chain } = parent; - const givenEvent = await givesDb.getGivenEventById( + const givenEvent = await givenEventsDataSource.getGivenEventById( [chain], transactionHash, logIndex, diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index c20cfb6..fee0a0e 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -46,14 +46,9 @@ export default class DripListsDataSource { public async getDripListsByFilter( chains: SupportedChain[], - where: DripListWhereInput, + where?: DripListWhereInput, ): Promise { - const dripListsDataValues = await dripListsQueries.getByFilter( - chains, - where, - ); - - return dripListsDataValues.filter((p) => p.isValid && p.name); + return dripListsQueries.getByFilter(chains, where); } public async getDripListsByIds( diff --git a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts index 1616c1d..7f1b2ff 100644 --- a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts +++ b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts @@ -1,5 +1,4 @@ import DataLoader from 'dataloader'; -import { QueryTypes } from 'sequelize'; import type { DripListSplitReceiverModelDataValues } from '../models/DripListSplitReceiverModel'; import type { AccountId, @@ -10,55 +9,28 @@ import type { ProjectId, ProjectMultiChainKey, } from '../common/types'; -import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; -import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import streams from '../utils/streams'; import type { ProtoStream } from '../utils/buildAssetConfigs'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import type { SupportedChain } from '../generated/graphql'; -import { dbConnection } from '../database/connectToDatabase'; import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; import addressDriverSplitReceiversQueries from './sqlQueries/addressDriverSplitReceiversQueries'; import givenEventsQueries from './sqlQueries/givenEventsQueries'; +import dripListSplitReceiversQueries from './sqlQueries/dripListSplitReceiversQueries'; +import repoDriverSplitReceiversQueries from './sqlQueries/repoDriverSplitReceiversQueries'; export default class ProjectAndDripListSupportDataSource { private readonly _batchProjectAndDripListSupportByDripListIds = new DataLoader(async (dripListKeys: readonly DripListMultiChainKey[]) => { const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."DripListSplitReceivers" - `; - - // Build the WHERE clause. - const conditions: string[] = [ - `"fundeeDripListId" IN (:fundeeDripListIds)`, - ]; - const parameters: { [key: string]: any } = { - fundeeDripListIds: dripListIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const dripListSplitReceiverModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: DripListSplitReceiverModel, - }) - ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); + const dripListSplitReceiverModelDataValues = + await dripListSplitReceiversQueries.getByFundeeDripListIds( + chains, + dripListIds, + ); const projectAndDripListSupportToDripListMapping = dripListSplitReceiverModelDataValues.reduce< @@ -82,35 +54,11 @@ export default class ProjectAndDripListSupportDataSource { async (projectKeys: readonly ProjectMultiChainKey[]) => { const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."RepoDriverSplitReceivers" - `; - - // Build the WHERE clause. - const conditions: string[] = [`"fundeeProjectId" IN (:fundeeProjectIds)`]; - const parameters: { [key: string]: any } = { - fundeeProjectIds: projectIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const repoDriverSplitReceiverModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: RepoDriverSplitReceiverModel, - }) - ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); + const repoDriverSplitReceiverModelDataValues = + await repoDriverSplitReceiversQueries.getByFundeeProjectIds( + chains, + projectIds, + ); const projectAndDripListSupportToProjectMapping = repoDriverSplitReceiverModelDataValues.reduce< diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 4798906..916a0bd 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -1,4 +1,3 @@ -import { QueryTypes } from 'sequelize'; import DataLoader from 'dataloader'; import type { ProjectDataValues } from '../project/ProjectModel'; import type { @@ -8,7 +7,6 @@ import type { } from '../common/types'; import { doesRepoExists, - isValidProjectName, toApiProject, toFakeUnclaimedProjectFromUrl, } from '../project/projectUtils'; @@ -17,12 +15,10 @@ import type { ProjectWhereInput, SupportedChain, } from '../generated/graphql'; -import type { SplitEventModelDataValues } from '../models/SplitEventModel'; -import SplitEventModel from '../models/SplitEventModel'; -import { dbConnection } from '../database/connectToDatabase'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import projectsQueries from './sqlQueries/projectsQueries'; import givenEventsQueries from './sqlQueries/givenEventsQueries'; +import splitEventsQueries from './sqlQueries/splitEventsQueries'; export default class ProjectsDataSource { private readonly _batchProjectsByIds = new DataLoader( @@ -96,8 +92,6 @@ export default class ProjectsDataSource { return Promise.all( projectsDataValues - .filter((p) => p.isValid) - .filter((p) => (p.name ? isValidProjectName(p.name) : true)) .map(toApiProject) .filter(Boolean) as ProjectDataValues[], ); @@ -134,34 +128,11 @@ export default class ProjectsDataSource { } private async _getIncomingSplitTotal( - accountId: string, + accountId: AccountId, chains: SupportedChain[], ) { - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."SplitEvents"`; - - // Initialize the WHERE clause parts. - const conditions: string[] = ['"receiver" = :receiver']; - const parameters: { [receiver: string]: any } = { receiver: accountId }; - - // Create the WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const incomingSplitEventModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: SplitEventModel, - }) - ).map((p) => p.dataValues as SplitEventModelDataValues); + const incomingSplitEventModelDataValues = + await splitEventsQueries.getByReceiver(chains, accountId); return incomingSplitEventModelDataValues.reduce< { diff --git a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts index cbe1b15..1cd48f4 100644 --- a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts @@ -1,6 +1,4 @@ import DataLoader from 'dataloader'; -import { QueryTypes } from 'sequelize'; -import { DependencyType } from '../common/types'; import type { ProjectMultiChainKey, DripListId, @@ -8,47 +6,20 @@ import type { DripListMultiChainKey, } from '../common/types'; import type { DripListSplitReceiverModelDataValues } from '../models/DripListSplitReceiverModel'; -import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; -import { dbConnection } from '../database/connectToDatabase'; import type { SupportedChain } from '../generated/graphql'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; +import dripListSplitReceiversQueries from './sqlQueries/dripListSplitReceiversQueries'; export default class ReceiversOfTypeDripListDataSource { private readonly _batchReceiversOfTypeDripListByProjectIds = new DataLoader( async (projectKeys: readonly ProjectMultiChainKey[]) => { const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain - FROM "${schema}"."DripListSplitReceivers" - `; - - // Build the WHERE clause. - const conditions: string[] = [ - `"funderDripListId" IN (:funderProjectIds)`, - `type = '${DependencyType.ProjectDependency}'`, - ]; - const parameters: { [key: string]: any } = { - funderProjectIds: projectIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const dripListSplitReceiverModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: DripListSplitReceiverModel, - }) - ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); + const dripListSplitReceiverModelDataValues = + await dripListSplitReceiversQueries.getByFunderProjectIds( + chains, + projectIds, + ); const receiversOfTypeDripListToProjectListMapping = dripListSplitReceiverModelDataValues.reduce< @@ -83,37 +54,11 @@ export default class ReceiversOfTypeDripListDataSource { async (dripListKeys: readonly DripListMultiChainKey[]) => { const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain - FROM "${schema}"."DripListSplitReceivers" - `; - - // Build the WHERE clause. - const conditions: string[] = [ - `"funderDripListId" IN (:funderDripListIds)`, - `type = '${DependencyType.DripListDependency}'`, - ]; - const parameters: { [key: string]: any } = { - funderDripListIds: dripListIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const dripListSplitReceiverModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: DripListSplitReceiverModel, - }) - ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); + const dripListSplitReceiverModelDataValues = + await dripListSplitReceiversQueries.getByFunderDripListIds( + chains, + dripListIds, + ); const receiversOfTypeDripListToDripListMapping = dripListSplitReceiverModelDataValues.reduce< diff --git a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts index 1d743fb..be2ff19 100644 --- a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts @@ -1,6 +1,4 @@ import DataLoader from 'dataloader'; -import { QueryTypes } from 'sequelize'; -import { DependencyType } from '../common/types'; import type { DripListMultiChainKey, DripListId, @@ -8,47 +6,20 @@ import type { ProjectMultiChainKey, } from '../common/types'; import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; -import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import type { SupportedChain } from '../generated/graphql'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; -import { dbConnection } from '../database/connectToDatabase'; +import repoDriverSplitReceiversQueries from './sqlQueries/repoDriverSplitReceiversQueries'; export default class ReceiversOfTypeProjectDataSource { private readonly _batchReceiversOfTypeProjectByProjectIds = new DataLoader( async (projectKeys: readonly ProjectMultiChainKey[]) => { const { chains, ids: projectIds } = parseMultiChainKeys(projectKeys); - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain - FROM "${schema}"."RepoDriverSplitReceivers" - `; - - // Build the WHERE clause. - const conditions: string[] = [ - `"funderProjectId" IN (:funderProjectIds)`, - `type = '${DependencyType.ProjectDependency}'`, - ]; - const parameters: { [key: string]: any } = { - funderProjectIds: projectIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const repoDriverSplitReceiverModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: RepoDriverSplitReceiverModel, - }) - ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); + const repoDriverSplitReceiverModelDataValues = + await repoDriverSplitReceiversQueries.getByFunderProjectIds( + chains, + projectIds, + ); const receiversOfTypeProjectToProjectMapping = repoDriverSplitReceiverModelDataValues.reduce< @@ -83,37 +54,11 @@ export default class ReceiversOfTypeProjectDataSource { async (dripListKeys: readonly DripListMultiChainKey[]) => { const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain - FROM "${schema}"."RepoDriverSplitReceivers" - `; - - // Build the WHERE clause. - const conditions: string[] = [ - `"funderDripListId" IN (:funderDripListIds)`, - `type = '${DependencyType.DripListDependency}'`, - ]; - const parameters: { [key: string]: any } = { - funderDripListIds: dripListIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const queries = chains.map((chain) => baseSQL(chain) + whereClause); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const repoDriverSplitReceiverModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: RepoDriverSplitReceiverModel, - }) - ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); + const repoDriverSplitReceiverModelDataValues = + await repoDriverSplitReceiversQueries.getByFunderDripListIds( + chains, + dripListIds, + ); const receiversOfTypeProjectToDripListMapping = repoDriverSplitReceiverModelDataValues.reduce< diff --git a/src/dataLoaders/TotalEarnedDataSource.ts b/src/dataLoaders/TotalEarnedDataSource.ts index d17de91..8340c9b 100644 --- a/src/dataLoaders/TotalEarnedDataSource.ts +++ b/src/dataLoaders/TotalEarnedDataSource.ts @@ -1,6 +1,5 @@ /* eslint-disable no-param-reassign */ import DataLoader from 'dataloader'; -import { QueryTypes } from 'sequelize'; import type { AccountId, DripListId, @@ -10,54 +9,26 @@ import type { } from '../common/types'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import type { SupportedChain } from '../generated/graphql'; -import { dbConnection } from '../database/connectToDatabase'; import type { SplitEventModelDataValues } from '../models/SplitEventModel'; -import SplitEventModel from '../models/SplitEventModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import { isDripListId, isProjectId } from '../utils/assert'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import givenEventsQueries from './sqlQueries/givenEventsQueries'; +import splitEventsQueries from './sqlQueries/splitEventsQueries'; export default class TotalEarnedDataSource { private readonly _batchTotalEarnedByProjectIds = new DataLoader( async (keys: readonly (DripListMultiChainKey | ProjectMultiChainKey)[]) => { const { chains, ids: projectIds } = parseMultiChainKeys(keys); - // Define base SQL to query from multiple chains (schemas). - const baseSplitEventsSQL = (schema: SupportedChain) => - `SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; - - // Build the WHERE clause. - const conditions: string[] = [`"receiver" IN (:receivers)`]; - const parameters: { [key: string]: any } = { - receivers: projectIds, - }; - - // Join conditions into a single WHERE clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Build the SQL for each specified schema. - const splitsQueries = chains.map( - (chain) => baseSplitEventsSQL(chain) + whereClause, - ); - - // Combine all schema queries with UNION. - const fullSplitsQuery = `${splitsQueries.join(' UNION ')} LIMIT 1000`; - - const splitEventModelDataValues = ( - await dbConnection.query(fullSplitsQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: SplitEventModel, - }) - ).map((p) => p.dataValues as SplitEventModelDataValues); - const givenEventModelDataValues = await givenEventsQueries.getByReceivers( chains, projectIds, ); + const splitEventModelDataValues = + await splitEventsQueries.getByProjectReceivers(chains, projectIds); + const splitEventsByDripListId = splitEventModelDataValues.reduce< Record >((mapping, event) => { diff --git a/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts b/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts new file mode 100644 index 0000000..fa44047 --- /dev/null +++ b/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts @@ -0,0 +1,40 @@ +import { QueryTypes } from 'sequelize'; +import type { AddressDriverId } from '../../common/types'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { SupportedChain } from '../../generated/graphql'; +import type { AccountMetadataEmittedEventModelDataValues } from '../../models/AccountMetadataEmittedEventModel'; +import AccountMetadataEmittedEventModel from '../../models/AccountMetadataEmittedEventModel'; + +async function getAccountMetadataEmittedEventsByAccountId( + chains: SupportedChain[], + accountId: AddressDriverId, +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *,'${schema}' AS chain FROM "${schema}"."AccountMetadataEmittedEvents"`; + + const conditions: string[] = ['"accountId" = :accountId']; + const parameters: { [key: string]: any } = { accountId }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const orderClause = ' ORDER BY "blockNumber" DESC, "logIndex" DESC'; + + const queries = chains.map( + (chain) => baseSQL(chain) + whereClause + orderClause, + ); + + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: AccountMetadataEmittedEventModel, + }) + ).map((p) => p.dataValues as AccountMetadataEmittedEventModelDataValues); +} + +export default { + getByAccountId: getAccountMetadataEmittedEventsByAccountId, +}; diff --git a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts index 130f072..9491d70 100644 --- a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts +++ b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts @@ -57,8 +57,7 @@ async function getAddressDriverSplitReceiversProjectDependenciesByFunders( funderProjectIds, }; - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); diff --git a/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts new file mode 100644 index 0000000..f635363 --- /dev/null +++ b/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts @@ -0,0 +1,113 @@ +import { QueryTypes } from 'sequelize'; +import { + DependencyType, + type DripListId, + type ProjectId, +} from '../../common/types'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { SupportedChain } from '../../generated/graphql'; +import type { DripListSplitReceiverModelDataValues } from '../../models/DripListSplitReceiverModel'; +import DripListSplitReceiverModel from '../../models/DripListSplitReceiverModel'; + +async function getDripListSplitReceiversByFundeeDripListIds( + chains: SupportedChain[], + fundeeDripListIds: DripListId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."DripListSplitReceivers" + `; + + const conditions: string[] = [`"fundeeDripListId" IN (:fundeeDripListIds)`]; + const parameters: { [key: string]: any } = { + fundeeDripListIds, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + // Combine all schema queries with UNION. + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListSplitReceiverModel, + }) + ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); +} + +async function getDripListSplitReceiversByFunderProjectIds( + chains: SupportedChain[], + funderProjectIds: ProjectId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."DripListSplitReceivers" + `; + + const conditions: string[] = [ + `"funderProjectId" IN (:funderProjectIds)`, + `type = '${DependencyType.ProjectDependency}'`, + ]; + const parameters: { [key: string]: any } = { + funderProjectIds, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListSplitReceiverModel, + }) + ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); +} + +async function getDripListSplitReceiversByFunderDripListIds( + chains: SupportedChain[], + funderDripListIds: DripListId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."DripListSplitReceivers" + `; + + const conditions: string[] = [ + `"funderDripListId" IN (:funderDripListIds)`, + `type = '${DependencyType.DripListDependency}'`, + ]; + const parameters: { [key: string]: any } = { + funderDripListIds, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: DripListSplitReceiverModel, + }) + ).map((p) => p.dataValues as DripListSplitReceiverModelDataValues); +} + +export default { + getByFundeeDripListIds: getDripListSplitReceiversByFundeeDripListIds, + getByFunderProjectIds: getDripListSplitReceiversByFunderProjectIds, + getByFunderDripListIds: getDripListSplitReceiversByFunderDripListIds, +}; diff --git a/src/dataLoaders/sqlQueries/dripListsQueries.ts b/src/dataLoaders/sqlQueries/dripListsQueries.ts index 57ef65a..536a392 100644 --- a/src/dataLoaders/sqlQueries/dripListsQueries.ts +++ b/src/dataLoaders/sqlQueries/dripListsQueries.ts @@ -10,15 +10,14 @@ import type { async function getDripListsByFilter( chains: SupportedChain[], - where: DripListWhereInput, + where?: DripListWhereInput, ) { - // Define base SQL to query from multiple chains (schemas). const baseSQL = (schema: SupportedChain) => ` SELECT "id", "isValid", "name", "creator", "description", "ownerAddress", "ownerAccountId", "latestVotingRoundId", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."DripLists" `; - const conditions: string[] = []; + const conditions: string[] = ['isValid = true', 'name IS NOT NULL']; const parameters: { [key: string]: any } = {}; if (where?.id) { @@ -30,8 +29,7 @@ async function getDripListsByFilter( parameters.ownerAddress = where.ownerAddress; } - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); diff --git a/src/dataLoaders/sqlQueries/projectsQueries.ts b/src/dataLoaders/sqlQueries/projectsQueries.ts index 174ea1f..ef1f27a 100644 --- a/src/dataLoaders/sqlQueries/projectsQueries.ts +++ b/src/dataLoaders/sqlQueries/projectsQueries.ts @@ -7,7 +7,6 @@ import type { } from '../../generated/graphql'; import type { ProjectDataValues } from '../../project/ProjectModel'; import ProjectModel from '../../project/ProjectModel'; -import { isValidProjectName } from '../../project/projectUtils'; import type { ProjectId } from '../../common/types'; async function getProjectByUrl( @@ -19,11 +18,10 @@ async function getProjectByUrl( FROM "${schema}"."GitProjects" `; - const conditions: string[] = ['"url" = :url']; + const conditions: string[] = ['"url" = :url', '"isValid" = true']; const parameters: { [key: string]: any } = { url }; - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; const query = `${baseSQL(chain) + whereClause} LIMIT 1`; @@ -51,7 +49,7 @@ async function getProjectsByIds( const parameters: { [key: string]: any } = { projectIds }; - const whereClause = ` WHERE "id" IN (:projectIds)`; + const whereClause = ` WHERE "id" IN (:projectIds) AND "isValid" = true`; const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); @@ -64,10 +62,7 @@ async function getProjectsByIds( mapToModel: true, model: ProjectModel, }) - ) - .map((p) => p.dataValues as ProjectDataValues) - .filter((p) => p.isValid) - .filter((p) => (p.name ? isValidProjectName(p.name) : true)); + ).map((p) => p.dataValues as ProjectDataValues); } async function getProjectsByFilter( @@ -80,7 +75,7 @@ async function getProjectsByFilter( "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."GitProjects" `; - const conditions: string[] = []; + const conditions: string[] = ['"isValid" = true']; const parameters: { [key: string]: any } = {}; if (where?.id) { @@ -100,18 +95,17 @@ async function getProjectsByFilter( parameters.verificationStatus = where.verificationStatus; } - const whereClause = - conditions.length > 0 ? ` WHERE ${conditions.join(' AND ')}` : ''; + const whereClause = ` WHERE ${conditions.join(' AND ')}`; const orderClause = sort ? ` ORDER BY "${sort.field}" ${sort.direction || 'DESC'}` : ''; - const chainQueries = chains.map( + const queries = chains.map( (chain) => baseSQL(chain) + whereClause + orderClause, ); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${queries.join(' UNION ')} LIMIT 1000`; return ( await dbConnection.query(multiChainQuery, { diff --git a/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts new file mode 100644 index 0000000..b832150 --- /dev/null +++ b/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts @@ -0,0 +1,110 @@ +import { QueryTypes } from 'sequelize'; +import { DependencyType } from '../../common/types'; +import type { DripListId, ProjectId } from '../../common/types'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { SupportedChain } from '../../generated/graphql'; +import type { RepoDriverSplitReceiverModelDataValues } from '../../models/RepoDriverSplitReceiverModel'; +import RepoDriverSplitReceiverModel from '../../models/RepoDriverSplitReceiverModel'; + +async function getRepoDriverSplitReceiversByFundeeProjectIds( + chains: SupportedChain[], + fundeeProjectIds: ProjectId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."RepoDriverSplitReceivers" +`; + + const conditions: string[] = [`"fundeeProjectId" IN (:fundeeProjectIds)`]; + const parameters: { [key: string]: any } = { + fundeeProjectIds, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: RepoDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); +} + +async function getRepoDriverSplitReceiversByFunderProjectIds( + chains: SupportedChain[], + funderProjectIds: ProjectId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."RepoDriverSplitReceivers" + `; + + // Build the WHERE clause. + const conditions: string[] = [ + `"funderProjectId" IN (:funderProjectIds)`, + `type = '${DependencyType.ProjectDependency}'`, + ]; + const parameters: { [key: string]: any } = { + funderProjectIds, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: RepoDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); +} + +async function getRepoDriverSplitReceiversByFunderDripListIds( + chains: SupportedChain[], + funderDripListIds: DripListId[], +) { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain + FROM "${schema}"."RepoDriverSplitReceivers" + `; + + const conditions: string[] = [ + `"funderDripListId" IN (:funderDripListIds)`, + `type = '${DependencyType.DripListDependency}'`, + ]; + const parameters: { [key: string]: any } = { + funderDripListIds, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: RepoDriverSplitReceiverModel, + }) + ).map((p) => p.dataValues as RepoDriverSplitReceiverModelDataValues); +} + +export default { + getByFundeeProjectIds: getRepoDriverSplitReceiversByFundeeProjectIds, + getByFunderProjectIds: getRepoDriverSplitReceiversByFunderProjectIds, + getByFunderDripListIds: getRepoDriverSplitReceiversByFunderDripListIds, +}; diff --git a/src/dataLoaders/sqlQueries/splitEventsQueries.ts b/src/dataLoaders/sqlQueries/splitEventsQueries.ts index 086108f..c505202 100644 --- a/src/dataLoaders/sqlQueries/splitEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/splitEventsQueries.ts @@ -38,6 +38,64 @@ async function getSplitEventsByAccountIdAndReceiver( ).map((p) => p.dataValues as SplitEventModelDataValues); } +async function getSplitEventsByReceiver( + chains: SupportedChain[], + receiver: AccountId, +): Promise { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."SplitEvents"`; + + const conditions: string[] = ['"receiver" = :receiver']; + const parameters: { [receiver: string]: any } = { receiver }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: SplitEventModel, + }) + ).map((p) => p.dataValues as SplitEventModelDataValues); +} + +async function getSplitEventsByProjectReceivers( + chains: SupportedChain[], + accountIds: AccountId[], +): Promise { + const baseSplitEventsSQL = (schema: SupportedChain) => + `SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; + + const conditions: string[] = [`"receiver" IN (:receivers)`]; + const parameters: { [key: string]: any } = { + receivers: accountIds, + }; + + const whereClause = ` WHERE ${conditions.join(' AND ')}`; + + const splitsQueries = chains.map( + (chain) => baseSplitEventsSQL(chain) + whereClause, + ); + + const fullSplitsQuery = `${splitsQueries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullSplitsQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: SplitEventModel, + }) + ).map((p) => p.dataValues as SplitEventModelDataValues); +} + export default { getByAccountIdAndReceiver: getSplitEventsByAccountIdAndReceiver, + getByReceiver: getSplitEventsByReceiver, + getByProjectReceivers: getSplitEventsByProjectReceivers, }; diff --git a/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts b/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts new file mode 100644 index 0000000..e53ea4b --- /dev/null +++ b/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts @@ -0,0 +1,31 @@ +import { QueryTypes } from 'sequelize'; +import type { AccountId } from '../../common/types'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { SupportedChain } from '../../generated/graphql'; +import type { StreamReceiverSeenEventModelDataValues } from '../../models/StreamReceiverSeenEventModel'; +import StreamReceiverSeenEventModel from '../../models/StreamReceiverSeenEventModel'; + +async function getStreamReceiverSeenEventsByAccountId( + chains: SupportedChain[], + accountId: AccountId, +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamReceiverSeenEvents" WHERE "accountId" = :accountId`; + + const fullQuery = `${chains + .map((chain) => `${baseSQL(chain)}`) + .join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: { accountId }, + mapToModel: true, + model: StreamReceiverSeenEventModel, + }) + ).map((p) => p.dataValues as StreamReceiverSeenEventModelDataValues); +} + +export default { + getByAccountId: getStreamReceiverSeenEventsByAccountId, +}; diff --git a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts new file mode 100644 index 0000000..68b43d0 --- /dev/null +++ b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts @@ -0,0 +1,70 @@ +import { QueryTypes } from 'sequelize'; +import type { AccountId } from '../../common/types'; +import { dbConnection } from '../../database/connectToDatabase'; +import type { SupportedChain } from '../../generated/graphql'; +import type { StreamsSetEventModelDataValues } from '../../models/StreamsSetEventModel'; +import StreamsSetEventModel from '../../models/StreamsSetEventModel'; + +async function getSortedStreamsSetEventsByAccountId( + chains: SupportedChain[], + accountId: AccountId, +) { + const baseStreamsSetEventsSQL = (schema: SupportedChain) => ` + SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; + + const streamsSetEventModelConditions: string[] = ['"accountId" = :accountId']; + const streamsSetEventModelParameters: { [key: string]: any } = { accountId }; + + const whereClause = ` WHERE ${streamsSetEventModelConditions.join(' AND ')}`; + + const orderClause = ' ORDER BY "blockNumber" ASC, "logIndex" ASC'; + + const streamsSetEventModelDataValuesQueries = chains.map( + (chain) => `${baseStreamsSetEventsSQL(chain) + whereClause + orderClause}`, + ); + + const fullQueryStreamsSetEventModelQuery = `${streamsSetEventModelDataValuesQueries.join( + ' UNION ', + )} LIMIT 1000`; + + return ( + await dbConnection.query(fullQueryStreamsSetEventModelQuery, { + type: QueryTypes.SELECT, + replacements: streamsSetEventModelParameters, + mapToModel: true, + model: StreamsSetEventModel, + }) + ).map((p) => p.dataValues as StreamsSetEventModelDataValues); +} + +async function getSortedStreamsSetEventsByReceiversHashes( + chains: SupportedChain[], + receiversHashes: string[], +) { + const baseSQL = (schema: SupportedChain) => + `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; + + const whereClause = receiversHashes.length + ? ` WHERE "receiversHash" IN (:receiversHashes)` + : ''; + + const queries = chains.map((chain) => baseSQL(chain) + whereClause); + + const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + + return ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: { + receiversHashes, + }, + mapToModel: true, + model: StreamsSetEventModel, + }) + ).map((p) => p.dataValues as StreamsSetEventModelDataValues); +} + +export default { + getByAccountIdSorted: getSortedStreamsSetEventsByAccountId, + getByReceiversHashes: getSortedStreamsSetEventsByReceiversHashes, +}; diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index a45aaae..680abb6 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -22,7 +22,7 @@ import type { Context } from '../server'; import assert, { isDripListId } from '../utils/assert'; import type { ProjectDataValues } from '../project/ProjectModel'; import queryableChains from '../common/queryableChains'; -import toResolverDripLists from './dripListUtils'; +import { toResolverDripList, toResolverDripLists } from './dripListUtils'; import verifyDripListsInput from './dripListValidators'; import type { DripListDataValues } from './DripListModel'; import { resolveTotalEarned } from '../common/commonResolverLogic'; @@ -30,53 +30,45 @@ import { resolveTotalEarned } from '../common/commonResolverLogic'; const dripListResolvers = { Query: { dripLists: async ( - _: any, + _: undefined, { chains, where, - }: { chains: SupportedChain[]; where: DripListWhereInput }, - { dataSources }: Context, + }: { chains?: SupportedChain[]; where?: DripListWhereInput }, + { dataSources: { dripListsDataSource } }: Context, ): Promise => { verifyDripListsInput({ chains, where }); const chainsToQuery = chains?.length ? chains : queryableChains; - const dripListDataValues = - await dataSources.dripListsDb.getDripListsByFilter( - chainsToQuery, - where, - ); + const dbDripLists = await dripListsDataSource.getDripListsByFilter( + chainsToQuery, + where, + ); - return toResolverDripLists(chainsToQuery, dripListDataValues); + return toResolverDripLists(chainsToQuery, dbDripLists); }, dripList: async ( - _: any, + _: undefined, { id, chain }: { id: DripListId; chain: SupportedChain }, - { dataSources }: Context, + { dataSources: { dripListsDataSource } }: Context, ): Promise => { assert(isDripListId(id)); assert(chain in SupportedChain); - const dripListDataValues = await dataSources.dripListsDb.getDripListById( - [chain], - id, - ); + const dbDripList = await dripListsDataSource.getDripListById([chain], id); - if (!dripListDataValues) { - return null; - } - - return (await toResolverDripLists([chain], [dripListDataValues]))[0]; + return dbDripList ? toResolverDripList(chain, dbDripList) : null; }, mintedTokensCountByOwnerAddress: async ( - _: any, + _: undefined, { ownerAddress, chain }: { ownerAddress: Address; chain: SupportedChain }, - { dataSources }: Context, + { dataSources: { dripListsDataSource } }: Context, ): Promise<{ chain: SupportedChain; total: number }> => { assert(isAddress(ownerAddress)); assert(chain in SupportedChain); - return dataSources.dripListsDb.getMintedTokensCountByAccountId( + return dripListsDataSource.getMintedTokensCountByAccountId( chain, ownerAddress, ); @@ -104,26 +96,22 @@ const dripListResolvers = { owner: (dripListData: ResolverDripListData): AddressDriverAccount => dripListData.owner, splits: async ( - dripListData: ResolverDripListData, - _: any, - context: Context, - ): Promise => { - const { + { + parentDripListInfo: { dripListId, dripListChain }, + }: ResolverDripListData, + _: {}, + { dataSources: { - projectsDb, - dripListsDb, - receiversOfTypeAddressDb, - receiversOfTypeProjectDb, - receiversOfTypeDripListDb, + projectsDataSource, + dripListsDataSource, + receiversOfTypeAddressDataSource, + receiversOfTypeProjectDataSource, + receiversOfTypeDripListDataSource, }, - } = context; - - const { - parentDripListInfo: { dripListId, dripListChain }, - } = dripListData; - + }: Context, + ): Promise => { const receiversOfTypeAddressModels = - await receiversOfTypeAddressDb.getReceiversOfTypeAddressByDripListId( + await receiversOfTypeAddressDataSource.getReceiversOfTypeAddressByDripListId( dripListId, [dripListChain], ); @@ -140,15 +128,16 @@ const dripListResolvers = { })) as AddressReceiver[]; const receiversOfTypeProjectModels = - await receiversOfTypeProjectDb.getReceiversOfTypeProjectByDripListId( + await receiversOfTypeProjectDataSource.getReceiversOfTypeProjectByDripListId( dripListId, [dripListChain], ); - const splitsOfTypeProjectModels = await projectsDb.getProjectsByIds( - receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), - [dripListChain], - ); + const splitsOfTypeProjectModels = + await projectsDataSource.getProjectsByIds( + receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), + [dripListChain], + ); const projectReceivers = receiversOfTypeProjectModels.map((receiver) => ({ driver: Driver.REPO, @@ -169,15 +158,16 @@ const dripListResolvers = { })); const receiversOfTypeDripListModels = - await receiversOfTypeDripListDb.getReceiversOfTypeDripListByDripListId( + await receiversOfTypeDripListDataSource.getReceiversOfTypeDripListByDripListId( dripListId, [dripListChain], ); - const splitsOfTypeDripListModels = await dripListsDb.getDripListsByIds( - receiversOfTypeDripListModels.map((r) => r.fundeeDripListId), - [dripListChain], - ); + const splitsOfTypeDripListModels = + await dripListsDataSource.getDripListsByIds( + receiversOfTypeDripListModels.map((r) => r.fundeeDripListId), + [dripListChain], + ); const dripListReceivers = receiversOfTypeDripListModels.map( (receiver) => ({ @@ -202,32 +192,26 @@ const dripListResolvers = { return [...addressSplits, ...projectReceivers, ...dripListReceivers]; }, support: async ( - dripListData: ResolverDripListData, - _: any, - context: Context, - ) => { - const { + { parentDripListInfo: { dripListId, dripListChain }, - } = dripListData; - - const { - dataSources: { projectAndDripListSupportDb }, - } = context; - + }: ResolverDripListData, + _: {}, + { dataSources: { projectAndDripListSupportDataSource } }: Context, + ) => { const projectAndDripListSupport = - await projectAndDripListSupportDb.getProjectAndDripListSupportByDripListId( + await projectAndDripListSupportDataSource.getProjectAndDripListSupportByDripListId( dripListId, [dripListChain], ); const oneTimeDonationSupport = - await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( + await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountId( [dripListChain], dripListId, ); const streamSupport = - await projectAndDripListSupportDb.getStreamSupportByAccountId( + await projectAndDripListSupportDataSource.getStreamSupportByAccountId( [dripListChain], dripListId, ); @@ -240,9 +224,9 @@ const dripListResolvers = { }, totalEarned: async ( dripListData: ResolverDripListData, - _: any, + _: {}, context: Context, - ) => resolveTotalEarned(dripListData, _, context), + ) => resolveTotalEarned(dripListData, context), }, }; diff --git a/src/drip-list/dripListUtils.ts b/src/drip-list/dripListUtils.ts index d5c638d..c52a00e 100644 --- a/src/drip-list/dripListUtils.ts +++ b/src/drip-list/dripListUtils.ts @@ -5,7 +5,14 @@ import type { import { Driver, type SupportedChain } from '../generated/graphql'; import type { DripListDataValues } from './DripListModel'; -export default async function toResolverDripLists( +export async function toResolverDripList( + chain: SupportedChain, + dripList: DripListDataValues, +): Promise { + return (await toResolverDripLists([chain], [dripList]))[0]; +} + +export async function toResolverDripLists( chains: SupportedChain[], dripLists: DripListDataValues[], ): Promise { diff --git a/src/drip-list/dripListValidators.ts b/src/drip-list/dripListValidators.ts index 2be3e50..0e2a950 100644 --- a/src/drip-list/dripListValidators.ts +++ b/src/drip-list/dripListValidators.ts @@ -1,24 +1,22 @@ import { isAddress } from 'ethers'; -import { SupportedChain } from '../generated/graphql'; -import type { DripListWhereInput } from '../generated/graphql'; -import assert, { isDripListId } from '../utils/assert'; +import { isDripListId } from '../utils/assert'; +import type dripListResolvers from './dripListResolvers'; +import { validateChainsQueryArg } from '../utils/commonInputValidators'; -export default function verifyDripListsInput(input: { - chains: SupportedChain[]; - where: DripListWhereInput; -}) { - const { where, chains } = input; +export default function verifyDripListsInput( + dripsListsQueryArgs: Parameters[1], +) { + const { where, chains } = dripsListsQueryArgs; - if (where?.id) { - assert(isDripListId(where.id)); + if (where?.id && !isDripListId(where.id)) { + throw new Error('Invalid drip list id.'); } - if (where?.ownerAddress) { - assert(isAddress(where.ownerAddress)); + + if (where?.ownerAddress && !isAddress(where.ownerAddress)) { + throw new Error('Invalid owner address.'); } - if (chains) { - chains.forEach((chain) => { - assert(chain in SupportedChain); - }); + if (chains?.length) { + validateChainsQueryArg(chains); } } diff --git a/src/given-event/givenEventResolvers.ts b/src/given-event/givenEventResolvers.ts index d139967..da65ef9 100644 --- a/src/given-event/givenEventResolvers.ts +++ b/src/given-event/givenEventResolvers.ts @@ -34,7 +34,7 @@ const givenEventResolvers = { const chainsToQuery = chains?.length ? chains : queryableChains; - return dataSources.givenEventsDb.getGivenEventsByFilter( + return dataSources.givenEventsDataSource.getGivenEventsByFilter( chainsToQuery, where, ); diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index f350827..c3ced64 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -32,28 +32,26 @@ import validateProjectsInput from './projectValidators'; import type { DripListDataValues } from '../drip-list/DripListModel'; import assert, { isGitHubUrl, isProjectId } from '../utils/assert'; import { resolveTotalEarned } from '../common/commonResolverLogic'; -import { validateChainsInput } from '../utils/inputValidators'; +import { validateChainsQueryArg } from '../utils/commonInputValidators'; const projectResolvers = { Query: { projects: async ( - _: any, - { - chains, - where, - sort, - }: { - chains: SupportedChain[]; - where: ProjectWhereInput; - sort: ProjectSortInput; + _: undefined, + args: { + chains?: SupportedChain[]; + where?: ProjectWhereInput; + sort?: ProjectSortInput; }, - { dataSources: { projectsDb } }: Context, + { dataSources: { projectsDataSource } }: Context, ): Promise => { - validateProjectsInput({ chains, where, sort }); + validateProjectsInput(args); + + const { chains, where, sort } = args; const chainsToQuery = chains?.length ? chains : queryableChains; - const dbProjects = await projectsDb.getProjectsByFilter( + const dbProjects = await projectsDataSource.getProjectsByFilter( chainsToQuery, where, sort, @@ -62,53 +60,58 @@ const projectResolvers = { return toResolverProjects(chainsToQuery, dbProjects); }, projectById: async ( - _: any, + _: undefined, { id, chain }: { id: ProjectId; chain: SupportedChain }, - { dataSources: { projectsDb } }: Context, + { dataSources: { projectsDataSource } }: Context, ): Promise => { assert(isProjectId(id)); assert(chain in SupportedChain); - const dbProjects = await projectsDb.getProjectById(id, chain); + const dbProject = await projectsDataSource.getProjectById(id, chain); - if (!dbProjects) { - return null; - } - - return toResolverProject(chain, dbProjects); + return dbProject ? toResolverProject(chain, dbProject) : null; }, projectByUrl: async ( - _: any, + _: undefined, { url, chain }: { url: string; chain: SupportedChain }, - { dataSources: { projectsDb } }: Context, + { dataSources: { projectsDataSource } }: Context, ): Promise => { assert(isGitHubUrl(url)); assert(chain in SupportedChain); - const dbProjects = await projectsDb.getProjectByUrl(url, chain); - - if (!dbProjects) { - return null; - } + const dbProject = await projectsDataSource.getProjectByUrl(url, chain); - return toResolverProject(chain, dbProjects); + return dbProject ? toResolverProject(chain, dbProject) : null; }, earnedFunds: async ( - _: any, - { projectId, chains }: { projectId: ProjectId; chains: SupportedChain[] }, - { dataSources: { projectsDb } }: Context, - ) => { + _: undefined, + { + projectId, + chains, + }: { projectId: ProjectId; chains?: SupportedChain[] }, + { dataSources: { projectsDataSource } }: Context, + ): Promise< + { + tokenAddress: string; + amount: string; + chain: SupportedChain; + }[] + > => { assert(isProjectId(projectId)); - validateChainsInput(chains); + if (chains?.length) { + validateChainsQueryArg(chains); + } const chainsToQuery = chains?.length ? chains : queryableChains; - return projectsDb.getEarnedFunds(projectId, chainsToQuery); + return projectsDataSource.getEarnedFunds(projectId, chainsToQuery); }, }, Project: { source: (project: ResolverProject): Source => project.source, account: (project: ResolverProject): RepoDriverAccount => project.account, + chainData: (project: ResolverProject): ProjectChainData[] => + project.chainData, }, ProjectChainData: { __resolveType(parent: ProjectChainData) { @@ -147,26 +150,22 @@ const projectResolvers = { owner: (projectData: ResolverClaimedProjectData): AddressDriverAccount => projectData.owner, splits: async ( - projectData: ResolverClaimedProjectData, - _: any, - context: Context, - ): Promise => { - const { + { + parentProjectInfo: { projectId, projectChain }, + }: ResolverClaimedProjectData, + _: {}, + { dataSources: { - projectsDb, - dripListsDb, - receiversOfTypeAddressDb, - receiversOfTypeProjectDb, - receiversOfTypeDripListDb, + projectsDataSource, + dripListsDataSource, + receiversOfTypeAddressDataSource, + receiversOfTypeProjectDataSource, + receiversOfTypeDripListDataSource, }, - } = context; - - const { - parentProjectInfo: { projectId, projectChain }, - } = projectData; - + }: Context, + ): Promise => { const receiversOfTypeAddressModels = - await receiversOfTypeAddressDb.getReceiversOfTypeAddressByProjectId( + await receiversOfTypeAddressDataSource.getReceiversOfTypeAddressByProjectId( projectId, [projectChain], ); @@ -196,15 +195,16 @@ const projectResolvers = { ) as AddressReceiver[]) || []; const receiversOfTypeProjectModels = - await receiversOfTypeProjectDb.getReceiversOfTypeProjectByProjectId( + await receiversOfTypeProjectDataSource.getReceiversOfTypeProjectByProjectId( projectId, [projectChain], ); - const splitsOfTypeProjectModels = await projectsDb.getProjectsByIds( - receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), - [projectChain], - ); + const splitsOfTypeProjectModels = + await projectsDataSource.getProjectsByIds( + receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), + [projectChain], + ); const dependenciesOfTypeProject = receiversOfTypeProjectModels.map( (receiver) => ({ @@ -227,15 +227,16 @@ const projectResolvers = { ); const receiversOfTypeDripListModels = - await receiversOfTypeDripListDb.getReceiversOfTypeDripListByProjectId( + await receiversOfTypeDripListDataSource.getReceiversOfTypeDripListByProjectId( projectId, [projectChain], ); - const splitsOfTypeDripListModels = await dripListsDb.getDripListsByIds( - receiversOfTypeDripListModels.map((r) => r.fundeeDripListId), - [projectChain], - ); + const splitsOfTypeDripListModels = + await dripListsDataSource.getDripListsByIds( + receiversOfTypeDripListModels.map((r) => r.fundeeDripListId), + [projectChain], + ); const dripListReceivers = receiversOfTypeDripListModels.map( (receiver) => ({ @@ -267,26 +268,20 @@ const projectResolvers = { }; }, support: async ( - projectData: ResolverClaimedProjectData, - _: any, - context: Context, - ) => { - const { + { parentProjectInfo: { projectId, projectChain }, - } = projectData; - - const { - dataSources: { projectAndDripListSupportDb }, - } = context; - + }: ResolverClaimedProjectData, + _: {}, + { dataSources: { projectAndDripListSupportDataSource } }: Context, + ) => { const projectAndDripListSupport = - await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( + await projectAndDripListSupportDataSource.getProjectAndDripListSupportByProjectId( projectId, [projectChain], ); const oneTimeDonationSupport = - await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( + await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountId( [projectChain], projectId, ); @@ -295,32 +290,28 @@ const projectResolvers = { }, totalEarned: async ( projectData: ResolverUnClaimedProjectData, - _: any, + _: {}, context: Context, - ) => resolveTotalEarned(projectData, _, context), + ) => resolveTotalEarned(projectData, context), }, UnClaimedProjectData: { verificationStatus: (projectData: ResolverUnClaimedProjectData) => projectData.verificationStatus, support: async ( - projectData: ResolverUnClaimedProjectData, - _: any, - context: Context, - ) => { - const { projectAndDripListSupportDb } = context.dataSources; - - const { + { parentProjectInfo: { projectId, projectChain }, - } = projectData; - + }: ResolverUnClaimedProjectData, + _: {}, + { dataSources: { projectAndDripListSupportDataSource } }: Context, + ) => { const projectAndDripListSupport = - await projectAndDripListSupportDb.getProjectAndDripListSupportByProjectId( + await projectAndDripListSupportDataSource.getProjectAndDripListSupportByProjectId( projectId, [projectChain], ); const oneTimeDonationSupport = - await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( + await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountId( [projectChain], projectId, ); @@ -329,9 +320,9 @@ const projectResolvers = { }, totalEarned: async ( projectData: ResolverUnClaimedProjectData, - _: any, + _: {}, context: Context, - ) => resolveTotalEarned(projectData, _, context), + ) => resolveTotalEarned(projectData, context), }, SplitsReceiver: { __resolveType(receiver: SplitsReceiver) { @@ -343,10 +334,6 @@ const projectResolvers = { return 'DripListReceiver'; } - if (receiver.driver === Driver.ADDRESS) { - return 'AddressReceiver'; - } - return shouldNeverHappen(); }, }, diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 8d469c3..3c8be6b 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -30,28 +30,6 @@ export function splitProjectName(projectName: string): { return { ownerName: components[0], repoName: components[1] }; } -export function isValidProjectName(name: string): boolean { - const components = name.split('/'); - - if (components.length !== 2) { - return false; - } - - const ownerName = components[0]; - const repoName = components[1]; - - const validProjectNameRegex: RegExp = /^[\w.-]+$/; - - if ( - !validProjectNameRegex.test(ownerName) || - !validProjectNameRegex.test(repoName) - ) { - return false; - } - - return true; -} - export async function doesRepoExists(url: string) { if (appSettings.pretendAllReposExist) return true; diff --git a/src/project/projectValidators.ts b/src/project/projectValidators.ts index a202ffd..1cf2369 100644 --- a/src/project/projectValidators.ts +++ b/src/project/projectValidators.ts @@ -1,48 +1,50 @@ import { isAddress } from 'ethers'; -import type { - SupportedChain, - ProjectSortInput, - ProjectWhereInput, -} from '../generated/graphql'; -import assert, { +import { SortDirection } from '../generated/graphql'; +import { isGitHubUrl, isProjectId, isProjectVerificationStatus, } from '../utils/assert'; -import { validateChainsInput } from '../utils/inputValidators'; +import { validateChainsQueryArg } from '../utils/commonInputValidators'; +import type projectResolvers from './projectResolvers'; function isSortableProjectField(field: string): boolean { return ['claimedAt'].includes(field); } -export default function validateProjectsInput(input: { - chains?: SupportedChain[]; - where?: ProjectWhereInput; - sort?: ProjectSortInput; -}) { - const { where, sort, chains } = input; +export default function validateProjectsInput( + projectsQueryArgs: Parameters[1], +) { + const { where, sort, chains } = projectsQueryArgs; - if (where?.id) { - assert(isProjectId(where.id)); + if (where?.id && !isProjectId(where.id)) { + throw new Error('Invalid project id.'); } - if (where?.ownerAddress) { - assert(isAddress(where.ownerAddress)); + if (where?.ownerAddress && !isAddress(where.ownerAddress)) { + throw new Error('Invalid owner address.'); } - if (where?.url) { - assert(isGitHubUrl(where.url)); + if (where?.url && !isGitHubUrl(where.url)) { + throw new Error('Invalid GitHub URL.'); } - if (where?.verificationStatus) { - assert(isProjectVerificationStatus(where.verificationStatus)); + if ( + where?.verificationStatus && + !isProjectVerificationStatus(where.verificationStatus) + ) { + throw new Error('Invalid verification status.'); } - if (sort?.field) { - assert(isSortableProjectField(sort.field)); + if (sort?.field && !isSortableProjectField(sort.field)) { + throw new Error('Invalid sort field.'); + } + + if (sort?.direction && sort.direction in SortDirection) { + throw new Error('Invalid sort direction.'); } if (chains?.length) { - validateChainsInput(chains); + validateChainsQueryArg(chains); } } diff --git a/src/schema.ts b/src/schema.ts index c8d348c..c44e211 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -15,6 +15,7 @@ const rootTypeDef = gql` ): [Project!]! projectById(id: ID!, chain: SupportedChain!): Project projectByUrl(url: String!, chain: SupportedChain!): Project + earnedFunds(projectId: String!, chains: [SupportedChain!]): [ChainAmount!]! dripLists( chains: [SupportedChain!] where: DripListWhereInput @@ -24,7 +25,6 @@ const rootTypeDef = gql` ownerAddress: String! chain: SupportedChain! ): MintedTokens! - earnedFunds(projectId: String!, chains: [SupportedChain!]): [ChainAmount!]! userById(accountId: ID!, chains: [SupportedChain!]): User! userByAddress(address: String!, chains: [SupportedChain!]): User! } diff --git a/src/server.ts b/src/server.ts index dd032f0..65b1600 100644 --- a/src/server.ts +++ b/src/server.ts @@ -34,17 +34,16 @@ import TotalEarnedDataSource from './dataLoaders/TotalEarnedDataSource'; export interface Context { dataSources: { - projectsDb: ProjectsDataSource; - givenEventsDb: GivenEventsDataSource; - dripListsDb: DripListsDataSource; - receiversOfTypeAddressDb: ReceiversOfTypeAddressDataSource; - receiversOfTypeProjectDb: ReceiversOfTypeProjectDataSource; - receiversOfTypeDripListDb: ReceiversOfTypeDripListDataSource; - projectAndDripListSupportDb: ProjectAndDripListSupportDataSource; - givesDb: GivenEventsDataSource; - usersDb: UsersDataSource; - streamsDb: StreamsDataSource; - totalEarnedDb: TotalEarnedDataSource; + projectsDataSource: ProjectsDataSource; + givenEventsDataSource: GivenEventsDataSource; + dripListsDataSource: DripListsDataSource; + receiversOfTypeAddressDataSource: ReceiversOfTypeAddressDataSource; + receiversOfTypeProjectDataSource: ReceiversOfTypeProjectDataSource; + receiversOfTypeDripListDataSource: ReceiversOfTypeDripListDataSource; + projectAndDripListSupportDataSource: ProjectAndDripListSupportDataSource; + usersDataSource: UsersDataSource; + streamsDataSource: StreamsDataSource; + totalEarnedDataSource: TotalEarnedDataSource; }; } @@ -139,18 +138,21 @@ const startServer = async () => { return { dataSources: { - projectsDb: new ProjectsDataSource(), - givenEventsDb: new GivenEventsDataSource(), - dripListsDb: new DripListsDataSource(), - receiversOfTypeAddressDb: new ReceiversOfTypeAddressDataSource(), - receiversOfTypeProjectDb: new ReceiversOfTypeProjectDataSource(), - receiversOfTypeDripListDb: new ReceiversOfTypeDripListDataSource(), - projectAndDripListSupportDb: + projectsDataSource: new ProjectsDataSource(), + givenEventsDataSource: new GivenEventsDataSource(), + dripListsDataSource: new DripListsDataSource(), + receiversOfTypeAddressDataSource: + new ReceiversOfTypeAddressDataSource(), + receiversOfTypeProjectDataSource: + new ReceiversOfTypeProjectDataSource(), + receiversOfTypeDripListDataSource: + new ReceiversOfTypeDripListDataSource(), + projectAndDripListSupportDataSource: new ProjectAndDripListSupportDataSource(), givesDb: new GivenEventsDataSource(), - usersDb: new UsersDataSource(), - streamsDb: new StreamsDataSource(), - totalEarnedDb: new TotalEarnedDataSource(), + usersDataSource: new UsersDataSource(), + streamsDataSource: new StreamsDataSource(), + totalEarnedDataSource: new TotalEarnedDataSource(), }, }; }, diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index 67b4ebf..2874e2b 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -12,14 +12,14 @@ const streamResolvers = { { dataSources }: Context, ) => { if (receiver.driver === Driver.ADDRESS) { - return dataSources.usersDb.getUserByAccountId( + return dataSources.usersDataSource.getUserByAccountId( [chain], receiver.accountId as AddressDriverId, ); } if (receiver.driver === Driver.NFT) { - return dataSources.dripListsDb.getDripListById( + return dataSources.dripListsDataSource.getDripListById( [chain], receiver.accountId as DripListId, ); @@ -33,14 +33,14 @@ const streamResolvers = { { dataSources }: Context, ) => { if (sender.driver === Driver.ADDRESS) { - return dataSources.usersDb.getUserByAccountId( + return dataSources.usersDataSource.getUserByAccountId( [chain], sender.accountId as AddressDriverId, ); } if (sender.driver === Driver.NFT) { - return dataSources.dripListsDb.getDripListById( + return dataSources.dripListsDataSource.getDripListById( [chain], sender.accountId as DripListId, ); diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index 7912ea2..92e2df5 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -1,3 +1,4 @@ +import { isAddress } from 'ethers'; import { assetOutgoingBalanceTimeline } from '../balances/estimate-reloaded'; import type { AccountId, @@ -8,51 +9,55 @@ import type { ResolverUserData, } from '../common/types'; import DripListModel from '../drip-list/DripListModel'; -import { SupportedChain } from '../generated/graphql'; -import type { AddressDriverAccount, User } from '../generated/graphql'; +import type { + SupportedChain, + AddressDriverAccount, + User, +} from '../generated/graphql'; import type { Context } from '../server'; import assert, { isAddressDriverId } from '../utils/assert'; import getAssetConfigs from '../utils/getAssetConfigs'; import getUserAddress from '../utils/getUserAddress'; import queryableChains from '../common/queryableChains'; import { toResolverProjects } from '../project/projectUtils'; -import toResolverDripLists from '../drip-list/dripListUtils'; +import { toResolverDripLists } from '../drip-list/dripListUtils'; import getLatestAccountMetadataByChain from '../utils/getLatestAccountMetadata'; +import { validateChainsQueryArg } from '../utils/commonInputValidators'; const userResolvers = { Query: { userById: async ( - _: any, + _: undefined, { chains, accountId, - }: { chains: SupportedChain[]; accountId: AddressDriverId }, - { dataSources }: Context, + }: { chains?: SupportedChain[]; accountId: AddressDriverId }, + { dataSources: { usersDataSource } }: Context, ): Promise => { - if (chains) { - chains.forEach((chain) => { - assert(chain in SupportedChain); - }); + if (chains?.length) { + validateChainsQueryArg(chains); } const chainsToQuery = chains?.length ? chains : queryableChains; - return dataSources.usersDb.getUserByAccountId(chainsToQuery, accountId); + return usersDataSource.getUserByAccountId(chainsToQuery, accountId); }, userByAddress: async ( - _: any, - { chains, address }: { chains: SupportedChain[]; address: Address }, + _: undefined, + { chains, address }: { chains?: SupportedChain[]; address: Address }, { dataSources }: Context, ): Promise => { - if (chains) { - chains.forEach((chain) => { - assert(chain in SupportedChain); - }); + assert(isAddress(address)); + if (chains?.length) { + validateChainsQueryArg(chains); } const chainsToQuery = chains?.length ? chains : queryableChains; - return dataSources.usersDb.getUserByAddress(chainsToQuery, address); + return dataSources.usersDataSource.getUserByAddress( + chainsToQuery, + address, + ); }, }, User: { @@ -64,21 +69,14 @@ const userResolvers = { data: (chainUserData: ResolverUserChainData) => chainUserData.data, }, UserData: { - streams: async (userData: ResolverUserData) => { - const { parentUserInfo, streams } = userData; - - return { - incoming: streams.incoming, - outgoing: streams.outgoing, - parentUserInfo, - }; - }, - balances: async (userData: ResolverUserData) => { - const { - parentUserInfo: { accountId, userChain }, - } = userData; - assert(isAddressDriverId(accountId)); - + streams: async ({ parentUserInfo, streams }: ResolverUserData) => ({ + incoming: streams.incoming, + outgoing: streams.outgoing, + parentUserInfo, + }), + balances: async ({ + parentUserInfo: { accountId, userChain }, + }: ResolverUserData) => { const chainMetadata = await getLatestAccountMetadataByChain( [userChain], accountId as AddressDriverId, @@ -102,56 +100,54 @@ const userResolvers = { })); }, projects: async ( - userData: ResolverUserData, - _: any, - { dataSources }: Context, + { parentUserInfo: { accountId, userChain } }: ResolverUserData, + _: {}, + { dataSources: { projectsDataSource } }: Context, ) => { - const { accountId, userChain } = userData.parentUserInfo; - assert(isAddressDriverId(accountId)); - - const projectDataValues = - await dataSources.projectsDb.getProjectsByFilter([userChain], { + const projectDataValues = await projectsDataSource.getProjectsByFilter( + [userChain], + { ownerAddress: getUserAddress(accountId), - }); + }, + ); return toResolverProjects([userChain], projectDataValues); }, dripLists: async ( - userData: ResolverUserData, - _: any, - { dataSources }: Context, + { parentUserInfo: { accountId, userChain } }: ResolverUserData, + _: {}, + { dataSources: { dripListsDataSource } }: Context, ) => { - const { accountId, userChain } = userData.parentUserInfo; - assert(isAddressDriverId(accountId)); - - const dripListDataValues = - await dataSources.dripListsDb.getDripListsByFilter([userChain], { + const dripListDataValues = await dripListsDataSource.getDripListsByFilter( + [userChain], + { ownerAddress: getUserAddress(accountId), - }); + }, + ); return toResolverDripLists([userChain], dripListDataValues); }, - support: async (userData: ResolverUserData, _: any, context: Context) => { - const { - dataSources: { projectAndDripListSupportDb }, - } = context; - + support: async ( + { parentUserInfo: { accountId, userChain } }: ResolverUserData, + _: {}, + { dataSources: { projectAndDripListSupportDataSource } }: Context, + ) => { const projectAndDripListSupport = - await projectAndDripListSupportDb.getProjectAndDripListSupportByAddressDriverId( - [userData.parentUserInfo.userChain], - userData.parentUserInfo.accountId as AddressDriverId, + await projectAndDripListSupportDataSource.getProjectAndDripListSupportByAddressDriverId( + [userChain], + accountId as AddressDriverId, ); const oneTimeDonationSupport = - await projectAndDripListSupportDb.getOneTimeDonationSupportByAccountId( - [userData.parentUserInfo.userChain], - userData.parentUserInfo.accountId as AccountId, + await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountId( + [userChain], + accountId as AccountId, ); const streamSupport = - await projectAndDripListSupportDb.getStreamSupportByAccountId( - [userData.parentUserInfo.userChain], - userData.parentUserInfo.accountId as AccountId, + await projectAndDripListSupportDataSource.getStreamSupportByAccountId( + [userChain], + accountId as AccountId, ); return [ @@ -160,11 +156,9 @@ const userResolvers = { ...oneTimeDonationSupport, ]; }, - latestMetadataIpfsHash: async (userData: ResolverUserData) => { - const { - parentUserInfo: { accountId, userChain }, - } = userData; - + latestMetadataIpfsHash: async ({ + parentUserInfo: { accountId, userChain }, + }: ResolverUserData) => { const chainMetadata = await getLatestAccountMetadataByChain( [userChain], accountId as AddressDriverId, @@ -178,14 +172,14 @@ const userResolvers = { userData: { parentUserInfo: { accountId: AccountId; userChain: SupportedChain }; }, - _: any, + _: {}, { dataSources }: Context, ) => { const { accountId, userChain } = userData.parentUserInfo; assert(isAddressDriverId(accountId)); return ( - await dataSources.streamsDb.getUserOutgoingStreams( + await dataSources.streamsDataSource.getUserOutgoingStreams( [userChain], accountId, ) @@ -202,7 +196,7 @@ const userResolvers = { assert(isAddressDriverId(accountId)); return ( - await dataSources.streamsDb.getUserIncomingStreams( + await dataSources.streamsDataSource.getUserIncomingStreams( [userChain], accountId, ) diff --git a/src/utils/inputValidators.ts b/src/utils/commonInputValidators.ts similarity index 66% rename from src/utils/inputValidators.ts rename to src/utils/commonInputValidators.ts index 53635c4..9148e31 100644 --- a/src/utils/inputValidators.ts +++ b/src/utils/commonInputValidators.ts @@ -1,11 +1,12 @@ import queryableChains from '../common/queryableChains'; import { SupportedChain } from '../generated/graphql'; -import assert from './assert'; // eslint-disable-next-line import/prefer-default-export -export function validateChainsInput(chains: SupportedChain[]) { +export function validateChainsQueryArg(chains: SupportedChain[]) { chains.forEach((chain) => { - assert(chain in SupportedChain); + if (!(chain in SupportedChain)) { + throw new Error(`Chain '${chain}' is not supported.`); + } if (!queryableChains.includes(chain)) { throw new Error(`Chain '${chain}' is missing RPC URL in the .env file.`); diff --git a/src/utils/getLatestAccountMetadata.ts b/src/utils/getLatestAccountMetadata.ts index bae06c4..78e2bb7 100644 --- a/src/utils/getLatestAccountMetadata.ts +++ b/src/utils/getLatestAccountMetadata.ts @@ -1,13 +1,10 @@ import type { AnyVersion } from '@efstajas/versioned-parser'; import { ethers } from 'ethers'; -import { QueryTypes } from 'sequelize'; import { addressDriverAccountMetadataParser } from '../schemas'; import type { AddressDriverId, IpfsHash } from '../common/types'; import appSettings from '../common/appSettings'; -import type { AccountMetadataEmittedEventModelDataValues } from '../models/AccountMetadataEmittedEventModel'; -import AccountMetadataEmittedEventModel from '../models/AccountMetadataEmittedEventModel'; import type { SupportedChain } from '../generated/graphql'; -import { dbConnection } from '../database/connectToDatabase'; +import accountMetadataEmittedEventsQueries from '../dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries'; function toIpfsHash(str: string): IpfsHash { const ipfsHash = ethers.toUtf8String(str); @@ -29,36 +26,8 @@ export default async function getLatestAccountMetadataByChain( chains: SupportedChain[], accountId: AddressDriverId, ) { - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => - `SELECT *,'${schema}' AS chain FROM "${schema}"."AccountMetadataEmittedEvents"`; - - // Initialize the WHERE clause parts. - const conditions: string[] = ['"accountId" = :accountId']; - const parameters: { [key: string]: any } = { accountId }; - - // Build the where clause. - const whereClause = ` WHERE ${conditions.join(' AND ')}`; - - // Define the order. - const orderClause = ' ORDER BY "blockNumber" DESC, "logIndex" DESC'; - - // Build the SQL for each specified schema. - const queries = chains.map( - (chain) => baseSQL(chain) + whereClause + orderClause, - ); - - // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; - - const accountMetadataEmittedEventModelDataValues = ( - await dbConnection.query(fullQuery, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: AccountMetadataEmittedEventModel, - }) - ).map((p) => p.dataValues as AccountMetadataEmittedEventModelDataValues); + const accountMetadataEmittedEventModelDataValues = + await accountMetadataEmittedEventsQueries.getByAccountId(chains, accountId); const response: { [chain in SupportedChain]?: { diff --git a/src/utils/getStreamsSetEventsWithReceivers.ts b/src/utils/getStreamsSetEventsWithReceivers.ts index 122c0b4..d9b2dd0 100644 --- a/src/utils/getStreamsSetEventsWithReceivers.ts +++ b/src/utils/getStreamsSetEventsWithReceivers.ts @@ -5,46 +5,16 @@ import type { } from '../common/types'; import type { StreamReceiverSeenEventModelDataValues } from '../models/StreamReceiverSeenEventModel'; import StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; -import type { StreamsSetEventModelDataValues } from '../models/StreamsSetEventModel'; -import StreamsSetEventModel from '../models/StreamsSetEventModel'; import type { SupportedChain } from '../generated/graphql'; import { dbConnection } from '../database/connectToDatabase'; +import streamsSetEventsQueries from '../dataLoaders/sqlQueries/streamsSetEventsQueries'; export default async function getStreamsSetEventsWithReceivers( chains: SupportedChain[], accountId: AddressDriverId, ): Promise { - const baseStreamsSetEventsSQL = (schema: SupportedChain) => ` - SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; - - // Initialize the WHERE clause parts. - const streamsSetEventModelConditions: string[] = ['"accountId" = :accountId']; - const streamsSetEventModelParameters: { [key: string]: any } = { accountId }; - - // Build the where clause. - const whereClause = ` WHERE ${streamsSetEventModelConditions.join(' AND ')}`; - - // Define the order. - const orderClause = ' ORDER BY "blockNumber" ASC, "logIndex" ASC'; - - // Build the SQL for each specified schema. - const streamsSetEventModelDataValuesQueries = chains.map( - (chain) => `${baseStreamsSetEventsSQL(chain) + whereClause + orderClause}`, - ); - - // Combine all schema queries with UNION. - const fullQueryStreamsSetEventModelQuery = `${streamsSetEventModelDataValuesQueries.join( - ' UNION ', - )} LIMIT 1000`; - - const sortedAccountStreamSetEventModelDataValues = ( - await dbConnection.query(fullQueryStreamsSetEventModelQuery, { - type: QueryTypes.SELECT, - replacements: streamsSetEventModelParameters, - mapToModel: true, - model: StreamsSetEventModel, - }) - ).map((p) => p.dataValues as StreamsSetEventModelDataValues); + const sortedAccountStreamSetEventModelDataValues = + await streamsSetEventsQueries.getByAccountIdSorted(chains, accountId); const uniqueReceiversHashes = [ ...new Set( diff --git a/src/utils/streams.ts b/src/utils/streams.ts index 063e8f2..037c886 100644 --- a/src/utils/streams.ts +++ b/src/utils/streams.ts @@ -1,8 +1,3 @@ -import { QueryTypes } from 'sequelize'; -import type { StreamReceiverSeenEventModelDataValues } from '../models/StreamReceiverSeenEventModel'; -import StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; -import type { StreamsSetEventModelDataValues } from '../models/StreamsSetEventModel'; -import StreamsSetEventModel from '../models/StreamsSetEventModel'; import assert, { isAddressDriverId } from './assert'; import getUserAccount from './getUserAccount'; import type { @@ -13,55 +8,22 @@ import type { import type { AccountId } from '../common/types'; import type { ProtoStream } from './buildAssetConfigs'; -import { dbConnection } from '../database/connectToDatabase'; +import streamReceiverSeenEventQueries from '../dataLoaders/sqlQueries/streamReceiverSeenEventQueries'; +import streamsSetEventsQueries from '../dataLoaders/sqlQueries/streamsSetEventsQueries'; async function getUserIncomingStreams( chains: SupportedChain[], accountId: AccountId, ) { - const baseStreamReceiverSeenEventsSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamReceiverSeenEvents" WHERE "accountId" = :accountId`; + const streamReceiverSeenEventModelDataValuesForUser = + await streamReceiverSeenEventQueries.getByAccountId(chains, accountId); - const streamReceiverSeenEventsSqlQueries = `${chains - .map((chain) => `${baseStreamReceiverSeenEventsSQL(chain)}`) - .join(' UNION ')} LIMIT 1000`; - - const streamReceiverSeenEventModelDataValuesForUser = ( - await dbConnection.query(streamReceiverSeenEventsSqlQueries, { - type: QueryTypes.SELECT, - replacements: { accountId }, - mapToModel: true, - model: StreamReceiverSeenEventModel, - }) - ).map((p) => p.dataValues as StreamReceiverSeenEventModelDataValues); - - const baseStreamsSetEventsSQL = (schema: SupportedChain) => - `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; - - const whereClause = streamReceiverSeenEventModelDataValuesForUser.length - ? ` WHERE "receiversHash" IN (:receiversHash)` - : ''; - - const streamsSetEventsSqlQueries = chains.map( - (chain) => baseStreamsSetEventsSQL(chain) + whereClause, + const receiversHashes = streamReceiverSeenEventModelDataValuesForUser.map( + (event) => event.receiversHash, ); - const fullStreamsSetEventsQuery = `${streamsSetEventsSqlQueries.join( - ' UNION ', - )} LIMIT 1000`; - - const streamsSetEventsWithMatchingHistoryHash = ( - await dbConnection.query(fullStreamsSetEventsQuery, { - type: QueryTypes.SELECT, - replacements: { - receiversHash: streamReceiverSeenEventModelDataValuesForUser.map( - (event) => event.receiversHash, - ), - }, - mapToModel: true, - model: StreamsSetEventModel, - }) - ).map((p) => p.dataValues as StreamsSetEventModelDataValues); + const streamsSetEventsWithMatchingHistoryHash = + await streamsSetEventsQueries.getByReceiversHashes(chains, receiversHashes); const accountIdsStreamingToUser = streamsSetEventsWithMatchingHistoryHash .map((event) => event.accountId) From 75432844e0d1c76526875ce5621efd73a67e8173 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 7 Jun 2024 13:44:58 +0200 Subject: [PATCH 14/37] refactor: minor polish --- src/common/dripsContracts.ts | 12 +++++-- src/stream/streamResolvers.ts | 40 ++++++++-------------- src/user/UserDataSource.ts | 21 +----------- src/user/userResolvers.ts | 64 ++++++++++++++++------------------- src/user/userUtils.ts | 6 ++-- 5 files changed, 57 insertions(+), 86 deletions(-) diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts index 17b644e..2ccbf62 100644 --- a/src/common/dripsContracts.ts +++ b/src/common/dripsContracts.ts @@ -7,7 +7,13 @@ import { } from '../generated/contracts'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import { SupportedChain } from '../generated/graphql'; -import type { AccountId, Address, Forge, ProjectId } from './types'; +import type { + AccountId, + Address, + AddressDriverId, + Forge, + ProjectId, +} from './types'; import queryableChains from './queryableChains'; const chainConfigs: Record< @@ -85,13 +91,13 @@ export default dripsContracts; export async function getCrossChainAddressDriverAccountIdByAddress( address: Address, -): Promise { +): Promise { // AddressDriver account IDs are the same across all chains. const { addressDriver } = dripsContracts[queryableChains[0]]!; const accountId = (await addressDriver.calcAccountId(address)).toString(); - return accountId as AccountId; + return accountId as AddressDriverId; } export async function getCrossChainRepoDriverAccountIdByAddress( diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index 2874e2b..d67facb 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -1,49 +1,37 @@ import type { AddressDriverId, DripListId } from '../common/types'; +import { toResolverDripList } from '../drip-list/dripListUtils'; import { Driver } from '../generated/graphql'; import type { Context } from '../server'; +import toResolverUser from '../user/userUtils'; import type { ProtoStream } from '../utils/buildAssetConfigs'; import shouldNeverHappen from '../utils/shouldNeverHappen'; const streamResolvers = { Stream: { - receiver: ( + receiver: async ( { chain, receiver }: ProtoStream, - _: any, + _: {}, { dataSources }: Context, ) => { if (receiver.driver === Driver.ADDRESS) { - return dataSources.usersDataSource.getUserByAccountId( - [chain], - receiver.accountId as AddressDriverId, - ); + return toResolverUser([chain], receiver.accountId as AddressDriverId); } if (receiver.driver === Driver.NFT) { - return dataSources.dripListsDataSource.getDripListById( - [chain], - receiver.accountId as DripListId, - ); + const dbDripList = + await dataSources.dripListsDataSource.getDripListById( + [chain], + receiver.accountId as DripListId, + ); + + return toResolverDripList(chain, dbDripList); } throw shouldNeverHappen(); }, - sender: ( - { chain, sender }: ProtoStream, - _: any, - { dataSources }: Context, - ) => { + sender: async ({ chain, sender }: ProtoStream) => { if (sender.driver === Driver.ADDRESS) { - return dataSources.usersDataSource.getUserByAccountId( - [chain], - sender.accountId as AddressDriverId, - ); - } - - if (sender.driver === Driver.NFT) { - return dataSources.dripListsDataSource.getDripListById( - [chain], - sender.accountId as DripListId, - ); + return toResolverUser([chain], sender.accountId as AddressDriverId); } throw shouldNeverHappen(); diff --git a/src/user/UserDataSource.ts b/src/user/UserDataSource.ts index 6e101dc..5537eb0 100644 --- a/src/user/UserDataSource.ts +++ b/src/user/UserDataSource.ts @@ -1,8 +1,6 @@ -import type { Address, AddressDriverId, ResolverUser } from '../common/types'; +import type { AddressDriverId } from '../common/types'; import type { SupportedChain } from '../generated/graphql'; import getUserAccount from '../utils/getUserAccount'; -import { getCrossChainAddressDriverAccountIdByAddress } from '../common/dripsContracts'; -import toResolverUsers from './userUtils'; export default class UsersDataSource { public async getUserAccount( @@ -11,21 +9,4 @@ export default class UsersDataSource { ) { return getUserAccount(chains, accountId); } - - public async getUserByAccountId( - chains: SupportedChain[], - accountId: AddressDriverId, - ): Promise { - return toResolverUsers(chains, accountId); - } - - public async getUserByAddress( - chains: SupportedChain[], - address: Address, - ): Promise { - const accountId = - await getCrossChainAddressDriverAccountIdByAddress(address); - - return this.getUserByAccountId(chains, accountId as AddressDriverId); - } } diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index 92e2df5..167b5c5 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -7,6 +7,7 @@ import type { ResolverUser, ResolverUserChainData, ResolverUserData, + UserDataParentDripListInfo, } from '../common/types'; import DripListModel from '../drip-list/DripListModel'; import type { @@ -23,29 +24,30 @@ import { toResolverProjects } from '../project/projectUtils'; import { toResolverDripLists } from '../drip-list/dripListUtils'; import getLatestAccountMetadataByChain from '../utils/getLatestAccountMetadata'; import { validateChainsQueryArg } from '../utils/commonInputValidators'; +import toResolverUser from './userUtils'; +import { getCrossChainAddressDriverAccountIdByAddress } from '../common/dripsContracts'; const userResolvers = { Query: { - userById: async ( + userById: ( _: undefined, { - chains, accountId, - }: { chains?: SupportedChain[]; accountId: AddressDriverId }, - { dataSources: { usersDataSource } }: Context, - ): Promise => { + chains, + }: { accountId: AddressDriverId; chains?: SupportedChain[] }, + ): ResolverUser => { + assert(isAddressDriverId(accountId)); if (chains?.length) { validateChainsQueryArg(chains); } const chainsToQuery = chains?.length ? chains : queryableChains; - return usersDataSource.getUserByAccountId(chainsToQuery, accountId); + return toResolverUser(chainsToQuery, accountId); }, userByAddress: async ( _: undefined, - { chains, address }: { chains?: SupportedChain[]; address: Address }, - { dataSources }: Context, + { address, chains }: { address: Address; chains?: SupportedChain[] }, ): Promise => { assert(isAddress(address)); if (chains?.length) { @@ -54,14 +56,15 @@ const userResolvers = { const chainsToQuery = chains?.length ? chains : queryableChains; - return dataSources.usersDataSource.getUserByAddress( - chainsToQuery, - address, - ); + const accountId = + await getCrossChainAddressDriverAccountIdByAddress(address); + + return toResolverUser(chainsToQuery, accountId); }, }, User: { account: (user: ResolverUser): AddressDriverAccount => user.account, + chainData: (user: ResolverUser): ResolverUserChainData[] => user.chainData, }, UserChainData: { chain: (chainUserData: ResolverUserChainData): SupportedChain => @@ -69,9 +72,12 @@ const userResolvers = { data: (chainUserData: ResolverUserChainData) => chainUserData.data, }, UserData: { - streams: async ({ parentUserInfo, streams }: ResolverUserData) => ({ - incoming: streams.incoming, - outgoing: streams.outgoing, + streams: async ({ + parentUserInfo, + streams: { incoming, outgoing }, + }: ResolverUserData) => ({ + incoming, + outgoing, parentUserInfo, }), balances: async ({ @@ -169,37 +175,27 @@ const userResolvers = { }, UserStreams: { outgoing: async ( - userData: { - parentUserInfo: { accountId: AccountId; userChain: SupportedChain }; - }, + { parentUserInfo }: UserDataParentDripListInfo, _: {}, - { dataSources }: Context, + { dataSources: { streamsDataSource } }: Context, ) => { - const { accountId, userChain } = userData.parentUserInfo; + const { accountId, userChain } = parentUserInfo; assert(isAddressDriverId(accountId)); return ( - await dataSources.streamsDataSource.getUserOutgoingStreams( - [userChain], - accountId, - ) + await streamsDataSource.getUserOutgoingStreams([userChain], accountId) )[userChain as SupportedChain]; }, incoming: async ( - userData: { - parentUserInfo: { accountId: AccountId; userChain: SupportedChain }; - }, - _: any, - { dataSources }: Context, + { parentUserInfo }: UserDataParentDripListInfo, + _: {}, + { dataSources: { streamsDataSource } }: Context, ) => { - const { accountId, userChain } = userData.parentUserInfo; + const { accountId, userChain } = parentUserInfo; assert(isAddressDriverId(accountId)); return ( - await dataSources.streamsDataSource.getUserIncomingStreams( - [userChain], - accountId, - ) + await streamsDataSource.getUserIncomingStreams([userChain], accountId) )[userChain as SupportedChain]; }, }, diff --git a/src/user/userUtils.ts b/src/user/userUtils.ts index a1d1432..5cf027e 100644 --- a/src/user/userUtils.ts +++ b/src/user/userUtils.ts @@ -1,10 +1,10 @@ -import type { AccountId, ResolverUser } from '../common/types'; +import type { AddressDriverId, ResolverUser } from '../common/types'; import { Driver, type SupportedChain } from '../generated/graphql'; import getUserAddress from '../utils/getUserAddress'; -export default function toResolverUsers( +export default function toResolverUser( chains: SupportedChain[], - accountId: AccountId, + accountId: AddressDriverId, ): ResolverUser { return { account: { From 263d273d9684f5be7a6d775e669ebe7d67bac432 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 7 Jun 2024 15:39:46 +0200 Subject: [PATCH 15/37] refactor: add missing total earned resolver in claimed project --- src/common/commonResolverLogic.ts | 1 + src/project/projectResolvers.ts | 5 ----- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/src/common/commonResolverLogic.ts b/src/common/commonResolverLogic.ts index 1a769a9..8af0bdd 100644 --- a/src/common/commonResolverLogic.ts +++ b/src/common/commonResolverLogic.ts @@ -83,5 +83,6 @@ export async function resolveTotalEarned( ).map((amount) => ({ ...amount, amount: amount.amount.toString(), + chain, })); } diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index c3ced64..fdf9e96 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -318,11 +318,6 @@ const projectResolvers = { return [...projectAndDripListSupport, ...oneTimeDonationSupport]; }, - totalEarned: async ( - projectData: ResolverUnClaimedProjectData, - _: {}, - context: Context, - ) => resolveTotalEarned(projectData, context), }, SplitsReceiver: { __resolveType(receiver: SplitsReceiver) { From efd7b7476d2dbafd9ac55acbbf92fcabf78e3518 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 7 Jun 2024 17:31:35 +0200 Subject: [PATCH 16/37] refactor: remove limit in queries --- .../sqlQueries/accountMetadataEmittedEventsQueries.ts | 2 +- .../sqlQueries/addressDriverSplitReceiversQueries.ts | 6 +++--- .../sqlQueries/dripListSplitReceiversQueries.ts | 6 +++--- src/dataLoaders/sqlQueries/givenEventsQueries.ts | 10 +++++----- .../sqlQueries/repoDriverSplitReceiversQueries.ts | 6 +++--- src/dataLoaders/sqlQueries/splitEventsQueries.ts | 8 ++++---- .../sqlQueries/streamReceiverSeenEventQueries.ts | 2 +- src/utils/getStreamsSetEventsWithReceivers.ts | 2 +- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts b/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts index fa44047..1d61c8b 100644 --- a/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts @@ -23,7 +23,7 @@ async function getAccountMetadataEmittedEventsByAccountId( (chain) => baseSQL(chain) + whereClause + orderClause, ); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')} LIMIT 1`; return ( await dbConnection.query(fullQuery, { diff --git a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts index 9491d70..8de21ce 100644 --- a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts +++ b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts @@ -28,7 +28,7 @@ async function getAddressDriverSplitReceiversDripListDependenciesByFunders( const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${chainQueries.join(' UNION ')}`; return ( await dbConnection.query(multiChainQuery, { @@ -61,7 +61,7 @@ async function getAddressDriverSplitReceiversProjectDependenciesByFunders( const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${chainQueries.join(' UNION ')}`; return ( await dbConnection.query(multiChainQuery, { @@ -90,7 +90,7 @@ async function getAddressDriverSplitReceiversByFundeeAccountIds( const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${chainQueries.join(' UNION ')}`; return ( await dbConnection.query(multiChainQuery, { diff --git a/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts index f635363..de851a8 100644 --- a/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts +++ b/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts @@ -28,7 +28,7 @@ async function getDripListSplitReceiversByFundeeDripListIds( const queries = chains.map((chain) => baseSQL(chain) + whereClause); // Combine all schema queries with UNION. - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -61,7 +61,7 @@ async function getDripListSplitReceiversByFunderProjectIds( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -94,7 +94,7 @@ async function getDripListSplitReceiversByFunderDripListIds( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { diff --git a/src/dataLoaders/sqlQueries/givenEventsQueries.ts b/src/dataLoaders/sqlQueries/givenEventsQueries.ts index dc50a2b..c9787be 100644 --- a/src/dataLoaders/sqlQueries/givenEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/givenEventsQueries.ts @@ -16,7 +16,7 @@ async function getDistinctErc20ByReceiver( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -56,7 +56,7 @@ async function getGivenEventsByFilter( const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${chainQueries.join(' UNION ')}`; return ( await dbConnection.query(multiChainQuery, { @@ -81,7 +81,7 @@ async function getGivenEventsByReceivers( const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${chainQueries.join(' UNION ')}`; return ( await dbConnection.query(multiChainQuery, { @@ -114,7 +114,7 @@ async function getGivenEventsByTxHashesAndLogIndex( const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${chainQueries.join(' UNION ')}`; return ( await dbConnection.query(multiChainQuery, { @@ -139,7 +139,7 @@ async function getGivenEventsByReceiver( const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${chainQueries.join(' UNION ')}`; return ( await dbConnection.query(multiChainQuery, { diff --git a/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts index b832150..f391f65 100644 --- a/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts +++ b/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts @@ -24,7 +24,7 @@ async function getRepoDriverSplitReceiversByFundeeProjectIds( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -58,7 +58,7 @@ async function getRepoDriverSplitReceiversByFunderProjectIds( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -91,7 +91,7 @@ async function getRepoDriverSplitReceiversByFunderDripListIds( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { diff --git a/src/dataLoaders/sqlQueries/splitEventsQueries.ts b/src/dataLoaders/sqlQueries/splitEventsQueries.ts index 13e0373..db6e56f 100644 --- a/src/dataLoaders/sqlQueries/splitEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/splitEventsQueries.ts @@ -16,7 +16,7 @@ async function getDistinctErc20ByReceiver( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -49,7 +49,7 @@ async function getSplitEventsByAccountIdAndReceiver( const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${chainQueries.join(' UNION ')}`; return ( await dbConnection.query(multiChainQuery, { @@ -75,7 +75,7 @@ async function getSplitEventsByReceiver( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -105,7 +105,7 @@ async function getSplitEventsByProjectReceivers( (chain) => baseSplitEventsSQL(chain) + whereClause, ); - const fullSplitsQuery = `${splitsQueries.join(' UNION ')} LIMIT 1000`; + const fullSplitsQuery = `${splitsQueries.join(' UNION ')}`; return ( await dbConnection.query(fullSplitsQuery, { diff --git a/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts b/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts index e53ea4b..8c4d72f 100644 --- a/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts +++ b/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts @@ -14,7 +14,7 @@ async function getStreamReceiverSeenEventsByAccountId( const fullQuery = `${chains .map((chain) => `${baseSQL(chain)}`) - .join(' UNION ')} LIMIT 1000`; + .join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { diff --git a/src/utils/getStreamsSetEventsWithReceivers.ts b/src/utils/getStreamsSetEventsWithReceivers.ts index d9b2dd0..7ab2490 100644 --- a/src/utils/getStreamsSetEventsWithReceivers.ts +++ b/src/utils/getStreamsSetEventsWithReceivers.ts @@ -53,7 +53,7 @@ export default async function getStreamsSetEventsWithReceivers( // Combine all schema queries with UNION. const fullQueryStreamReceiverSeenEventModelQuery = `${streamReceiverSeenEventModelQueries.join( ' UNION ', - )} LIMIT 1000`; + )}`; const streamReceiverSeenEventModelDataValues = ( await dbConnection.query(fullQueryStreamReceiverSeenEventModelQuery, { From 53c96f8d26e0ab6ff2d1a0754f4fdef7c78349ef Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 7 Jun 2024 17:32:20 +0200 Subject: [PATCH 17/37] refactor: remove limit in queries (leftovers) --- src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts index 9129302..32d36dc 100644 --- a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts @@ -16,7 +16,7 @@ async function getDistinctErc20ByReceiversHashes( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -45,7 +45,7 @@ async function getSortedStreamsSetEventsByAccountId( (chain) => `${baseSQL(chain) + whereClause + orderClause}`, ); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { @@ -70,7 +70,7 @@ async function getSortedStreamsSetEventsByReceiversHashes( const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( await dbConnection.query(fullQuery, { From c9a0670764dee3d1bc744975cc14a8144abaaa94 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Tue, 11 Jun 2024 10:39:22 +0200 Subject: [PATCH 18/37] fix: wrong query where conditions --- src/dataLoaders/sqlQueries/dripListsQueries.ts | 2 +- src/project/projectResolvers.ts | 4 ++++ src/schema.ts | 1 + 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/dataLoaders/sqlQueries/dripListsQueries.ts b/src/dataLoaders/sqlQueries/dripListsQueries.ts index 536a392..ee299a3 100644 --- a/src/dataLoaders/sqlQueries/dripListsQueries.ts +++ b/src/dataLoaders/sqlQueries/dripListsQueries.ts @@ -17,7 +17,7 @@ async function getDripListsByFilter( FROM "${schema}"."DripLists" `; - const conditions: string[] = ['isValid = true', 'name IS NOT NULL']; + const conditions: string[] = ['"isValid" = true', 'name IS NOT NULL']; const parameters: { [key: string]: any } = {}; if (where?.id) { diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 7150937..6112d41 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -338,6 +338,10 @@ const projectResolvers = { return 'DripListReceiver'; } + if (receiver.driver === Driver.ADDRESS) { + return 'AddressReceiver'; + } + return shouldNeverHappen(); }, }, diff --git a/src/schema.ts b/src/schema.ts index c44e211..76c8761 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -27,6 +27,7 @@ const rootTypeDef = gql` ): MintedTokens! userById(accountId: ID!, chains: [SupportedChain!]): User! userByAddress(address: String!, chains: [SupportedChain!]): User! + streams(where: StreamWhereInput): [Stream!]! } `; From 45ad69037de761508397e37d1630116a7d89c1a4 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Tue, 11 Jun 2024 11:40:13 +0200 Subject: [PATCH 19/37] fix: wrong queries --- src/dataLoaders/sqlQueries/givenEventsQueries.ts | 2 +- src/dataLoaders/sqlQueries/splitEventsQueries.ts | 2 +- src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts | 6 ++++-- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/dataLoaders/sqlQueries/givenEventsQueries.ts b/src/dataLoaders/sqlQueries/givenEventsQueries.ts index c9787be..1dbafa6 100644 --- a/src/dataLoaders/sqlQueries/givenEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/givenEventsQueries.ts @@ -10,7 +10,7 @@ async function getDistinctErc20ByReceiver( receiver: AccountId, ) { const baseSQL = (schema: SupportedChain) => - `SELECT DISTINCT ON ("erc20"), "erc20", '${schema}' AS chain FROM "${schema}"."GivenEvents"`; + `SELECT DISTINCT ON ("erc20") "erc20", '${schema}' AS chain FROM "${schema}"."GivenEvents"`; const whereClause = ` WHERE "accountId" = :receiver`; diff --git a/src/dataLoaders/sqlQueries/splitEventsQueries.ts b/src/dataLoaders/sqlQueries/splitEventsQueries.ts index db6e56f..639292a 100644 --- a/src/dataLoaders/sqlQueries/splitEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/splitEventsQueries.ts @@ -10,7 +10,7 @@ async function getDistinctErc20ByReceiver( receiver: AccountId, ) { const baseSQL = (schema: SupportedChain) => - `SELECT DISTINCT ON ("erc20"), "erc20", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; + `SELECT DISTINCT ON ("erc20") "erc20", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; const whereClause = ` WHERE "accountId" = :receiver`; diff --git a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts index 32d36dc..8331dd9 100644 --- a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts @@ -10,9 +10,11 @@ async function getDistinctErc20ByReceiversHashes( receiversHashes: string[], ) { const baseSQL = (schema: SupportedChain) => - `SELECT DISTINCT ON ("erc20"), "erc20", '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; + `SELECT DISTINCT ON ("erc20") "erc20", '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; - const whereClause = ` WHERE "receiversHash" IN (:receiversHashes})`; + const whereClause = receiversHashes?.length + ? ` WHERE "receiversHash" IN (:receiversHashes)` + : ''; const queries = chains.map((chain) => baseSQL(chain) + whereClause); From eb25d952862e05e32478669fce1ea580f44422ef Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Tue, 11 Jun 2024 13:00:33 +0200 Subject: [PATCH 20/37] fix: compilation errors --- src/project/projectUtils.ts | 2 ++ src/user/userUtils.ts | 1 + 2 files changed, 3 insertions(+) diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 3c8be6b..42ffc6b 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -164,6 +164,7 @@ export async function toResolverProjects( support: [], // Will be populated by the resolver. claimedAt: project.claimedAt, totalEarned: [], // Will be populated by the resolver. + withdrawableBalances: [], // Will be populated by the resolver. }, } as ResolverClaimedProjectChainData; } @@ -180,6 +181,7 @@ export async function toResolverProjects( verificationStatus: fakeUnclaimedProject.verificationStatus, support: [], // Will be populated by the resolver. totalEarned: [], // Will be populated by the resolver. + withdrawableBalances: [], // Will be populated by the resolver. }, } as ResolverUnClaimedProjectChainData; }), diff --git a/src/user/userUtils.ts b/src/user/userUtils.ts index 5cf027e..f91d2a4 100644 --- a/src/user/userUtils.ts +++ b/src/user/userUtils.ts @@ -28,6 +28,7 @@ export default function toResolverUser( outgoing: [], // Will be populated by the resolver. }, support: [], // Will be populated by the resolver. + withdrawableBalances: [], // Will be populated by the resolver. }, })), }; From 30d1c1d769006c0bbf35720ad2d2f51967efbd9a Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Mon, 17 Jun 2024 11:58:39 +0200 Subject: [PATCH 21/37] fix: wrong resolvers's logic after comparing with the current working API responses --- src/balances/estimate-reloaded.ts | 30 -- src/common/commonResolvers.ts | 134 +++++--- src/common/types.ts | 29 +- src/dataLoaders/DripListsDataSource.ts | 20 +- .../ProjectAndDripListSupportDataSource.ts | 70 +++-- src/dataLoaders/ProjectsDataSource.ts | 79 +++-- .../ReceiversOfTypeAddressDataSource.ts | 28 +- .../ReceiversOfTypeDripListDataSource.ts | 28 +- .../ReceiversOfTypeProjectDataSource.ts | 28 +- .../accountMetadataEmittedEventsQueries.ts | 10 +- .../addressDriverSplitReceiversQueries.ts | 8 +- src/dataLoaders/sqlQueries/projectsQueries.ts | 71 ++--- .../sqlQueries/streamsSetEventsQueries.ts | 117 ++++++- src/drip-list/dripListResolvers.ts | 164 ++++++---- src/drip-list/dripListTypeDef.ts | 8 +- src/drip-list/dripListUtils.ts | 59 ++-- src/project/projectResolvers.ts | 295 ++++++++++++------ src/project/projectTypeDef.ts | 16 +- src/project/projectUtils.ts | 201 +++++++++--- src/project/projectValidators.ts | 2 +- src/resolvers.ts | 12 +- src/schema.ts | 9 +- src/stream/StreamsDataSource.ts | 5 +- src/stream/streamResolvers.ts | 26 +- src/stream/streamTypeDef.ts | 5 + src/stream/streamValidators.ts | 21 ++ src/user/userResolvers.ts | 113 +++++-- src/user/userTypeDef.ts | 8 +- src/user/userUtils.ts | 28 +- src/utils/getAssetConfigs.ts | 16 +- src/utils/getStreamsSetEventsWithReceivers.ts | 110 ------- src/utils/getUserAccount.ts | 1 + src/utils/linq.ts | 12 + 33 files changed, 1068 insertions(+), 695 deletions(-) create mode 100644 src/stream/streamValidators.ts delete mode 100644 src/utils/getStreamsSetEventsWithReceivers.ts diff --git a/src/balances/estimate-reloaded.ts b/src/balances/estimate-reloaded.ts index 4172e7f..a451c66 100644 --- a/src/balances/estimate-reloaded.ts +++ b/src/balances/estimate-reloaded.ts @@ -116,17 +116,6 @@ export function assetOutgoingBalanceTimeline( : previousBalance + totalStreamedSinceLastEvent; if (currentBalance < 0) currentBalance = 0n; - if (ts.getTime() === new Date('2024-05-23T03:03:15.000Z').getTime()) { - console.log('last item', { - previousTimelineItem, - previousBalance, - previousDeltaPerSecond, - secondsPassedSinceLastEvent, - totalStreamedSinceLastEvent, - currentBalance, - }); - } - let currentDeltaPerSecond = currentBalance > 0n ? streams.reduce((acc, stream) => { @@ -162,25 +151,6 @@ export function assetOutgoingBalanceTimeline( currentDeltaPerSecond = 0n; } - if ( - item.balance.tokenAddress === - '0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48' - ) { - console.log({ - result: { - timestamp: ts, - currentAmount: { - tokenAddress: item.balance.tokenAddress, - amount: currentBalance.toString(), - }, - deltaPerSecond: { - tokenAddress: item.balance.tokenAddress, - amount: (-currentDeltaPerSecond).toString(), - }, - }, - }); - } - timeline.push({ timestamp: ts, currentAmount: { diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index 104792f..bcdb093 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -1,49 +1,52 @@ import type { AddressDriverAccount, Amount, + DripList, NftDriverAccount, + Project, RepoDriverAccount, + SplitsReceiver, SupportedChain, } from '../generated/graphql'; import { Driver } from '../generated/graphql'; -import type GivenEventModel from '../given-event/GivenEventModel'; -import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import type { Context } from '../server'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { AddressDriverId, DripListId, ProjectId } from './types'; import { DependencyType } from './types'; import getUserAddress from '../utils/getUserAddress'; import type { ProtoStream } from '../utils/buildAssetConfigs'; -import { toResolverProjects } from '../project/projectUtils'; +import { toResolverProject } from '../project/projectUtils'; import { toResolverDripLists } from '../drip-list/dripListUtils'; -import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; +import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; import mergeAmounts from '../utils/mergeAmounts'; -import AddressDriverSplitReceiverModel, { - AddressDriverSplitReceiverType, -} from '../models/AddressDriverSplitReceiverModel'; +import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; +import { AddressDriverSplitReceiverType } from '../models/AddressDriverSplitReceiverModel'; import splitEventsQueries from '../dataLoaders/sqlQueries/splitEventsQueries'; +import type projectResolvers from '../project/projectResolvers'; +import type dripListResolvers from '../drip-list/dripListResolvers'; +import type { DripListSplitReceiverModelDataValues } from '../models/DripListSplitReceiverModel'; +import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; async function resolveTotalSplit( - chains: SupportedChain[], parent: - | DripListSplitReceiverModel - | RepoDriverSplitReceiverModel - | AddressDriverSplitReceiverModel, + | DripListSplitReceiverModelDataValues + | RepoDriverSplitReceiverModelDataValues + | AddressDriverSplitReceiverModelDataValues, ) { let incomingAccountId: DripListId | ProjectId; let recipientAccountId: DripListId | ProjectId | AddressDriverId; - if (parent instanceof DripListSplitReceiverModel) { + if ('fundeeDripListId' in parent) { const { fundeeDripListId, funderDripListId, funderProjectId } = parent; recipientAccountId = fundeeDripListId; incomingAccountId = funderDripListId || funderProjectId || shouldNeverHappen(); - } else if (parent instanceof RepoDriverSplitReceiverModel) { + } else if ('fundeeProjectId' in parent) { const { fundeeProjectId, funderDripListId, funderProjectId } = parent; recipientAccountId = fundeeProjectId; incomingAccountId = funderDripListId || funderProjectId || shouldNeverHappen(); - } else if (parent instanceof AddressDriverSplitReceiverModel) { + } else if ('fundeeAccountId' in parent) { const { fundeeAccountId, funderDripListId, funderProjectId } = parent; recipientAccountId = fundeeAccountId; @@ -52,9 +55,8 @@ async function resolveTotalSplit( } else { shouldNeverHappen('Invalid SupportItem type'); } - const splitEvents = await splitEventsQueries.getByAccountIdAndReceiver( - chains, + [parent.chain], incomingAccountId, recipientAccountId, ); @@ -72,16 +74,34 @@ async function resolveTotalSplit( } const commonResolvers = { + AddressReceiver: { + weight: async ({ weight }: { weight: number }) => weight, + driver: async ({ driver }: { driver: Driver }) => driver, + account: async ({ account }: { account: AddressDriverAccount }) => account, + }, + DripListReceiver: { + weight: async ({ weight }: { weight: number }) => weight, + driver: async ({ driver }: { driver: Driver }) => driver, + dripList: async ({ dripList }: { dripList: DripList }) => dripList, + account: async ({ account }: { account: NftDriverAccount }) => account, + }, + ProjectReceiver: { + weight: async ({ weight }: { weight: number }) => weight, + driver: async ({ driver }: { driver: Driver }) => driver, + project: async ({ project }: { project: Project }) => project, + account: async ({ account }: { account: RepoDriverAccount }) => account, + }, SupportItem: { __resolveType( parent: - | DripListSplitReceiverModel - | RepoDriverSplitReceiverModel - | AddressDriverSplitReceiverModel - | GivenEventModel - | ProtoStream, + | Awaited< + ReturnType + >[number] + | Awaited< + ReturnType + >[number], ) { - if ('funderDripListId' in parent || 'funderProjectId' in parent) { + if ('dripList' in parent || 'project' in parent) { const { type } = parent as any; if ( @@ -102,11 +122,11 @@ const commonResolvers = { return shouldNeverHappen('Invalid SupportItem type'); } - if ('receiver' in parent) { - return 'OneTimeDonationSupport'; + if ('stream' in parent) { + return 'StreamSupport'; } - return 'StreamSupport'; + return 'OneTimeDonationSupport'; }, }, ProjectSupport: { @@ -124,10 +144,11 @@ const commonResolvers = { const { funderProjectId, chain } = parent; - const project = await projectsDataSource.getProjectById( - funderProjectId, - chain, - ); + const project = + (await projectsDataSource.getProjectByIdOnChain( + funderProjectId, + chain, + )) || shouldNeverHappen(); return { driver: Driver.REPO, @@ -152,19 +173,17 @@ const commonResolvers = { const { funderProjectId, chain } = parent; const projectDataValues = - (await projectsDataSource.getProjectById(funderProjectId, chain)) || - shouldNeverHappen(); - - const resolverProjects = await toResolverProjects( - [chain], - [projectDataValues], - ); + (await projectsDataSource.getProjectByIdOnChain( + funderProjectId, + chain, + )) || shouldNeverHappen(); - const [project] = resolverProjects; + const project = await toResolverProject([chain], projectDataValues); return project; }, - totalSplit: resolveTotalSplit, + totalSplit: (parent: RepoDriverSplitReceiverModelDataValues) => + resolveTotalSplit(parent), }, DripListSupport: { account: async ( @@ -182,8 +201,8 @@ const commonResolvers = { const { funderDripListId, chain } = parent; const dripList = await dripListsDataSource.getDripListById( - [chain], funderDripListId, + [chain], ); return { @@ -205,10 +224,9 @@ const commonResolvers = { const { funderDripListId, chain } = parent; const dripListDataValues = - (await dripListsDataSource.getDripListById( - [chain], - funderDripListId, - )) || shouldNeverHappen(); + (await dripListsDataSource.getDripListById(funderDripListId, [ + chain, + ])) || shouldNeverHappen(); const resolverDripLists = await toResolverDripLists( [chain], @@ -219,15 +237,12 @@ const commonResolvers = { return dripLists; }, - totalSplit: resolveTotalSplit, + totalSplit: (parent: DripListSplitReceiverModelDataValues) => + resolveTotalSplit(parent), }, OneTimeDonationSupport: { account: async ( - parent: { - transactionHash: string; - logIndex: number; - chain: SupportedChain; - }, + parent: GivenEventModelDataValues, _: any, context: Context, ): Promise => { @@ -249,11 +264,11 @@ const commonResolvers = { address: getUserAddress(givenEvent.accountId), }; }, - amount: (parent: GivenEventModel): Amount => ({ + amount: (parent: GivenEventModelDataValues): Amount => ({ tokenAddress: parent.erc20, amount: parent.amt, }), - date: (parent: { blockTimestamp: Date }): Date => parent.blockTimestamp, + date: (parent: GivenEventModelDataValues): Date => parent.blockTimestamp, }, StreamSupport: { account: async (parent: ProtoStream): Promise => @@ -264,6 +279,23 @@ const commonResolvers = { SupportGroup: { // TODO: implement. }, + SplitsReceiver: { + __resolveType(receiver: SplitsReceiver) { + if (receiver.driver === Driver.REPO) { + return 'ProjectReceiver'; + } + + if (receiver.driver === Driver.NFT) { + return 'DripListReceiver'; + } + + if (receiver.driver === Driver.ADDRESS) { + return 'AddressReceiver'; + } + + return shouldNeverHappen(); + }, + }, }; export default commonResolvers; diff --git a/src/common/types.ts b/src/common/types.ts index 4760571..ee89d11 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -73,10 +73,7 @@ export type StreamHistoryHashes = string & { }; export type ResolverProject = Project & { - chainData: ( - | ResolverClaimedProjectChainData - | ResolverUnClaimedProjectChainData - )[]; + chainData: (ResolverClaimedProjectData | ResolverUnClaimedProjectData)[]; }; type ProjectDataParentProjectInfo = { @@ -90,19 +87,9 @@ type ProjectDataParentProjectInfo = { export type ResolverClaimedProjectData = ClaimedProjectData & ProjectDataParentProjectInfo; -export type ResolverClaimedProjectChainData = { - chain: SupportedChain; - data: ResolverClaimedProjectData; -}; - export type ResolverUnClaimedProjectData = UnClaimedProjectData & ProjectDataParentProjectInfo; -export type ResolverUnClaimedProjectChainData = { - chain: SupportedChain; - data: ResolverUnClaimedProjectData; -}; - export interface MultiChainKey { id: T; chains: SupportedChain[]; @@ -111,12 +98,7 @@ export type ProjectMultiChainKey = MultiChainKey; export type DripListMultiChainKey = MultiChainKey; export type ResolverDripList = DripList & { - chainData: ResolverDripListChainData[]; -}; - -export type ResolverDripListChainData = { - chain: SupportedChain; - data: ResolverDripListData | null; + chainData?: ResolverDripListData[]; }; type DripListDataParentDripListInfo = { @@ -146,12 +128,7 @@ export type ResolverGiveChainData = { }; export type ResolverUser = User & { - chainData: ResolverUserChainData[]; -}; - -export type ResolverUserChainData = { - chain: SupportedChain; - data: ResolverUserData | null; + chainData: ResolverUserData[]; }; export type ResolverUserData = UserData & UserDataParentDripListInfo; diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index fee0a0e..e5ef19a 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -35,8 +35,8 @@ export default class DripListsDataSource { ); public async getDripListById( - chains: SupportedChain[], id: DripListId, + chains: SupportedChain[], ): Promise { return this._batchDripListsByIds.load({ id, @@ -51,16 +51,18 @@ export default class DripListsDataSource { return dripListsQueries.getByFilter(chains, where); } - public async getDripListsByIds( + public async getDripListsByIdsOnChain( ids: DripListId[], - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchDripListsByIds.loadMany( - ids.map((id) => ({ - id, - chains, - })), - ) as Promise; + return ( + await (this._batchDripListsByIds.loadMany( + ids.map((id) => ({ + id, + chains: [chain], + })), + ) as Promise) + ).filter((dripList) => dripList.chain === chain); } public async getMintedTokensCountByAccountId( diff --git a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts index 7f1b2ff..d6fa11d 100644 --- a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts +++ b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts @@ -174,53 +174,63 @@ export default class ProjectAndDripListSupportDataSource { }, ); - public async getProjectAndDripListSupportByDripListId( + public async getProjectAndDripListSupportByDripListIdOnChain( id: DripListId, - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchProjectAndDripListSupportByDripListIds.load({ - id, - chains, - }); + return ( + await this._batchProjectAndDripListSupportByDripListIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } - public async getProjectAndDripListSupportByProjectId( + public async getProjectAndDripListSupportByProjectIdOnChain( id: ProjectId, - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchProjectAndDripListSupportByProjectIds.load({ - id, - chains, - }); + return ( + await this._batchProjectAndDripListSupportByProjectIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } - public async getProjectAndDripListSupportByAddressDriverId( - chains: SupportedChain[], + public async getProjectAndDripListSupportByAddressDriverIdOnChain( id: AddressDriverId, + chain: SupportedChain, ): Promise { - return this._batchProjectAndDripListSupportByAddressDriverIds.load({ - id, - chains, - }); + return ( + await this._batchProjectAndDripListSupportByAddressDriverIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } - public async getOneTimeDonationSupportByAccountId( - chains: SupportedChain[], + public async getOneTimeDonationSupportByAccountIdOnChain( id: AccountId, + chain: SupportedChain, ): Promise { - return this._batchOneTimeDonationSupportByAccountIds.load({ - id, - chains, - }); + return ( + await this._batchOneTimeDonationSupportByAccountIds.load({ + id, + chains: [chain], + }) + ).filter((support) => support.chain === chain); } - public async getStreamSupportByAccountId( - chains: SupportedChain[], + public async getStreamSupportByAccountIdOnChain( id: AccountId, + chain: SupportedChain, ) { - return this._batchStreamSupportByAccountIds.load({ - id, - chains, - }); + return ( + await this._batchStreamSupportByAccountIds.load({ + id, + chains: [chain], + }) + ).filter((s) => s.chain === chain); } } diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 916a0bd..2a08211 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -5,11 +5,7 @@ import type { ProjectId, ProjectMultiChainKey, } from '../common/types'; -import { - doesRepoExists, - toApiProject, - toFakeUnclaimedProjectFromUrl, -} from '../project/projectUtils'; +import { toApiProject } from '../project/projectUtils'; import type { ProjectSortInput, ProjectWhereInput, @@ -19,6 +15,7 @@ import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import projectsQueries from './sqlQueries/projectsQueries'; import givenEventsQueries from './sqlQueries/givenEventsQueries'; import splitEventsQueries from './sqlQueries/splitEventsQueries'; +import shouldNeverHappen from '../utils/shouldNeverHappen'; export default class ProjectsDataSource { private readonly _batchProjectsByIds = new DataLoader( @@ -52,31 +49,57 @@ export default class ProjectsDataSource { }, ); - public async getProjectById( + public async getProjectByIdOnChain( id: ProjectId, chain: SupportedChain, ): Promise { - return toApiProject( - await this._batchProjectsByIds.load({ - id, - chains: [chain], - }), - ); + const dbProject = await this._batchProjectsByIds.load({ + id, + chains: [chain], + }); + + return dbProject ?? null; + } + + public async getProjectById( + id: ProjectId, + chains: SupportedChain[], + ): Promise { + const dbProjects = ( + await this._batchProjectsByIds.loadMany([{ id, chains }]) + ).filter(Boolean) as ProjectDataValues[]; + + if (!dbProjects?.length) { + return null; + } + + if (dbProjects.some((p) => p.id !== dbProjects[0].id)) { + shouldNeverHappen( + 'Found same project with different ids on different chains.', + ); + } + + return dbProjects; } public async getProjectByUrl( url: string, - chain: SupportedChain, - ): Promise { - const project = await projectsQueries.getByUrl(chain, url); + chains: SupportedChain[], + ): Promise { + // TODO: To Data Loader. + const dbProjects = await projectsQueries.getByUrl(chains, url); - if (project) { - return toApiProject(project); + if (!dbProjects?.length) { + return null; } - const exists = await doesRepoExists(url); + if (dbProjects.some((p) => p.id !== dbProjects[0].id)) { + shouldNeverHappen( + 'Found same project with different ids on different chains.', + ); + } - return exists ? toFakeUnclaimedProjectFromUrl(url) : null; + return dbProjects; } public async getProjectsByFilter( @@ -97,16 +120,18 @@ export default class ProjectsDataSource { ); } - public async getProjectsByIds( + public async getProjectsByIdsOnChain( ids: ProjectId[], - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchProjectsByIds.loadMany( - ids.map((id) => ({ - id, - chains, - })), - ) as Promise; + return ( + await (this._batchProjectsByIds.loadMany( + ids.map((id) => ({ + id, + chains: [chain], + })), + ) as Promise) + ).filter((p) => p.chain === chain); } public async getEarnedFunds( diff --git a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts index 1ff1797..b15da85 100644 --- a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts @@ -40,14 +40,16 @@ export default class ReceiversOfTypeAddressDataSource { }, ); - public async getReceiversOfTypeAddressByProjectId( + public async getReceiversOfTypeAddressByProjectIdOnChain( id: ProjectId, - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchReceiversOfTypeAddressByProjectIds.load({ - id, - chains, - }); + return ( + await this._batchReceiversOfTypeAddressByProjectIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } private readonly _batchReceiversOfTypeAddressByDripListIds = new DataLoader( @@ -79,13 +81,15 @@ export default class ReceiversOfTypeAddressDataSource { }, ); - public async getReceiversOfTypeAddressByDripListId( + public async getReceiversOfTypeAddressByDripListIdOnChain( id: DripListId, - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchReceiversOfTypeAddressByDripListIds.load({ - id, - chains, - }); + return ( + await this._batchReceiversOfTypeAddressByDripListIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } } diff --git a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts index 1cd48f4..4db8f52 100644 --- a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts @@ -40,14 +40,16 @@ export default class ReceiversOfTypeDripListDataSource { }, ); - public async getReceiversOfTypeDripListByProjectId( + public async getReceiversOfTypeDripListByProjectIdOnChain( id: ProjectId, - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchReceiversOfTypeDripListByProjectIds.load({ - id, - chains, - }); + return ( + await this._batchReceiversOfTypeDripListByProjectIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } private readonly _batchReceiversOfTypeDripListByDripListIds = new DataLoader( @@ -79,13 +81,15 @@ export default class ReceiversOfTypeDripListDataSource { }, ); - public async getReceiversOfTypeDripListByDripListId( + public async getReceiversOfTypeDripListByDripListIdOnChain( id: DripListId, - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchReceiversOfTypeDripListByDripListIds.load({ - id, - chains, - }); + return ( + await this._batchReceiversOfTypeDripListByDripListIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } } diff --git a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts index be2ff19..b753f3b 100644 --- a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts @@ -40,14 +40,16 @@ export default class ReceiversOfTypeProjectDataSource { }, ); - public async getReceiversOfTypeProjectByProjectId( + public async getReceiversOfTypeProjectByProjectIdOnChain( id: ProjectId, - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchReceiversOfTypeProjectByProjectIds.load({ - id, - chains, - }); + return ( + await this._batchReceiversOfTypeProjectByProjectIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } private readonly _batchReceiversOfTypeProjectByDripListIds = new DataLoader( @@ -79,13 +81,15 @@ export default class ReceiversOfTypeProjectDataSource { }, ); - public async getReceiversOfTypeProjectByDripListId( + public async getReceiversOfTypeProjectByDripListIdOnChain( id: DripListId, - chains: SupportedChain[], + chain: SupportedChain, ): Promise { - return this._batchReceiversOfTypeProjectByDripListIds.load({ - id, - chains, - }); + return ( + await this._batchReceiversOfTypeProjectByDripListIds.load({ + id, + chains: [chain], + }) + ).filter((receiver) => receiver.chain === chain); } } diff --git a/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts b/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts index 1d61c8b..091d32e 100644 --- a/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts @@ -9,21 +9,19 @@ async function getAccountMetadataEmittedEventsByAccountId( chains: SupportedChain[], accountId: AddressDriverId, ) { + // TODO: Prevent SQL injection in all queries from schema input. const baseSQL = (schema: SupportedChain) => `SELECT *,'${schema}' AS chain FROM "${schema}"."AccountMetadataEmittedEvents"`; - const conditions: string[] = ['"accountId" = :accountId']; const parameters: { [key: string]: any } = { accountId }; - const whereClause = ` WHERE ${conditions.join(' AND ')}`; + const whereClause = ` WHERE "accountId" = :accountId`; const orderClause = ' ORDER BY "blockNumber" DESC, "logIndex" DESC'; - const queries = chains.map( - (chain) => baseSQL(chain) + whereClause + orderClause, - ); + const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const fullQuery = `${queries.join(' UNION ')} LIMIT 1`; + const fullQuery = `${queries.join(' UNION ')}${orderClause} LIMIT 1`; return ( await dbConnection.query(fullQuery, { diff --git a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts index 8de21ce..78d319c 100644 --- a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts +++ b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts @@ -50,14 +50,16 @@ async function getAddressDriverSplitReceiversProjectDependenciesByFunders( `; const conditions: string[] = [ - `"funderDripListId" IN (:funderProjectIds)`, + `"funderProjectId" IN (:funderProjectIds)`, `type IN ('${AddressDriverSplitReceiverType.ProjectMaintainer}', '${AddressDriverSplitReceiverType.ProjectDependency}')`, ]; const parameters: { [key: string]: any } = { funderProjectIds, }; - const whereClause = ` WHERE ${conditions.join(' AND ')}`; + const whereClause = funderProjectIds?.length + ? ` WHERE ${conditions.join(' AND ')}` + : ''; const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); @@ -78,7 +80,7 @@ async function getAddressDriverSplitReceiversByFundeeAccountIds( fundeeAccountIds: AccountId[], ) { const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "createdAt", "updatedAt", '${schema}' AS chain + SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."AddressDriverSplitReceivers" `; diff --git a/src/dataLoaders/sqlQueries/projectsQueries.ts b/src/dataLoaders/sqlQueries/projectsQueries.ts index ef1f27a..474e967 100644 --- a/src/dataLoaders/sqlQueries/projectsQueries.ts +++ b/src/dataLoaders/sqlQueries/projectsQueries.ts @@ -10,9 +10,9 @@ import ProjectModel from '../../project/ProjectModel'; import type { ProjectId } from '../../common/types'; async function getProjectByUrl( - chain: SupportedChain, + chains: SupportedChain[], url: string, -): Promise { +): Promise { const baseSQL = (schema: SupportedChain) => ` SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."GitProjects" @@ -23,40 +23,12 @@ async function getProjectByUrl( const whereClause = ` WHERE ${conditions.join(' AND ')}`; - const query = `${baseSQL(chain) + whereClause} LIMIT 1`; - - const dbProject = ( - await dbConnection.query(query, { - type: QueryTypes.SELECT, - replacements: parameters, - mapToModel: true, - model: ProjectModel, - }) - ).map((p) => p.dataValues as ProjectDataValues)[0]; + const queries = chains.map((chain) => baseSQL(chain) + whereClause); - return dbProject || null; -} - -async function getProjectsByIds( - chains: SupportedChain[], - projectIds: ProjectId[], -): Promise { - // Define base SQL to query from multiple chains (schemas). - const baseSQL = (schema: SupportedChain) => ` - SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain - FROM "${schema}"."GitProjects" -`; - - const parameters: { [key: string]: any } = { projectIds }; - - const whereClause = ` WHERE "id" IN (:projectIds) AND "isValid" = true`; - - const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); - - const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; + const fullQuery = `${queries.join(' UNION ')}`; return ( - await dbConnection.query(multiChainQuery, { + await dbConnection.query(fullQuery, { type: QueryTypes.SELECT, replacements: parameters, mapToModel: true, @@ -101,11 +73,36 @@ async function getProjectsByFilter( ? ` ORDER BY "${sort.field}" ${sort.direction || 'DESC'}` : ''; - const queries = chains.map( - (chain) => baseSQL(chain) + whereClause + orderClause, - ); + const queries = chains.map((chain) => baseSQL(chain) + whereClause); - const multiChainQuery = `${queries.join(' UNION ')} LIMIT 1000`; + const multiChainQuery = `${queries.join(' UNION ')}${orderClause} LIMIT 1000`; + + return ( + await dbConnection.query(multiChainQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: ProjectModel, + }) + ).map((p) => p.dataValues as ProjectDataValues); +} + +async function getProjectsByIds( + chains: SupportedChain[], + projectIds: ProjectId[], +): Promise { + const baseSQL = (schema: SupportedChain) => ` + SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain + FROM "${schema}"."GitProjects" +`; + + const parameters: { [key: string]: any } = { projectIds }; + + const whereClause = ` WHERE "id" IN (:projectIds) AND "isValid" = true`; + + const chainQueries = chains.map((chain) => baseSQL(chain) + whereClause); + + const multiChainQuery = `${chainQueries.join(' UNION ')} LIMIT 1000`; return ( await dbConnection.query(multiChainQuery, { diff --git a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts index 8331dd9..230face 100644 --- a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts @@ -1,20 +1,29 @@ import { QueryTypes } from 'sequelize'; -import type { AccountId } from '../../common/types'; +import type { + AccountId, + AddressDriverId, + StreamsSetEventWithReceivers, +} from '../../common/types'; import { dbConnection } from '../../database/connectToDatabase'; import type { SupportedChain } from '../../generated/graphql'; import type { StreamsSetEventModelDataValues } from '../../models/StreamsSetEventModel'; import StreamsSetEventModel from '../../models/StreamsSetEventModel'; +import type { StreamReceiverSeenEventModelDataValues } from '../../models/StreamReceiverSeenEventModel'; +import StreamReceiverSeenEventModel from '../../models/StreamReceiverSeenEventModel'; +// TODO: Investigate queries and add DataLoader if needed. async function getDistinctErc20ByReceiversHashes( chains: SupportedChain[], receiversHashes: string[], ) { + if (!receiversHashes?.length) { + return []; + } + const baseSQL = (schema: SupportedChain) => `SELECT DISTINCT ON ("erc20") "erc20", '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; - const whereClause = receiversHashes?.length - ? ` WHERE "receiversHash" IN (:receiversHashes)` - : ''; + const whereClause = ` WHERE "receiversHash" IN (:receiversHashes)`; const queries = chains.map((chain) => baseSQL(chain) + whereClause); @@ -43,11 +52,9 @@ async function getSortedStreamsSetEventsByAccountId( const orderClause = ' ORDER BY "blockNumber" ASC, "logIndex" ASC'; - const queries = chains.map( - (chain) => `${baseSQL(chain) + whereClause + orderClause}`, - ); + const queries = chains.map((chain) => `${baseSQL(chain) + whereClause}`); - const fullQuery = `${queries.join(' UNION ')}`; + const fullQuery = `${queries.join(' UNION ')}${orderClause}`; return ( await dbConnection.query(fullQuery, { @@ -63,12 +70,14 @@ async function getSortedStreamsSetEventsByReceiversHashes( chains: SupportedChain[], receiversHashes: string[], ) { + if (!receiversHashes?.length) { + return []; + } + const baseSQL = (schema: SupportedChain) => `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; - const whereClause = receiversHashes.length - ? ` WHERE "receiversHash" IN (:receiversHashes)` - : ''; + const whereClause = ` WHERE "receiversHash" IN (:receiversHashes)`; const queries = chains.map((chain) => baseSQL(chain) + whereClause); @@ -86,8 +95,94 @@ async function getSortedStreamsSetEventsByReceiversHashes( ).map((p) => p.dataValues as StreamsSetEventModelDataValues); } +async function getStreamsSetEventsWithReceivers( + chains: SupportedChain[], + accountId: AddressDriverId, +): Promise { + const sortedAccountStreamSetEventModelDataValues = + await getSortedStreamsSetEventsByAccountId(chains, accountId); + + const uniqueReceiversHashes = [ + ...new Set( + sortedAccountStreamSetEventModelDataValues.map( + (event) => event.receiversHash, + ), + ), + ]; + + const baseSQL = (schema: SupportedChain) => ` + SELECT *, '${schema}' AS chain FROM "${schema}"."StreamReceiverSeenEvents"`; + + const conditions: string[] = ['"receiversHash" IN (:uniqueReceiversHashes)']; + const parameters: { [key: string]: any } = { + uniqueReceiversHashes, + }; + + const whereClause = uniqueReceiversHashes?.length + ? ` WHERE ${conditions.join(' AND ')}` + : ''; + + const queries = chains.map((chain) => `${baseSQL(chain) + whereClause}`); + + const fullQuery = `${queries.join(' UNION ')}`; + + const streamReceiverSeenEventModelDataValues = ( + await dbConnection.query(fullQuery, { + type: QueryTypes.SELECT, + replacements: parameters, + mapToModel: true, + model: StreamReceiverSeenEventModel, + }) + ).map((p) => p.dataValues as StreamReceiverSeenEventModelDataValues); + + const receiversGroupedByHash = streamReceiverSeenEventModelDataValues.reduce<{ + [receiversHash: string]: StreamReceiverSeenEventModelDataValues[]; + }>((acc, receiver) => { + if (!acc[receiver.receiversHash]) { + acc[receiver.receiversHash] = []; + } + acc[receiver.receiversHash].push(receiver); + return acc; + }, {}); + + Object.keys(receiversGroupedByHash).forEach((hash) => { + receiversGroupedByHash[hash] = [ + ...new Map( + receiversGroupedByHash[hash].map((receiver) => [ + receiver.config, + receiver, + ]), + ).values(), + ]; + }); + + const streamsSetEventsWithReceivers = + sortedAccountStreamSetEventModelDataValues.reduce< + StreamsSetEventWithReceivers[] + >( + (acc, streamsSetEvent) => [ + ...acc, + { + accountId: streamsSetEvent.accountId, + erc20: streamsSetEvent.erc20, + receiversHash: streamsSetEvent.receiversHash, + streamsHistoryHash: streamsSetEvent.streamsHistoryHash, + balance: streamsSetEvent.balance, + maxEnd: streamsSetEvent.maxEnd, + blockTimestamp: streamsSetEvent.blockTimestamp, + receivers: + receiversGroupedByHash[streamsSetEvent.receiversHash] || [], + }, + ], + [], + ); + + return streamsSetEventsWithReceivers; +} + export default { getByAccountIdSorted: getSortedStreamsSetEventsByAccountId, getByReceiversHashes: getSortedStreamsSetEventsByReceiversHashes, getDistinctErc20ByReceiversHashes, + getStreamsSetEventsWithReceivers, }; diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index 680abb6..f4ab8dd 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -3,18 +3,14 @@ import type { Address, DripListId, ResolverDripList, - ResolverDripListChainData, ResolverDripListData, } from '../common/types'; import type DripListModel from './DripListModel'; import type { AddressDriverAccount, AddressReceiver, - DripList, DripListWhereInput, NftDriverAccount, - Project, - SplitsReceiver, } from '../generated/graphql'; import { SupportedChain, Driver } from '../generated/graphql'; import shouldNeverHappen from '../utils/shouldNeverHappen'; @@ -26,6 +22,7 @@ import { toResolverDripList, toResolverDripLists } from './dripListUtils'; import verifyDripListsInput from './dripListValidators'; import type { DripListDataValues } from './DripListModel'; import { resolveTotalEarned } from '../common/commonResolverLogic'; +import { toResolverProject } from '../project/projectUtils'; const dripListResolvers = { Query: { @@ -56,7 +53,7 @@ const dripListResolvers = { assert(isDripListId(id)); assert(chain in SupportedChain); - const dbDripList = await dripListsDataSource.getDripListById([chain], id); + const dbDripList = await dripListsDataSource.getDripListById(id, [chain]); return dbDripList ? toResolverDripList(chain, dbDripList) : null; }, @@ -77,12 +74,6 @@ const dripListResolvers = { DripList: { account: (dripList: ResolverDripList): NftDriverAccount => dripList.account, }, - DripListChainData: { - chain: (chainDripListData: ResolverDripListChainData): SupportedChain => - chainDripListData.chain, - data: (chainDripListData: ResolverDripListChainData) => - chainDripListData.data, - }, DripListData: { name: (dripListData: ResolverDripListData) => dripListData.name ?? 'Unnamed Drip List', @@ -109,11 +100,11 @@ const dripListResolvers = { receiversOfTypeDripListDataSource, }, }: Context, - ): Promise => { + ) => { const receiversOfTypeAddressModels = - await receiversOfTypeAddressDataSource.getReceiversOfTypeAddressByDripListId( + await receiversOfTypeAddressDataSource.getReceiversOfTypeAddressByDripListIdOnChain( dripListId, - [dripListChain], + dripListChain, ); const addressSplits = receiversOfTypeAddressModels.map((receiver) => ({ @@ -128,56 +119,61 @@ const dripListResolvers = { })) as AddressReceiver[]; const receiversOfTypeProjectModels = - await receiversOfTypeProjectDataSource.getReceiversOfTypeProjectByDripListId( + await receiversOfTypeProjectDataSource.getReceiversOfTypeProjectByDripListIdOnChain( dripListId, - [dripListChain], + dripListChain, ); const splitsOfTypeProjectModels = - await projectsDataSource.getProjectsByIds( + await projectsDataSource.getProjectsByIdsOnChain( receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), - [dripListChain], + dripListChain, ); - const projectReceivers = receiversOfTypeProjectModels.map((receiver) => ({ - driver: Driver.REPO, - weight: receiver.weight, - receiverType: receiver.type, - account: { + const projectReceivers = await Promise.all( + receiversOfTypeProjectModels.map(async (receiver) => ({ driver: Driver.REPO, - accountId: receiver.fundeeProjectId, - }, - project: - (splitsOfTypeProjectModels - .filter( - (p): p is ProjectDataValues => p && (p as any).id !== undefined, - ) - .find( - (p) => (p as any).id === receiver.fundeeProjectId, - ) as unknown as Project) || shouldNeverHappen(), - })); + weight: receiver.weight, + receiverType: receiver.type, + account: { + driver: Driver.REPO, + accountId: receiver.fundeeProjectId, + }, + project: await toResolverProject( + [dripListChain], + (splitsOfTypeProjectModels + .filter( + (p): p is ProjectDataValues => p && (p as any).id !== undefined, + ) + .find( + (p) => (p as any).id === receiver.fundeeProjectId, + ) as unknown as ProjectDataValues) || shouldNeverHappen(), + ), + })), + ); const receiversOfTypeDripListModels = - await receiversOfTypeDripListDataSource.getReceiversOfTypeDripListByDripListId( + await receiversOfTypeDripListDataSource.getReceiversOfTypeDripListByDripListIdOnChain( dripListId, - [dripListChain], + dripListChain, ); const splitsOfTypeDripListModels = - await dripListsDataSource.getDripListsByIds( + await dripListsDataSource.getDripListsByIdsOnChain( receiversOfTypeDripListModels.map((r) => r.fundeeDripListId), - [dripListChain], + dripListChain, ); - const dripListReceivers = receiversOfTypeDripListModels.map( - (receiver) => ({ + const dripListReceivers = await Promise.all( + receiversOfTypeDripListModels.map(async (receiver) => ({ driver: Driver.NFT, weight: receiver.weight, account: { driver: Driver.NFT, accountId: receiver.fundeeDripListId, }, - dripList: + dripList: await toResolverDripList( + dripListChain, (splitsOfTypeDripListModels .filter( (l): l is DripListDataValues => @@ -185,8 +181,9 @@ const dripListResolvers = { ) .find( (p) => (p as any).id === receiver.fundeeDripListId, - ) as unknown as DripList) || shouldNeverHappen(), - }), + ) as unknown as DripListDataValues) || shouldNeverHappen(), + ), + })), ); return [...addressSplits, ...projectReceivers, ...dripListReceivers]; @@ -196,30 +193,91 @@ const dripListResolvers = { parentDripListInfo: { dripListId, dripListChain }, }: ResolverDripListData, _: {}, - { dataSources: { projectAndDripListSupportDataSource } }: Context, + { + dataSources: { + projectsDataSource, + dripListsDataSource, + projectAndDripListSupportDataSource, + }, + }: Context, ) => { - const projectAndDripListSupport = - await projectAndDripListSupportDataSource.getProjectAndDripListSupportByDripListId( + // All `RepoDriverSplitReceiver`s that represent the Drip List as a receiver. + const dbRepoDriverSplitReceivers = + await projectAndDripListSupportDataSource.getProjectAndDripListSupportByDripListIdOnChain( dripListId, - [dripListChain], + dripListChain, ); + const projectsAndDripListsSupport = await Promise.all( + dbRepoDriverSplitReceivers.map(async (receiver) => { + const { + funderProjectId, + funderDripListId, + fundeeDripListId, + blockTimestamp, + } = receiver; + + // Supported is a Project. + if (funderProjectId && !funderDripListId) { + return { + ...receiver, + account: { + driver: Driver.NFT, + accountId: fundeeDripListId, + }, + date: blockTimestamp, + totalSplit: [], + project: await toResolverProject( + [dripListChain], + (await projectsDataSource.getProjectByIdOnChain( + funderProjectId, + dripListChain, + )) || shouldNeverHappen(), + ), + }; + // Supported is a DripList. + } + if (funderDripListId && !funderProjectId) { + return { + ...receiver, + account: { + driver: Driver.NFT, + accountId: fundeeDripListId, + }, + date: blockTimestamp, + totalSplit: [], + dripList: await toResolverDripList( + dripListChain, + (await dripListsDataSource.getDripListById(funderDripListId, [ + dripListChain, + ])) || shouldNeverHappen(), + ), + }; + } + + return shouldNeverHappen( + 'Supported is neither a Project nor a DripList.', + ); + }), + ); + + // `GivenEventModelDataValues`s that represent one time donations to the Project. const oneTimeDonationSupport = - await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountId( - [dripListChain], + await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountIdOnChain( dripListId, + dripListChain, ); const streamSupport = - await projectAndDripListSupportDataSource.getStreamSupportByAccountId( - [dripListChain], + await projectAndDripListSupportDataSource.getStreamSupportByAccountIdOnChain( dripListId, + dripListChain, ); return [ - ...projectAndDripListSupport, - ...streamSupport, + ...projectsAndDripListsSupport, ...oneTimeDonationSupport, + ...streamSupport, ]; }, totalEarned: async ( diff --git a/src/drip-list/dripListTypeDef.ts b/src/drip-list/dripListTypeDef.ts index 558b472..4b06a9d 100644 --- a/src/drip-list/dripListTypeDef.ts +++ b/src/drip-list/dripListTypeDef.ts @@ -3,15 +3,11 @@ import gql from 'graphql-tag'; const dripListTypeDef = gql` type DripList { account: NftDriverAccount! - chainData: [DripListChainData!]! - } - - type DripListChainData { - chain: SupportedChain! - data: DripListData + chainData: [DripListData!]! } type DripListData { + chain: SupportedChain! name: String! creator: String! description: String diff --git a/src/drip-list/dripListUtils.ts b/src/drip-list/dripListUtils.ts index c52a00e..dede5d9 100644 --- a/src/drip-list/dripListUtils.ts +++ b/src/drip-list/dripListUtils.ts @@ -1,7 +1,4 @@ -import type { - ResolverDripList, - ResolverDripListChainData, -} from '../common/types'; +import type { ResolverDripList, ResolverDripListData } from '../common/types'; import { Driver, type SupportedChain } from '../generated/graphql'; import type { DripListDataValues } from './DripListModel'; @@ -18,39 +15,33 @@ export async function toResolverDripLists( ): Promise { return Promise.all( dripLists.map(async (dripList) => { + const relevantChains = chains.filter((chain) => dripList.chain === chain); + const chainData = await Promise.all( - chains.map(async (chain) => { - if (dripList.chain === chain) { - return { + relevantChains.map( + async (chain) => + ({ chain, - data: { - parentDripListInfo: { - dripListId: dripList.id, - dripListChain: chain, - queriedChains: chains, - }, - name: dripList.name, - creator: dripList.creator, - description: dripList.description, - owner: { - driver: Driver.ADDRESS, - accountId: dripList.ownerAccountId, - address: dripList.ownerAddress as string, - }, - previousOwnerAddress: dripList.previousOwnerAddress, - support: [], // Will be populated by the resolver. - splits: [], // Will be populated by the resolver. - latestVotingRoundId: dripList.latestVotingRoundId, - totalEarned: [], // Will be populated by the resolver. + parentDripListInfo: { + dripListId: dripList.id, + dripListChain: chain, + queriedChains: chains, }, - } as ResolverDripListChainData; - } - - return { - chain, - data: null, - }; - }), + name: dripList.name, + creator: dripList.creator, + description: dripList.description, + owner: { + driver: Driver.ADDRESS, + accountId: dripList.ownerAccountId, + address: dripList.ownerAddress as string, + }, + previousOwnerAddress: dripList.previousOwnerAddress, + support: [], // Will be populated by the resolver. + splits: [], // Will be populated by the resolver. + latestVotingRoundId: dripList.latestVotingRoundId, + totalEarned: [], // Will be populated by the resolver. + }) as ResolverDripListData, + ), ); return { diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 6112d41..d322ee9 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -1,27 +1,26 @@ import type { ProjectId, - ResolverClaimedProjectChainData, ResolverClaimedProjectData, ResolverProject, - ResolverUnClaimedProjectChainData, ResolverUnClaimedProjectData, } from '../common/types'; -import { toResolverProject, toResolverProjects } from './projectUtils'; +import { + mergeProjects, + toResolverProject, + toResolverProjects, +} from './projectUtils'; import shouldNeverHappen from '../utils/shouldNeverHappen'; -import { Driver, SupportedChain } from '../generated/graphql'; +import { Driver } from '../generated/graphql'; import type { - SplitsReceiver, Source, RepoDriverAccount, AddressDriverAccount, - Splits, - Project, AddressReceiver, - DripList, ProjectWhereInput, ProjectSortInput, - ProjectChainData, Avatar, + SupportedChain, + ProjectData, } from '../generated/graphql'; import type { Context } from '../server'; import { AddressDriverSplitReceiverType } from '../models/AddressDriverSplitReceiverModel'; @@ -34,6 +33,7 @@ import assert, { isGitHubUrl, isProjectId } from '../utils/assert'; import { resolveTotalEarned } from '../common/commonResolverLogic'; import { validateChainsQueryArg } from '../utils/commonInputValidators'; import getWithdrawableBalances from '../utils/getWithdrawableBalances'; +import { toResolverDripList } from '../drip-list/dripListUtils'; const projectResolvers = { Query: { @@ -62,27 +62,41 @@ const projectResolvers = { }, projectById: async ( _: undefined, - { id, chain }: { id: ProjectId; chain: SupportedChain }, + { id, chains }: { id: ProjectId; chains?: SupportedChain[] }, { dataSources: { projectsDataSource } }: Context, ): Promise => { assert(isProjectId(id)); - assert(chain in SupportedChain); + if (chains?.length) { + validateChainsQueryArg(chains); + } - const dbProject = await projectsDataSource.getProjectById(id, chain); + const chainsToQuery = chains?.length ? chains : queryableChains; + + const dbProjects = await projectsDataSource.getProjectById( + id, + chainsToQuery, + ); - return dbProject ? toResolverProject(chain, dbProject) : null; + return dbProjects ? mergeProjects(dbProjects, chainsToQuery) : null; }, projectByUrl: async ( _: undefined, - { url, chain }: { url: string; chain: SupportedChain }, + { url, chains }: { url: string; chains?: SupportedChain[] }, { dataSources: { projectsDataSource } }: Context, ): Promise => { assert(isGitHubUrl(url)); - assert(chain in SupportedChain); + if (chains?.length) { + validateChainsQueryArg(chains); + } - const dbProject = await projectsDataSource.getProjectByUrl(url, chain); + const chainsToQuery = chains?.length ? chains : queryableChains; + + const dbProjects = await projectsDataSource.getProjectByUrl( + url, + chainsToQuery, + ); - return dbProject ? toResolverProject(chain, dbProject) : null; + return dbProjects ? mergeProjects(dbProjects, chainsToQuery) : null; }, earnedFunds: async ( _: undefined, @@ -111,37 +125,21 @@ const projectResolvers = { Project: { source: (project: ResolverProject): Source => project.source, account: (project: ResolverProject): RepoDriverAccount => project.account, - chainData: (project: ResolverProject): ProjectChainData[] => - project.chainData, + chainData: (project: ResolverProject): ProjectData[] => project.chainData, }, - ProjectChainData: { - __resolveType(parent: ProjectChainData) { - if ('claimedAt' in parent.data) { - return 'ClaimedProjectChainData'; + ProjectData: { + __resolveType(parent: ProjectData) { + if ('claimedAt' in parent && !!parent.claimedAt) { + return 'ClaimedProjectData'; } - return 'UnClaimedProjectChainData'; + return 'UnClaimedProjectData'; }, }, - ClaimedProjectChainData: { - chain: ( - chainProjectData: ResolverClaimedProjectChainData, - ): SupportedChain => chainProjectData.chain, - data: (chainProjectData: ResolverClaimedProjectChainData) => - chainProjectData.data, - }, - UnClaimedProjectChainData: { - chain: ( - chainProjectData: ResolverUnClaimedProjectChainData, - ): SupportedChain => chainProjectData.chain, - data: (chainProjectData: ResolverUnClaimedProjectChainData) => - chainProjectData.data, - }, ClaimedProjectData: { verificationStatus: (projectData: ResolverClaimedProjectData) => projectData.verificationStatus, - color: (projectData: ResolverClaimedProjectData): string => - projectData.color, + color: (projectData: any): string => projectData.color, description: (projectData: ResolverClaimedProjectData) => projectData.description, emoji: (projectData: ResolverClaimedProjectData): string => @@ -164,11 +162,11 @@ const projectResolvers = { receiversOfTypeDripListDataSource, }, }: Context, - ): Promise => { + ) => { const receiversOfTypeAddressModels = - await receiversOfTypeAddressDataSource.getReceiversOfTypeAddressByProjectId( + await receiversOfTypeAddressDataSource.getReceiversOfTypeAddressByProjectIdOnChain( projectId, - [projectChain], + projectChain, ); const maintainersAndAddressDependencies = groupBy( @@ -196,19 +194,19 @@ const projectResolvers = { ) as AddressReceiver[]) || []; const receiversOfTypeProjectModels = - await receiversOfTypeProjectDataSource.getReceiversOfTypeProjectByProjectId( + await receiversOfTypeProjectDataSource.getReceiversOfTypeProjectByProjectIdOnChain( projectId, - [projectChain], + projectChain, ); const splitsOfTypeProjectModels = - await projectsDataSource.getProjectsByIds( + await projectsDataSource.getProjectsByIdsOnChain( receiversOfTypeProjectModels.map((r) => r.fundeeProjectId), - [projectChain], + projectChain, ); - const dependenciesOfTypeProject = receiversOfTypeProjectModels.map( - (receiver) => ({ + const dependenciesOfTypeProject = await Promise.all( + receiversOfTypeProjectModels.map(async (receiver) => ({ driver: Driver.REPO, weight: receiver.weight, receiverType: receiver.type, @@ -216,38 +214,41 @@ const projectResolvers = { driver: Driver.REPO, accountId: receiver.fundeeProjectId, }, - project: - (splitsOfTypeProjectModels + project: await toResolverProject( + [projectChain], + splitsOfTypeProjectModels .filter( (p): p is ProjectDataValues => p && (p as any).id !== undefined, ) .find( - (p) => (p as any).id === receiver.fundeeProjectId, - ) as unknown as Project) || shouldNeverHappen(), - }), + (p) => p.id === receiver.fundeeProjectId, + ) as unknown as ProjectDataValues, + ), + })), ); const receiversOfTypeDripListModels = - await receiversOfTypeDripListDataSource.getReceiversOfTypeDripListByProjectId( + await receiversOfTypeDripListDataSource.getReceiversOfTypeDripListByProjectIdOnChain( projectId, - [projectChain], + projectChain, ); const splitsOfTypeDripListModels = - await dripListsDataSource.getDripListsByIds( + await dripListsDataSource.getDripListsByIdsOnChain( receiversOfTypeDripListModels.map((r) => r.fundeeDripListId), - [projectChain], + projectChain, ); - const dripListReceivers = receiversOfTypeDripListModels.map( - (receiver) => ({ + const dripListReceivers = await Promise.all( + receiversOfTypeDripListModels.map(async (receiver) => ({ driver: Driver.NFT, weight: receiver.weight, account: { driver: Driver.NFT, accountId: receiver.fundeeDripListId, }, - dripList: + dripList: await toResolverDripList( + projectChain, (splitsOfTypeDripListModels .filter( (l): l is DripListDataValues => @@ -255,8 +256,9 @@ const projectResolvers = { ) .find( (p) => (p as any).id === receiver.fundeeDripListId, - ) as unknown as DripList) || shouldNeverHappen(), - }), + ) as unknown as DripListDataValues) || shouldNeverHappen(), + ), + })), ); return { @@ -273,21 +275,82 @@ const projectResolvers = { parentProjectInfo: { projectId, projectChain }, }: ResolverClaimedProjectData, _: {}, - { dataSources: { projectAndDripListSupportDataSource } }: Context, + { + dataSources: { + projectsDataSource, + dripListsDataSource, + projectAndDripListSupportDataSource, + }, + }: Context, ) => { - const projectAndDripListSupport = - await projectAndDripListSupportDataSource.getProjectAndDripListSupportByProjectId( + // `RepoDriverSplitReceiver`s that represent the Project as a receiver. + const dbRepoDriverSplitReceivers = + await projectAndDripListSupportDataSource.getProjectAndDripListSupportByProjectIdOnChain( projectId, - [projectChain], + projectChain, ); + const projectsAndDripListsSupport = await Promise.all( + dbRepoDriverSplitReceivers.map(async (receiver) => { + const { + funderProjectId, + funderDripListId, + fundeeProjectId, + blockTimestamp, + } = receiver; + + // Support is a Project. + if (funderProjectId && !funderDripListId) { + return { + ...receiver, + account: { + driver: Driver.NFT, + accountId: fundeeProjectId, + }, + date: blockTimestamp, + totalSplit: [], + project: await toResolverProject( + [projectChain], + (await projectsDataSource.getProjectByIdOnChain( + funderProjectId, + projectChain, + )) || shouldNeverHappen(), + ), + }; + // Support is a DripList. + } + if (funderDripListId && !funderProjectId) { + return { + ...receiver, + account: { + driver: Driver.NFT, + accountId: fundeeProjectId, + }, + date: blockTimestamp, + totalSplit: [], + dripList: await toResolverDripList( + projectChain, + (await dripListsDataSource.getDripListById(funderDripListId, [ + projectChain, + ])) || shouldNeverHappen(), + ), + }; + } + + return shouldNeverHappen( + 'Supported is neither a Project nor a DripList.', + ); + }), + ); + + // `GivenEventModelDataValues`s that represent one time donations to the Project. const oneTimeDonationSupport = - await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountId( - [projectChain], + await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountIdOnChain( projectId, + projectChain, ); - return [...projectAndDripListSupport, ...oneTimeDonationSupport]; + return [...projectsAndDripListsSupport, ...oneTimeDonationSupport]; }, totalEarned: async ( projectData: ResolverUnClaimedProjectData, @@ -307,44 +370,88 @@ const projectResolvers = { parentProjectInfo: { projectId, projectChain }, }: ResolverUnClaimedProjectData, _: {}, - { dataSources: { projectAndDripListSupportDataSource } }: Context, + { + dataSources: { + projectsDataSource, + dripListsDataSource, + projectAndDripListSupportDataSource, + }, + }: Context, ) => { - const projectAndDripListSupport = - await projectAndDripListSupportDataSource.getProjectAndDripListSupportByProjectId( + // `RepoDriverSplitReceiver`s that represent the Project as a receiver. + const dbRepoDriverSplitReceivers = + await projectAndDripListSupportDataSource.getProjectAndDripListSupportByProjectIdOnChain( projectId, - [projectChain], + projectChain, ); + const projectsAndDripListsSupport = await Promise.all( + dbRepoDriverSplitReceivers.map(async (receiver) => { + const { + funderProjectId, + funderDripListId, + fundeeProjectId, + blockTimestamp, + } = receiver; + + // Support is a Project. + if (funderProjectId && !funderDripListId) { + return { + ...receiver, + account: { + driver: Driver.NFT, + accountId: fundeeProjectId, + }, + date: blockTimestamp, + totalSplit: [], + project: await toResolverProject( + [projectChain], + (await projectsDataSource.getProjectByIdOnChain( + funderProjectId, + projectChain, + )) || shouldNeverHappen(), + ), + }; + // Support is a DripList. + } + if (funderDripListId && !funderProjectId) { + return { + ...receiver, + account: { + driver: Driver.NFT, + accountId: fundeeProjectId, + }, + date: blockTimestamp, + totalSplit: [], + dripList: await toResolverDripList( + projectChain, + (await dripListsDataSource.getDripListById(funderDripListId, [ + projectChain, + ])) || shouldNeverHappen(), + ), + }; + } + + return shouldNeverHappen( + 'Supported is neither a Project nor a DripList.', + ); + }), + ); + + // `GivenEventModelDataValues`s that represent one time donations to the Project. const oneTimeDonationSupport = - await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountId( - [projectChain], + await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountIdOnChain( projectId, + projectChain, ); - return [...projectAndDripListSupport, ...oneTimeDonationSupport]; + return [...projectsAndDripListsSupport, ...oneTimeDonationSupport]; }, withdrawableBalances: async ({ parentProjectInfo: { projectId, projectChain }, }: ResolverUnClaimedProjectData) => getWithdrawableBalances(projectId, projectChain), }, - SplitsReceiver: { - __resolveType(receiver: SplitsReceiver) { - if (receiver.driver === Driver.REPO) { - return 'ProjectReceiver'; - } - - if (receiver.driver === Driver.NFT) { - return 'DripListReceiver'; - } - - if (receiver.driver === Driver.ADDRESS) { - return 'AddressReceiver'; - } - - return shouldNeverHappen(); - }, - }, Avatar: { __resolveType(parent: { cid: string } | { emoji: string }) { if ('cid' in parent) { diff --git a/src/project/projectTypeDef.ts b/src/project/projectTypeDef.ts index d9ca9a4..0eb2982 100644 --- a/src/project/projectTypeDef.ts +++ b/src/project/projectTypeDef.ts @@ -28,17 +28,13 @@ const projectTypeDef = gql` type Project { source: Source! account: RepoDriverAccount! - chainData: [ProjectChainData!]! + chainData: [ProjectData!]! } - union ProjectChainData = ClaimedProjectChainData | UnClaimedProjectChainData - - type ClaimedProjectChainData { - chain: SupportedChain! - data: ClaimedProjectData! - } + union ProjectData = ClaimedProjectData | UnClaimedProjectData type ClaimedProjectData { + chain: SupportedChain! color: String! emoji: String! @deprecated(reason: "Use avatar instead") avatar: Avatar! @@ -52,12 +48,8 @@ const projectTypeDef = gql` withdrawableBalances: [WithdrawableBalance!]! } - type UnClaimedProjectChainData { - chain: SupportedChain! - data: UnClaimedProjectData! - } - type UnClaimedProjectData { + chain: SupportedChain! verificationStatus: ProjectVerificationStatus! support: [SupportItem!]! withdrawableBalances: [WithdrawableBalance!]! diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 42ffc6b..b1b6e1c 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -1,8 +1,8 @@ import type { Forge, - ResolverClaimedProjectChainData, + ResolverClaimedProjectData, ResolverProject, - ResolverUnClaimedProjectChainData, + ResolverUnClaimedProjectData, } from '../common/types'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import type { ProjectDataValues } from './ProjectModel'; @@ -16,6 +16,7 @@ import type { SupportedChain, Splits, } from '../generated/graphql'; +import { singleOrDefault } from '../utils/linq'; export function splitProjectName(projectName: string): { ownerName: string; @@ -92,6 +93,7 @@ export async function toFakeUnclaimedProjectFromUrl(url: string) { forge, url, verificationStatus: ProjectVerificationStatus.Unclaimed, + isValid: true, } as ProjectDataValues; } @@ -117,73 +119,109 @@ export async function toFakeUnclaimedProject( forge, url: toUrl(forge, name), verificationStatus: ProjectVerificationStatus.Unclaimed, + isValid: true, + chain: project.chain, } as ProjectDataValues; } export async function toResolverProject( - chain: SupportedChain, + chains: SupportedChain[], + project: ProjectDataValues, +) { + const resolverProjects = await toResolverProjects(chains, [project]); + + return singleOrDefault(resolverProjects); +} + +function mapClaimedProjectChainData( project: ProjectDataValues, + projectChain: SupportedChain, + queriedChains: SupportedChain[], +) { + return { + chain: projectChain, + parentProjectInfo: { + projectId: project.id, + queriedChains, + projectChain, + }, + color: project.color, + emoji: project.emoji, + avatar: project.avatarCid + ? { + cid: project.avatarCid, + } + : { + emoji: project.emoji || '💧', + }, + splits: {} as Splits, // Will be populated by the resolver. + description: project.description, + owner: { + driver: Driver.ADDRESS, + accountId: project.ownerAccountId, + address: project.ownerAddress as string, + }, + verificationStatus: project.verificationStatus, + support: [], // Will be populated by the resolver. + claimedAt: project.claimedAt, + totalEarned: [], // Will be populated by the resolver. + withdrawableBalances: [], // Will be populated by the resolver. + } as ResolverClaimedProjectData; +} + +function mapUnClaimedProjectChainData( + fakeUnclaimedProject: ProjectDataValues, + projectChain: SupportedChain, + queriedChains: SupportedChain[], ) { - return (await toResolverProjects([chain], [project]))[0]; + return { + chain: projectChain, + parentProjectInfo: { + queriedChains, + projectId: fakeUnclaimedProject.id, + projectChain, + }, + verificationStatus: fakeUnclaimedProject.verificationStatus, + support: [], // Will be populated by the resolver. + totalEarned: [], // Will be populated by the resolver. + withdrawableBalances: [], // Will be populated by the resolver. + } as ResolverUnClaimedProjectData; } export async function toResolverProjects( chains: SupportedChain[], projects: ProjectDataValues[], ): Promise { - return Promise.all( - projects.map(async (project) => { + const projectsMap = new Map(); + const duplicates = new Map(); + + projects.forEach((project) => { + if (projectsMap.has(project.id)) { + if (!duplicates.has(project.id)) { + duplicates.set(project.id, [projectsMap.get(project.id)!, project]); + projectsMap.delete(project.id); + } else { + duplicates.get(project.id)!.push(project); + } + } else { + projectsMap.set(project.id, project); + } + }); + + const resolverProjects = await Promise.all( + Array.from(projectsMap.values()).map(async (project) => { const chainData = await Promise.all( chains.map(async (chain) => { if (project.chain === chain) { - return { - chain, - data: { - parentProjectInfo: { - projectId: project.id, - queriedChains: chains, - projectChain: chain, - }, - color: project.color, - emoji: project.emoji, - avatar: project.avatarCid - ? { - cid: project.avatarCid, - } - : { - emoji: project.emoji || '💧', - }, - splits: {} as Splits, // Will be populated by the resolver. - description: project.description, - owner: { - driver: Driver.ADDRESS, - accountId: project.ownerAccountId, - address: project.ownerAddress as string, - }, - verificationStatus: project.verificationStatus, - support: [], // Will be populated by the resolver. - claimedAt: project.claimedAt, - totalEarned: [], // Will be populated by the resolver. - withdrawableBalances: [], // Will be populated by the resolver. - }, - } as ResolverClaimedProjectChainData; + return mapClaimedProjectChainData(project, chain, chains); } const fakeUnclaimedProject = await toFakeUnclaimedProject(project); - return { + return mapUnClaimedProjectChainData( + fakeUnclaimedProject, chain, - data: { - parentProjectInfo: { - queriedChains: chains, - projectId: fakeUnclaimedProject.id, - projectChain: chain, - }, - verificationStatus: fakeUnclaimedProject.verificationStatus, - support: [], // Will be populated by the resolver. - totalEarned: [], // Will be populated by the resolver. - withdrawableBalances: [], // Will be populated by the resolver. - }, - } as ResolverUnClaimedProjectChainData; + chains, + ); }), ); @@ -204,4 +242,67 @@ export async function toResolverProjects( } as ResolverProject; }), ); + + const mergedProject = await Promise.all( + Array.from(duplicates.values()).map(async (p) => mergeProjects(p, chains)), + ); + + return resolverProjects.concat(mergedProject); +} + +export async function mergeProjects( + projects: ProjectDataValues[], + chains: SupportedChain[], +) { + if (projects.some((p) => p.id !== projects[0].id)) { + throw new Error('All projects should have the same id when merging.'); + } + + // It doesn't matter which project we choose as the base. This will only be used for the common, chain-agnostic, properties. + const projectBase = projects[0]; + + const chainData = [] as ( + | ResolverClaimedProjectData + | ResolverUnClaimedProjectData + )[]; + + await Promise.all( + chains.map(async (chain) => { + let projectOnChain = projects.filter((p) => p.chain === chain)[0]; + + if (projectOnChain?.claimedAt) { + chainData.push( + mapClaimedProjectChainData(projectOnChain, chain, chains), + ); + } else { + if (!projectOnChain) { + projectOnChain = await toFakeUnclaimedProjectFromUrl( + projectBase.url!, + ); + } + + chainData.push( + mapUnClaimedProjectChainData(projectOnChain, chain, chains), + ); + } + }), + ); + + const mergedProject = { + account: { + accountId: projectBase.id, + driver: Driver.REPO, + }, + source: { + url: projectBase.url || shouldNeverHappen(), + repoName: splitProjectName(projectBase.name || shouldNeverHappen()) + .repoName, + ownerName: splitProjectName(projectBase.name || shouldNeverHappen()) + .ownerName, + forge: (projectBase.forge as GraphQlForge) || shouldNeverHappen(), + }, + chainData, + } as ResolverProject; + + return mergedProject; } diff --git a/src/project/projectValidators.ts b/src/project/projectValidators.ts index 1cf2369..7771661 100644 --- a/src/project/projectValidators.ts +++ b/src/project/projectValidators.ts @@ -40,7 +40,7 @@ export default function validateProjectsInput( throw new Error('Invalid sort field.'); } - if (sort?.direction && sort.direction in SortDirection) { + if (sort?.direction && sort.direction in Object.values(SortDirection)) { throw new Error('Invalid sort direction.'); } diff --git a/src/resolvers.ts b/src/resolvers.ts index a516987..0e01475 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -10,17 +10,17 @@ const resolvers = { ...projectResolvers.Query, ...dripListResolvers.Query, ...userResolvers.Query, + ...streamResolvers.Query, }, Project: projectResolvers.Project, - ProjectChainData: projectResolvers.ProjectChainData, + ProjectReceiver: commonResolvers.ProjectReceiver, + ProjectData: projectResolvers.ProjectData, ClaimedProjectData: projectResolvers.ClaimedProjectData, - ClaimedProjectChainData: projectResolvers.ClaimedProjectChainData, UnClaimedProjectData: projectResolvers.UnClaimedProjectData, - UnClaimedProjectChainData: projectResolvers.UnClaimedProjectChainData, DripList: dripListResolvers.DripList, - DripListChainData: dripListResolvers.DripListChainData, + DripListReceiver: commonResolvers.DripListReceiver, DripListData: dripListResolvers.DripListData, - SplitsReceiver: projectResolvers.SplitsReceiver, + SplitsReceiver: commonResolvers.SplitsReceiver, SupportItem: commonResolvers.SupportItem, Avatar: projectResolvers.Avatar, ProjectSupport: commonResolvers.ProjectSupport, @@ -29,11 +29,11 @@ const resolvers = { OneTimeDonationSupport: commonResolvers.OneTimeDonationSupport, Date: dateScalar, User: userResolvers.User, - UserChainData: userResolvers.UserChainData, UserData: userResolvers.UserData, UserStreams: userResolvers.UserStreams, Stream: streamResolvers.Stream, StreamReceiver: userResolvers.StreamReceiver, + AddressReceiver: commonResolvers.AddressReceiver, }; export default resolvers; diff --git a/src/schema.ts b/src/schema.ts index 76c8761..9615ea6 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -13,8 +13,8 @@ const rootTypeDef = gql` where: ProjectWhereInput sort: ProjectSortInput ): [Project!]! - projectById(id: ID!, chain: SupportedChain!): Project - projectByUrl(url: String!, chain: SupportedChain!): Project + projectById(id: ID!, chains: [SupportedChain!]): Project + projectByUrl(url: String!, chains: [SupportedChain!]): Project earnedFunds(projectId: String!, chains: [SupportedChain!]): [ChainAmount!]! dripLists( chains: [SupportedChain!] @@ -27,7 +27,10 @@ const rootTypeDef = gql` ): MintedTokens! userById(accountId: ID!, chains: [SupportedChain!]): User! userByAddress(address: String!, chains: [SupportedChain!]): User! - streams(where: StreamWhereInput): [Stream!]! + streams( + where: StreamWhereInput + chains: [SupportedChain!] + ): [StreamChainData!]! } `; diff --git a/src/stream/StreamsDataSource.ts b/src/stream/StreamsDataSource.ts index 405f6ff..fbbd91b 100644 --- a/src/stream/StreamsDataSource.ts +++ b/src/stream/StreamsDataSource.ts @@ -34,7 +34,10 @@ export default class StreamsDataSource { chains: SupportedChain[], where: StreamWhereInput, ) { - const streams = {} as Record; + const streams = chains.reduce( + (acc, chain) => ({ ...acc, [chain]: [] }), + {} as Record, + ); if (!where.senderId && !where.receiverId) { throw new Error( diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index d67facb..5352422 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -1,12 +1,36 @@ +import queryableChains from '../common/queryableChains'; import type { AddressDriverId, DripListId } from '../common/types'; import { toResolverDripList } from '../drip-list/dripListUtils'; +import type { StreamWhereInput, SupportedChain } from '../generated/graphql'; import { Driver } from '../generated/graphql'; import type { Context } from '../server'; import toResolverUser from '../user/userUtils'; import type { ProtoStream } from '../utils/buildAssetConfigs'; import shouldNeverHappen from '../utils/shouldNeverHappen'; +import verifyStreamsInput from './streamValidators'; const streamResolvers = { + Query: { + streams: async ( + _: any, + { where, chains }: { where: StreamWhereInput; chains?: SupportedChain[] }, + { dataSources: { streamsDataSource } }: Context, + ) => { + verifyStreamsInput({ where, chains }); + + const chainsToQuery = chains?.length ? chains : queryableChains; + + const streamsByChain = await streamsDataSource.getStreamsByFilter( + chainsToQuery, + where, + ); + + return Object.entries(streamsByChain).map(([chain, streams]) => ({ + chain, + data: streams, + })); + }, + }, Stream: { receiver: async ( { chain, receiver }: ProtoStream, @@ -20,8 +44,8 @@ const streamResolvers = { if (receiver.driver === Driver.NFT) { const dbDripList = await dataSources.dripListsDataSource.getDripListById( - [chain], receiver.accountId as DripListId, + [chain], ); return toResolverDripList(chain, dbDripList); diff --git a/src/stream/streamTypeDef.ts b/src/stream/streamTypeDef.ts index 1998cc9..b60edee 100644 --- a/src/stream/streamTypeDef.ts +++ b/src/stream/streamTypeDef.ts @@ -40,6 +40,11 @@ const streamTypeDef = gql` endsAt: Date } + type StreamChainData { + chain: SupportedChain! + data: [Stream!]! + } + input StreamWhereInput { senderId: ID receiverId: ID diff --git a/src/stream/streamValidators.ts b/src/stream/streamValidators.ts new file mode 100644 index 0000000..9e5db15 --- /dev/null +++ b/src/stream/streamValidators.ts @@ -0,0 +1,21 @@ +import { isAccountId } from '../utils/assert'; +import { validateChainsQueryArg } from '../utils/commonInputValidators'; +import type streamResolvers from './streamResolvers'; + +export default function verifyStreamsInput( + dripsListsQueryArgs: Parameters[1], +) { + const { where, chains } = dripsListsQueryArgs; + + if (where?.receiverId && !isAccountId(where.receiverId)) { + throw new Error('Invalid receiver id.'); + } + + if (where?.senderId && !isAccountId(where.senderId)) { + throw new Error('Invalid sender id.'); + } + + if (chains?.length) { + validateChainsQueryArg(chains); + } +} diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index 4fde81e..85972f0 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -5,28 +5,32 @@ import type { Address, AddressDriverId, ResolverUser, - ResolverUserChainData, ResolverUserData, UserDataParentDripListInfo, } from '../common/types'; -import DripListModel from '../drip-list/DripListModel'; +import type DripListModel from '../drip-list/DripListModel'; import type { SupportedChain, AddressDriverAccount, User, } from '../generated/graphql'; +import { Driver } from '../generated/graphql'; import type { Context } from '../server'; import assert, { isAddressDriverId } from '../utils/assert'; import getAssetConfigs from '../utils/getAssetConfigs'; import getUserAddress from '../utils/getUserAddress'; import queryableChains from '../common/queryableChains'; -import { toResolverProjects } from '../project/projectUtils'; -import { toResolverDripLists } from '../drip-list/dripListUtils'; +import { toResolverProject, toResolverProjects } from '../project/projectUtils'; +import { + toResolverDripList, + toResolverDripLists, +} from '../drip-list/dripListUtils'; import getLatestAccountMetadataByChain from '../utils/getLatestAccountMetadata'; import { validateChainsQueryArg } from '../utils/commonInputValidators'; import toResolverUser from './userUtils'; import { getCrossChainAddressDriverAccountIdByAddress } from '../common/dripsContracts'; import getWithdrawableBalances from '../utils/getWithdrawableBalances'; +import shouldNeverHappen from '../utils/shouldNeverHappen'; const userResolvers = { Query: { @@ -65,12 +69,7 @@ const userResolvers = { }, User: { account: (user: ResolverUser): AddressDriverAccount => user.account, - chainData: (user: ResolverUser): ResolverUserChainData[] => user.chainData, - }, - UserChainData: { - chain: (chainUserData: ResolverUserChainData): SupportedChain => - chainUserData.chain, - data: (chainUserData: ResolverUserChainData) => chainUserData.data, + chainData: (user: ResolverUser): ResolverUserData[] => user.chainData, }, UserData: { streams: async ({ @@ -97,16 +96,14 @@ const userResolvers = { const assetConfigs = await getAssetConfigs( accountId as AddressDriverId, metadata, + [userChain], ); - return Object.entries(assetConfigs).map(([chain, chainAssetConfigs]) => ({ - chain: chain as SupportedChain, - - assetConfigs: chainAssetConfigs.map((ac) => ({ - tokenAddress: ac.tokenAddress, - incoming: [], - outgoing: assetOutgoingBalanceTimeline(ac.history), - })), + return assetConfigs[userChain].map((assetConfig) => ({ + chain: userChain, + tokenAddress: assetConfig.tokenAddress, + incoming: [], + outgoing: assetOutgoingBalanceTimeline(assetConfig.history), })); }, projects: async ( @@ -140,28 +137,88 @@ const userResolvers = { support: async ( { parentUserInfo: { accountId, userChain } }: ResolverUserData, _: {}, - { dataSources: { projectAndDripListSupportDataSource } }: Context, + { + dataSources: { + projectsDataSource, + dripListsDataSource, + projectAndDripListSupportDataSource, + }, + }: Context, ) => { - const projectAndDripListSupport = - await projectAndDripListSupportDataSource.getProjectAndDripListSupportByAddressDriverId( - [userChain], + // `RepoDriverSplitReceiver`s that represent the Project as a receiver. + const dbAddressDriverSplitReceivers = + await projectAndDripListSupportDataSource.getProjectAndDripListSupportByAddressDriverIdOnChain( accountId as AddressDriverId, + userChain, ); + const projectsAndDripListsSupport = await Promise.all( + dbAddressDriverSplitReceivers.map(async (receiver) => { + const { + funderProjectId, + funderDripListId, + fundeeAccountId, + blockTimestamp, + } = receiver; + + // Supported is a Project. + if (funderProjectId && !funderDripListId) { + return { + ...receiver, + account: { + driver: Driver.NFT, + accountId: fundeeAccountId, + }, + date: blockTimestamp, + totalSplit: [], + project: await toResolverProject( + [userChain], + (await projectsDataSource.getProjectByIdOnChain( + funderProjectId, + userChain, + )) || shouldNeverHappen(), + ), + }; + // Supported is a DripList. + } + if (funderDripListId && !funderProjectId) { + return { + ...receiver, + account: { + driver: Driver.NFT, + accountId: fundeeAccountId, + }, + date: blockTimestamp, + totalSplit: [], + dripList: await toResolverDripList( + userChain, + (await dripListsDataSource.getDripListById(funderDripListId, [ + userChain, + ])) || shouldNeverHappen(), + ), + }; + } + + return shouldNeverHappen( + 'Supported is neither a Project nor a DripList.', + ); + }), + ); + const oneTimeDonationSupport = - await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountId( - [userChain], + await projectAndDripListSupportDataSource.getOneTimeDonationSupportByAccountIdOnChain( accountId as AccountId, + userChain, ); const streamSupport = - await projectAndDripListSupportDataSource.getStreamSupportByAccountId( - [userChain], + await projectAndDripListSupportDataSource.getStreamSupportByAccountIdOnChain( accountId as AccountId, + userChain, ); return [ - ...projectAndDripListSupport, + ...projectsAndDripListsSupport, ...streamSupport, ...oneTimeDonationSupport, ]; @@ -205,7 +262,7 @@ const userResolvers = { }, StreamReceiver: { __resolveType(parent: DripListModel | User) { - if (parent instanceof DripListModel) { + if ('account' in parent && parent.account.driver === Driver.NFT) { return 'DripList'; } diff --git a/src/user/userTypeDef.ts b/src/user/userTypeDef.ts index 290c860..adc60d4 100644 --- a/src/user/userTypeDef.ts +++ b/src/user/userTypeDef.ts @@ -20,15 +20,11 @@ const userTypeDef = gql` type User { account: AddressDriverAccount! - chainData: [UserChainData!]! - } - - type UserChainData { - chain: SupportedChain! - data: UserData + chainData: [UserData!]! } type UserData { + chain: SupportedChain! streams: UserStreams! projects: [Project]! dripLists: [DripList]! diff --git a/src/user/userUtils.ts b/src/user/userUtils.ts index f91d2a4..8be9162 100644 --- a/src/user/userUtils.ts +++ b/src/user/userUtils.ts @@ -14,22 +14,20 @@ export default function toResolverUser( }, chainData: chains.map((chain) => ({ chain, - data: { - parentUserInfo: { - accountId, - queriedChains: chains, - userChain: chain, - }, - balances: [], // Will be populated by the resolver. - dripLists: [], // Will be populated by the resolver. - projects: [], // Will be populated by the resolver. - streams: { - incoming: [], // Will be populated by the resolver. - outgoing: [], // Will be populated by the resolver. - }, - support: [], // Will be populated by the resolver. - withdrawableBalances: [], // Will be populated by the resolver. + parentUserInfo: { + accountId, + queriedChains: chains, + userChain: chain, }, + balances: [], // Will be populated by the resolver. + dripLists: [], // Will be populated by the resolver. + projects: [], // Will be populated by the resolver. + streams: { + incoming: [], // Will be populated by the resolver. + outgoing: [], // Will be populated by the resolver. + }, + support: [], // Will be populated by the resolver. + withdrawableBalances: [], // Will be populated by the resolver. })), }; } diff --git a/src/utils/getAssetConfigs.ts b/src/utils/getAssetConfigs.ts index 4a537a1..b79432c 100644 --- a/src/utils/getAssetConfigs.ts +++ b/src/utils/getAssetConfigs.ts @@ -1,8 +1,8 @@ import type { AddressDriverId } from '../common/types'; +import streamsSetEventsQueries from '../dataLoaders/sqlQueries/streamsSetEventsQueries'; import type { SupportedChain } from '../generated/graphql'; import buildAssetConfigs from './buildAssetConfigs'; import type getLatestAccountMetadataByChain from './getLatestAccountMetadata'; -import getStreamsSetEventsWithReceivers from './getStreamsSetEventsWithReceivers'; import groupBy from './linq'; export default async function getAssetConfigs( @@ -10,15 +10,13 @@ export default async function getAssetConfigs( accountMetadata: NonNullable< Awaited> >, + chains: SupportedChain[], ): Promise>> { - const chainsToQuery = Object.keys(accountMetadata) as SupportedChain[]; - - if (!chainsToQuery.length) { - return {} as Record>; - } - const accountStreamsSetEventsWithReceivers = - await getStreamsSetEventsWithReceivers(chainsToQuery, accountId); + await streamsSetEventsQueries.getStreamsSetEventsWithReceivers( + chains, + accountId, + ); const accountStreamsSetEventsWithReceiversByErc20 = groupBy( accountStreamsSetEventsWithReceivers, @@ -30,7 +28,7 @@ export default async function getAssetConfigs( ReturnType >; - chainsToQuery.forEach((chain) => { + chains.forEach((chain) => { response[chain] = buildAssetConfigs( accountId, accountMetadata[chain]?.metadata, diff --git a/src/utils/getStreamsSetEventsWithReceivers.ts b/src/utils/getStreamsSetEventsWithReceivers.ts deleted file mode 100644 index 7ab2490..0000000 --- a/src/utils/getStreamsSetEventsWithReceivers.ts +++ /dev/null @@ -1,110 +0,0 @@ -import { QueryTypes } from 'sequelize'; -import type { - AddressDriverId, - StreamsSetEventWithReceivers, -} from '../common/types'; -import type { StreamReceiverSeenEventModelDataValues } from '../models/StreamReceiverSeenEventModel'; -import StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; -import type { SupportedChain } from '../generated/graphql'; -import { dbConnection } from '../database/connectToDatabase'; -import streamsSetEventsQueries from '../dataLoaders/sqlQueries/streamsSetEventsQueries'; - -export default async function getStreamsSetEventsWithReceivers( - chains: SupportedChain[], - accountId: AddressDriverId, -): Promise { - const sortedAccountStreamSetEventModelDataValues = - await streamsSetEventsQueries.getByAccountIdSorted(chains, accountId); - - const uniqueReceiversHashes = [ - ...new Set( - sortedAccountStreamSetEventModelDataValues.map( - (event) => event.receiversHash, - ), - ), - ]; - - // Define base SQL to query from multiple chains (schemas). - const baseStreamReceiverSeenEventModelSQL = (schema: SupportedChain) => ` - SELECT *, '${schema}' AS chain FROM "${schema}"."StreamReceiverSeenEvents"`; - - // Initialize the WHERE clause parts. - const streamReceiverSeenEventModelConditions: string[] = [ - '"receiversHash" IN (:uniqueReceiversHashes)', - ]; - const streamReceiverSeenEventModelParameters: { [key: string]: any } = { - uniqueReceiversHashes, - }; - - // Build the where clause. - const streamReceiverSeenEventModelWhereClause = ` WHERE ${streamReceiverSeenEventModelConditions.join( - ' AND ', - )}`; - - // Build the SQL for each specified schema. - const streamReceiverSeenEventModelQueries = chains.map( - (chain) => - `${ - baseStreamReceiverSeenEventModelSQL(chain) + - streamReceiverSeenEventModelWhereClause - }`, - ); - - // Combine all schema queries with UNION. - const fullQueryStreamReceiverSeenEventModelQuery = `${streamReceiverSeenEventModelQueries.join( - ' UNION ', - )}`; - - const streamReceiverSeenEventModelDataValues = ( - await dbConnection.query(fullQueryStreamReceiverSeenEventModelQuery, { - type: QueryTypes.SELECT, - replacements: streamReceiverSeenEventModelParameters, - mapToModel: true, - model: StreamReceiverSeenEventModel, - }) - ).map((p) => p.dataValues as StreamReceiverSeenEventModelDataValues); - - const receiversGroupedByHash = streamReceiverSeenEventModelDataValues.reduce<{ - [receiversHash: string]: StreamReceiverSeenEventModelDataValues[]; - }>((acc, receiver) => { - if (!acc[receiver.receiversHash]) { - acc[receiver.receiversHash] = []; - } - acc[receiver.receiversHash].push(receiver); - return acc; - }, {}); - - Object.keys(receiversGroupedByHash).forEach((hash) => { - receiversGroupedByHash[hash] = [ - ...new Map( - receiversGroupedByHash[hash].map((receiver) => [ - receiver.config, - receiver, - ]), - ).values(), - ]; - }); - - const streamsSetEventsWithReceivers = - sortedAccountStreamSetEventModelDataValues.reduce< - StreamsSetEventWithReceivers[] - >( - (acc, streamsSetEvent) => [ - ...acc, - { - accountId: streamsSetEvent.accountId, - erc20: streamsSetEvent.erc20, - receiversHash: streamsSetEvent.receiversHash, - streamsHistoryHash: streamsSetEvent.streamsHistoryHash, - balance: streamsSetEvent.balance, - maxEnd: streamsSetEvent.maxEnd, - blockTimestamp: streamsSetEvent.blockTimestamp, - receivers: - receiversGroupedByHash[streamsSetEvent.receiversHash] || [], - }, - ], - [], - ); - - return streamsSetEventsWithReceivers; -} diff --git a/src/utils/getUserAccount.ts b/src/utils/getUserAccount.ts index a416e02..92fe13d 100644 --- a/src/utils/getUserAccount.ts +++ b/src/utils/getUserAccount.ts @@ -15,6 +15,7 @@ export default async function getUserAccount( const assetConfigsByChain = await getAssetConfigs( accountId, latestAccountMetadataByChain, + chains, ); const response = {} as Record< diff --git a/src/utils/linq.ts b/src/utils/linq.ts index 680bec9..7d5bdbb 100644 --- a/src/utils/linq.ts +++ b/src/utils/linq.ts @@ -14,3 +14,15 @@ export default function groupBy( }); return map; } + +export function singleOrDefault(array: T[]): T | null { + if (array.length === 1) { + return array[0]; + } + + if (array.length === 0) { + return null; + } + + throw new Error('The array contains more than one element.'); +} From 6956ae395c39011dd880552eadc480b407867177 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 20 Jun 2024 12:15:39 +0200 Subject: [PATCH 22/37] refactor: remove direct usage of endpoint chain argument # Conflicts: # src/drip-list/dripListResolvers.ts # src/project/projectResolvers.ts # src/user/userResolvers.ts # src/utils/getLatestAccountMetadata.ts # src/utils/getWithdrawableBalances.ts --- .env.template | 2 +- src/common/appSettings.ts | 11 ++++--- src/common/commonResolverLogic.ts | 6 ++-- src/common/commonResolvers.ts | 15 +++++---- src/common/commonTypeDef.ts | 8 ++--- src/common/constants.ts | 7 +++++ src/common/dripsContracts.ts | 8 ++--- src/common/types.ts | 24 +++++++------- src/dataLoaders/DripListsDataSource.ts | 12 ++++--- src/dataLoaders/GivenEventsDataSource.ts | 9 +++--- .../ProjectAndDripListSupportDataSource.ts | 16 +++++----- src/dataLoaders/ProjectsDataSource.ts | 30 +++++++++++------- .../ReceiversOfTypeAddressDataSource.ts | 6 ++-- .../ReceiversOfTypeDripListDataSource.ts | 6 ++-- .../ReceiversOfTypeProjectDataSource.ts | 6 ++-- src/dataLoaders/TotalEarnedDataSource.ts | 4 +-- .../accountMetadataEmittedEventsQueries.ts | 7 ++--- .../addressDriverSplitReceiversQueries.ts | 16 +++++----- .../dripListSplitReceiversQueries.ts | 20 +++++------- .../sqlQueries/dripListsQueries.ts | 15 ++++----- .../sqlQueries/givenEventsQueries.ts | 24 +++++++------- src/dataLoaders/sqlQueries/projectsQueries.ts | 15 +++++---- .../repoDriverSplitReceiversQueries.ts | 15 +++++---- .../sqlQueries/splitEventsQueries.ts | 19 ++++++------ .../streamReceiverSeenEventQueries.ts | 7 ++--- .../sqlQueries/streamsSetEventsQueries.ts | 18 +++++------ src/drip-list/dripListResolvers.ts | 23 ++++++++++---- src/drip-list/dripListUtils.ts | 15 ++++++--- src/given-event/givenEventResolvers.ts | 7 +++-- src/given-event/givesUtils.ts | 12 ++++--- src/project/projectResolvers.ts | 31 ++++++++++++------- src/project/projectUtils.ts | 26 +++++++--------- src/stream/StreamsDataSource.ts | 21 ++++++------- src/stream/streamResolvers.ts | 7 +++-- src/user/UserDataSource.ts | 8 ++--- src/user/userResolvers.ts | 17 ++++++---- src/user/userUtils.ts | 9 +++--- src/utils/buildAssetConfigs.ts | 8 ++--- src/utils/chainSchemaMappings.ts | 16 ++++++++++ src/utils/commonInputValidators.ts | 5 +-- src/utils/getAssetConfigs.ts | 12 +++---- src/utils/getLatestAccountMetadata.ts | 11 +++---- src/utils/getUserAccount.ts | 17 +++++----- src/utils/getWithdrawableBalances.ts | 8 ++--- src/utils/mergeAmounts.ts | 4 +-- src/utils/parseMultiChainKeys.ts | 5 ++- src/utils/streamUtils.ts | 4 +-- src/utils/streams.ts | 7 ++--- 48 files changed, 321 insertions(+), 278 deletions(-) create mode 100644 src/utils/chainSchemaMappings.ts diff --git a/.env.template b/.env.template index fb7580d..e45c1df 100644 --- a/.env.template +++ b/.env.template @@ -1,6 +1,6 @@ PORT=string # Optional. The API server port. Defaults to 8080. -NETWORK=string # Required. The network to connect to. See `SupportedNetworks` in `types.ts` for supported networks. +NETWORK=string # Required. The network to connect to. See `SupportedChains` in `types.ts` for supported networks. # You should provide at least one of the following RPC URLs: RPC_URL_MAINNET=string # The RPC URL for the Mainnet provider. diff --git a/src/common/appSettings.ts b/src/common/appSettings.ts index 2707d18..190990c 100644 --- a/src/common/appSettings.ts +++ b/src/common/appSettings.ts @@ -1,15 +1,16 @@ import dotenv from 'dotenv'; +import type { SupportedChain } from '../generated/graphql'; dotenv.config({ path: `.env.${process.env.ENV}` }); export default { port: (process.env.PORT || 8080) as number, rpcUrls: { - mainnet: process.env.RPC_URL_MAINNET, - sepolia: process.env.RPC_URL_SEPOLIA, - optimism_sepolia: process.env.RPC_URL_OPTIMISM_SEPOLIA, - polygon_amoy: process.env.RPC_URL_POLYGON_AMOY, - }, + MAINNET: process.env.RPC_URL_MAINNET, + SEPOLIA: process.env.RPC_URL_SEPOLIA, + OPTIMISM_SEPOLIA: process.env.RPC_URL_OPTIMISM_SEPOLIA, + POLYGON_AMOY: process.env.RPC_URL_POLYGON_AMOY, + } as Record, publicApiKeys: process.env.PUBLIC_API_KEYS?.split(',') || [], dripsApiKey: process.env.DRIPS_API_KEY, postgresConnectionString: process.env.POSTGRES_CONNECTION_STRING, diff --git a/src/common/commonResolverLogic.ts b/src/common/commonResolverLogic.ts index 8af0bdd..08fdbc5 100644 --- a/src/common/commonResolverLogic.ts +++ b/src/common/commonResolverLogic.ts @@ -1,4 +1,5 @@ import type { + DbSchema, DripListId, ProjectId, ResolverDripListData, @@ -9,11 +10,10 @@ import mergeAmounts from '../utils/mergeAmounts'; import DripListSplitReceiverModel from '../models/DripListSplitReceiverModel'; import RepoDriverSplitReceiverModel from '../models/RepoDriverSplitReceiverModel'; import shouldNeverHappen from '../utils/shouldNeverHappen'; -import type { SupportedChain } from '../generated/graphql'; import splitEventsQueries from '../dataLoaders/sqlQueries/splitEventsQueries'; export async function resolveTotalSplit( - chains: SupportedChain[], + chains: DbSchema[], parent: DripListSplitReceiverModel | RepoDriverSplitReceiverModel, ) { let incomingAccountId: DripListId | ProjectId; @@ -57,7 +57,7 @@ export async function resolveTotalEarned( context: Context, ) { let accountId: ProjectId | DripListId; - let chain: SupportedChain; + let chain: DbSchema; if ('parentProjectInfo' in projectOrDripListData) { accountId = projectOrDripListData.parentProjectInfo.projectId; chain = projectOrDripListData.parentProjectInfo.projectChain; diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index bcdb093..84e7bd6 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -6,12 +6,11 @@ import type { Project, RepoDriverAccount, SplitsReceiver, - SupportedChain, } from '../generated/graphql'; import { Driver } from '../generated/graphql'; import type { Context } from '../server'; import shouldNeverHappen from '../utils/shouldNeverHappen'; -import type { AddressDriverId, DripListId, ProjectId } from './types'; +import type { AddressDriverId, DbSchema, DripListId, ProjectId } from './types'; import { DependencyType } from './types'; import getUserAddress from '../utils/getUserAddress'; import type { ProtoStream } from '../utils/buildAssetConfigs'; @@ -23,9 +22,9 @@ import type { AddressDriverSplitReceiverModelDataValues } from '../models/Addres import { AddressDriverSplitReceiverType } from '../models/AddressDriverSplitReceiverModel'; import splitEventsQueries from '../dataLoaders/sqlQueries/splitEventsQueries'; import type projectResolvers from '../project/projectResolvers'; -import type dripListResolvers from '../drip-list/dripListResolvers'; import type { DripListSplitReceiverModelDataValues } from '../models/DripListSplitReceiverModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; +import type dripListResolvers from '../drip-list/dripListResolvers'; async function resolveTotalSplit( parent: @@ -133,7 +132,7 @@ const commonResolvers = { account: async ( parent: { funderProjectId: ProjectId; - chain: SupportedChain; + chain: DbSchema; }, _: any, context: Context, @@ -160,8 +159,8 @@ const commonResolvers = { project: async ( parent: { funderProjectId: ProjectId; - chain: SupportedChain; - queriedChains: SupportedChain[]; + chain: DbSchema; + queriedChains: DbSchema[]; }, _: any, context: Context, @@ -189,7 +188,7 @@ const commonResolvers = { account: async ( parent: { funderDripListId: DripListId; - chain: SupportedChain; + chain: DbSchema; }, _: any, context: Context, @@ -213,7 +212,7 @@ const commonResolvers = { date: (parent: { blockTimestamp: Date }): Date => parent.blockTimestamp, weight: (parent: { weight: number }): number => parent.weight, dripList: async ( - parent: { funderDripListId: DripListId; chain: SupportedChain }, + parent: { funderDripListId: DripListId; chain: DbSchema }, _: any, context: Context, ) => { diff --git a/src/common/commonTypeDef.ts b/src/common/commonTypeDef.ts index 297fb72..1639c14 100644 --- a/src/common/commonTypeDef.ts +++ b/src/common/commonTypeDef.ts @@ -132,10 +132,10 @@ const commonTypeDef = gql` } enum SupportedChain { - mainnet - sepolia - optimism_sepolia - polygon_amoy + MAINNET + SEPOLIA + OPTIMISM_SEPOLIA + POLYGON_AMOY } type WithdrawableBalance { diff --git a/src/common/constants.ts b/src/common/constants.ts index 1370d0d..13ac75a 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -29,3 +29,10 @@ export const FORGES_MAP = { } as const; export const AMT_PER_SEC_MULTIPLIER = 1_000_000_000; + +export const DB_SCHEMAS = [ + 'mainnet', + 'sepolia', + 'optimism_sepolia', + 'polygon_amoy', +] as const; diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts index c943cf3..d4cb640 100644 --- a/src/common/dripsContracts.ts +++ b/src/common/dripsContracts.ts @@ -25,22 +25,22 @@ const chainConfigs: Record< repoDriverAddress: string; } > = { - mainnet: { + MAINNET: { dripsAddress: '0xd0Dd053392db676D57317CD4fe96Fc2cCf42D0b4', addressDriverAddress: '0x1455d9bD6B98f95dd8FEB2b3D60ed825fcef0610', repoDriverAddress: '0x770023d55D09A9C110694827F1a6B32D5c2b373E', }, - sepolia: { + SEPOLIA: { dripsAddress: '0x74A32a38D945b9527524900429b083547DeB9bF4', addressDriverAddress: '0x70E1E1437AeFe8024B6780C94490662b45C3B567', repoDriverAddress: '0xa71bdf410D48d4AA9aE1517A69D7E1Ef0c179b2B', }, - optimism_sepolia: { + OPTIMISM_SEPOLIA: { dripsAddress: '0x74A32a38D945b9527524900429b083547DeB9bF4', addressDriverAddress: '0x70E1E1437AeFe8024B6780C94490662b45C3B567', repoDriverAddress: '0xa71bdf410D48d4AA9aE1517A69D7E1Ef0c179b2B', }, - polygon_amoy: { + POLYGON_AMOY: { dripsAddress: '0xeebCd570e50fa31bcf6eF10f989429C87C3A6981', addressDriverAddress: '0x004310a6d47893Dd6e443cbE471c24aDA1e6c619', repoDriverAddress: '0x54372850Db72915Fd9C5EC745683EB607b4a8642', diff --git a/src/common/types.ts b/src/common/types.ts index ee89d11..56a3199 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -5,13 +5,12 @@ import type { DripListData, Give, Project, - SupportedChain, UnClaimedProjectData, User, UserData, } from '../generated/graphql'; import type StreamReceiverSeenEventModel from '../models/StreamReceiverSeenEventModel'; -import type { FORGES_MAP } from './constants'; +import type { DB_SCHEMAS, FORGES_MAP } from './constants'; import type { addressDriverAccountMetadataParser } from '../schemas'; import type StreamsSetEventModel from '../models/StreamsSetEventModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; @@ -33,7 +32,6 @@ export type Address = string & { __brand: 'Address' }; export type BigIntString = string & { __brand: 'BigIntString' }; export type Forge = ValuesOf; -export type DbSchema = SupportedChain; export enum DependencyType { ProjectDependency = 'ProjectDependency', @@ -79,8 +77,8 @@ export type ResolverProject = Project & { type ProjectDataParentProjectInfo = { parentProjectInfo: { projectId: ProjectId; - projectChain: SupportedChain; - queriedChains: SupportedChain[]; + projectChain: DbSchema; + queriedChains: DbSchema[]; }; }; @@ -92,7 +90,7 @@ export type ResolverUnClaimedProjectData = UnClaimedProjectData & export interface MultiChainKey { id: T; - chains: SupportedChain[]; + chains: DbSchema[]; } export type ProjectMultiChainKey = MultiChainKey; export type DripListMultiChainKey = MultiChainKey; @@ -104,8 +102,8 @@ export type ResolverDripList = DripList & { type DripListDataParentDripListInfo = { parentDripListInfo: { dripListId: DripListId; - dripListChain: SupportedChain; - queriedChains: SupportedChain[]; + dripListChain: DbSchema; + queriedChains: DbSchema[]; }; }; @@ -115,7 +113,7 @@ export type ResolverDripListData = DripListData & export type CommonDataValues = { createdAt: Date; updatedAt: Date; - chain: SupportedChain; + chain: DbSchema; }; export type ResolverGive = Give & { @@ -123,7 +121,7 @@ export type ResolverGive = Give & { }; export type ResolverGiveChainData = { - chain: SupportedChain; + chain: DbSchema; data: GivenEventModelDataValues | null; }; @@ -136,7 +134,9 @@ export type ResolverUserData = UserData & UserDataParentDripListInfo; export type UserDataParentDripListInfo = { parentUserInfo: { accountId: AccountId; - userChain: SupportedChain; - queriedChains: SupportedChain[]; + userChain: DbSchema; + queriedChains: DbSchema[]; }; }; + +export type DbSchema = (typeof DB_SCHEMAS)[number]; diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index e5ef19a..ec3663c 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -1,6 +1,7 @@ import DataLoader from 'dataloader'; import type { Address, + DbSchema, DripListId, DripListMultiChainKey, } from '../common/types'; @@ -9,6 +10,7 @@ import type { DripListDataValues } from '../drip-list/DripListModel'; import TransferEventModel from '../drip-list/TransferEventModel'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import dripListsQueries from './sqlQueries/dripListsQueries'; +import { dbSchemaToChain } from '../utils/chainSchemaMappings'; export default class DripListsDataSource { private readonly _batchDripListsByIds = new DataLoader( @@ -36,7 +38,7 @@ export default class DripListsDataSource { public async getDripListById( id: DripListId, - chains: SupportedChain[], + chains: DbSchema[], ): Promise { return this._batchDripListsByIds.load({ id, @@ -45,7 +47,7 @@ export default class DripListsDataSource { } public async getDripListsByFilter( - chains: SupportedChain[], + chains: DbSchema[], where?: DripListWhereInput, ): Promise { return dripListsQueries.getByFilter(chains, where); @@ -53,7 +55,7 @@ export default class DripListsDataSource { public async getDripListsByIdsOnChain( ids: DripListId[], - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await (this._batchDripListsByIds.loadMany( @@ -66,7 +68,7 @@ export default class DripListsDataSource { } public async getMintedTokensCountByAccountId( - chain: SupportedChain, + chain: DbSchema, ownerAddress: Address, ): Promise<{ chain: SupportedChain; @@ -80,7 +82,7 @@ export default class DripListsDataSource { }); return { - chain, + chain: dbSchemaToChain[chain], total, }; } diff --git a/src/dataLoaders/GivenEventsDataSource.ts b/src/dataLoaders/GivenEventsDataSource.ts index 2dd7309..1ac6409 100644 --- a/src/dataLoaders/GivenEventsDataSource.ts +++ b/src/dataLoaders/GivenEventsDataSource.ts @@ -1,9 +1,10 @@ /* eslint-disable no-param-reassign */ import DataLoader from 'dataloader'; -import type { GiveWhereInput, SupportedChain } from '../generated/graphql'; +import type { GiveWhereInput } from '../generated/graphql'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import givenEventsQueries from './sqlQueries/givenEventsQueries'; +import type { DbSchema } from '../common/types'; type TransactionHash = string; type LogIndex = number; @@ -13,7 +14,7 @@ export default class GivenEventsDataSource { private readonly _batchGivenEventsByIds = new DataLoader( async ( keys: readonly { - chains: SupportedChain[]; + chains: DbSchema[]; key: CompositePrimaryKey; }[], ): Promise => { @@ -46,7 +47,7 @@ export default class GivenEventsDataSource { ); public async getGivenEventById( - chains: SupportedChain[], + chains: DbSchema[], transactionHash: TransactionHash, logIndex: LogIndex, ): Promise { @@ -57,7 +58,7 @@ export default class GivenEventsDataSource { } public async getGivenEventsByFilter( - chains: SupportedChain[], + chains: DbSchema[], where: GiveWhereInput, ): Promise { return givenEventsQueries.getByFilter(chains, where); diff --git a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts index d6fa11d..d0be61e 100644 --- a/src/dataLoaders/ProjectAndDripListSupportDataSource.ts +++ b/src/dataLoaders/ProjectAndDripListSupportDataSource.ts @@ -3,6 +3,7 @@ import type { DripListSplitReceiverModelDataValues } from '../models/DripListSpl import type { AccountId, AddressDriverId, + DbSchema, DripListId, DripListMultiChainKey, MultiChainKey, @@ -14,7 +15,6 @@ import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDrive import streams from '../utils/streams'; import type { ProtoStream } from '../utils/buildAssetConfigs'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; -import type { SupportedChain } from '../generated/graphql'; import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; import addressDriverSplitReceiversQueries from './sqlQueries/addressDriverSplitReceiversQueries'; import givenEventsQueries from './sqlQueries/givenEventsQueries'; @@ -125,7 +125,7 @@ export default class ProjectAndDripListSupportDataSource { Object.entries(s).map(([chain, protoStreamsForChain]) => protoStreamsForChain.map((protoStream) => ({ ...protoStream, - chain: chain as SupportedChain, + chain: chain as DbSchema, })), ), ) @@ -142,7 +142,7 @@ export default class ProjectAndDripListSupportDataSource { ], }), {}, - ) as Record; + ) as Record; return accountIds.map((id) => streamSupportToAccountMapping[id] || []); }, @@ -176,7 +176,7 @@ export default class ProjectAndDripListSupportDataSource { public async getProjectAndDripListSupportByDripListIdOnChain( id: DripListId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchProjectAndDripListSupportByDripListIds.load({ @@ -188,7 +188,7 @@ export default class ProjectAndDripListSupportDataSource { public async getProjectAndDripListSupportByProjectIdOnChain( id: ProjectId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchProjectAndDripListSupportByProjectIds.load({ @@ -200,7 +200,7 @@ export default class ProjectAndDripListSupportDataSource { public async getProjectAndDripListSupportByAddressDriverIdOnChain( id: AddressDriverId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchProjectAndDripListSupportByAddressDriverIds.load({ @@ -212,7 +212,7 @@ export default class ProjectAndDripListSupportDataSource { public async getOneTimeDonationSupportByAccountIdOnChain( id: AccountId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchOneTimeDonationSupportByAccountIds.load({ @@ -224,7 +224,7 @@ export default class ProjectAndDripListSupportDataSource { public async getStreamSupportByAccountIdOnChain( id: AccountId, - chain: SupportedChain, + chain: DbSchema, ) { return ( await this._batchStreamSupportByAccountIds.load({ diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 2a08211..acfc701 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -2,6 +2,7 @@ import DataLoader from 'dataloader'; import type { ProjectDataValues } from '../project/ProjectModel'; import type { AccountId, + DbSchema, ProjectId, ProjectMultiChainKey, } from '../common/types'; @@ -16,6 +17,7 @@ import projectsQueries from './sqlQueries/projectsQueries'; import givenEventsQueries from './sqlQueries/givenEventsQueries'; import splitEventsQueries from './sqlQueries/splitEventsQueries'; import shouldNeverHappen from '../utils/shouldNeverHappen'; +import { dbSchemaToChain } from '../utils/chainSchemaMappings'; export default class ProjectsDataSource { private readonly _batchProjectsByIds = new DataLoader( @@ -51,7 +53,7 @@ export default class ProjectsDataSource { public async getProjectByIdOnChain( id: ProjectId, - chain: SupportedChain, + chain: DbSchema, ): Promise { const dbProject = await this._batchProjectsByIds.load({ id, @@ -63,7 +65,7 @@ export default class ProjectsDataSource { public async getProjectById( id: ProjectId, - chains: SupportedChain[], + chains: DbSchema[], ): Promise { const dbProjects = ( await this._batchProjectsByIds.loadMany([{ id, chains }]) @@ -84,7 +86,7 @@ export default class ProjectsDataSource { public async getProjectByUrl( url: string, - chains: SupportedChain[], + chains: DbSchema[], ): Promise { // TODO: To Data Loader. const dbProjects = await projectsQueries.getByUrl(chains, url); @@ -103,7 +105,7 @@ export default class ProjectsDataSource { } public async getProjectsByFilter( - chains: SupportedChain[], + chains: DbSchema[], where?: ProjectWhereInput, sort?: ProjectSortInput, ): Promise { @@ -122,7 +124,7 @@ export default class ProjectsDataSource { public async getProjectsByIdsOnChain( ids: ProjectId[], - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await (this._batchProjectsByIds.loadMany( @@ -136,7 +138,7 @@ export default class ProjectsDataSource { public async getEarnedFunds( projectId: ProjectId, - chains: SupportedChain[], + chains: DbSchema[], ): Promise< { tokenAddress: string; @@ -154,7 +156,7 @@ export default class ProjectsDataSource { private async _getIncomingSplitTotal( accountId: AccountId, - chains: SupportedChain[], + chains: DbSchema[], ) { const incomingSplitEventModelDataValues = await splitEventsQueries.getByReceiver(chains, accountId); @@ -163,7 +165,7 @@ export default class ProjectsDataSource { { tokenAddress: string; amount: bigint; - chain: SupportedChain; + chain: DbSchema; }[] >((acc, curr) => { const existing = acc.find((e) => e.tokenAddress === curr.erc20); @@ -186,7 +188,7 @@ export default class ProjectsDataSource { private async _getIncomingGivesTotal( accountId: AccountId, - chains: SupportedChain[], + chains: DbSchema[], ) { const incomingGivenEventModelDataValues = await givenEventsQueries.getByReceiver(chains, accountId); @@ -195,7 +197,7 @@ export default class ProjectsDataSource { { tokenAddress: string; amount: bigint; - chain: SupportedChain; + chain: DbSchema; }[] >((acc, curr) => { const existing = acc.find((e) => e.tokenAddress === curr.erc20); @@ -219,7 +221,7 @@ export default class ProjectsDataSource { ...args: { tokenAddress: string; amount: bigint; - chain: SupportedChain; + chain: DbSchema; }[][] ) { const amounts = new Map< @@ -238,10 +240,14 @@ export default class ProjectsDataSource { if (existingAmount) { amounts.set(key, { ...existingAmount, + chain: dbSchemaToChain[amount.chain], amount: existingAmount.amount + amount.amount, }); } else { - amounts.set(key, amount); + amounts.set(key, { + ...amount, + chain: dbSchemaToChain[amount.chain], + }); } }); }); diff --git a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts index b15da85..37677ad 100644 --- a/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeAddressDataSource.ts @@ -1,12 +1,12 @@ import DataLoader from 'dataloader'; import type { + DbSchema, DripListId, DripListMultiChainKey, ProjectId, ProjectMultiChainKey, } from '../common/types'; import type { AddressDriverSplitReceiverModelDataValues } from '../models/AddressDriverSplitReceiverModel'; -import type { SupportedChain } from '../generated/graphql'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import addressDriverSplitReceiversQueries from './sqlQueries/addressDriverSplitReceiversQueries'; @@ -42,7 +42,7 @@ export default class ReceiversOfTypeAddressDataSource { public async getReceiversOfTypeAddressByProjectIdOnChain( id: ProjectId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchReceiversOfTypeAddressByProjectIds.load({ @@ -83,7 +83,7 @@ export default class ReceiversOfTypeAddressDataSource { public async getReceiversOfTypeAddressByDripListIdOnChain( id: DripListId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchReceiversOfTypeAddressByDripListIds.load({ diff --git a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts index 4db8f52..16bc9f0 100644 --- a/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeDripListDataSource.ts @@ -4,9 +4,9 @@ import type { DripListId, ProjectId, DripListMultiChainKey, + DbSchema, } from '../common/types'; import type { DripListSplitReceiverModelDataValues } from '../models/DripListSplitReceiverModel'; -import type { SupportedChain } from '../generated/graphql'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import dripListSplitReceiversQueries from './sqlQueries/dripListSplitReceiversQueries'; @@ -42,7 +42,7 @@ export default class ReceiversOfTypeDripListDataSource { public async getReceiversOfTypeDripListByProjectIdOnChain( id: ProjectId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchReceiversOfTypeDripListByProjectIds.load({ @@ -83,7 +83,7 @@ export default class ReceiversOfTypeDripListDataSource { public async getReceiversOfTypeDripListByDripListIdOnChain( id: DripListId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchReceiversOfTypeDripListByDripListIds.load({ diff --git a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts index b753f3b..353a5b3 100644 --- a/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts +++ b/src/dataLoaders/ReceiversOfTypeProjectDataSource.ts @@ -4,9 +4,9 @@ import type { DripListId, ProjectId, ProjectMultiChainKey, + DbSchema, } from '../common/types'; import type { RepoDriverSplitReceiverModelDataValues } from '../models/RepoDriverSplitReceiverModel'; -import type { SupportedChain } from '../generated/graphql'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; import repoDriverSplitReceiversQueries from './sqlQueries/repoDriverSplitReceiversQueries'; @@ -42,7 +42,7 @@ export default class ReceiversOfTypeProjectDataSource { public async getReceiversOfTypeProjectByProjectIdOnChain( id: ProjectId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchReceiversOfTypeProjectByProjectIds.load({ @@ -83,7 +83,7 @@ export default class ReceiversOfTypeProjectDataSource { public async getReceiversOfTypeProjectByDripListIdOnChain( id: DripListId, - chain: SupportedChain, + chain: DbSchema, ): Promise { return ( await this._batchReceiversOfTypeProjectByDripListIds.load({ diff --git a/src/dataLoaders/TotalEarnedDataSource.ts b/src/dataLoaders/TotalEarnedDataSource.ts index 8340c9b..ada2ff7 100644 --- a/src/dataLoaders/TotalEarnedDataSource.ts +++ b/src/dataLoaders/TotalEarnedDataSource.ts @@ -2,13 +2,13 @@ import DataLoader from 'dataloader'; import type { AccountId, + DbSchema, DripListId, DripListMultiChainKey, ProjectId, ProjectMultiChainKey, } from '../common/types'; import parseMultiChainKeys from '../utils/parseMultiChainKeys'; -import type { SupportedChain } from '../generated/graphql'; import type { SplitEventModelDataValues } from '../models/SplitEventModel'; import type { GivenEventModelDataValues } from '../given-event/GivenEventModel'; import { isDripListId, isProjectId } from '../utils/assert'; @@ -62,7 +62,7 @@ export default class TotalEarnedDataSource { public async getTotalEarnedByProjectIds( id: DripListId | ProjectId, - chains: SupportedChain[], + chains: DbSchema[], ): Promise<{ splitEventsForDripListDataValues: SplitEventModelDataValues[]; givenEventsForDripListDataValues: GivenEventModelDataValues[]; diff --git a/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts b/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts index 091d32e..2001506 100644 --- a/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries.ts @@ -1,16 +1,15 @@ import { QueryTypes } from 'sequelize'; -import type { AddressDriverId } from '../../common/types'; +import type { AddressDriverId, DbSchema } from '../../common/types'; import { dbConnection } from '../../database/connectToDatabase'; -import type { SupportedChain } from '../../generated/graphql'; import type { AccountMetadataEmittedEventModelDataValues } from '../../models/AccountMetadataEmittedEventModel'; import AccountMetadataEmittedEventModel from '../../models/AccountMetadataEmittedEventModel'; async function getAccountMetadataEmittedEventsByAccountId( - chains: SupportedChain[], + chains: DbSchema[], accountId: AddressDriverId, ) { // TODO: Prevent SQL injection in all queries from schema input. - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *,'${schema}' AS chain FROM "${schema}"."AccountMetadataEmittedEvents"`; const parameters: { [key: string]: any } = { accountId }; diff --git a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts index 78d319c..999e1a0 100644 --- a/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts +++ b/src/dataLoaders/sqlQueries/addressDriverSplitReceiversQueries.ts @@ -1,17 +1,17 @@ import { QueryTypes } from 'sequelize'; import { dbConnection } from '../../database/connectToDatabase'; -import type { SupportedChain } from '../../generated/graphql'; -import type { AccountId, DripListId } from '../../common/types'; + +import type { AccountId, DbSchema, DripListId } from '../../common/types'; import type { AddressDriverSplitReceiverModelDataValues } from '../../models/AddressDriverSplitReceiverModel'; import AddressDriverSplitReceiverModel, { AddressDriverSplitReceiverType, } from '../../models/AddressDriverSplitReceiverModel'; async function getAddressDriverSplitReceiversDripListDependenciesByFunders( - chains: SupportedChain[], + chains: DbSchema[], funderDripListIds: DripListId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."AddressDriverSplitReceivers" `; @@ -41,10 +41,10 @@ async function getAddressDriverSplitReceiversDripListDependenciesByFunders( } async function getAddressDriverSplitReceiversProjectDependenciesByFunders( - chains: SupportedChain[], + chains: DbSchema[], funderProjectIds: AccountId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "createdAt", "updatedAt",'${schema}' AS chain FROM "${schema}"."AddressDriverSplitReceivers" `; @@ -76,10 +76,10 @@ async function getAddressDriverSplitReceiversProjectDependenciesByFunders( } async function getAddressDriverSplitReceiversByFundeeAccountIds( - chains: SupportedChain[], + chains: DbSchema[], fundeeAccountIds: AccountId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeAccountId", "fundeeAccountAddress", "funderProjectId", "funderDripListId","weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."AddressDriverSplitReceivers" `; diff --git a/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts index de851a8..1f63fa9 100644 --- a/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts +++ b/src/dataLoaders/sqlQueries/dripListSplitReceiversQueries.ts @@ -1,19 +1,15 @@ import { QueryTypes } from 'sequelize'; -import { - DependencyType, - type DripListId, - type ProjectId, -} from '../../common/types'; +import { DependencyType } from '../../common/types'; +import type { DbSchema, DripListId, ProjectId } from '../../common/types'; import { dbConnection } from '../../database/connectToDatabase'; -import type { SupportedChain } from '../../generated/graphql'; import type { DripListSplitReceiverModelDataValues } from '../../models/DripListSplitReceiverModel'; import DripListSplitReceiverModel from '../../models/DripListSplitReceiverModel'; async function getDripListSplitReceiversByFundeeDripListIds( - chains: SupportedChain[], + chains: DbSchema[], fundeeDripListIds: DripListId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."DripListSplitReceivers" `; @@ -41,10 +37,10 @@ async function getDripListSplitReceiversByFundeeDripListIds( } async function getDripListSplitReceiversByFunderProjectIds( - chains: SupportedChain[], + chains: DbSchema[], funderProjectIds: ProjectId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain FROM "${schema}"."DripListSplitReceivers" `; @@ -74,10 +70,10 @@ async function getDripListSplitReceiversByFunderProjectIds( } async function getDripListSplitReceiversByFunderDripListIds( - chains: SupportedChain[], + chains: DbSchema[], funderDripListIds: DripListId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeDripListId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain FROM "${schema}"."DripListSplitReceivers" `; diff --git a/src/dataLoaders/sqlQueries/dripListsQueries.ts b/src/dataLoaders/sqlQueries/dripListsQueries.ts index ee299a3..e07342b 100644 --- a/src/dataLoaders/sqlQueries/dripListsQueries.ts +++ b/src/dataLoaders/sqlQueries/dripListsQueries.ts @@ -1,18 +1,15 @@ import { QueryTypes } from 'sequelize'; -import type { DripListId } from '../../common/types'; +import type { DbSchema, DripListId } from '../../common/types'; import { dbConnection } from '../../database/connectToDatabase'; import type { DripListDataValues } from '../../drip-list/DripListModel'; import DripListModel from '../../drip-list/DripListModel'; -import type { - DripListWhereInput, - SupportedChain, -} from '../../generated/graphql'; +import type { DripListWhereInput } from '../../generated/graphql'; async function getDripListsByFilter( - chains: SupportedChain[], + chains: DbSchema[], where?: DripListWhereInput, ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "isValid", "name", "creator", "description", "ownerAddress", "ownerAccountId", "latestVotingRoundId", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."DripLists" `; @@ -46,10 +43,10 @@ async function getDripListsByFilter( } async function getDripListsByIds( - chains: SupportedChain[], + chains: DbSchema[], dripListIds: DripListId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "isValid", "ownerAddress", "ownerAccountId", "name", "latestVotingRoundId", "description", "creator", "previousOwnerAddress", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."DripLists" `; diff --git a/src/dataLoaders/sqlQueries/givenEventsQueries.ts b/src/dataLoaders/sqlQueries/givenEventsQueries.ts index 1dbafa6..0fbc355 100644 --- a/src/dataLoaders/sqlQueries/givenEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/givenEventsQueries.ts @@ -1,15 +1,15 @@ import { QueryTypes } from 'sequelize'; import { dbConnection } from '../../database/connectToDatabase'; -import type { GiveWhereInput, SupportedChain } from '../../generated/graphql'; -import type { AccountId } from '../../common/types'; +import type { GiveWhereInput } from '../../generated/graphql'; +import type { AccountId, DbSchema } from '../../common/types'; import type { GivenEventModelDataValues } from '../../given-event/GivenEventModel'; import GivenEventModel from '../../given-event/GivenEventModel'; async function getDistinctErc20ByReceiver( - chains: SupportedChain[], + chains: DbSchema[], receiver: AccountId, ) { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT DISTINCT ON ("erc20") "erc20", '${schema}' AS chain FROM "${schema}"."GivenEvents"`; const whereClause = ` WHERE "accountId" = :receiver`; @@ -29,10 +29,10 @@ async function getDistinctErc20ByReceiver( } async function getGivenEventsByFilter( - chains: SupportedChain[], + chains: DbSchema[], where: GiveWhereInput, ) { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; const conditions: string[] = []; @@ -69,10 +69,10 @@ async function getGivenEventsByFilter( } async function getGivenEventsByReceivers( - chains: SupportedChain[], + chains: DbSchema[], receivers: AccountId[], ) { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; const parameters: { [key: string]: any } = { receivers }; @@ -94,11 +94,11 @@ async function getGivenEventsByReceivers( } async function getGivenEventsByTxHashesAndLogIndex( - chains: SupportedChain[], + chains: DbSchema[], transactionHashes: string[], logIndexes: number[], ) { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; const conditions: string[] = [ @@ -127,10 +127,10 @@ async function getGivenEventsByTxHashesAndLogIndex( } async function getGivenEventsByReceiver( - chains: SupportedChain[], + chains: DbSchema[], receiver: AccountId, ) { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *, '${schema}' AS chain FROM "${schema}"."GivenEvents"`; const parameters: { [receiver: string]: any } = { receiver }; diff --git a/src/dataLoaders/sqlQueries/projectsQueries.ts b/src/dataLoaders/sqlQueries/projectsQueries.ts index 474e967..f7b4d6b 100644 --- a/src/dataLoaders/sqlQueries/projectsQueries.ts +++ b/src/dataLoaders/sqlQueries/projectsQueries.ts @@ -3,17 +3,16 @@ import { dbConnection } from '../../database/connectToDatabase'; import type { ProjectSortInput, ProjectWhereInput, - SupportedChain, } from '../../generated/graphql'; import type { ProjectDataValues } from '../../project/ProjectModel'; import ProjectModel from '../../project/ProjectModel'; -import type { ProjectId } from '../../common/types'; +import type { DbSchema, ProjectId } from '../../common/types'; async function getProjectByUrl( - chains: SupportedChain[], + chains: DbSchema[], url: string, ): Promise { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."GitProjects" `; @@ -38,11 +37,11 @@ async function getProjectByUrl( } async function getProjectsByFilter( - chains: SupportedChain[], + chains: DbSchema[], where?: ProjectWhereInput, sort?: ProjectSortInput, ): Promise { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."GitProjects" `; @@ -88,10 +87,10 @@ async function getProjectsByFilter( } async function getProjectsByIds( - chains: SupportedChain[], + chains: DbSchema[], projectIds: ProjectId[], ): Promise { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "isValid", "name", "verificationStatus"::TEXT, "claimedAt", "forge"::TEXT, "ownerAddress", "ownerAccountId", "url", "emoji", "avatarCid", "color", "description", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."GitProjects" `; diff --git a/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts b/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts index f391f65..9ef32b4 100644 --- a/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts +++ b/src/dataLoaders/sqlQueries/repoDriverSplitReceiversQueries.ts @@ -1,16 +1,15 @@ import { QueryTypes } from 'sequelize'; import { DependencyType } from '../../common/types'; -import type { DripListId, ProjectId } from '../../common/types'; +import type { DbSchema, DripListId, ProjectId } from '../../common/types'; import { dbConnection } from '../../database/connectToDatabase'; -import type { SupportedChain } from '../../generated/graphql'; import type { RepoDriverSplitReceiverModelDataValues } from '../../models/RepoDriverSplitReceiverModel'; import RepoDriverSplitReceiverModel from '../../models/RepoDriverSplitReceiverModel'; async function getRepoDriverSplitReceiversByFundeeProjectIds( - chains: SupportedChain[], + chains: DbSchema[], fundeeProjectIds: ProjectId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."RepoDriverSplitReceivers" `; @@ -37,10 +36,10 @@ async function getRepoDriverSplitReceiversByFundeeProjectIds( } async function getRepoDriverSplitReceiversByFunderProjectIds( - chains: SupportedChain[], + chains: DbSchema[], funderProjectIds: ProjectId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain FROM "${schema}"."RepoDriverSplitReceivers" `; @@ -71,10 +70,10 @@ async function getRepoDriverSplitReceiversByFunderProjectIds( } async function getRepoDriverSplitReceiversByFunderDripListIds( - chains: SupportedChain[], + chains: DbSchema[], funderDripListIds: DripListId[], ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT "id", "fundeeProjectId", "funderProjectId", "funderDripListId", "weight", "type"::TEXT, "blockTimestamp", "createdAt", "updatedAt",'${schema}' AS chain FROM "${schema}"."RepoDriverSplitReceivers" `; diff --git a/src/dataLoaders/sqlQueries/splitEventsQueries.ts b/src/dataLoaders/sqlQueries/splitEventsQueries.ts index 639292a..85099a5 100644 --- a/src/dataLoaders/sqlQueries/splitEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/splitEventsQueries.ts @@ -1,15 +1,14 @@ import { QueryTypes } from 'sequelize'; -import type { AccountId } from '../../common/types'; +import type { AccountId, DbSchema } from '../../common/types'; import { dbConnection } from '../../database/connectToDatabase'; -import type { SupportedChain } from '../../generated/graphql'; import type { SplitEventModelDataValues } from '../../models/SplitEventModel'; import SplitEventModel from '../../models/SplitEventModel'; async function getDistinctErc20ByReceiver( - chains: SupportedChain[], + chains: DbSchema[], receiver: AccountId, ) { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT DISTINCT ON ("erc20") "erc20", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; const whereClause = ` WHERE "accountId" = :receiver`; @@ -29,11 +28,11 @@ async function getDistinctErc20ByReceiver( } async function getSplitEventsByAccountIdAndReceiver( - chains: SupportedChain[], + chains: DbSchema[], accountId: AccountId, receiver: AccountId, ): Promise { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *, '${schema}' AS chain FROM "${schema}"."SplitEvents"`; const conditions: string[] = [ @@ -62,10 +61,10 @@ async function getSplitEventsByAccountIdAndReceiver( } async function getSplitEventsByReceiver( - chains: SupportedChain[], + chains: DbSchema[], receiver: AccountId, ): Promise { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *, '${schema}' AS chain FROM "${schema}"."SplitEvents"`; const conditions: string[] = ['"receiver" = :receiver']; @@ -88,10 +87,10 @@ async function getSplitEventsByReceiver( } async function getSplitEventsByProjectReceivers( - chains: SupportedChain[], + chains: DbSchema[], accountIds: AccountId[], ): Promise { - const baseSplitEventsSQL = (schema: SupportedChain) => + const baseSplitEventsSQL = (schema: DbSchema) => `SELECT "accountId", "receiver", "erc20", "amt", "transactionHash", "logIndex", "blockTimestamp", "blockNumber", "createdAt", "updatedAt", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; const conditions: string[] = [`"receiver" IN (:receivers)`]; diff --git a/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts b/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts index 8c4d72f..a3f37bd 100644 --- a/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts +++ b/src/dataLoaders/sqlQueries/streamReceiverSeenEventQueries.ts @@ -1,15 +1,14 @@ import { QueryTypes } from 'sequelize'; -import type { AccountId } from '../../common/types'; +import type { AccountId, DbSchema } from '../../common/types'; import { dbConnection } from '../../database/connectToDatabase'; -import type { SupportedChain } from '../../generated/graphql'; import type { StreamReceiverSeenEventModelDataValues } from '../../models/StreamReceiverSeenEventModel'; import StreamReceiverSeenEventModel from '../../models/StreamReceiverSeenEventModel'; async function getStreamReceiverSeenEventsByAccountId( - chains: SupportedChain[], + chains: DbSchema[], accountId: AccountId, ) { - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamReceiverSeenEvents" WHERE "accountId" = :accountId`; const fullQuery = `${chains diff --git a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts index 230face..5a0df4e 100644 --- a/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/streamsSetEventsQueries.ts @@ -2,10 +2,10 @@ import { QueryTypes } from 'sequelize'; import type { AccountId, AddressDriverId, + DbSchema, StreamsSetEventWithReceivers, } from '../../common/types'; import { dbConnection } from '../../database/connectToDatabase'; -import type { SupportedChain } from '../../generated/graphql'; import type { StreamsSetEventModelDataValues } from '../../models/StreamsSetEventModel'; import StreamsSetEventModel from '../../models/StreamsSetEventModel'; import type { StreamReceiverSeenEventModelDataValues } from '../../models/StreamReceiverSeenEventModel'; @@ -13,14 +13,14 @@ import StreamReceiverSeenEventModel from '../../models/StreamReceiverSeenEventMo // TODO: Investigate queries and add DataLoader if needed. async function getDistinctErc20ByReceiversHashes( - chains: SupportedChain[], + chains: DbSchema[], receiversHashes: string[], ) { if (!receiversHashes?.length) { return []; } - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT DISTINCT ON ("erc20") "erc20", '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; const whereClause = ` WHERE "receiversHash" IN (:receiversHashes)`; @@ -40,10 +40,10 @@ async function getDistinctErc20ByReceiversHashes( } async function getSortedStreamsSetEventsByAccountId( - chains: SupportedChain[], + chains: DbSchema[], accountId: AccountId, ) { - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; const parameters: { [key: string]: any } = { accountId }; @@ -67,14 +67,14 @@ async function getSortedStreamsSetEventsByAccountId( } async function getSortedStreamsSetEventsByReceiversHashes( - chains: SupportedChain[], + chains: DbSchema[], receiversHashes: string[], ) { if (!receiversHashes?.length) { return []; } - const baseSQL = (schema: SupportedChain) => + const baseSQL = (schema: DbSchema) => `SELECT *, '${schema}' AS chain FROM "${schema}"."StreamsSetEvents"`; const whereClause = ` WHERE "receiversHash" IN (:receiversHashes)`; @@ -96,7 +96,7 @@ async function getSortedStreamsSetEventsByReceiversHashes( } async function getStreamsSetEventsWithReceivers( - chains: SupportedChain[], + chains: DbSchema[], accountId: AddressDriverId, ): Promise { const sortedAccountStreamSetEventModelDataValues = @@ -110,7 +110,7 @@ async function getStreamsSetEventsWithReceivers( ), ]; - const baseSQL = (schema: SupportedChain) => ` + const baseSQL = (schema: DbSchema) => ` SELECT *, '${schema}' AS chain FROM "${schema}"."StreamReceiverSeenEvents"`; const conditions: string[] = ['"receiversHash" IN (:uniqueReceiversHashes)']; diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index f4ab8dd..113b4b0 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -23,6 +23,7 @@ import verifyDripListsInput from './dripListValidators'; import type { DripListDataValues } from './DripListModel'; import { resolveTotalEarned } from '../common/commonResolverLogic'; import { toResolverProject } from '../project/projectUtils'; +import { chainToDbSchema } from '../utils/chainSchemaMappings'; const dripListResolvers = { Query: { @@ -36,14 +37,16 @@ const dripListResolvers = { ): Promise => { verifyDripListsInput({ chains, where }); - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); const dbDripLists = await dripListsDataSource.getDripListsByFilter( - chainsToQuery, + dbSchemasToQuery, where, ); - return toResolverDripLists(chainsToQuery, dbDripLists); + return toResolverDripLists(dbSchemasToQuery, dbDripLists); }, dripList: async ( _: undefined, @@ -53,9 +56,15 @@ const dripListResolvers = { assert(isDripListId(id)); assert(chain in SupportedChain); - const dbDripList = await dripListsDataSource.getDripListById(id, [chain]); + const dbSchemaToQuery = chainToDbSchema[chain]; + + const dbDripList = await dripListsDataSource.getDripListById(id, [ + dbSchemaToQuery, + ]); - return dbDripList ? toResolverDripList(chain, dbDripList) : null; + return dbDripList + ? toResolverDripList(dbSchemaToQuery, dbDripList) + : null; }, mintedTokensCountByOwnerAddress: async ( _: undefined, @@ -65,8 +74,10 @@ const dripListResolvers = { assert(isAddress(ownerAddress)); assert(chain in SupportedChain); + const dbSchemaToQuery = chainToDbSchema[chain]; + return dripListsDataSource.getMintedTokensCountByAccountId( - chain, + dbSchemaToQuery, ownerAddress, ); }, diff --git a/src/drip-list/dripListUtils.ts b/src/drip-list/dripListUtils.ts index dede5d9..44e4606 100644 --- a/src/drip-list/dripListUtils.ts +++ b/src/drip-list/dripListUtils.ts @@ -1,16 +1,21 @@ -import type { ResolverDripList, ResolverDripListData } from '../common/types'; -import { Driver, type SupportedChain } from '../generated/graphql'; +import type { + DbSchema, + ResolverDripList, + ResolverDripListData, +} from '../common/types'; +import { Driver } from '../generated/graphql'; +import { dbSchemaToChain } from '../utils/chainSchemaMappings'; import type { DripListDataValues } from './DripListModel'; export async function toResolverDripList( - chain: SupportedChain, + chain: DbSchema, dripList: DripListDataValues, ): Promise { return (await toResolverDripLists([chain], [dripList]))[0]; } export async function toResolverDripLists( - chains: SupportedChain[], + chains: DbSchema[], dripLists: DripListDataValues[], ): Promise { return Promise.all( @@ -21,7 +26,7 @@ export async function toResolverDripLists( relevantChains.map( async (chain) => ({ - chain, + chain: dbSchemaToChain[chain], parentDripListInfo: { dripListId: dripList.id, dripListChain: chain, diff --git a/src/given-event/givenEventResolvers.ts b/src/given-event/givenEventResolvers.ts index da65ef9..7d9ce20 100644 --- a/src/given-event/givenEventResolvers.ts +++ b/src/given-event/givenEventResolvers.ts @@ -6,6 +6,7 @@ import assert, { isAccountId } from '../utils/assert'; import queryableChains from '../common/queryableChains'; import type { GivenEventModelDataValues } from './GivenEventModel'; import type { ResolverGive } from '../common/types'; +import { chainToDbSchema } from '../utils/chainSchemaMappings'; const givenEventResolvers = { Query: { @@ -32,10 +33,12 @@ const givenEventResolvers = { }); } - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); return dataSources.givenEventsDataSource.getGivenEventsByFilter( - chainsToQuery, + dbSchemasToQuery, where, ); }, diff --git a/src/given-event/givesUtils.ts b/src/given-event/givesUtils.ts index 16b5f88..745c00a 100644 --- a/src/given-event/givesUtils.ts +++ b/src/given-event/givesUtils.ts @@ -1,9 +1,13 @@ -import type { ResolverGive, ResolverGiveChainData } from '../common/types'; -import { type SupportedChain } from '../generated/graphql'; +import type { + DbSchema, + ResolverGive, + ResolverGiveChainData, +} from '../common/types'; +import { dbSchemaToChain } from '../utils/chainSchemaMappings'; import type { GivenEventModelDataValues } from './GivenEventModel'; export default async function toResolverGives( - chains: SupportedChain[], + chains: DbSchema[], givenEventsDataValues: GivenEventModelDataValues[], ): Promise { return Promise.all( @@ -20,7 +24,7 @@ export default async function toResolverGives( } return { - chain, + chain: dbSchemaToChain[chain], data: null, }; }), diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index d322ee9..30d7104 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -34,6 +34,7 @@ import { resolveTotalEarned } from '../common/commonResolverLogic'; import { validateChainsQueryArg } from '../utils/commonInputValidators'; import getWithdrawableBalances from '../utils/getWithdrawableBalances'; import { toResolverDripList } from '../drip-list/dripListUtils'; +import { chainToDbSchema } from '../utils/chainSchemaMappings'; const projectResolvers = { Query: { @@ -50,15 +51,17 @@ const projectResolvers = { const { chains, where, sort } = args; - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); const dbProjects = await projectsDataSource.getProjectsByFilter( - chainsToQuery, + dbSchemasToQuery, where, sort, ); - return toResolverProjects(chainsToQuery, dbProjects); + return toResolverProjects(dbSchemasToQuery, dbProjects); }, projectById: async ( _: undefined, @@ -70,14 +73,16 @@ const projectResolvers = { validateChainsQueryArg(chains); } - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); const dbProjects = await projectsDataSource.getProjectById( id, - chainsToQuery, + dbSchemasToQuery, ); - return dbProjects ? mergeProjects(dbProjects, chainsToQuery) : null; + return dbProjects ? mergeProjects(dbProjects, dbSchemasToQuery) : null; }, projectByUrl: async ( _: undefined, @@ -89,14 +94,16 @@ const projectResolvers = { validateChainsQueryArg(chains); } - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); const dbProjects = await projectsDataSource.getProjectByUrl( url, - chainsToQuery, + dbSchemasToQuery, ); - return dbProjects ? mergeProjects(dbProjects, chainsToQuery) : null; + return dbProjects ? mergeProjects(dbProjects, dbSchemasToQuery) : null; }, earnedFunds: async ( _: undefined, @@ -117,9 +124,11 @@ const projectResolvers = { validateChainsQueryArg(chains); } - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); - return projectsDataSource.getEarnedFunds(projectId, chainsToQuery); + return projectsDataSource.getEarnedFunds(projectId, dbSchemasToQuery); }, }, Project: { diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index b1b6e1c..6669755 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -1,4 +1,5 @@ import type { + DbSchema, Forge, ResolverClaimedProjectData, ResolverProject, @@ -11,12 +12,9 @@ import assert from '../utils/assert'; import appSettings from '../common/appSettings'; import { getCrossChainRepoDriverAccountIdByAddress } from '../common/dripsContracts'; import { Driver } from '../generated/graphql'; -import type { - Forge as GraphQlForge, - SupportedChain, - Splits, -} from '../generated/graphql'; +import type { Forge as GraphQlForge, Splits } from '../generated/graphql'; import { singleOrDefault } from '../utils/linq'; +import { dbSchemaToChain } from '../utils/chainSchemaMappings'; export function splitProjectName(projectName: string): { ownerName: string; @@ -125,7 +123,7 @@ export async function toFakeUnclaimedProject( } export async function toResolverProject( - chains: SupportedChain[], + chains: DbSchema[], project: ProjectDataValues, ) { const resolverProjects = await toResolverProjects(chains, [project]); @@ -135,11 +133,11 @@ export async function toResolverProject( function mapClaimedProjectChainData( project: ProjectDataValues, - projectChain: SupportedChain, - queriedChains: SupportedChain[], + projectChain: DbSchema, + queriedChains: DbSchema[], ) { return { - chain: projectChain, + chain: dbSchemaToChain[projectChain], parentProjectInfo: { projectId: project.id, queriedChains, @@ -171,11 +169,11 @@ function mapClaimedProjectChainData( function mapUnClaimedProjectChainData( fakeUnclaimedProject: ProjectDataValues, - projectChain: SupportedChain, - queriedChains: SupportedChain[], + projectChain: DbSchema, + queriedChains: DbSchema[], ) { return { - chain: projectChain, + chain: dbSchemaToChain[projectChain], parentProjectInfo: { queriedChains, projectId: fakeUnclaimedProject.id, @@ -189,7 +187,7 @@ function mapUnClaimedProjectChainData( } export async function toResolverProjects( - chains: SupportedChain[], + chains: DbSchema[], projects: ProjectDataValues[], ): Promise { const projectsMap = new Map(); @@ -252,7 +250,7 @@ export async function toResolverProjects( export async function mergeProjects( projects: ProjectDataValues[], - chains: SupportedChain[], + chains: DbSchema[], ) { if (projects.some((p) => p.id !== projects[0].id)) { throw new Error('All projects should have the same id when merging.'); diff --git a/src/stream/StreamsDataSource.ts b/src/stream/StreamsDataSource.ts index fbbd91b..b199e59 100644 --- a/src/stream/StreamsDataSource.ts +++ b/src/stream/StreamsDataSource.ts @@ -1,5 +1,5 @@ -import type { AddressDriverId } from '../common/types'; -import type { StreamWhereInput, SupportedChain } from '../generated/graphql'; +import type { AddressDriverId, DbSchema } from '../common/types'; +import type { StreamWhereInput } from '../generated/graphql'; import assert, { isAddressDriverId } from '../utils/assert'; import type { ProtoStream } from '../utils/buildAssetConfigs'; import getUserAccount from '../utils/getUserAccount'; @@ -7,12 +7,12 @@ import streamsUtils from '../utils/streams'; export default class StreamsDataSource { public async getUserOutgoingStreams( - chains: SupportedChain[], + chains: DbSchema[], accountId: AddressDriverId, ) { const userAccount = await getUserAccount(chains, accountId); - const response = {} as Record; + const response = {} as Record; chains.forEach((chain) => { response[chain] = userAccount[chain].assetConfigs.flatMap( @@ -24,19 +24,16 @@ export default class StreamsDataSource { } public async getUserIncomingStreams( - chains: SupportedChain[], + chains: DbSchema[], accountId: AddressDriverId, ) { return streamsUtils.getUserIncomingStreams(chains, accountId); } - public async getStreamsByFilter( - chains: SupportedChain[], - where: StreamWhereInput, - ) { + public async getStreamsByFilter(chains: DbSchema[], where: StreamWhereInput) { const streams = chains.reduce( (acc, chain) => ({ ...acc, [chain]: [] }), - {} as Record, + {} as Record, ); if (!where.senderId && !where.receiverId) { @@ -54,7 +51,7 @@ export default class StreamsDataSource { ); Object.entries(senderOutgoingStreams).forEach(([chain, chainStreams]) => { - streams[chain as SupportedChain].push(...chainStreams); + streams[chain as DbSchema].push(...chainStreams); }); } @@ -68,7 +65,7 @@ export default class StreamsDataSource { Object.entries(receiverIncomingStreams).forEach( ([chain, chainStreams]) => { - streams[chain as SupportedChain].push(...chainStreams); + streams[chain as DbSchema].push(...chainStreams); }, ); } diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index 5352422..5bd69fa 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -6,6 +6,7 @@ import { Driver } from '../generated/graphql'; import type { Context } from '../server'; import toResolverUser from '../user/userUtils'; import type { ProtoStream } from '../utils/buildAssetConfigs'; +import { chainToDbSchema } from '../utils/chainSchemaMappings'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import verifyStreamsInput from './streamValidators'; @@ -18,10 +19,12 @@ const streamResolvers = { ) => { verifyStreamsInput({ where, chains }); - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); const streamsByChain = await streamsDataSource.getStreamsByFilter( - chainsToQuery, + dbSchemasToQuery, where, ); diff --git a/src/user/UserDataSource.ts b/src/user/UserDataSource.ts index 5537eb0..94b6668 100644 --- a/src/user/UserDataSource.ts +++ b/src/user/UserDataSource.ts @@ -1,12 +1,8 @@ -import type { AddressDriverId } from '../common/types'; -import type { SupportedChain } from '../generated/graphql'; +import type { AddressDriverId, DbSchema } from '../common/types'; import getUserAccount from '../utils/getUserAccount'; export default class UsersDataSource { - public async getUserAccount( - chains: SupportedChain[], - accountId: AddressDriverId, - ) { + public async getUserAccount(chains: DbSchema[], accountId: AddressDriverId) { return getUserAccount(chains, accountId); } } diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index 85972f0..eec4d4b 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -31,6 +31,7 @@ import toResolverUser from './userUtils'; import { getCrossChainAddressDriverAccountIdByAddress } from '../common/dripsContracts'; import getWithdrawableBalances from '../utils/getWithdrawableBalances'; import shouldNeverHappen from '../utils/shouldNeverHappen'; +import { chainToDbSchema } from '../utils/chainSchemaMappings'; const userResolvers = { Query: { @@ -46,9 +47,11 @@ const userResolvers = { validateChainsQueryArg(chains); } - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); - return toResolverUser(chainsToQuery, accountId); + return toResolverUser(dbSchemasToQuery, accountId); }, userByAddress: async ( _: undefined, @@ -59,12 +62,14 @@ const userResolvers = { validateChainsQueryArg(chains); } - const chainsToQuery = chains?.length ? chains : queryableChains; + const dbSchemasToQuery = (chains?.length ? chains : queryableChains).map( + (chain) => chainToDbSchema[chain], + ); const accountId = await getCrossChainAddressDriverAccountIdByAddress(address); - return toResolverUser(chainsToQuery, accountId); + return toResolverUser(dbSchemasToQuery, accountId); }, }, User: { @@ -245,7 +250,7 @@ const userResolvers = { return ( await streamsDataSource.getUserOutgoingStreams([userChain], accountId) - )[userChain as SupportedChain]; + )[userChain]; }, incoming: async ( { parentUserInfo }: UserDataParentDripListInfo, @@ -257,7 +262,7 @@ const userResolvers = { return ( await streamsDataSource.getUserIncomingStreams([userChain], accountId) - )[userChain as SupportedChain]; + )[userChain]; }, }, StreamReceiver: { diff --git a/src/user/userUtils.ts b/src/user/userUtils.ts index 8be9162..55ad93a 100644 --- a/src/user/userUtils.ts +++ b/src/user/userUtils.ts @@ -1,9 +1,10 @@ -import type { AddressDriverId, ResolverUser } from '../common/types'; -import { Driver, type SupportedChain } from '../generated/graphql'; +import type { AddressDriverId, DbSchema, ResolverUser } from '../common/types'; +import { Driver } from '../generated/graphql'; +import { dbSchemaToChain } from '../utils/chainSchemaMappings'; import getUserAddress from '../utils/getUserAddress'; export default function toResolverUser( - chains: SupportedChain[], + chains: DbSchema[], accountId: AddressDriverId, ): ResolverUser { return { @@ -13,7 +14,7 @@ export default function toResolverUser( driver: Driver.ADDRESS, }, chainData: chains.map((chain) => ({ - chain, + chain: dbSchemaToChain[chain], parentUserInfo: { accountId, queriedChains: chains, diff --git a/src/utils/buildAssetConfigs.ts b/src/utils/buildAssetConfigs.ts index d139caa..4d31ebd 100644 --- a/src/utils/buildAssetConfigs.ts +++ b/src/utils/buildAssetConfigs.ts @@ -8,12 +8,12 @@ import buildStreamReceiver, { import type { AddressDriverAccount, NftDriverAccount, - SupportedChain, } from '../generated/graphql'; import getUserAddress from './getUserAddress'; import type { AccountMetadata, AddressDriverId, + DbSchema, StreamsSetEventWithReceivers, } from '../common/types'; import { AMT_PER_SEC_MULTIPLIER } from '../common/constants'; @@ -28,7 +28,7 @@ export interface AssetConfig { } export interface AssetConfigHistoryItem { - chain: SupportedChain; + chain: DbSchema; timestamp: Date; balance: { tokenAddress: string; @@ -41,7 +41,7 @@ export interface AssetConfigHistoryItem { } export interface ProtoStream { - chain: SupportedChain; + chain: DbSchema; streamId: string; config: | { @@ -66,7 +66,7 @@ export default function buildAssetConfigs( accountId: AddressDriverId, accountMetadata: AccountMetadata | undefined, accountStreamsSetEvents: Map, - chain: SupportedChain, + chain: DbSchema, ) { const firstAppearanceMap = new Map(); diff --git a/src/utils/chainSchemaMappings.ts b/src/utils/chainSchemaMappings.ts new file mode 100644 index 0000000..3583c09 --- /dev/null +++ b/src/utils/chainSchemaMappings.ts @@ -0,0 +1,16 @@ +import type { DbSchema } from '../common/types'; +import { SupportedChain } from '../generated/graphql'; + +export const dbSchemaToChain: Record = { + mainnet: SupportedChain.MAINNET, + sepolia: SupportedChain.SEPOLIA, + optimism_sepolia: SupportedChain.OPTIMISM_SEPOLIA, + polygon_amoy: SupportedChain.POLYGON_AMOY, +}; + +export const chainToDbSchema: Record = { + [SupportedChain.MAINNET]: 'mainnet', + [SupportedChain.SEPOLIA]: 'sepolia', + [SupportedChain.OPTIMISM_SEPOLIA]: 'optimism_sepolia', + [SupportedChain.POLYGON_AMOY]: 'polygon_amoy', +}; diff --git a/src/utils/commonInputValidators.ts b/src/utils/commonInputValidators.ts index 9148e31..a306bb9 100644 --- a/src/utils/commonInputValidators.ts +++ b/src/utils/commonInputValidators.ts @@ -1,10 +1,11 @@ +import { DB_SCHEMAS } from '../common/constants'; import queryableChains from '../common/queryableChains'; -import { SupportedChain } from '../generated/graphql'; +import type { SupportedChain } from '../generated/graphql'; // eslint-disable-next-line import/prefer-default-export export function validateChainsQueryArg(chains: SupportedChain[]) { chains.forEach((chain) => { - if (!(chain in SupportedChain)) { + if (!(chain in DB_SCHEMAS)) { throw new Error(`Chain '${chain}' is not supported.`); } diff --git a/src/utils/getAssetConfigs.ts b/src/utils/getAssetConfigs.ts index b79432c..d0bd00d 100644 --- a/src/utils/getAssetConfigs.ts +++ b/src/utils/getAssetConfigs.ts @@ -1,6 +1,5 @@ -import type { AddressDriverId } from '../common/types'; +import type { AddressDriverId, DbSchema } from '../common/types'; import streamsSetEventsQueries from '../dataLoaders/sqlQueries/streamsSetEventsQueries'; -import type { SupportedChain } from '../generated/graphql'; import buildAssetConfigs from './buildAssetConfigs'; import type getLatestAccountMetadataByChain from './getLatestAccountMetadata'; import groupBy from './linq'; @@ -10,8 +9,8 @@ export default async function getAssetConfigs( accountMetadata: NonNullable< Awaited> >, - chains: SupportedChain[], -): Promise>> { + chains: DbSchema[], +): Promise>> { const accountStreamsSetEventsWithReceivers = await streamsSetEventsQueries.getStreamsSetEventsWithReceivers( chains, @@ -23,10 +22,7 @@ export default async function getAssetConfigs( (event) => event.erc20, ); - const response = {} as Record< - SupportedChain, - ReturnType - >; + const response = {} as Record>; chains.forEach((chain) => { response[chain] = buildAssetConfigs( diff --git a/src/utils/getLatestAccountMetadata.ts b/src/utils/getLatestAccountMetadata.ts index 78e2bb7..e7cd6ed 100644 --- a/src/utils/getLatestAccountMetadata.ts +++ b/src/utils/getLatestAccountMetadata.ts @@ -1,9 +1,8 @@ import type { AnyVersion } from '@efstajas/versioned-parser'; import { ethers } from 'ethers'; import { addressDriverAccountMetadataParser } from '../schemas'; -import type { AddressDriverId, IpfsHash } from '../common/types'; +import type { AddressDriverId, DbSchema, IpfsHash } from '../common/types'; import appSettings from '../common/appSettings'; -import type { SupportedChain } from '../generated/graphql'; import accountMetadataEmittedEventsQueries from '../dataLoaders/sqlQueries/accountMetadataEmittedEventsQueries'; function toIpfsHash(str: string): IpfsHash { @@ -23,14 +22,14 @@ async function getIpfsFile(hash: IpfsHash): Promise { } export default async function getLatestAccountMetadataByChain( - chains: SupportedChain[], + chains: DbSchema[], accountId: AddressDriverId, ) { const accountMetadataEmittedEventModelDataValues = await accountMetadataEmittedEventsQueries.getByAccountId(chains, accountId); const response: { - [chain in SupportedChain]?: { + [chain in DbSchema]?: { metadata: AnyVersion; ipfsHash: IpfsHash; } | null; @@ -38,7 +37,7 @@ export default async function getLatestAccountMetadataByChain( for (const metadataDataValues of accountMetadataEmittedEventModelDataValues) { if (!accountMetadataEmittedEventModelDataValues.length) { - response[metadataDataValues.chain as SupportedChain] = null; + response[metadataDataValues.chain as DbSchema] = null; } else { const ipfsHash = toIpfsHash( accountMetadataEmittedEventModelDataValues[0].value, @@ -47,7 +46,7 @@ export default async function getLatestAccountMetadataByChain( const ipfsFile = await (await getIpfsFile(ipfsHash)).json(); const metadata = addressDriverAccountMetadataParser.parseAny(ipfsFile); - response[metadataDataValues.chain as SupportedChain] = { + response[metadataDataValues.chain as DbSchema] = { metadata, ipfsHash, }; diff --git a/src/utils/getUserAccount.ts b/src/utils/getUserAccount.ts index 92fe13d..83d1760 100644 --- a/src/utils/getUserAccount.ts +++ b/src/utils/getUserAccount.ts @@ -1,12 +1,11 @@ -import type { AddressDriverId } from '../common/types'; -import type { SupportedChain } from '../generated/graphql'; +import type { AddressDriverId, DbSchema } from '../common/types'; import { Driver } from '../generated/graphql'; import getUserAddress from './getUserAddress'; import getAssetConfigs from './getAssetConfigs'; import getLatestAccountMetadataByChain from './getLatestAccountMetadata'; export default async function getUserAccount( - chains: SupportedChain[], + chains: DbSchema[], accountId: AddressDriverId, ) { const latestAccountMetadataByChain = @@ -19,7 +18,7 @@ export default async function getUserAccount( ); const response = {} as Record< - SupportedChain, + DbSchema, { user: { accountId: AddressDriverId; @@ -29,7 +28,7 @@ export default async function getUserAccount( name: string | undefined; description: string | undefined; emoji: string | undefined; - assetConfigs: Awaited>[SupportedChain]; + assetConfigs: Awaited>[DbSchema]; lastUpdated: Date | undefined; lastUpdatedByAddress: string | undefined; lastIpfsHash: string | undefined; @@ -37,12 +36,10 @@ export default async function getUserAccount( >; Object.entries(assetConfigsByChain).forEach(([chain, assetConfigs]) => { - const metadata = - latestAccountMetadataByChain[chain as SupportedChain]?.metadata; - const ipfsHash = - latestAccountMetadataByChain[chain as SupportedChain]?.ipfsHash; + const metadata = latestAccountMetadataByChain[chain as DbSchema]?.metadata; + const ipfsHash = latestAccountMetadataByChain[chain as DbSchema]?.ipfsHash; - response[chain as SupportedChain] = { + response[chain as DbSchema] = { user: { accountId, driver: Driver.ADDRESS, diff --git a/src/utils/getWithdrawableBalances.ts b/src/utils/getWithdrawableBalances.ts index abcbf17..ccf49ed 100644 --- a/src/utils/getWithdrawableBalances.ts +++ b/src/utils/getWithdrawableBalances.ts @@ -1,14 +1,14 @@ -import type { AccountId } from '../common/types'; -import type { SupportedChain } from '../generated/graphql'; +import type { AccountId, DbSchema } from '../common/types'; import dripsContracts from '../common/dripsContracts'; import streamReceiverSeenEventQueries from '../dataLoaders/sqlQueries/streamReceiverSeenEventQueries'; import streamsSetEventsQueries from '../dataLoaders/sqlQueries/streamsSetEventsQueries'; import givenEventsQueries from '../dataLoaders/sqlQueries/givenEventsQueries'; import splitEventsQueries from '../dataLoaders/sqlQueries/splitEventsQueries'; +import { dbSchemaToChain } from './chainSchemaMappings'; export default async function getWithdrawableBalances( accountId: AccountId, - chain: SupportedChain, + chain: DbSchema, ) { const streamReceiverSeenEventsForUser = await streamReceiverSeenEventQueries.getByAccountId([chain], accountId); @@ -47,7 +47,7 @@ export default async function getWithdrawableBalances( } = Object.fromEntries( await Promise.all( relevantTokenAddresses.map(async (tokenAddress) => { - const { drips } = dripsContracts[chain]!; + const { drips } = dripsContracts[dbSchemaToChain[chain]]!; const [splittable, receivable, collectable] = await Promise.all([ drips.splittable(accountId, tokenAddress), diff --git a/src/utils/mergeAmounts.ts b/src/utils/mergeAmounts.ts index 0fbe1bc..eafc186 100644 --- a/src/utils/mergeAmounts.ts +++ b/src/utils/mergeAmounts.ts @@ -1,4 +1,4 @@ -import type { SupportedChain } from '../generated/graphql'; +import type { DbSchema } from '../common/types'; type Amount = { amount: bigint; @@ -11,7 +11,7 @@ type Amount = { * @param args The arrays of amounts to add together. */ export default function mergeAmounts( - ...args: (Amount & { chain: SupportedChain })[][] + ...args: (Amount & { chain: DbSchema })[][] ) { const amounts = new Map(); diff --git a/src/utils/parseMultiChainKeys.ts b/src/utils/parseMultiChainKeys.ts index 785f2d8..c9c187f 100644 --- a/src/utils/parseMultiChainKeys.ts +++ b/src/utils/parseMultiChainKeys.ts @@ -1,9 +1,8 @@ -import type { MultiChainKey } from '../common/types'; -import type { SupportedChain } from '../generated/graphql'; +import type { DbSchema, MultiChainKey } from '../common/types'; type ExtractedValues = { ids: (T extends { id: infer ID } ? ID : never)[]; - chains: SupportedChain[]; + chains: DbSchema[]; }; export default function parseMultiChainKeys( diff --git a/src/utils/streamUtils.ts b/src/utils/streamUtils.ts index cf8d992..c9b1d14 100644 --- a/src/utils/streamUtils.ts +++ b/src/utils/streamUtils.ts @@ -7,13 +7,13 @@ import type { AddressDriverId, AssetConfigMetadata, BigIntString, + DbSchema, } from '../common/types'; import { Driver } from '../generated/graphql'; import type { NftDriverAccount, AddressDriverAccount, StreamConfig, - SupportedChain, } from '../generated/graphql'; import getContractNameByAccountId from './getContractNameByAccountId'; import getUserAddress from './getUserAddress'; @@ -115,7 +115,7 @@ export default function buildStreamReceiver( } export function mapReceiverToStream( - chain: SupportedChain, + chain: DbSchema, receiver: ProtoStream, senderAccountId: string, tokenAddress: string, diff --git a/src/utils/streams.ts b/src/utils/streams.ts index 037c886..b466d7c 100644 --- a/src/utils/streams.ts +++ b/src/utils/streams.ts @@ -3,16 +3,15 @@ import getUserAccount from './getUserAccount'; import type { AddressDriverAccount, NftDriverAccount, - SupportedChain, } from '../generated/graphql'; -import type { AccountId } from '../common/types'; +import type { AccountId, DbSchema } from '../common/types'; import type { ProtoStream } from './buildAssetConfigs'; import streamReceiverSeenEventQueries from '../dataLoaders/sqlQueries/streamReceiverSeenEventQueries'; import streamsSetEventsQueries from '../dataLoaders/sqlQueries/streamsSetEventsQueries'; async function getUserIncomingStreams( - chains: SupportedChain[], + chains: DbSchema[], accountId: AccountId, ) { const streamReceiverSeenEventModelDataValuesForUser = @@ -36,7 +35,7 @@ async function getUserIncomingStreams( }), ); - const response = {} as Record; + const response = {} as Record; chains.forEach((chain) => { response[chain] = accountsStreamingToUser.reduce( From 12cf3dc5695dc1dc738d69aad7b8ed07cc8e27fc Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 21 Jun 2024 14:04:26 +0200 Subject: [PATCH 23/37] fix: wrong query --- src/dataLoaders/sqlQueries/splitEventsQueries.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dataLoaders/sqlQueries/splitEventsQueries.ts b/src/dataLoaders/sqlQueries/splitEventsQueries.ts index 85099a5..48966a1 100644 --- a/src/dataLoaders/sqlQueries/splitEventsQueries.ts +++ b/src/dataLoaders/sqlQueries/splitEventsQueries.ts @@ -11,7 +11,7 @@ async function getDistinctErc20ByReceiver( const baseSQL = (schema: DbSchema) => `SELECT DISTINCT ON ("erc20") "erc20", '${schema}' AS chain FROM "${schema}"."SplitEvents"`; - const whereClause = ` WHERE "accountId" = :receiver`; + const whereClause = ` WHERE "receiver" = :receiver`; const queries = chains.map((chain) => baseSQL(chain) + whereClause); From 1fdafaa8c473dfef4c32062a718efe49f4903065 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 21 Jun 2024 14:24:36 +0200 Subject: [PATCH 24/37] refactor: simplify drip list queries responses --- src/common/commonResolvers.ts | 2 +- src/common/types.ts | 6 +-- src/drip-list/dripListResolvers.ts | 2 - src/drip-list/dripListTypeDef.ts | 4 -- src/drip-list/dripListUtils.ts | 82 ++++++++++++++---------------- src/project/projectUtils.ts | 1 + src/resolvers.ts | 1 - 7 files changed, 43 insertions(+), 55 deletions(-) diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index 47a173f..d2a031a 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -97,7 +97,7 @@ const commonResolvers = { ReturnType >[number] | Awaited< - ReturnType + ReturnType >[number], ) { if ('dripList' in parent || 'project' in parent) { diff --git a/src/common/types.ts b/src/common/types.ts index 56a3199..631df5e 100644 --- a/src/common/types.ts +++ b/src/common/types.ts @@ -2,7 +2,6 @@ import type { AnyVersion } from '@efstajas/versioned-parser'; import type { ClaimedProjectData, DripList, - DripListData, Give, Project, UnClaimedProjectData, @@ -103,12 +102,11 @@ type DripListDataParentDripListInfo = { parentDripListInfo: { dripListId: DripListId; dripListChain: DbSchema; - queriedChains: DbSchema[]; + queriedChain: DbSchema; }; }; -export type ResolverDripListData = DripListData & - DripListDataParentDripListInfo; +export type ResolverDripListData = DripList & DripListDataParentDripListInfo; export type CommonDataValues = { createdAt: Date; diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index 25835e4..95dd8c5 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -84,8 +84,6 @@ const dripListResolvers = { }, DripList: { account: (dripList: ResolverDripList): NftDriverAccount => dripList.account, - }, - DripListData: { name: (dripListData: ResolverDripListData) => dripListData.name ?? 'Unnamed Drip List', creator: (dripListData: ResolverDripListData) => dripListData.creator, diff --git a/src/drip-list/dripListTypeDef.ts b/src/drip-list/dripListTypeDef.ts index dbdadfd..5ae7af6 100644 --- a/src/drip-list/dripListTypeDef.ts +++ b/src/drip-list/dripListTypeDef.ts @@ -3,10 +3,6 @@ import gql from 'graphql-tag'; const dripListTypeDef = gql` type DripList { account: NftDriverAccount! - chainData: [DripListData!]! - } - - type DripListData { chain: SupportedChain! name: String! creator: String! diff --git a/src/drip-list/dripListUtils.ts b/src/drip-list/dripListUtils.ts index 44e4606..a7d1c1f 100644 --- a/src/drip-list/dripListUtils.ts +++ b/src/drip-list/dripListUtils.ts @@ -1,10 +1,7 @@ -import type { - DbSchema, - ResolverDripList, - ResolverDripListData, -} from '../common/types'; +import type { DbSchema, ResolverDripList } from '../common/types'; import { Driver } from '../generated/graphql'; import { dbSchemaToChain } from '../utils/chainSchemaMappings'; +import { singleOrDefault } from '../utils/linq'; import type { DripListDataValues } from './DripListModel'; export async function toResolverDripList( @@ -18,44 +15,43 @@ export async function toResolverDripLists( chains: DbSchema[], dripLists: DripListDataValues[], ): Promise { - return Promise.all( - dripLists.map(async (dripList) => { - const relevantChains = chains.filter((chain) => dripList.chain === chain); + return ( + await Promise.all( + dripLists.map(async (dripList) => { + const dripListChain = singleOrDefault( + chains.filter((chain) => dripList.chain === chain), + ); - const chainData = await Promise.all( - relevantChains.map( - async (chain) => - ({ - chain: dbSchemaToChain[chain], - parentDripListInfo: { - dripListId: dripList.id, - dripListChain: chain, - queriedChains: chains, - }, - name: dripList.name, - creator: dripList.creator, - description: dripList.description, - owner: { - driver: Driver.ADDRESS, - accountId: dripList.ownerAccountId, - address: dripList.ownerAddress as string, - }, - previousOwnerAddress: dripList.previousOwnerAddress, - support: [], // Will be populated by the resolver. - splits: [], // Will be populated by the resolver. - latestVotingRoundId: dripList.latestVotingRoundId, - totalEarned: [], // Will be populated by the resolver. - }) as ResolverDripListData, - ), - ); + if (!dripListChain) { + return null; + } - return { - account: { - accountId: dripList.id, - driver: Driver.NFT, - }, - chainData, - } as ResolverDripList; - }), - ); + return { + account: { + accountId: dripList.id, + driver: Driver.NFT, + }, + chain: dbSchemaToChain[dripListChain], + parentDripListInfo: { + dripListId: dripList.id, + dripListChain, + queriedChains: chains, + }, + name: dripList.name, + creator: dripList.creator, + description: dripList.description, + owner: { + driver: Driver.ADDRESS, + accountId: dripList.ownerAccountId, + address: dripList.ownerAddress as string, + }, + previousOwnerAddress: dripList.previousOwnerAddress, + support: [], // Will be populated by the resolver. + splits: [], // Will be populated by the resolver. + latestVotingRoundId: dripList.latestVotingRoundId, + totalEarned: [], // Will be populated by the resolver. + } as ResolverDripList; + }), + ) + ).filter(Boolean) as ResolverDripList[]; } diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index 6669755..ecb63eb 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -164,6 +164,7 @@ function mapClaimedProjectChainData( claimedAt: project.claimedAt, totalEarned: [], // Will be populated by the resolver. withdrawableBalances: [], // Will be populated by the resolver. + latestMetadataIpfsHash: '', // Will be populated by the resolver. } as ResolverClaimedProjectData; } diff --git a/src/resolvers.ts b/src/resolvers.ts index 0e01475..619052f 100644 --- a/src/resolvers.ts +++ b/src/resolvers.ts @@ -19,7 +19,6 @@ const resolvers = { UnClaimedProjectData: projectResolvers.UnClaimedProjectData, DripList: dripListResolvers.DripList, DripListReceiver: commonResolvers.DripListReceiver, - DripListData: dripListResolvers.DripListData, SplitsReceiver: commonResolvers.SplitsReceiver, SupportItem: commonResolvers.SupportItem, Avatar: projectResolvers.Avatar, From 950a589cd59e3b614cd925c4c3dc55a14abcd6d2 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Mon, 24 Jun 2024 16:03:26 +0200 Subject: [PATCH 25/37] fix: DataLoader return order in cases that nulls were not handled --- src/common/commonResolvers.ts | 11 ++++++----- src/dataLoaders/DripListsDataSource.ts | 6 +++--- src/dataLoaders/GivenEventsDataSource.ts | 14 ++++++++------ src/dataLoaders/ProjectsDataSource.ts | 4 ++-- src/stream/streamResolvers.ts | 4 ++-- 5 files changed, 21 insertions(+), 18 deletions(-) diff --git a/src/common/commonResolvers.ts b/src/common/commonResolvers.ts index d2a031a..a6ca30b 100644 --- a/src/common/commonResolvers.ts +++ b/src/common/commonResolvers.ts @@ -251,11 +251,12 @@ const commonResolvers = { const { transactionHash, logIndex, chain } = parent; - const givenEvent = await givenEventsDataSource.getGivenEventById( - [chain], - transactionHash, - logIndex, - ); + const givenEvent = + (await givenEventsDataSource.getGivenEventByIdOnChain( + chain, + transactionHash, + logIndex, + )) || shouldNeverHappen("Expected 'GivenEvent' to exist."); return { driver: Driver.ADDRESS, diff --git a/src/dataLoaders/DripListsDataSource.ts b/src/dataLoaders/DripListsDataSource.ts index ec3663c..09c93e0 100644 --- a/src/dataLoaders/DripListsDataSource.ts +++ b/src/dataLoaders/DripListsDataSource.ts @@ -16,7 +16,7 @@ export default class DripListsDataSource { private readonly _batchDripListsByIds = new DataLoader( async ( dripListKeys: readonly DripListMultiChainKey[], - ): Promise => { + ): Promise<(DripListDataValues | null)[]> => { const { chains, ids: dripListIds } = parseMultiChainKeys(dripListKeys); const dripListDataValues = await dripListsQueries.getByIds( @@ -32,14 +32,14 @@ export default class DripListsDataSource { return mapping; }, {}); - return dripListIds.map((id) => dripListIdToDripListMap[id]); + return dripListKeys.map(({ id }) => dripListIdToDripListMap[id] || null); }, ); public async getDripListById( id: DripListId, chains: DbSchema[], - ): Promise { + ): Promise { return this._batchDripListsByIds.load({ id, chains, diff --git a/src/dataLoaders/GivenEventsDataSource.ts b/src/dataLoaders/GivenEventsDataSource.ts index 1ac6409..b56f2b9 100644 --- a/src/dataLoaders/GivenEventsDataSource.ts +++ b/src/dataLoaders/GivenEventsDataSource.ts @@ -17,7 +17,7 @@ export default class GivenEventsDataSource { chains: DbSchema[]; key: CompositePrimaryKey; }[], - ): Promise => { + ): Promise<(GivenEventModelDataValues | null)[]> => { const chains = [...new Set(keys.flatMap((key) => key.chains))]; const givenEventIds = keys.map(({ key }) => key); const transactionHashes = givenEventIds.map( @@ -42,17 +42,19 @@ export default class GivenEventsDataSource { return mapping; }, {}); - return givenEventIds.map((id) => idToEventMap[`${id[0]}-${id[1]}`]); + return givenEventIds.map( + (id) => idToEventMap[`${id[0]}-${id[1]}`] || null, + ); }, ); - public async getGivenEventById( - chains: DbSchema[], + public async getGivenEventByIdOnChain( + chain: DbSchema, transactionHash: TransactionHash, logIndex: LogIndex, - ): Promise { + ): Promise { return this._batchGivenEventsByIds.load({ - chains, + chains: [chain], key: [transactionHash, logIndex], }); } diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index acfc701..907ba37 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -31,11 +31,11 @@ export default class ProjectsDataSource { projectIds, ); - const projectsDataValuesWithApi = await Promise.all( + const apiProjectsDataValues = await Promise.all( projectsDataValues.map(toApiProject), ); - const filteredProjectsDataValues = projectsDataValuesWithApi.filter( + const filteredProjectsDataValues = apiProjectsDataValues.filter( Boolean, ) as ProjectDataValues[]; diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index 5bd69fa..0d82fe7 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -46,10 +46,10 @@ const streamResolvers = { if (receiver.driver === Driver.NFT) { const dbDripList = - await dataSources.dripListsDataSource.getDripListById( + (await dataSources.dripListsDataSource.getDripListById( receiver.accountId as DripListId, [chain], - ); + )) || shouldNeverHappen('Expected Drip List to exist.'); return toResolverDripList(chain, dbDripList); } From a617d25117c310fd8bba8a16fa95fc36b9802212 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 5 Jul 2024 12:44:53 +0200 Subject: [PATCH 26/37] refactor: flatten stream response --- package-lock.json | 6678 +++++++++++++++++---------------- src/schema.ts | 5 +- src/stream/streamResolvers.ts | 12 +- src/stream/streamTypeDef.ts | 4 - 4 files changed, 3453 insertions(+), 3246 deletions(-) diff --git a/package-lock.json b/package-lock.json index 57a9397..49b376b 100644 --- a/package-lock.json +++ b/package-lock.json @@ -48,28 +48,21 @@ "typescript": "^5.2.2" } }, - "node_modules/@aashutoshrathi/word-wrap": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz", - "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/@adraffy/ens-normalize": { - "version": "1.9.2", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.9.2.tgz", - "integrity": "sha512-0h+FrQDqe2Wn+IIGFkTCd4aAwTJ+7834Ek1COohCyV26AXhwQ7WQaz+4F/nLOeVl/3BtWHOHLPsq46V8YB46Eg==" + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.10.1.tgz", + "integrity": "sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==", + "license": "MIT" }, "node_modules/@ampproject/remapping": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", - "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", + "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@jridgewell/gen-mapping": "^0.3.0", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" @@ -79,6 +72,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/@apollo/cache-control-types/-/cache-control-types-1.0.3.tgz", "integrity": "sha512-F17/vCp7QVwom9eG7ToauIKdAxpSoadsJnqIfyryLFSkLSOEqu+eC5Z3N8OXcUVStuOMcNHlyraRsA6rRICu4g==", + "license": "MIT", "peerDependencies": { "graphql": "14.x || 15.x || 16.x" } @@ -88,6 +82,7 @@ "resolved": "https://registry.npmjs.org/@apollo/protobufjs/-/protobufjs-1.2.7.tgz", "integrity": "sha512-Lahx5zntHPZia35myYDBRuF58tlwPskwHc5CWBZC/4bMKB6siTBWwtMrkqXcsNwQiFSzSx5hKdRPUmemrEp3Gg==", "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.2", "@protobufjs/base64": "^1.1.2", @@ -108,9 +103,10 @@ } }, "node_modules/@apollo/server": { - "version": "4.9.3", - "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.9.3.tgz", - "integrity": "sha512-U56Sx/UmzR3Es344hQ/Ptf2EJrH+kV4ZPoLmgGjWoiwf2wYQ/pRSvkSXgjOvoyE34wSa8Gh7f92ljfLfY+6q1w==", + "version": "4.10.4", + "resolved": "https://registry.npmjs.org/@apollo/server/-/server-4.10.4.tgz", + "integrity": "sha512-HS12CUa1wq8f5zKXOKJRwRdESFp4por9AINecpcsEUV9jsCP/NqPILgx0hCOOFJuKxmnaL7070xO6l5xmOq4Fw==", + "license": "MIT", "dependencies": { "@apollo/cache-control-types": "^1.0.3", "@apollo/server-gateway-interface": "^1.1.1", @@ -128,7 +124,6 @@ "@types/express-serve-static-core": "^4.17.30", "@types/node-fetch": "^2.6.1", "async-retry": "^1.2.1", - "body-parser": "^1.20.0", "cors": "^2.8.5", "express": "^4.17.1", "loglevel": "^1.6.8", @@ -150,6 +145,7 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/@apollo/server-gateway-interface/-/server-gateway-interface-1.1.1.tgz", "integrity": "sha512-pGwCl/po6+rxRmDMFgozKQo2pbsSwE91TpsDBAOgf74CRDPXHHtM88wbwjab0wMMZh95QfR45GGyDIdhY24bkQ==", + "license": "MIT", "dependencies": { "@apollo/usage-reporting-protobuf": "^4.1.1", "@apollo/utils.fetcher": "^2.0.0", @@ -160,18 +156,11 @@ "graphql": "14.x || 15.x || 16.x" } }, - "node_modules/@apollo/server/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, "node_modules/@apollo/usage-reporting-protobuf": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/@apollo/usage-reporting-protobuf/-/usage-reporting-protobuf-4.1.1.tgz", "integrity": "sha512-u40dIUePHaSKVshcedO7Wp+mPiZsaU6xjv9J+VyxpoU/zL6Jle+9zWeG98tr/+SZ0nZ4OXhrbb8SNr0rAPpIDA==", + "license": "MIT", "dependencies": { "@apollo/protobufjs": "1.2.7" } @@ -180,6 +169,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.createhash/-/utils.createhash-2.0.1.tgz", "integrity": "sha512-fQO4/ZOP8LcXWvMNhKiee+2KuKyqIcfHrICA+M4lj/h/Lh1H10ICcUtk6N/chnEo5HXu0yejg64wshdaiFitJg==", + "license": "MIT", "dependencies": { "@apollo/utils.isnodelike": "^2.0.1", "sha.js": "^2.4.11" @@ -192,6 +182,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.dropunuseddefinitions/-/utils.dropunuseddefinitions-2.0.1.tgz", "integrity": "sha512-EsPIBqsSt2BwDsv8Wu76LK5R1KtsVkNoO4b0M5aK0hx+dGg9xJXuqlr7Fo34Dl+y83jmzn+UvEW+t1/GP2melA==", + "license": "MIT", "engines": { "node": ">=14" }, @@ -203,6 +194,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.fetcher/-/utils.fetcher-2.0.1.tgz", "integrity": "sha512-jvvon885hEyWXd4H6zpWeN3tl88QcWnHp5gWF5OPF34uhvoR+DFqcNxs9vrRaBBSY3qda3Qe0bdud7tz2zGx1A==", + "license": "MIT", "engines": { "node": ">=14" } @@ -211,6 +203,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.isnodelike/-/utils.isnodelike-2.0.1.tgz", "integrity": "sha512-w41XyepR+jBEuVpoRM715N2ZD0xMD413UiJx8w5xnAZD2ZkSJnMJBoIzauK83kJpSgNuR6ywbV29jG9NmxjK0Q==", + "license": "MIT", "engines": { "node": ">=14" } @@ -219,6 +212,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/@apollo/utils.keyvaluecache/-/utils.keyvaluecache-2.1.1.tgz", "integrity": "sha512-qVo5PvUUMD8oB9oYvq4ViCjYAMWnZ5zZwEjNF37L2m1u528x5mueMlU+Cr1UinupCgdB78g+egA1G98rbJ03Vw==", + "license": "MIT", "dependencies": { "@apollo/utils.logger": "^2.0.1", "lru-cache": "^7.14.1" @@ -227,18 +221,11 @@ "node": ">=14" } }, - "node_modules/@apollo/utils.keyvaluecache/node_modules/lru-cache": { - "version": "7.18.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", - "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", - "engines": { - "node": ">=12" - } - }, "node_modules/@apollo/utils.logger": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.logger/-/utils.logger-2.0.1.tgz", "integrity": "sha512-YuplwLHaHf1oviidB7MxnCXAdHp3IqYV8n0momZ3JfLniae92eYqMIx+j5qJFX6WKJPs6q7bczmV4lXIsTu5Pg==", + "license": "MIT", "engines": { "node": ">=14" } @@ -247,6 +234,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.printwithreducedwhitespace/-/utils.printwithreducedwhitespace-2.0.1.tgz", "integrity": "sha512-9M4LUXV/fQBh8vZWlLvb/HyyhjJ77/I5ZKu+NBWV/BmYGyRmoEP9EVAy7LCVoY3t8BDcyCAGfxJaLFCSuQkPUg==", + "license": "MIT", "engines": { "node": ">=14" }, @@ -258,6 +246,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.removealiases/-/utils.removealiases-2.0.1.tgz", "integrity": "sha512-0joRc2HBO4u594Op1nev+mUF6yRnxoUH64xw8x3bX7n8QBDYdeYgY4tF0vJReTy+zdn2xv6fMsquATSgC722FA==", + "license": "MIT", "engines": { "node": ">=14" }, @@ -269,6 +258,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.sortast/-/utils.sortast-2.0.1.tgz", "integrity": "sha512-eciIavsWpJ09za1pn37wpsCGrQNXUhM0TktnZmHwO+Zy9O4fu/WdB4+5BvVhFiZYOXvfjzJUcc+hsIV8RUOtMw==", + "license": "MIT", "dependencies": { "lodash.sortby": "^4.7.0" }, @@ -283,6 +273,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.stripsensitiveliterals/-/utils.stripsensitiveliterals-2.0.1.tgz", "integrity": "sha512-QJs7HtzXS/JIPMKWimFnUMK7VjkGQTzqD9bKD1h3iuPAqLsxd0mUNVbkYOPTsDhUKgcvUOfOqOJWYohAKMvcSA==", + "license": "MIT", "engines": { "node": ">=14" }, @@ -294,6 +285,7 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/@apollo/utils.usagereporting/-/utils.usagereporting-2.1.0.tgz", "integrity": "sha512-LPSlBrn+S17oBy5eWkrRSGb98sWmnEzo3DPTZgp8IQc8sJe0prDgDuppGq4NeQlpoqEHz0hQeYHAOA0Z3aQsxQ==", + "license": "MIT", "dependencies": { "@apollo/usage-reporting-protobuf": "^4.1.0", "@apollo/utils.dropunuseddefinitions": "^2.0.1", @@ -313,6 +305,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/@apollo/utils.withrequired/-/utils.withrequired-2.0.1.tgz", "integrity": "sha512-YBDiuAX9i1lLc6GeTy1m7DGLFn/gMnvXqlalOIMjM7DeOgIacEjjfwPqb0M1CQ2v11HhR15d1NmxJoRCfrNqcA==", + "license": "MIT", "engines": { "node": ">=14" } @@ -322,6 +315,7 @@ "resolved": "https://registry.npmjs.org/@ardatan/relay-compiler/-/relay-compiler-12.0.0.tgz", "integrity": "sha512-9anThAaj1dQr6IGmzBMcfzOQKTa5artjuPmw8NYK/fiGEMjADbSguBY2FMDykt+QhilR3wc9VA/3yVju7JHg7Q==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.14.0", "@babel/generator": "^7.14.0", @@ -348,71 +342,24 @@ "graphql": "*" } }, - "node_modules/@ardatan/relay-compiler/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, "node_modules/@ardatan/relay-compiler/node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.0", "wrap-ansi": "^6.2.0" } }, - "node_modules/@ardatan/relay-compiler/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/@ardatan/relay-compiler/node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" @@ -421,20 +368,12 @@ "node": ">=8" } }, - "node_modules/@ardatan/relay-compiler/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/@ardatan/relay-compiler/node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, @@ -447,6 +386,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, + "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, @@ -462,6 +402,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, @@ -469,43 +410,19 @@ "node": ">=8" } }, - "node_modules/@ardatan/relay-compiler/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@ardatan/relay-compiler/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@ardatan/relay-compiler/node_modules/y18n": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/@ardatan/relay-compiler/node_modules/yargs": { "version": "15.4.1", "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^6.0.0", "decamelize": "^1.2.0", @@ -528,6 +445,7 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", "dev": true, + "license": "ISC", "dependencies": { "camelcase": "^5.0.0", "decamelize": "^1.2.0" @@ -541,6 +459,7 @@ "resolved": "https://registry.npmjs.org/@ardatan/sync-fetch/-/sync-fetch-0.0.1.tgz", "integrity": "sha512-xhlTqH0m31mnsG0tIP4ETgfSB6gXDaYYsUWTrlUV93fFQPI9dd8hE0Ot6MHLCtqgB32hwJAC3YZMWlXZw7AleA==", "dev": true, + "license": "MIT", "dependencies": { "node-fetch": "^2.6.1" }, @@ -549,43 +468,46 @@ } }, "node_modules/@babel/code-frame": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.22.13.tgz", - "integrity": "sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", + "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/highlight": "^7.22.13", - "chalk": "^2.4.2" + "@babel/highlight": "^7.24.7", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/compat-data": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.2.tgz", - "integrity": "sha512-0S9TQMmDHlqAZ2ITT95irXKfxN9bncq8ZCoJhun3nHL/lLUxd2NKBJYoNGWH7S0hz6fRQwWlAWn/ILM0C70KZQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.24.7.tgz", + "integrity": "sha512-qJzAIcv03PyaWqxRgO4mSU3lihncDT296vnyuE2O8uA4w3UHWI4S3hgeZd1L8W1Bft40w9JxJ2b412iDUFFRhw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/core": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.2.tgz", - "integrity": "sha512-n7s51eWdaWZ3vGT2tD4T7J6eJs3QoBXydv7vkUM06Bf1cbVD2Kc2UrkzhiQwobfV7NwOnQXYL7UBJ5VPU+RGoQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.24.7.tgz", + "integrity": "sha512-nykK+LEK86ahTkX/3TgauT0ikKoNCfKHEaZYTUVupJdTLzGNvrblu4u6fa7DhZONAltdf8e662t/abY8idrd/g==", "dev": true, + "license": "MIT", "dependencies": { "@ampproject/remapping": "^2.2.0", - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helpers": "^7.23.2", - "@babel/parser": "^7.23.0", - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helpers": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/template": "^7.24.7", + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7", "convert-source-map": "^2.0.0", "debug": "^4.1.0", "gensync": "^1.0.0-beta.2", @@ -600,73 +522,45 @@ "url": "https://opencollective.com/babel" } }, - "node_modules/@babel/core/node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@babel/core/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.0.tgz", - "integrity": "sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.7.tgz", + "integrity": "sha512-oipXieGC3i45Y1A41t4tAqpnEZWgB/lC6Ehh6+rOviR5XWpTtMmLN+fGjz9vOiNRt0p6RtO6DtD0pdU3vpqdSA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.23.0", - "@jridgewell/gen-mapping": "^0.3.2", - "@jridgewell/trace-mapping": "^0.3.17", + "@babel/types": "^7.24.7", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/trace-mapping": { - "version": "0.3.19", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.19.tgz", - "integrity": "sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==", - "dev": true, - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, "node_modules/@babel/helper-annotate-as-pure": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz", - "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.24.7.tgz", + "integrity": "sha512-BaDeOonYvhdKw+JoMVkAixAAJzG2jVPIwWoKBPdYuY9b452e2rPuI9QPYh3KpofZ3pW2akOmwZLOiOsHMiqRAg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.22.15.tgz", - "integrity": "sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.24.7.tgz", + "integrity": "sha512-ctSdRHBi20qWOfy27RUb4Fhp07KSJ3sXcuSvTrXrc4aG8NSYDo1ici3Vhg9bg69y5bj0Mr1lh0aeEgTvc12rMg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.22.9", - "@babel/helper-validator-option": "^7.22.15", - "browserslist": "^4.21.9", + "@babel/compat-data": "^7.24.7", + "@babel/helper-validator-option": "^7.24.7", + "browserslist": "^4.22.2", "lru-cache": "^5.1.1", "semver": "^6.3.1" }, @@ -679,39 +573,26 @@ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", "dev": true, + "license": "ISC", "dependencies": { "yallist": "^3.0.2" } }, - "node_modules/@babel/helper-compilation-targets/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true - }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.22.15.tgz", - "integrity": "sha512-jKkwA59IXcvSaiK2UN45kKwSC9o+KuoXsBDvHvU/7BecYIp8GQ2UwrVvFgJASUT+hBnwJx6MhvMCuMzwZZ7jlg==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.24.7.tgz", + "integrity": "sha512-kTkaDl7c9vO80zeX1rJxnuRpEsD5tA81yh11X1gQo+PhSti3JS+7qeZo9U4RHobKRiFPKaGK3svUAeb8D0Q7eg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", "semver": "^6.3.1" }, "engines": { @@ -721,84 +602,86 @@ "@babel/core": "^7.0.0" } }, - "node_modules/@babel/helper-create-class-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/helper-environment-visitor": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz", - "integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-function-name": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz", - "integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz", + "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-hoist-variables": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz", - "integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz", + "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-member-expression-to-functions": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.23.0.tgz", - "integrity": "sha512-6gfrPwh7OuT6gZyJZvd6WbTfrqAo7vm4xCzAXOusKqq/vWdKXphTpj5klHKNmRUU6/QRGlBsyU9mAIPaWHlqJA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.24.7.tgz", + "integrity": "sha512-LGeMaf5JN4hAT471eJdBs/GK1DoYIJ5GCtZN/EsL6KUiiDZOvO/eKE11AMZJa2zP4zk4qe9V2O/hxAmkRc8p6w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.23.0" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-imports": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.22.15.tgz", - "integrity": "sha512-0pYVBnDKZO2fnSPCrgM/6WMc7eS20Fbok+0r88fp+YtWVLZrp4CkafFGIp+W0VKw4a22sgebPT99y+FDNMdP4w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.24.7.tgz", + "integrity": "sha512-8AyH3C+74cgCVVXow/myrynrAGv+nTVg5vKu2nZph9x7RcRwzmh0VFallJuFTZ9mx6u4eSdXZfcOzSqTUm0HCA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.15" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-module-transforms": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.0.tgz", - "integrity": "sha512-WhDWw1tdrlT0gMgUJSlX0IQvoO1eN279zrAUbVB+KpV2c3Tylz8+GnKOLllCS6Z/iZQEyVYxhZVUdPTqs2YYPw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.24.7.tgz", + "integrity": "sha512-1fuJEwIrp+97rM4RWdO+qrRsZlAeL1lQJoPqtCYWv0NL115XM93hIH4CSRln2w52SqvmY5hqdtauB6QFCDiZNQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-simple-access": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/helper-validator-identifier": "^7.22.20" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -808,35 +691,38 @@ } }, "node_modules/@babel/helper-optimise-call-expression": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.22.5.tgz", - "integrity": "sha512-HBwaojN0xFRx4yIvpwGqxiV2tUfl7401jlok564NgB9EHS1y6QT17FmKWm4ztqjeVdXLuC4fSvHc5ePpQjoTbw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.24.7.tgz", + "integrity": "sha512-jKiTsW2xmWwxT1ixIdfXUZp+P5yURx2suzLZr5Hi64rURpDYdMW0pv+Uf17EYk2Rd428Lx4tLsnjGJzYKDM/6A==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-plugin-utils": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz", - "integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.24.7.tgz", + "integrity": "sha512-Rq76wjt7yz9AAc1KnlRKNAi/dMSVWgDRx43FHoJEbcYU6xOWaE2dVPwcdTukJrjxS65GITyfbvEYHvkirZ6uEg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-replace-supers": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.22.20.tgz", - "integrity": "sha512-qsW0In3dbwQUbK8kejJ4R7IHVGwHJlV6lpG6UA7a9hSa2YEiAib+N1T2kr6PEeUT+Fl7najmSOS6SmAwCHK6Tw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.24.7.tgz", + "integrity": "sha512-qTAxxBM81VEyoAY0TtLrx1oAEJc09ZK67Q9ljQToqCnA+55eNwCORaxlKyu+rNfX86o8OXRUSNUnrtsAZXM9sg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-member-expression-to-functions": "^7.22.15", - "@babel/helper-optimise-call-expression": "^7.22.5" + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-member-expression-to-functions": "^7.24.7", + "@babel/helper-optimise-call-expression": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -846,101 +732,190 @@ } }, "node_modules/@babel/helper-simple-access": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz", - "integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.24.7.tgz", + "integrity": "sha512-zBAIvbCMh5Ts+b86r/CjU+4XGYIs+R1j951gxI3KmmxBMhCg4oQMsv6ZXQ64XOm/cvzfU1FmoCyt6+owc5QMYg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-skip-transparent-expression-wrappers": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.22.5.tgz", - "integrity": "sha512-tK14r66JZKiC43p8Ki33yLBVJKlQDFoA8GYN67lWCDCqoL6EMMSuM9b+Iff2jHaM/RRFYl7K+iiru7hbRqNx8Q==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.24.7.tgz", + "integrity": "sha512-IO+DLT3LQUElMbpzlatRASEyQtfhSE0+m465v++3jyyXeBTBUjtVZg28/gHeV5mrTJqvEKhKroBGAvhW+qPHiQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-split-export-declaration": { - "version": "7.22.6", - "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz", - "integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz", + "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/types": "^7.22.5" + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz", - "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.7.tgz", + "integrity": "sha512-7MbVt6xrwFQbunH2DNQsAP5sTGxfqQtErvBIvIMi6EQnbgUOuVYanvREcmFrOPhoXBrTtjhhP+lW+o5UfK+tDg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", + "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-option": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.22.15.tgz", - "integrity": "sha512-bMn7RmyFjY/mdECUbgn9eoSY4vqvacUnS9i9vGAGttgFWesO6B4CYWA7XlpbWgBt71iv/hfbPlynohStqnu5hA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.24.7.tgz", + "integrity": "sha512-yy1/KvjhV/ZCL+SM7hBrvnZJ3ZuT9OuZgIJAGpPEToANvc3iM6iDvBnRjtElWibHU6n8/LPR/EjX9EtIEYO3pw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helpers": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.2.tgz", - "integrity": "sha512-lzchcp8SjTSVe/fPmLwtWVBFC7+Tbn8LGHDVfDp9JGxpAY5opSaEFgt8UQvrnECWOTdji2mOWMz1rOhkHscmGQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.24.7.tgz", + "integrity": "sha512-NlmJJtvcw72yRJRcnCmGvSi+3jDEg8qFu3z0AFoymmzLx5ERVWyzd9kVXr7Th9/8yIJi2Zc6av4Tqz3wFs8QWg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/template": "^7.22.15", - "@babel/traverse": "^7.23.2", - "@babel/types": "^7.23.0" + "@babel/template": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { - "version": "7.22.13", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.22.13.tgz", - "integrity": "sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", + "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", + "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", - "js-tokens": "^4.0.0" + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@babel/highlight/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/@babel/parser": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz", - "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.24.7.tgz", + "integrity": "sha512-9uUYRm6OqQrCqQdG1iCBwBPZgN8ciDBro2nIOFaiRz1/BCxaI7CNvQbDHvsArAC7Tw9Hda/B3U+6ui9u4HWXPw==", "dev": true, + "license": "MIT", "bin": { "parser": "bin/babel-parser.js" }, @@ -954,6 +929,7 @@ "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-create-class-features-plugin": "^7.18.6", "@babel/helper-plugin-utils": "^7.18.6" @@ -971,6 +947,7 @@ "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", "dev": true, + "license": "MIT", "dependencies": { "@babel/compat-data": "^7.20.5", "@babel/helper-compilation-targets": "^7.20.7", @@ -990,6 +967,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz", "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.12.13" }, @@ -998,12 +976,13 @@ } }, "node_modules/@babel/plugin-syntax-flow": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.22.5.tgz", - "integrity": "sha512-9RdCl0i+q0QExayk2nOS7853w08yLucnnPML6EN9S8fgMPVtdLDCdx/cOQ/i44Lb9UeQX9A35yaqBBOMMZxPxQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.24.7.tgz", + "integrity": "sha512-9G8GYT/dxn/D1IIKOUBmGX0mnmj46mGH9NnZyJLwtCpgh5f7D2VbuKodb+2s9m1Yavh1s7ASQN8lf0eqrb1LTw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1013,12 +992,13 @@ } }, "node_modules/@babel/plugin-syntax-import-assertions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.22.5.tgz", - "integrity": "sha512-rdV97N7KqsRzeNGoWUOK6yUsWarLjE5Su/Snk9IYPU9CwkWHs4t+rTGOvffTR8XGkJMTAdLfO0xVnXm8wugIJg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.24.7.tgz", + "integrity": "sha512-Ec3NRUMoi8gskrkBe3fNmEQfxDvY8bgfQpz6jlk/41kX9eUjvpyqWU7PBP/pLAvMaSQjbMNKJmvX57jP+M6bPg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1028,12 +1008,13 @@ } }, "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz", - "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.24.7.tgz", + "integrity": "sha512-6ddciUPe/mpMnOKv/U+RSd2vvVy+Yw/JfBB0ZHYjEZt9NLHmCUylNYlsbqCCS1Bffjlb0fCwC9Vqz+sBz6PsiQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1047,6 +1028,7 @@ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz", "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==", "dev": true, + "license": "MIT", "dependencies": { "@babel/helper-plugin-utils": "^7.8.0" }, @@ -1055,12 +1037,13 @@ } }, "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.22.5.tgz", - "integrity": "sha512-26lTNXoVRdAnsaDXPpvCNUq+OVWEVC6bx7Vvz9rC53F2bagUWW4u4ii2+h8Fejfh7RYqPxn+libeFBBck9muEw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1070,12 +1053,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.22.5.tgz", - "integrity": "sha512-tdXZ2UdknEKQWKJP1KMNmuF5Lx3MymtMN/pvA+p/VEkhK8jVcQ1fzSy8KM9qRYhAf2/lV33hoMPKI/xaI9sADA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1085,12 +1069,13 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.23.0.tgz", - "integrity": "sha512-cOsrbmIOXmf+5YbL99/S49Y3j46k/T16b9ml8bm9lP6N9US5iQ2yBK7gpui1pg0V/WMcXdkfKbTb7HXq9u+v4g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.24.7.tgz", + "integrity": "sha512-Nd5CvgMbWc+oWzBsuaMcbwjJWAcp5qzrbg69SZdHSP7AMY0AbWFqFO0WTFCA1jxhMCwodRwvRec8k0QUbZk7RQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1100,19 +1085,19 @@ } }, "node_modules/@babel/plugin-transform-classes": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.22.15.tgz", - "integrity": "sha512-VbbC3PGjBdE0wAWDdHM9G8Gm977pnYI0XpqMd6LrKISj8/DJXEsWqgRuTYaNE9Bv0JGhTZUzHDlMk18IpOuoqw==", - "dev": true, - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-compilation-targets": "^7.22.15", - "@babel/helper-environment-visitor": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-optimise-call-expression": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.9", - "@babel/helper-split-export-declaration": "^7.22.6", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.24.7.tgz", + "integrity": "sha512-CFbbBigp8ln4FU6Bpy6g7sE8B/WmCmzvivzUC6xDAdWVsjYTXijpuuGJmYkAaoWAzcItGKT3IOAbxRItZ5HTjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", "globals": "^11.1.0" }, "engines": { @@ -1122,23 +1107,15 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-transform-classes/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.22.5.tgz", - "integrity": "sha512-4GHWBgRf0krxPX+AaPtgBAlTgTeZmqDynokHOX7aqqAB4tHs3U2Y02zH6ETFdLZGcg9UQSD1WCmkVrE9ErHeOg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/template": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1148,12 +1125,13 @@ } }, "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.23.0.tgz", - "integrity": "sha512-vaMdgNXFkYrB+8lbgniSYWHsgqK5gjaMNcc84bMIOMRLH0L9AqYq3hwMdvnyqj1OPqea8UtjPEuS/DCenah1wg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.7.tgz", + "integrity": "sha512-19eJO/8kdCQ9zISOf+SEUJM/bAUIsvY3YDnXZTupUCQ8LgrWnsG/gFB9dvXqdXnRXMAM8fvt7b0CBKQHNGy1mw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1163,13 +1141,14 @@ } }, "node_modules/@babel/plugin-transform-flow-strip-types": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.22.5.tgz", - "integrity": "sha512-tujNbZdxdG0/54g/oua8ISToaXTFBf8EnSb5PgQSciIXWOWKX3S4+JR7ZE9ol8FZwf9kxitzkGQ+QWeov/mCiA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.24.7.tgz", + "integrity": "sha512-cjRKJ7FobOH2eakx7Ja+KpJRj8+y+/SiB3ooYm/n2UJfxu0oEaOoxOinitkJcPqv9KxS0kxTGPUaR7L2XcXDXA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-flow": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-flow": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1179,12 +1158,14 @@ } }, "node_modules/@babel/plugin-transform-for-of": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.22.15.tgz", - "integrity": "sha512-me6VGeHsx30+xh9fbDLLPi0J1HzmeIIyenoOQHuw2D4m2SAU3NrspX5XxJLBpqn5yrLzrlw2Iy3RA//Bx27iOA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1194,14 +1175,15 @@ } }, "node_modules/@babel/plugin-transform-function-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.22.5.tgz", - "integrity": "sha512-UIzQNMS0p0HHiQm3oelztj+ECwFnj+ZRV4KnguvlsD2of1whUeM6o7wGNj6oLwcDoAXQ8gEqfgC24D+VdIcevg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.24.7.tgz", + "integrity": "sha512-U9FcnA821YoILngSmYkW6FjyQe2TyZD5pHt4EVIhmcTkrJw/3KqcrRSxuOo5tFZJi7TE19iDyI1u+weTI7bn2w==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-compilation-targets": "^7.22.5", - "@babel/helper-function-name": "^7.22.5", - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1211,12 +1193,13 @@ } }, "node_modules/@babel/plugin-transform-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.22.5.tgz", - "integrity": "sha512-fTLj4D79M+mepcw3dgFBTIDYpbcB9Sm0bpm4ppXPaO+U+PKFFyV9MGRvS0gvGw62sd10kT5lRMKXAADb9pWy8g==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.24.7.tgz", + "integrity": "sha512-vcwCbb4HDH+hWi8Pqenwnjy+UiklO4Kt1vfspcQYFhJdpthSnW8XvWGyDZWKNVrVbVViI/S7K9PDJZiUmP2fYQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1226,12 +1209,13 @@ } }, "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.22.5.tgz", - "integrity": "sha512-RZEdkNtzzYCFl9SE9ATaUMTj2hqMb4StarOJLrZRbqqU4HSBE7UlBw9WBWQiDzrJZJdUWiMTVDI6Gv/8DPvfew==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1241,14 +1225,15 @@ } }, "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.23.0.tgz", - "integrity": "sha512-32Xzss14/UVc7k9g775yMIvkVK8xwKE0DPdP5JTapr3+Z9w4tzeOuLNY6BXDQR6BdnzIlXnCGAzsk/ICHBLVWQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.24.7.tgz", + "integrity": "sha512-iFI8GDxtevHJ/Z22J5xQpVqFLlMNstcLXh994xifFwxxGslr2ZXXLWgtBeLctOD63UFDArdvN6Tg8RFw+aEmjQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.23.0", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-simple-access": "^7.22.5" + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-simple-access": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1258,13 +1243,14 @@ } }, "node_modules/@babel/plugin-transform-object-super": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.22.5.tgz", - "integrity": "sha512-klXqyaT9trSjIUrcsYIfETAzmOEZL3cBYqOYLJxBHfMFFggmXOv+NYSX/Jbs9mzMVESw/WycLFPRx8ba/b2Ipw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-replace-supers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1274,12 +1260,13 @@ } }, "node_modules/@babel/plugin-transform-parameters": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.22.15.tgz", - "integrity": "sha512-hjk7qKIqhyzhhUvRT683TYQOFa/4cQKwQy7ALvTpODswN40MljzNDa0YldevS6tGbxwaEKVn502JmY0dP7qEtQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1289,12 +1276,13 @@ } }, "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.22.5.tgz", - "integrity": "sha512-TiOArgddK3mK/x1Qwf5hay2pxI6wCZnvQqrFSqbtg1GLl2JcNMitVH/YnqjP+M31pLUeTfzY1HAXFDnUBV30rQ==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1304,12 +1292,13 @@ } }, "node_modules/@babel/plugin-transform-react-display-name": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.22.5.tgz", - "integrity": "sha512-PVk3WPYudRF5z4GKMEYUrLjPl38fJSKNaEOkFuoprioowGuWN6w2RKznuFNSlJx7pzzXXStPUnNSOEO0jL5EVw==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.24.7.tgz", + "integrity": "sha512-H/Snz9PFxKsS1JLI4dJLtnJgCJRoo0AUm3chP6NYr+9En1JMKloheEiLIhlp5MDVznWo+H3AAC1Mc8lmUEpsgg==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1319,16 +1308,17 @@ } }, "node_modules/@babel/plugin-transform-react-jsx": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.22.15.tgz", - "integrity": "sha512-oKckg2eZFa8771O/5vi7XeTvmM6+O9cxZu+kanTU7tD4sin5nO/G8jGJhq8Hvt2Z0kUoEDRayuZLaUlYl8QuGA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.24.7.tgz", + "integrity": "sha512-+Dj06GDZEFRYvclU6k4bme55GKBEWUmByM/eoKuqg4zTNQHiApWRhQph5fxQB2wAEFvRzL1tOEj1RJ19wJrhoA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.22.5", - "@babel/helper-module-imports": "^7.22.15", - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/plugin-syntax-jsx": "^7.22.5", - "@babel/types": "^7.22.15" + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1338,12 +1328,13 @@ } }, "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.22.5.tgz", - "integrity": "sha512-vM4fq9IXHscXVKzDv5itkO1X52SmdFBFcMIBZ2FRn2nqVYqw6dBexUgMvAjHW+KXpPPViD/Yo3GrDEBaRC0QYA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1353,13 +1344,14 @@ } }, "node_modules/@babel/plugin-transform-spread": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.22.5.tgz", - "integrity": "sha512-5ZzDQIGyvN4w8+dMmpohL6MBo+l2G7tfC/O2Dg7/hjpgeWvUx8FzfeOKxGog9IimPa4YekaQ9PlDqTLOljkcxg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5", - "@babel/helper-skip-transparent-expression-wrappers": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1369,12 +1361,13 @@ } }, "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.22.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.22.5.tgz", - "integrity": "sha512-5ciOehRNf+EyUeewo8NkbQiUs4d6ZxiHo6BcBcnFlgiJfu16q0bQUw9Jvo0b0gBKFG1SMhDSjeKXSYuJLeFSMA==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.22.5" + "@babel/helper-plugin-utils": "^7.24.7" }, "engines": { "node": ">=6.9.0" @@ -1384,10 +1377,11 @@ } }, "node_modules/@babel/runtime": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.23.2.tgz", - "integrity": "sha512-mM8eg4yl5D6i3lu2QKPuPH4FArvJ8KhTofbE7jwMUv9KX5mBvwPAqnV3MlyBNqdp9RyRKP6Yck8TrfYrPvX3bg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.7.tgz", + "integrity": "sha512-UwgBRMjJP+xv857DCngvqXI3Iq6J4v0wXmwc6sapg+zyhbwmQX67LUEFrkK5tbyJ30jGuG3ZvWpBiB9LCy1kWw==", "dev": true, + "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" }, @@ -1396,57 +1390,51 @@ } }, "node_modules/@babel/template": { - "version": "7.22.15", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz", - "integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz", + "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/parser": "^7.22.15", - "@babel/types": "^7.22.15" + "@babel/code-frame": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.23.2", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.2.tgz", - "integrity": "sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==", - "dev": true, - "dependencies": { - "@babel/code-frame": "^7.22.13", - "@babel/generator": "^7.23.0", - "@babel/helper-environment-visitor": "^7.22.20", - "@babel/helper-function-name": "^7.23.0", - "@babel/helper-hoist-variables": "^7.22.5", - "@babel/helper-split-export-declaration": "^7.22.6", - "@babel/parser": "^7.23.0", - "@babel/types": "^7.23.0", - "debug": "^4.1.0", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.7.tgz", + "integrity": "sha512-yb65Ed5S/QAcewNPh0nZczy9JdYXkkAbIsEo+P7BE7yO3txAY30Y/oPa3QkQ5It3xVG2kpKMg9MsdxZaO31uKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.24.7", + "@babel/helper-environment-visitor": "^7.24.7", + "@babel/helper-function-name": "^7.24.7", + "@babel/helper-hoist-variables": "^7.24.7", + "@babel/helper-split-export-declaration": "^7.24.7", + "@babel/parser": "^7.24.7", + "@babel/types": "^7.24.7", + "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/traverse/node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/@babel/types": { - "version": "7.23.0", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz", - "integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==", + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.24.7.tgz", + "integrity": "sha512-XEFXSlxiG5td2EJRe8vOmRbaXVgfcBlszKujvVmWIK/UpywWljQCfzAv3RQCGujWQ1RD4YYWEAqDXfuJiy8f5Q==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-string-parser": "^7.22.5", - "@babel/helper-validator-identifier": "^7.22.20", + "@babel/helper-string-parser": "^7.24.7", + "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { @@ -1454,268 +1442,156 @@ } }, "node_modules/@commitlint/config-validator": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-17.6.7.tgz", - "integrity": "sha512-vJSncmnzwMvpr3lIcm0I8YVVDJTzyjy7NZAeXbTXy+MPUdAr9pKyyg7Tx/ebOQ9kqzE6O9WT6jg2164br5UdsQ==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-19.0.3.tgz", + "integrity": "sha512-2D3r4PKjoo59zBc2auodrSCaUnCSALCx54yveOFwwP/i2kfEAQrygwOleFWswLqK0UL/F9r07MFi5ev2ohyM4Q==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { - "@commitlint/types": "^17.4.4", + "@commitlint/types": "^19.0.3", "ajv": "^8.11.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/execute-rule": { - "version": "17.4.0", - "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-17.4.0.tgz", - "integrity": "sha512-LIgYXuCSO5Gvtc0t9bebAMSwd68ewzmqLypqI2Kke1rqOqqDbMpYcYfoPfFlv9eyLIh4jocHWwCK5FS7z9icUA==", + "version": "19.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-19.0.0.tgz", + "integrity": "sha512-mtsdpY1qyWgAO/iOK0L6gSGeR7GFcdW7tIjcNFxcWkfLDF5qVbPHKuGATFqRMsxcO8OUKNj0+3WOHB7EHm4Jdw==", "dev": true, + "license": "MIT", "optional": true, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/load": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-17.7.1.tgz", - "integrity": "sha512-S/QSOjE1ztdogYj61p6n3UbkUvweR17FQ0zDbNtoTLc+Hz7vvfS7ehoTMQ27hPSjVBpp7SzEcOQu081RLjKHJQ==", + "version": "19.2.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-19.2.0.tgz", + "integrity": "sha512-XvxxLJTKqZojCxaBQ7u92qQLFMMZc4+p9qrIq/9kJDy8DOrEa7P1yx7Tjdc2u2JxIalqT4KOGraVgCE7eCYJyQ==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { - "@commitlint/config-validator": "^17.6.7", - "@commitlint/execute-rule": "^17.4.0", - "@commitlint/resolve-extends": "^17.6.7", - "@commitlint/types": "^17.4.4", - "@types/node": "20.4.7", - "chalk": "^4.1.0", - "cosmiconfig": "^8.0.0", - "cosmiconfig-typescript-loader": "^4.0.0", + "@commitlint/config-validator": "^19.0.3", + "@commitlint/execute-rule": "^19.0.0", + "@commitlint/resolve-extends": "^19.1.0", + "@commitlint/types": "^19.0.3", + "chalk": "^5.3.0", + "cosmiconfig": "^9.0.0", + "cosmiconfig-typescript-loader": "^5.0.0", "lodash.isplainobject": "^4.0.6", "lodash.merge": "^4.6.2", - "lodash.uniq": "^4.5.0", - "resolve-from": "^5.0.0", - "ts-node": "^10.8.1", - "typescript": "^4.6.4 || ^5.0.0" + "lodash.uniq": "^4.5.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, - "node_modules/@commitlint/load/node_modules/@types/node": { - "version": "20.4.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.4.7.tgz", - "integrity": "sha512-bUBrPjEry2QUTsnuEjzjbS7voGWCc30W0qzgMf90GPeDGFRakvrz47ju+oqDAKCXLUCe39u57/ORMl/O/04/9g==", - "dev": true, - "optional": true - }, - "node_modules/@commitlint/load/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/@commitlint/load/node_modules/chalk": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, + "license": "MIT", "optional": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { - "node": ">=8" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@commitlint/load/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/@commitlint/load/node_modules/cosmiconfig": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-9.0.0.tgz", + "integrity": "sha512-itvL5h8RETACmOTFc4UfIyB2RfEHi71Ax6E/PivVxq9NseKbOWpeyHEOIbmAw1rs8Ak0VursQNww7lf7YtUwzg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "env-paths": "^2.2.1", + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0" }, "engines": { - "node": ">=10" + "node": ">=14" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@commitlint/load/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "optional": true, - "dependencies": { - "color-name": "~1.1.4" + "url": "https://github.com/sponsors/d-fischer" }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@commitlint/load/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "optional": true - }, - "node_modules/@commitlint/load/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/load/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "optional": true, - "dependencies": { - "has-flag": "^4.0.0" + "peerDependencies": { + "typescript": ">=4.9.5" }, - "engines": { - "node": ">=8" + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/@commitlint/resolve-extends": { - "version": "17.6.7", - "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-17.6.7.tgz", - "integrity": "sha512-PfeoAwLHtbOaC9bGn/FADN156CqkFz6ZKiVDMjuC2N5N0740Ke56rKU7Wxdwya8R8xzLK9vZzHgNbuGhaOVKIg==", + "version": "19.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-19.1.0.tgz", + "integrity": "sha512-z2riI+8G3CET5CPgXJPlzftH+RiWYLMYv4C9tSLdLXdr6pBNimSKukYP9MS27ejmscqCTVA4almdLh0ODD2KYg==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { - "@commitlint/config-validator": "^17.6.7", - "@commitlint/types": "^17.4.4", - "import-fresh": "^3.0.0", + "@commitlint/config-validator": "^19.0.3", + "@commitlint/types": "^19.0.3", + "global-directory": "^4.0.1", + "import-meta-resolve": "^4.0.0", "lodash.mergewith": "^4.6.2", - "resolve-from": "^5.0.0", - "resolve-global": "^1.0.0" + "resolve-from": "^5.0.0" }, "engines": { - "node": ">=v14" + "node": ">=v18" } }, "node_modules/@commitlint/types": { - "version": "17.4.4", - "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-17.4.4.tgz", - "integrity": "sha512-amRN8tRLYOsxRr6mTnGGGvB5EmW/4DDjLMgiwK3CCVEmN6Sr/6xePGEpWaspKkckILuUORCwe6VfDBw6uj4axQ==", + "version": "19.0.3", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-19.0.3.tgz", + "integrity": "sha512-tpyc+7i6bPG9mvaBbtKUeghfyZSDgWquIDfMgqYtTbmZ9Y9VzEm2je9EYcQ0aoz5o7NvGS+rcDec93yO08MHYA==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { - "chalk": "^4.1.0" + "@types/conventional-commits-parser": "^5.0.0", + "chalk": "^5.3.0" }, "engines": { - "node": ">=v14" - } - }, - "node_modules/@commitlint/types/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "optional": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "node": ">=v18" } }, "node_modules/@commitlint/types/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, + "license": "MIT", "optional": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, "engines": { - "node": ">=10" + "node": "^12.17.0 || ^14.13 || >=16.0.0" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/@commitlint/types/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "optional": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@commitlint/types/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "optional": true - }, - "node_modules/@commitlint/types/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "optional": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@commitlint/types/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "optional": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@cspotcode/source-map-support": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", - "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", - "dev": true, - "optional": true, - "dependencies": { - "@jridgewell/trace-mapping": "0.3.9" - }, - "engines": { - "node": ">=12" - } - }, "node_modules/@efstajas/versioned-parser": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/@efstajas/versioned-parser/-/versioned-parser-0.1.4.tgz", - "integrity": "sha512-R/MUEOeMGvegThqacHCasp03RtE66szRqt9d6Qa+LI2lNweyV1SyAk66JlgRppoJHXwmcIDJ5hAUEws0g/Xx2Q==" + "integrity": "sha512-R/MUEOeMGvegThqacHCasp03RtE66szRqt9d6Qa+LI2lNweyV1SyAk66JlgRppoJHXwmcIDJ5hAUEws0g/Xx2Q==", + "license": "Apache-2.0" }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", "dev": true, + "license": "MIT", "dependencies": { "eslint-visitor-keys": "^3.3.0" }, @@ -1727,19 +1603,21 @@ } }, "node_modules/@eslint-community/regexpp": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.8.0.tgz", - "integrity": "sha512-JylOEEzDiOryeUnFbQz+oViCXS0KsvR1mvHkoMiu5+UiBvy+RYX7tzlIIIEstF/gVa2tj9AQXk3dgnxv6KxhFg==", + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.0.tgz", + "integrity": "sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, "node_modules/@eslint/eslintrc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.2.tgz", - "integrity": "sha512-+wvgpDsrB1YqAMdEUCcnTlpfVBH7Vqn6A/NT3D8WVXFIaKMlErPIZT3oCIAVCOtarRpMtelZLqJeU3t7WY6X6g==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", @@ -1763,6 +1641,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1774,32 +1653,103 @@ "url": "https://github.com/sponsors/epoberezkin" } }, + "node_modules/@eslint/eslintrc/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/@eslint/eslintrc/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } }, "node_modules/@eslint/js": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.48.0.tgz", - "integrity": "sha512-ZSjtmelB7IJfWD2Fvb7+Z+ChTIKWq6kjda95fLcQKNS5aheVHn4IkfgRQE3sIIzTcSLwLcLZUD9UBt+V7+h+Pw==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", + "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", "dev": true, + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, + "node_modules/@graphql-codegen/add": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/@graphql-codegen/add/-/add-5.0.3.tgz", + "integrity": "sha512-SxXPmramkth8XtBlAHu4H4jYcYXM/o3p01+psU+0NADQowA8jtYkK6MW5rV6T+CxkEaNZItfSmZRPgIuypcqnA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@graphql-codegen/plugin-helpers": "^5.0.3", + "tslib": "~2.6.0" + }, + "peerDependencies": { + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" + } + }, "node_modules/@graphql-codegen/cli": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-5.0.0.tgz", - "integrity": "sha512-A7J7+be/a6e+/ul2KI5sfJlpoqeqwX8EzktaKCeduyVKgOLA6W5t+NUGf6QumBDXU8PEOqXk3o3F+RAwCWOiqA==", + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/@graphql-codegen/cli/-/cli-5.0.2.tgz", + "integrity": "sha512-MBIaFqDiLKuO4ojN6xxG9/xL9wmfD3ZjZ7RsPjwQnSHBCUXnEkdKvX+JVpx87Pq29Ycn8wTJUguXnTZ7Di0Mlw==", "dev": true, + "license": "MIT", "dependencies": { "@babel/generator": "^7.18.13", "@babel/template": "^7.18.10", "@babel/types": "^7.18.13", - "@graphql-codegen/core": "^4.0.0", - "@graphql-codegen/plugin-helpers": "^5.0.1", + "@graphql-codegen/client-preset": "^4.2.2", + "@graphql-codegen/core": "^4.0.2", + "@graphql-codegen/plugin-helpers": "^5.0.3", "@graphql-tools/apollo-engine-loader": "^8.0.0", "@graphql-tools/code-file-loader": "^8.0.0", "@graphql-tools/git-loader": "^8.0.0", @@ -1846,115 +1796,55 @@ } } }, - "node_modules/@graphql-codegen/cli/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "node_modules/@graphql-codegen/client-preset": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/@graphql-codegen/client-preset/-/client-preset-4.3.2.tgz", + "integrity": "sha512-42jHyG6u2uFDIVNvzue8zR529aPT16EYIJQmvMk8XuYHo3PneQVlWmQ3j2fBy+RuWCBzpJKPKm7IGSKiw19nmg==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/template": "^7.20.7", + "@graphql-codegen/add": "^5.0.3", + "@graphql-codegen/gql-tag-operations": "4.0.9", + "@graphql-codegen/plugin-helpers": "^5.0.4", + "@graphql-codegen/typed-document-node": "^5.0.9", + "@graphql-codegen/typescript": "^4.0.9", + "@graphql-codegen/typescript-operations": "^4.2.3", + "@graphql-codegen/visitor-plugin-common": "^5.3.1", + "@graphql-tools/documents": "^1.0.0", + "@graphql-tools/utils": "^10.0.0", + "@graphql-typed-document-node/core": "3.2.0", + "tslib": "~2.6.0" }, "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-codegen/cli/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@graphql-codegen/cli/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@graphql-codegen/cli/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@graphql-codegen/cli/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@graphql-codegen/cli/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@graphql-codegen/cli/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "node_modules/@graphql-codegen/core": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-4.0.0.tgz", - "integrity": "sha512-JAGRn49lEtSsZVxeIlFVIRxts2lWObR+OQo7V2LHDJ7ohYYw3ilv7nJ8pf8P4GTg/w6ptcYdSdVVdkI8kUHB/Q==", + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/@graphql-codegen/core/-/core-4.0.2.tgz", + "integrity": "sha512-IZbpkhwVqgizcjNiaVzNAzm/xbWT6YnGgeOLwVjm4KbJn3V2jchVtuzHH09G5/WkkLSk2wgbXNdwjM41JxO6Eg==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.0", + "@graphql-codegen/plugin-helpers": "^5.0.3", "@graphql-tools/schema": "^10.0.0", "@graphql-tools/utils": "^10.0.0", - "tslib": "~2.5.0" + "tslib": "~2.6.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "node_modules/@graphql-codegen/core/node_modules/@graphql-tools/merge": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", - "integrity": "sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.4.tgz", + "integrity": "sha512-MivbDLUQ+4Q8G/Hp/9V72hbn810IJDEZQ57F01sHnlrrijyadibfVhaQfW/pNH+9T/l8ySZpaR/DpL5i+ruZ+g==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.0.13", "tslib": "^2.4.0" }, "engines": { @@ -1965,13 +1855,14 @@ } }, "node_modules/@graphql-codegen/core/node_modules/@graphql-tools/schema": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.0.tgz", - "integrity": "sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.4.tgz", + "integrity": "sha512-HuIwqbKxPaJujox25Ra4qwz0uQzlpsaBOzO6CVfzB/MemZdd+Gib8AIvfhQArK0YIN40aDran/yi+E5Xf0mQww==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/merge": "^9.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/merge": "^9.0.3", + "@graphql-tools/utils": "^10.2.1", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" }, @@ -1982,220 +1873,139 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-codegen/core/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "node_modules/@graphql-codegen/gql-tag-operations": { + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@graphql-codegen/gql-tag-operations/-/gql-tag-operations-4.0.9.tgz", + "integrity": "sha512-lVgu1HClel896HqZAEjynatlU6eJrYOw+rh05DPgM150xvmb7Gz5TnRHA2vfwlDNIXDaToAIpz5RFfkjjnYM1Q==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" + "@graphql-codegen/plugin-helpers": "^5.0.4", + "@graphql-codegen/visitor-plugin-common": "5.3.1", + "@graphql-tools/utils": "^10.0.0", + "auto-bind": "~4.0.0", + "tslib": "~2.6.0" }, "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@graphql-codegen/core/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, "node_modules/@graphql-codegen/plugin-helpers": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.1.tgz", - "integrity": "sha512-6L5sb9D8wptZhnhLLBcheSPU7Tg//DGWgc5tQBWX46KYTOTQHGqDpv50FxAJJOyFVJrveN9otWk9UT9/yfY4ww==", + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/@graphql-codegen/plugin-helpers/-/plugin-helpers-5.0.4.tgz", + "integrity": "sha512-MOIuHFNWUnFnqVmiXtrI+4UziMTYrcquljaI5f/T/Bc7oO7sXcfkAvgkNWEEi9xWreYwvuer3VHCuPI/lAFWbw==", "dev": true, + "license": "MIT", "dependencies": { "@graphql-tools/utils": "^10.0.0", "change-case-all": "1.0.15", "common-tags": "1.8.2", "import-from": "4.0.0", "lodash": "~4.17.0", - "tslib": "~2.5.0" + "tslib": "~2.6.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@graphql-codegen/plugin-helpers/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-codegen/plugin-helpers/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, "node_modules/@graphql-codegen/schema-ast": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-4.0.0.tgz", - "integrity": "sha512-WIzkJFa9Gz28FITAPILbt+7A8+yzOyd1NxgwFh7ie+EmO9a5zQK6UQ3U/BviirguXCYnn+AR4dXsoDrSrtRA1g==", + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@graphql-codegen/schema-ast/-/schema-ast-4.1.0.tgz", + "integrity": "sha512-kZVn0z+th9SvqxfKYgztA6PM7mhnSZaj4fiuBWvMTqA+QqQ9BBed6Pz41KuD/jr0gJtnlr2A4++/0VlpVbCTmQ==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.0", + "@graphql-codegen/plugin-helpers": "^5.0.3", "@graphql-tools/utils": "^10.0.0", - "tslib": "~2.5.0" + "tslib": "~2.6.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@graphql-codegen/schema-ast/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "node_modules/@graphql-codegen/typed-document-node": { + "version": "5.0.9", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typed-document-node/-/typed-document-node-5.0.9.tgz", + "integrity": "sha512-Wx6fyA4vpfIbfNTMiWUECGnjqzKkJdEbZHxVMIegiCBPzBYPAJV4mZZcildLAfm2FtZcgW4YKtFoTbnbXqPB3w==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" + "@graphql-codegen/plugin-helpers": "^5.0.4", + "@graphql-codegen/visitor-plugin-common": "5.3.1", + "auto-bind": "~4.0.0", + "change-case-all": "1.0.15", + "tslib": "~2.6.0" }, "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@graphql-codegen/schema-ast/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, "node_modules/@graphql-codegen/typescript": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-4.0.1.tgz", - "integrity": "sha512-3YziQ21dCVdnHb+Us1uDb3pA6eG5Chjv0uTK+bt9dXeMlwYBU8MbtzvQTo4qvzWVC1AxSOKj0rgfNu1xCXqJyA==", + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript/-/typescript-4.0.9.tgz", + "integrity": "sha512-0O35DMR4d/ctuHL1Zo6mRUUzp0BoszKfeWsa6sCm/g70+S98+hEfTwZNDkQHylLxapiyjssF9uw/F+sXqejqLw==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.0", - "@graphql-codegen/schema-ast": "^4.0.0", - "@graphql-codegen/visitor-plugin-common": "4.0.1", + "@graphql-codegen/plugin-helpers": "^5.0.4", + "@graphql-codegen/schema-ast": "^4.0.2", + "@graphql-codegen/visitor-plugin-common": "5.3.1", "auto-bind": "~4.0.0", - "tslib": "~2.5.0" + "tslib": "~2.6.0" }, "peerDependencies": { "graphql": "^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, "node_modules/@graphql-codegen/typescript-operations": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-4.0.1.tgz", - "integrity": "sha512-GpUWWdBVUec/Zqo23aFLBMrXYxN2irypHqDcKjN78JclDPdreasAEPcIpMfqf4MClvpmvDLy4ql+djVAwmkjbw==", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/@graphql-codegen/typescript-operations/-/typescript-operations-4.2.3.tgz", + "integrity": "sha512-6z7avSSOr03l5SyKbeDs7MzRyGwnQFSCqQm8Om5wIuoIgXVu2gXRmcJAY/I7SLdAy9xbF4Sho7XNqieFM2CAFQ==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.0", - "@graphql-codegen/typescript": "^4.0.1", - "@graphql-codegen/visitor-plugin-common": "4.0.1", + "@graphql-codegen/plugin-helpers": "^5.0.4", + "@graphql-codegen/typescript": "^4.0.9", + "@graphql-codegen/visitor-plugin-common": "5.3.1", "auto-bind": "~4.0.0", - "tslib": "~2.5.0" + "tslib": "~2.6.0" }, "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@graphql-codegen/typescript-operations/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, - "node_modules/@graphql-codegen/typescript/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, "node_modules/@graphql-codegen/visitor-plugin-common": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-4.0.1.tgz", - "integrity": "sha512-Bi/1z0nHg4QMsAqAJhds+ForyLtk7A3HQOlkrZNm3xEkY7lcBzPtiOTLBtvziwopBsXUxqeSwVjOOFPLS5Yw1Q==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/@graphql-codegen/visitor-plugin-common/-/visitor-plugin-common-5.3.1.tgz", + "integrity": "sha512-MktoBdNZhSmugiDjmFl1z6rEUUaqyxtFJYWnDilE7onkPgyw//O0M+TuPBJPBWdyV6J2ond0Hdqtq+rkghgSIQ==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-codegen/plugin-helpers": "^5.0.0", + "@graphql-codegen/plugin-helpers": "^5.0.4", "@graphql-tools/optimize": "^2.0.0", "@graphql-tools/relay-operation-optimizer": "^7.0.0", "@graphql-tools/utils": "^10.0.0", - "auto-bind": "~4.0.0", - "change-case-all": "1.0.15", - "dependency-graph": "^0.11.0", - "graphql-tag": "^2.11.0", - "parse-filepath": "^1.0.2", - "tslib": "~2.5.0" - }, - "peerDependencies": { - "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" - } - }, - "node_modules/@graphql-codegen/visitor-plugin-common/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-codegen/visitor-plugin-common/node_modules/tslib": { - "version": "2.5.3", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.3.tgz", - "integrity": "sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w==", - "dev": true - }, - "node_modules/@graphql-tools/apollo-engine-loader": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-8.0.0.tgz", - "integrity": "sha512-axQTbN5+Yxs1rJ6cWQBOfw3AEeC+fvIuZSfJLPLLvFJLj4pUm9fhxey/g6oQZAAQJqKPfw+tLDUQvnfvRK8Kmg==", - "dev": true, - "dependencies": { - "@ardatan/sync-fetch": "^0.0.1", - "@graphql-tools/utils": "^10.0.0", - "@whatwg-node/fetch": "^0.9.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" + "auto-bind": "~4.0.0", + "change-case-all": "1.0.15", + "dependency-graph": "^0.11.0", + "graphql-tag": "^2.11.0", + "parse-filepath": "^1.0.2", + "tslib": "~2.6.0" }, "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0" } }, - "node_modules/@graphql-tools/apollo-engine-loader/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "node_modules/@graphql-tools/apollo-engine-loader": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/apollo-engine-loader/-/apollo-engine-loader-8.0.1.tgz", + "integrity": "sha512-NaPeVjtrfbPXcl+MLQCJLWtqe2/E4bbAqcauEOQ+3sizw1Fc2CNmhHRF8a6W4D0ekvTRRXAMptXYgA2uConbrA==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", + "@ardatan/sync-fetch": "^0.0.1", + "@graphql-tools/utils": "^10.0.13", + "@whatwg-node/fetch": "^0.9.0", "tslib": "^2.4.0" }, "engines": { @@ -2210,33 +2020,36 @@ "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", "dev": true, + "license": "MIT", "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/apollo-engine-loader/node_modules/@whatwg-node/fetch": { - "version": "0.9.13", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.13.tgz", - "integrity": "sha512-PPtMwhjtS96XROnSpowCQM85gCUG2m7AXZFw0PZlGbhzx2GK7f2iOXilfgIJ0uSlCuuGbOIzfouISkA7C4FJOw==", + "version": "0.9.18", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", + "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", "dev": true, + "license": "MIT", "dependencies": { - "@whatwg-node/node-fetch": "^0.4.17", - "urlpattern-polyfill": "^9.0.0" + "@whatwg-node/node-fetch": "^0.5.7", + "urlpattern-polyfill": "^10.0.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/apollo-engine-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.4.19.tgz", - "integrity": "sha512-AW7/m2AuweAoSXmESrYQr/KBafueScNbn2iNO0u6xFr2JZdPmYsSm5yvAXYk6yDLv+eDmSSKrf7JnFZ0CsJIdA==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", + "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", "dev": true, + "license": "MIT", "dependencies": { + "@kamilkisiela/fast-url-parser": "^1.1.4", "@whatwg-node/events": "^0.1.0", "busboy": "^1.6.0", "fast-querystring": "^1.1.1", - "fast-url-parser": "^1.1.3", "tslib": "^2.3.1" }, "engines": { @@ -2244,18 +2057,20 @@ } }, "node_modules/@graphql-tools/apollo-engine-loader/node_modules/urlpattern-polyfill": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz", - "integrity": "sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==", - "dev": true + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true, + "license": "MIT" }, "node_modules/@graphql-tools/batch-execute": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-9.0.2.tgz", - "integrity": "sha512-Y2uwdZI6ZnatopD/SYfZ1eGuQFI7OU2KGZ2/B/7G9ISmgMl5K+ZZWz/PfIEXeiHirIDhyk54s4uka5rj2xwKqQ==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/batch-execute/-/batch-execute-9.0.4.tgz", + "integrity": "sha512-kkebDLXgDrep5Y0gK1RN3DMUlLqNhg60OAz0lTCqrYeja6DshxLtLkj+zV4mVbBA4mQOEoBmw6g1LZs3dA84/w==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.5", + "@graphql-tools/utils": "^10.0.13", "dataloader": "^2.2.2", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" @@ -2267,31 +2082,15 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/batch-execute/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-tools/code-file-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-8.0.2.tgz", - "integrity": "sha512-AKNpkElUL2cWocYpC4DzNEpo6qJw8Lp+L3bKQ/mIfmbsQxgLz5uve6zHBMhDaFPdlwfIox41N3iUSvi77t9e8A==", + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/code-file-loader/-/code-file-loader-8.1.2.tgz", + "integrity": "sha512-GrLzwl1QV2PT4X4TEEfuTmZYzIZHLqoTGBjczdUzSqgCCcqwWzLB3qrJxFQfI8e5s1qZ1bhpsO9NoMn7tvpmyA==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/graphql-tag-pluck": "8.0.2", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/graphql-tag-pluck": "8.3.1", + "@graphql-tools/utils": "^10.0.13", "globby": "^11.0.3", "tslib": "^2.4.0", "unixify": "^1.0.0" @@ -2303,33 +2102,17 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/code-file-loader/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-tools/delegate": { - "version": "10.0.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-10.0.3.tgz", - "integrity": "sha512-Jor9oazZ07zuWkykD3OOhT/2XD74Zm6Ar0ENZMk75MDD51wB2UWUIMljtHxbJhV5A6UBC2v8x6iY0xdCGiIlyw==", + "version": "10.0.13", + "resolved": "https://registry.npmjs.org/@graphql-tools/delegate/-/delegate-10.0.13.tgz", + "integrity": "sha512-9l7cwrHQFbvR6zhZOKYABa3ffqgyV51gNglammupXhptE3Z94p6A6hP0hLw7GHErkm6MiQINl3VBVpFJDlrZuQ==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/batch-execute": "^9.0.1", - "@graphql-tools/executor": "^1.0.0", - "@graphql-tools/schema": "^10.0.0", - "@graphql-tools/utils": "^10.0.5", + "@graphql-tools/batch-execute": "^9.0.4", + "@graphql-tools/executor": "^1.2.8", + "@graphql-tools/schema": "^10.0.4", + "@graphql-tools/utils": "^10.2.3", "dataloader": "^2.2.2", "tslib": "^2.5.0" }, @@ -2341,12 +2124,13 @@ } }, "node_modules/@graphql-tools/delegate/node_modules/@graphql-tools/merge": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", - "integrity": "sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.4.tgz", + "integrity": "sha512-MivbDLUQ+4Q8G/Hp/9V72hbn810IJDEZQ57F01sHnlrrijyadibfVhaQfW/pNH+9T/l8ySZpaR/DpL5i+ruZ+g==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.0.13", "tslib": "^2.4.0" }, "engines": { @@ -2357,13 +2141,14 @@ } }, "node_modules/@graphql-tools/delegate/node_modules/@graphql-tools/schema": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.0.tgz", - "integrity": "sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.4.tgz", + "integrity": "sha512-HuIwqbKxPaJujox25Ra4qwz0uQzlpsaBOzO6CVfzB/MemZdd+Gib8AIvfhQArK0YIN40aDran/yi+E5Xf0mQww==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/merge": "^9.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/merge": "^9.0.3", + "@graphql-tools/utils": "^10.2.1", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" }, @@ -2374,14 +2159,14 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/delegate/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "node_modules/@graphql-tools/documents": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/documents/-/documents-1.0.1.tgz", + "integrity": "sha512-aweoMH15wNJ8g7b2r4C4WRuJxZ0ca8HtNO54rkye/3duxTkW4fGBEutCx03jCIr5+a1l+4vFJNP859QnAVBVCA==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", + "lodash.sortby": "^4.7.0", "tslib": "^2.4.0" }, "engines": { @@ -2392,12 +2177,13 @@ } }, "node_modules/@graphql-tools/executor": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.2.0.tgz", - "integrity": "sha512-SKlIcMA71Dha5JnEWlw4XxcaJ+YupuXg0QCZgl2TOLFz4SkGCwU/geAsJvUJFwK2RbVLpQv/UMq67lOaBuwDtg==", + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor/-/executor-1.2.8.tgz", + "integrity": "sha512-0qZs/iuRiYRir7bBkA7oN+21wwmSMPQuFK8WcAcxUYJZRhvnlrJ8Nid++PN4OCzTgHPV70GNFyXOajseVCCffA==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.2.3", "@graphql-typed-document-node/core": "3.2.0", "@repeaterjs/repeater": "^3.0.4", "tslib": "^2.4.0", @@ -2411,12 +2197,13 @@ } }, "node_modules/@graphql-tools/executor-graphql-ws": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-1.1.0.tgz", - "integrity": "sha512-yM67SzwE8rYRpm4z4AuGtABlOp9mXXVy6sxXnTJRoYIdZrmDbKVfIY+CpZUJCqS0FX3xf2+GoHlsj7Qswaxgcg==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-graphql-ws/-/executor-graphql-ws-1.1.2.tgz", + "integrity": "sha512-+9ZK0rychTH1LUv4iZqJ4ESbmULJMTsv3XlFooPUngpxZkk00q6LqHKJRrsLErmQrVaC7cwQCaRBJa0teK17Lg==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.2", + "@graphql-tools/utils": "^10.0.13", "@types/ws": "^8.0.0", "graphql-ws": "^5.14.0", "isomorphic-ws": "^5.0.0", @@ -2430,51 +2217,14 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/executor-graphql-ws/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/executor-graphql-ws/node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, "node_modules/@graphql-tools/executor-http": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-1.0.3.tgz", - "integrity": "sha512-5WZIMBevRaxMabZ8U2Ty0dTUPy/PpeYSlMNEmC/YJjKKykgSfc/AwSejx2sE4FFKZ0I2kxRKRenyoWMHRAV49Q==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-http/-/executor-http-1.0.9.tgz", + "integrity": "sha512-+NXaZd2MWbbrWHqU4EhXcrDbogeiCDmEbrAN+rMn4Nu2okDjn2MTFDbTIab87oEubQCH4Te1wDkWPKrzXup7+Q==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.2", + "@graphql-tools/utils": "^10.0.13", "@repeaterjs/repeater": "^3.0.4", "@whatwg-node/fetch": "^0.9.0", "extract-files": "^11.0.0", @@ -2489,55 +2239,41 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/executor-http/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-tools/executor-http/node_modules/@whatwg-node/events": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", "dev": true, + "license": "MIT", "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/executor-http/node_modules/@whatwg-node/fetch": { - "version": "0.9.13", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.13.tgz", - "integrity": "sha512-PPtMwhjtS96XROnSpowCQM85gCUG2m7AXZFw0PZlGbhzx2GK7f2iOXilfgIJ0uSlCuuGbOIzfouISkA7C4FJOw==", + "version": "0.9.18", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", + "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", "dev": true, + "license": "MIT", "dependencies": { - "@whatwg-node/node-fetch": "^0.4.17", - "urlpattern-polyfill": "^9.0.0" + "@whatwg-node/node-fetch": "^0.5.7", + "urlpattern-polyfill": "^10.0.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/executor-http/node_modules/@whatwg-node/node-fetch": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.4.19.tgz", - "integrity": "sha512-AW7/m2AuweAoSXmESrYQr/KBafueScNbn2iNO0u6xFr2JZdPmYsSm5yvAXYk6yDLv+eDmSSKrf7JnFZ0CsJIdA==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", + "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", "dev": true, + "license": "MIT", "dependencies": { + "@kamilkisiela/fast-url-parser": "^1.1.4", "@whatwg-node/events": "^0.1.0", "busboy": "^1.6.0", "fast-querystring": "^1.1.1", - "fast-url-parser": "^1.1.3", "tslib": "^2.3.1" }, "engines": { @@ -2545,77 +2281,24 @@ } }, "node_modules/@graphql-tools/executor-http/node_modules/urlpattern-polyfill": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz", - "integrity": "sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==", - "dev": true + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true, + "license": "MIT" }, "node_modules/@graphql-tools/executor-legacy-ws": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-1.0.3.tgz", - "integrity": "sha512-rr3IDeO9Dh+8u8KIro++5kzJJYPHkcrIAWzqXtN663nhInC85iW7Ko91yOYwf7ovBci/7s+4Rqe4ZRyca1LGjQ==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@graphql-tools/executor-legacy-ws/-/executor-legacy-ws-1.0.6.tgz", + "integrity": "sha512-lDSxz9VyyquOrvSuCCnld3256Hmd+QI2lkmkEv7d4mdzkxkK4ddAWW1geQiWrQvWmdsmcnGGlZ7gDGbhEExwqg==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.0.13", "@types/ws": "^8.0.0", - "isomorphic-ws": "5.0.0", + "isomorphic-ws": "^5.0.0", "tslib": "^2.4.0", - "ws": "8.14.1" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/executor-legacy-ws/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/executor-legacy-ws/node_modules/ws": { - "version": "8.14.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.1.tgz", - "integrity": "sha512-4OOseMUq8AzRBI/7SLMUwO+FEDnguetSk7KMb1sHwvF2w2Wv5Hoj0nlifx8vtGsftE/jWHojPy8sMMzYLJ2G/A==", - "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "node_modules/@graphql-tools/executor/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" + "ws": "^8.15.0" }, "engines": { "node": ">=16.0.0" @@ -2625,13 +2308,14 @@ } }, "node_modules/@graphql-tools/git-loader": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-8.0.2.tgz", - "integrity": "sha512-AuCB0nlPvsHh8u42zRZdlD/ZMaWP9A44yAkQUVCZir1E/LG63fsZ9svTWJ+CbusW3Hd0ZP9qpxEhlHxnd4Tlsg==", + "version": "8.0.6", + "resolved": "https://registry.npmjs.org/@graphql-tools/git-loader/-/git-loader-8.0.6.tgz", + "integrity": "sha512-FQFO4H5wHAmHVyuUQrjvPE8re3qJXt50TWHuzrK3dEaief7JosmlnkLMDMbMBwtwITz9u1Wpl6doPhT2GwKtlw==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/graphql-tag-pluck": "8.0.2", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/graphql-tag-pluck": "8.3.1", + "@graphql-tools/utils": "^10.0.13", "is-glob": "4.0.3", "micromatch": "^4.0.4", "tslib": "^2.4.0", @@ -2644,33 +2328,17 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/git-loader/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-tools/github-loader": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-8.0.0.tgz", - "integrity": "sha512-VuroArWKcG4yaOWzV0r19ElVIV6iH6UKDQn1MXemND0xu5TzrFme0kf3U9o0YwNo0kUYEk9CyFM0BYg4he17FA==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/github-loader/-/github-loader-8.0.1.tgz", + "integrity": "sha512-W4dFLQJ5GtKGltvh/u1apWRFKBQOsDzFxO9cJkOYZj1VzHCpRF43uLST4VbCfWve+AwBqOuKr7YgkHoxpRMkcg==", "dev": true, + "license": "MIT", "dependencies": { "@ardatan/sync-fetch": "^0.0.1", - "@graphql-tools/executor-http": "^1.0.0", + "@graphql-tools/executor-http": "^1.0.9", "@graphql-tools/graphql-tag-pluck": "^8.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.0.13", "@whatwg-node/fetch": "^0.9.0", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" @@ -2682,55 +2350,41 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/github-loader/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-tools/github-loader/node_modules/@whatwg-node/events": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", "dev": true, + "license": "MIT", "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/github-loader/node_modules/@whatwg-node/fetch": { - "version": "0.9.13", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.13.tgz", - "integrity": "sha512-PPtMwhjtS96XROnSpowCQM85gCUG2m7AXZFw0PZlGbhzx2GK7f2iOXilfgIJ0uSlCuuGbOIzfouISkA7C4FJOw==", + "version": "0.9.18", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", + "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", "dev": true, + "license": "MIT", "dependencies": { - "@whatwg-node/node-fetch": "^0.4.17", - "urlpattern-polyfill": "^9.0.0" + "@whatwg-node/node-fetch": "^0.5.7", + "urlpattern-polyfill": "^10.0.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/github-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.4.19.tgz", - "integrity": "sha512-AW7/m2AuweAoSXmESrYQr/KBafueScNbn2iNO0u6xFr2JZdPmYsSm5yvAXYk6yDLv+eDmSSKrf7JnFZ0CsJIdA==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", + "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", "dev": true, + "license": "MIT", "dependencies": { + "@kamilkisiela/fast-url-parser": "^1.1.4", "@whatwg-node/events": "^0.1.0", "busboy": "^1.6.0", "fast-querystring": "^1.1.1", - "fast-url-parser": "^1.1.3", "tslib": "^2.3.1" }, "engines": { @@ -2738,19 +2392,21 @@ } }, "node_modules/@graphql-tools/github-loader/node_modules/urlpattern-polyfill": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz", - "integrity": "sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==", - "dev": true + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true, + "license": "MIT" }, "node_modules/@graphql-tools/graphql-file-loader": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-8.0.0.tgz", - "integrity": "sha512-wRXj9Z1IFL3+zJG1HWEY0S4TXal7+s1vVhbZva96MSp0kbb/3JBF7j0cnJ44Eq0ClccMgGCDFqPFXty4JlpaPg==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-file-loader/-/graphql-file-loader-8.0.1.tgz", + "integrity": "sha512-7gswMqWBabTSmqbaNyWSmRRpStWlcCkBc73E6NZNlh4YNuiyKOwbvSkOUYFOqFMfEL+cFsXgAvr87Vz4XrYSbA==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/import": "7.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/import": "7.0.1", + "@graphql-tools/utils": "^10.0.13", "globby": "^11.0.3", "tslib": "^2.4.0", "unixify": "^1.0.0" @@ -2762,86 +2418,19 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/graphql-file-loader/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-tools/graphql-tag-pluck": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.0.2.tgz", - "integrity": "sha512-U6fE4yEHxuk/nqmPixHpw1WhqdS6aYuaV60m1bEmUmGJNbpAhaMBy01JncpvpF15yZR5LZ0UjkHg+A3Lhoc8YQ==", + "version": "8.3.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/graphql-tag-pluck/-/graphql-tag-pluck-8.3.1.tgz", + "integrity": "sha512-ujits9tMqtWQQq4FI4+qnVPpJvSEn7ogKtyN/gfNT+ErIn6z1e4gyVGQpTK5sgAUXq1lW4gU/5fkFFC5/sL2rQ==", "dev": true, + "license": "MIT", "dependencies": { "@babel/core": "^7.22.9", "@babel/parser": "^7.16.8", "@babel/plugin-syntax-import-assertions": "^7.20.0", - "@babel/traverse": "^7.16.8", - "@babel/types": "^7.16.8", - "@graphql-tools/utils": "^10.0.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/graphql-tag-pluck/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/import": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-7.0.0.tgz", - "integrity": "sha512-NVZiTO8o1GZs6OXzNfjB+5CtQtqsZZpQOq+Uu0w57kdUkT4RlQKlwhT8T81arEsbV55KpzkpFsOZP7J1wdmhBw==", - "dev": true, - "dependencies": { - "@graphql-tools/utils": "^10.0.0", - "resolve-from": "5.0.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/import/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", + "@babel/traverse": "^7.16.8", + "@babel/types": "^7.16.8", + "@graphql-tools/utils": "^10.0.13", "tslib": "^2.4.0" }, "engines": { @@ -2851,16 +2440,16 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/json-file-loader": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-8.0.0.tgz", - "integrity": "sha512-ki6EF/mobBWJjAAC84xNrFMhNfnUFD6Y0rQMGXekrUgY0NdeYXHU0ZUgHzC9O5+55FslqUmAUHABePDHTyZsLg==", + "node_modules/@graphql-tools/import": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/import/-/import-7.0.1.tgz", + "integrity": "sha512-935uAjAS8UAeXThqHfYVr4HEAp6nHJ2sximZKO1RzUTq5WoALMAhhGARl0+ecm6X+cqNUwIChJbjtaa6P/ML0w==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.0", - "globby": "^11.0.3", - "tslib": "^2.4.0", - "unixify": "^1.0.0" + "@graphql-tools/utils": "^10.0.13", + "resolve-from": "5.0.0", + "tslib": "^2.4.0" }, "engines": { "node": ">=16.0.0" @@ -2869,15 +2458,17 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/json-file-loader/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "node_modules/@graphql-tools/json-file-loader": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/json-file-loader/-/json-file-loader-8.0.1.tgz", + "integrity": "sha512-lAy2VqxDAHjVyqeJonCP6TUemrpYdDuKt25a10X6zY2Yn3iFYGnuIDQ64cv3ytyGY6KPyPB+Kp+ZfOkNDG3FQA==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" + "@graphql-tools/utils": "^10.0.13", + "globby": "^11.0.3", + "tslib": "^2.4.0", + "unixify": "^1.0.0" }, "engines": { "node": ">=16.0.0" @@ -2887,13 +2478,14 @@ } }, "node_modules/@graphql-tools/load": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-8.0.0.tgz", - "integrity": "sha512-Cy874bQJH0FP2Az7ELPM49iDzOljQmK1PPH6IuxsWzLSTxwTqd8dXA09dcVZrI7/LsN26heTY2R8q2aiiv0GxQ==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/load/-/load-8.0.2.tgz", + "integrity": "sha512-S+E/cmyVmJ3CuCNfDuNF2EyovTwdWfQScXv/2gmvJOti2rGD8jTt9GYVzXaxhblLivQR9sBUCNZu/w7j7aXUCA==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/schema": "^10.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/schema": "^10.0.3", + "@graphql-tools/utils": "^10.0.13", "p-limit": "3.1.0", "tslib": "^2.4.0" }, @@ -2905,12 +2497,13 @@ } }, "node_modules/@graphql-tools/load/node_modules/@graphql-tools/merge": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", - "integrity": "sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.4.tgz", + "integrity": "sha512-MivbDLUQ+4Q8G/Hp/9V72hbn810IJDEZQ57F01sHnlrrijyadibfVhaQfW/pNH+9T/l8ySZpaR/DpL5i+ruZ+g==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.0.13", "tslib": "^2.4.0" }, "engines": { @@ -2921,13 +2514,14 @@ } }, "node_modules/@graphql-tools/load/node_modules/@graphql-tools/schema": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.0.tgz", - "integrity": "sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.4.tgz", + "integrity": "sha512-HuIwqbKxPaJujox25Ra4qwz0uQzlpsaBOzO6CVfzB/MemZdd+Gib8AIvfhQArK0YIN40aDran/yi+E5Xf0mQww==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/merge": "^9.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/merge": "^9.0.3", + "@graphql-tools/utils": "^10.2.1", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" }, @@ -2938,29 +2532,26 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/load/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, + "node_modules/@graphql-tools/merge": { + "version": "8.4.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", + "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", + "license": "MIT", "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", + "@graphql-tools/utils": "^9.2.1", "tslib": "^2.4.0" }, - "engines": { - "node": ">=16.0.0" - }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/merge": { - "version": "8.4.2", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-8.4.2.tgz", - "integrity": "sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==", + "node_modules/@graphql-tools/merge/node_modules/@graphql-tools/utils": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", + "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^9.2.1", + "@graphql-typed-document-node/core": "^3.1.1", "tslib": "^2.4.0" }, "peerDependencies": { @@ -2972,6 +2563,7 @@ "resolved": "https://registry.npmjs.org/@graphql-tools/optimize/-/optimize-2.0.0.tgz", "integrity": "sha512-nhdT+CRGDZ+bk68ic+Jw1OZ99YCDIKYA5AlVAnBHJvMawSx9YQqQAIj4refNc1/LRieGiuWvhbG3jvPVYho0Dg==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.4.0" }, @@ -2983,15 +2575,15 @@ } }, "node_modules/@graphql-tools/prisma-loader": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-8.0.1.tgz", - "integrity": "sha512-bl6e5sAYe35Z6fEbgKXNrqRhXlCJYeWKBkarohgYA338/SD9eEhXtg3Cedj7fut3WyRLoQFpHzfiwxKs7XrgXg==", + "version": "8.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/prisma-loader/-/prisma-loader-8.0.4.tgz", + "integrity": "sha512-hqKPlw8bOu/GRqtYr0+dINAI13HinTVYBDqhwGAPIFmLr5s+qKskzgCiwbsckdrb5LWVFmVZc+UXn80OGiyBzg==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/url-loader": "^8.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/url-loader": "^8.0.2", + "@graphql-tools/utils": "^10.0.13", "@types/js-yaml": "^4.0.0", - "@types/json-stable-stringify": "^1.0.32", "@whatwg-node/fetch": "^0.9.0", "chalk": "^4.1.0", "debug": "^4.3.1", @@ -2999,9 +2591,8 @@ "graphql-request": "^6.0.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", - "jose": "^4.11.4", + "jose": "^5.0.0", "js-yaml": "^4.0.0", - "json-stable-stringify": "^1.0.1", "lodash": "^4.17.20", "scuid": "^1.1.0", "tslib": "^2.4.0", @@ -3014,162 +2605,63 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/prisma-loader/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-tools/prisma-loader/node_modules/@whatwg-node/events": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", "dev": true, + "license": "MIT", "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/prisma-loader/node_modules/@whatwg-node/fetch": { - "version": "0.9.13", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.13.tgz", - "integrity": "sha512-PPtMwhjtS96XROnSpowCQM85gCUG2m7AXZFw0PZlGbhzx2GK7f2iOXilfgIJ0uSlCuuGbOIzfouISkA7C4FJOw==", + "version": "0.9.18", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", + "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", "dev": true, + "license": "MIT", "dependencies": { - "@whatwg-node/node-fetch": "^0.4.17", - "urlpattern-polyfill": "^9.0.0" + "@whatwg-node/node-fetch": "^0.5.7", + "urlpattern-polyfill": "^10.0.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/prisma-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.4.19.tgz", - "integrity": "sha512-AW7/m2AuweAoSXmESrYQr/KBafueScNbn2iNO0u6xFr2JZdPmYsSm5yvAXYk6yDLv+eDmSSKrf7JnFZ0CsJIdA==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", + "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", "dev": true, + "license": "MIT", "dependencies": { + "@kamilkisiela/fast-url-parser": "^1.1.4", "@whatwg-node/events": "^0.1.0", "busboy": "^1.6.0", "fast-querystring": "^1.1.1", - "fast-url-parser": "^1.1.3", "tslib": "^2.3.1" }, "engines": { "node": ">=16.0.0" } }, - "node_modules/@graphql-tools/prisma-loader/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/@graphql-tools/prisma-loader/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/@graphql-tools/prisma-loader/node_modules/urlpattern-polyfill": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz", - "integrity": "sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==", - "dev": true + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", + "dev": true, + "license": "MIT" }, "node_modules/@graphql-tools/relay-operation-optimizer": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.0.0.tgz", - "integrity": "sha512-UNlJi5y3JylhVWU4MBpL0Hun4Q7IoJwv9xYtmAz+CgRa066szzY7dcuPfxrA7cIGgG/Q6TVsKsYaiF4OHPs1Fw==", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/relay-operation-optimizer/-/relay-operation-optimizer-7.0.1.tgz", + "integrity": "sha512-y0ZrQ/iyqWZlsS/xrJfSir3TbVYJTYmMOu4TaSz6F4FRDTQ3ie43BlKkhf04rC28pnUOS4BO9pDcAo1D30l5+A==", "dev": true, + "license": "MIT", "dependencies": { "@ardatan/relay-compiler": "12.0.0", - "@graphql-tools/utils": "^10.0.0", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, - "node_modules/@graphql-tools/relay-operation-optimizer/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", + "@graphql-tools/utils": "^10.0.13", "tslib": "^2.4.0" }, "engines": { @@ -3183,6 +2675,7 @@ "version": "9.0.19", "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-9.0.19.tgz", "integrity": "sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==", + "license": "MIT", "dependencies": { "@graphql-tools/merge": "^8.4.1", "@graphql-tools/utils": "^9.2.1", @@ -3193,19 +2686,33 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, + "node_modules/@graphql-tools/schema/node_modules/@graphql-tools/utils": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", + "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", + "license": "MIT", + "dependencies": { + "@graphql-typed-document-node/core": "^3.1.1", + "tslib": "^2.4.0" + }, + "peerDependencies": { + "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + } + }, "node_modules/@graphql-tools/url-loader": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-8.0.0.tgz", - "integrity": "sha512-rPc9oDzMnycvz+X+wrN3PLrhMBQkG4+sd8EzaFN6dypcssiefgWKToXtRKI8HHK68n2xEq1PyrOpkjHFJB+GwA==", + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@graphql-tools/url-loader/-/url-loader-8.0.2.tgz", + "integrity": "sha512-1dKp2K8UuFn7DFo1qX5c1cyazQv2h2ICwA9esHblEqCYrgf69Nk8N7SODmsfWg94OEaI74IqMoM12t7eIGwFzQ==", "dev": true, + "license": "MIT", "dependencies": { "@ardatan/sync-fetch": "^0.0.1", - "@graphql-tools/delegate": "^10.0.0", - "@graphql-tools/executor-graphql-ws": "^1.0.0", - "@graphql-tools/executor-http": "^1.0.0", - "@graphql-tools/executor-legacy-ws": "^1.0.0", - "@graphql-tools/utils": "^10.0.0", - "@graphql-tools/wrap": "^10.0.0", + "@graphql-tools/delegate": "^10.0.4", + "@graphql-tools/executor-graphql-ws": "^1.1.2", + "@graphql-tools/executor-http": "^1.0.9", + "@graphql-tools/executor-legacy-ws": "^1.0.6", + "@graphql-tools/utils": "^10.0.13", + "@graphql-tools/wrap": "^10.0.2", "@types/ws": "^8.0.0", "@whatwg-node/fetch": "^0.9.0", "isomorphic-ws": "^5.0.0", @@ -3220,55 +2727,41 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/url-loader/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-tools/url-loader/node_modules/@whatwg-node/events": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.1.1.tgz", "integrity": "sha512-AyQEn5hIPV7Ze+xFoXVU3QTHXVbWPrzaOkxtENMPMuNL6VVHrp4hHfDt9nrQpjO7BgvuM95dMtkycX5M/DZR3w==", "dev": true, + "license": "MIT", "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/url-loader/node_modules/@whatwg-node/fetch": { - "version": "0.9.13", - "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.13.tgz", - "integrity": "sha512-PPtMwhjtS96XROnSpowCQM85gCUG2m7AXZFw0PZlGbhzx2GK7f2iOXilfgIJ0uSlCuuGbOIzfouISkA7C4FJOw==", + "version": "0.9.18", + "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.9.18.tgz", + "integrity": "sha512-hqoz6StCW+AjV/3N+vg0s1ah82ptdVUb9nH2ttj3UbySOXUvytWw2yqy8c1cKzyRk6mDD00G47qS3fZI9/gMjg==", "dev": true, + "license": "MIT", "dependencies": { - "@whatwg-node/node-fetch": "^0.4.17", - "urlpattern-polyfill": "^9.0.0" + "@whatwg-node/node-fetch": "^0.5.7", + "urlpattern-polyfill": "^10.0.0" }, "engines": { "node": ">=16.0.0" } }, "node_modules/@graphql-tools/url-loader/node_modules/@whatwg-node/node-fetch": { - "version": "0.4.19", - "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.4.19.tgz", - "integrity": "sha512-AW7/m2AuweAoSXmESrYQr/KBafueScNbn2iNO0u6xFr2JZdPmYsSm5yvAXYk6yDLv+eDmSSKrf7JnFZ0CsJIdA==", + "version": "0.5.11", + "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.5.11.tgz", + "integrity": "sha512-LS8tSomZa3YHnntpWt3PP43iFEEl6YeIsvDakczHBKlay5LdkXFr8w7v8H6akpG5nRrzydyB0k1iE2eoL6aKIQ==", "dev": true, + "license": "MIT", "dependencies": { + "@kamilkisiela/fast-url-parser": "^1.1.4", "@whatwg-node/events": "^0.1.0", "busboy": "^1.6.0", "fast-querystring": "^1.1.1", - "fast-url-parser": "^1.1.3", "tslib": "^2.3.1" }, "engines": { @@ -3276,53 +2769,41 @@ } }, "node_modules/@graphql-tools/url-loader/node_modules/urlpattern-polyfill": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-9.0.0.tgz", - "integrity": "sha512-WHN8KDQblxd32odxeIgo83rdVDE2bvdkb86it7bMhYZwWKJz0+O0RK/eZiHYnM+zgt/U7hAHOlCQGfjjvSkw2g==", - "dev": true - }, - "node_modules/@graphql-tools/url-loader/node_modules/ws": { - "version": "8.14.2", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.14.2.tgz", - "integrity": "sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==", + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-10.0.0.tgz", + "integrity": "sha512-H/A06tKD7sS1O1X2SshBVeA5FLycRpjqiBeqGKmBwBDBy28EnRjORxTNe269KSSr5un5qyWi1iL61wLxpd+ZOg==", "dev": true, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } + "license": "MIT" }, "node_modules/@graphql-tools/utils": { - "version": "9.2.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-9.2.1.tgz", - "integrity": "sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==", + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.2.3.tgz", + "integrity": "sha512-j7x0sO0VtWVhD3FubyY42abx+g61/at5W5Y3DSOckPkBo7yVjkcnAsXoB4jiUnznhGme/o+uX5VgA8HrjyR5ZQ==", + "dev": true, + "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", + "cross-inspect": "1.0.0", + "dset": "^3.1.2", "tslib": "^2.4.0" }, + "engines": { + "node": ">=16.0.0" + }, "peerDependencies": { "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "node_modules/@graphql-tools/wrap": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-10.0.1.tgz", - "integrity": "sha512-Cw6hVrKGM2OKBXeuAGltgy4tzuqQE0Nt7t/uAqnuokSXZhMHXJUb124Bnvxc2gPZn5chfJSDafDe4Cp8ZAVJgg==", + "version": "10.0.5", + "resolved": "https://registry.npmjs.org/@graphql-tools/wrap/-/wrap-10.0.5.tgz", + "integrity": "sha512-Cbr5aYjr3HkwdPvetZp1cpDWTGdD1Owgsb3z/ClzhmrboiK86EnQDxDvOJiQkDCPWE9lNBwj8Y4HfxroY0D9DQ==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/delegate": "^10.0.3", - "@graphql-tools/schema": "^10.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/delegate": "^10.0.4", + "@graphql-tools/schema": "^10.0.3", + "@graphql-tools/utils": "^10.1.1", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" }, @@ -3334,12 +2815,13 @@ } }, "node_modules/@graphql-tools/wrap/node_modules/@graphql-tools/merge": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", - "integrity": "sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.4.tgz", + "integrity": "sha512-MivbDLUQ+4Q8G/Hp/9V72hbn810IJDEZQ57F01sHnlrrijyadibfVhaQfW/pNH+9T/l8ySZpaR/DpL5i+ruZ+g==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.0.13", "tslib": "^2.4.0" }, "engines": { @@ -3350,13 +2832,14 @@ } }, "node_modules/@graphql-tools/wrap/node_modules/@graphql-tools/schema": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.0.tgz", - "integrity": "sha512-kf3qOXMFcMs2f/S8Y3A8fm/2w+GaHAkfr3Gnhh2LOug/JgpY/ywgFVxO3jOeSpSEdoYcDKLcXVjMigNbY4AdQg==", + "version": "10.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/schema/-/schema-10.0.4.tgz", + "integrity": "sha512-HuIwqbKxPaJujox25Ra4qwz0uQzlpsaBOzO6CVfzB/MemZdd+Gib8AIvfhQArK0YIN40aDran/yi+E5Xf0mQww==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/merge": "^9.0.0", - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/merge": "^9.0.3", + "@graphql-tools/utils": "^10.2.1", "tslib": "^2.4.0", "value-or-promise": "^1.0.12" }, @@ -3367,50 +2850,61 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/@graphql-tools/wrap/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", - "dev": true, - "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" - } - }, "node_modules/@graphql-typed-document-node/core": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/@graphql-typed-document-node/core/-/core-3.2.0.tgz", "integrity": "sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==", + "license": "MIT", "peerDependencies": { "graphql": "^0.8.0 || ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, "node_modules/@humanwhocodes/config-array": { - "version": "0.11.11", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.11.tgz", - "integrity": "sha512-N2brEuAadi0CcdeMXUkhbZB84eskAc8MEX1By6qEchoVywSgXPIjou4rYsl0V3Hj0ZnuGycGCjdNgockbzeWNA==", + "version": "0.11.14", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", + "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "deprecated": "Use @eslint/config-array instead", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", + "@humanwhocodes/object-schema": "^2.0.2", + "debug": "^4.3.1", "minimatch": "^3.0.5" }, "engines": { "node": ">=10.10.0" } }, + "node_modules/@humanwhocodes/config-array/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/@humanwhocodes/module-importer": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true, + "license": "Apache-2.0", "engines": { "node": ">=12.22" }, @@ -3420,44 +2914,50 @@ } }, "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "dev": true + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/@josephg/resolvable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/@josephg/resolvable/-/resolvable-1.0.1.tgz", - "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==" + "integrity": "sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==", + "license": "ISC" }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/set-array": "^1.0.1", + "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", - "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz", - "integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -3466,45 +2966,57 @@ "version": "1.4.15", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.9", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", - "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "node_modules/@kamilkisiela/fast-url-parser": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/@kamilkisiela/fast-url-parser/-/fast-url-parser-1.1.4.tgz", + "integrity": "sha512-gbkePEBupNydxCelHCESvFSFM8XPh1Zs/OAVRW/rKpEqPAl5PbOM90Si8mv9bvnR53uPD2s/FiRxdvSejpRJew==", "dev": true, + "license": "MIT" + }, + "node_modules/@noble/curves": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz", + "integrity": "sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==", + "license": "MIT", "dependencies": { - "@jridgewell/resolve-uri": "^3.0.3", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@noble/hashes": "1.3.2" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/@noble/hashes": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.1.2.tgz", - "integrity": "sha512-KYRCASVTv6aeUi1tsF8/vpyR7zpfs3FUzy2Jqm+MU+LmUKhQ0y2FpfwqkCcxSg2ua4GALJd8k2R76WxwZGbQpA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] - }, - "node_modules/@noble/secp256k1": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.7.1.tgz", - "integrity": "sha512-hOUk6AyBFmqVrv7k5WAw/LpszxVbj9gGN4JRkIX52fdFAj1UA61KXmZDvqVEm+pOyec3+fIeZB02LYa/pWOArw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ] + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz", + "integrity": "sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==", + "license": "MIT", + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -3518,6 +3030,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -3527,6 +3040,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -3536,14 +3050,15 @@ } }, "node_modules/@peculiar/asn1-schema": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.6.tgz", - "integrity": "sha512-izNRxPoaeJeg/AyH8hER6s+H7p4itk+03QCa4sbxI3lNdseQYCuxzgsuNK8bTXChtLTjpJz6NmXKA73qLa3rCA==", + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.3.8.tgz", + "integrity": "sha512-ULB1XqHKx1WBU/tTFIA+uARuRoBVZ4pNdOA878RDrRbBfBGcSzi5HBkdScC6ZbHn8z7L8gmKCgPC1LHRrP46tA==", "dev": true, + "license": "MIT", "dependencies": { "asn1js": "^3.0.5", - "pvtsutils": "^1.3.2", - "tslib": "^2.4.0" + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" } }, "node_modules/@peculiar/json-schema": { @@ -3551,6 +3066,7 @@ "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz", "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.0" }, @@ -3559,16 +3075,17 @@ } }, "node_modules/@peculiar/webcrypto": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.3.tgz", - "integrity": "sha512-VtaY4spKTdN5LjJ04im/d/joXuvLbQdgy5Z4DXF4MFZhQ+MTrejbNMkfZBp1Bs3O5+bFqnJgyGdPuZQflvIa5A==", + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz", + "integrity": "sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg==", "dev": true, + "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.8", "@peculiar/json-schema": "^1.1.12", - "pvtsutils": "^1.3.2", - "tslib": "^2.5.0", - "webcrypto-core": "^1.7.7" + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2", + "webcrypto-core": "^1.8.0" }, "engines": { "node": ">=10.12.0" @@ -3577,27 +3094,32 @@ "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==" + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/base64": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==" + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/codegen": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==" + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/eventemitter": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==" + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/fetch": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", "dependencies": { "@protobufjs/aspromise": "^1.1.1", "@protobufjs/inquire": "^1.1.0" @@ -3606,67 +3128,46 @@ "node_modules/@protobufjs/float": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==" + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/inquire": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==" + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/path": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==" + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/pool": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==" + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" }, "node_modules/@protobufjs/utf8": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==" + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" }, "node_modules/@repeaterjs/repeater": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.4.tgz", - "integrity": "sha512-AW8PKd6iX3vAZ0vA43nOUOnbq/X5ihgU+mSXXqunMkeQADGiqw/PY0JNeYtD5sr0PAy51YPgAPbDoeapv9r8WA==", - "dev": true - }, - "node_modules/@tsconfig/node10": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", - "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", - "dev": true, - "optional": true - }, - "node_modules/@tsconfig/node12": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", - "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", - "dev": true, - "optional": true - }, - "node_modules/@tsconfig/node14": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", - "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", - "dev": true, - "optional": true - }, - "node_modules/@tsconfig/node16": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", - "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@repeaterjs/repeater/-/repeater-3.0.6.tgz", + "integrity": "sha512-Javneu5lsuhwNCryN+pXH93VPQ8g0dBX7wItHFgYiwQmzE1sVdg5tWHiOgHywzL2W21XQopa7IwIEnNbmeUJYA==", "dev": true, - "optional": true + "license": "MIT" }, "node_modules/@typechain/ethers-v6": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/@typechain/ethers-v6/-/ethers-v6-0.5.1.tgz", "integrity": "sha512-F+GklO8jBWlsaVV+9oHaPh5NJdd6rAKN4tklGfInX1Q7h0xPgVLP39Jl3eCulPB5qexI71ZFHwbljx4ZXNfouA==", "dev": true, + "license": "MIT", "dependencies": { "lodash": "^4.17.15", "ts-essentials": "^7.0.1" @@ -3678,18 +3179,31 @@ } }, "node_modules/@types/body-parser": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", - "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "license": "MIT", "dependencies": { "@types/connect": "*", "@types/node": "*" } }, "node_modules/@types/connect": { - "version": "3.4.35", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", - "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/conventional-commits-parser": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@types/conventional-commits-parser/-/conventional-commits-parser-5.0.0.tgz", + "integrity": "sha512-loB369iXNmAZglwWATL+WRe+CRMmmBPtpolYzIebFaX4YA3x+BEfLqhUAV9WanycKI3TG1IMr5bMJDajDKLlUQ==", + "dev": true, + "license": "MIT", + "optional": true, "dependencies": { "@types/node": "*" } @@ -3699,22 +3213,25 @@ "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@types/debug": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.8.tgz", - "integrity": "sha512-/vPO1EPOs306Cvhwv7KfVfYvOJqA/S/AXjaHQiJboCZzcNDb+TIJFN9/2C9DZ//ijSKWioNyUxD792QmDJ+HKQ==", + "version": "4.1.12", + "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", + "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", + "license": "MIT", "dependencies": { "@types/ms": "*" } }, "node_modules/@types/express": { - "version": "4.17.17", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", - "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "license": "MIT", "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^4.17.33", @@ -3723,9 +3240,10 @@ } }, "node_modules/@types/express-serve-static-core": { - "version": "4.17.36", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.36.tgz", - "integrity": "sha512-zbivROJ0ZqLAtMzgzIUC4oNqDG9iF0lSsAqpOD9kbs5xcIM3dTiyuHvBc7R8MtWBp3AAWGaovJa+wzWPjLYW7Q==", + "version": "4.19.5", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.5.tgz", + "integrity": "sha512-y6W03tvrACO72aijJ5uF02FRq5cgDR9lUxddQ8vyF+GvmjJQqbzDcJngEjURc+ZsG31VI3hODNZJ2URj86pzmg==", + "license": "MIT", "dependencies": { "@types/node": "*", "@types/qs": "*", @@ -3738,6 +3256,7 @@ "resolved": "https://registry.npmjs.org/@types/graphql-depth-limit/-/graphql-depth-limit-1.1.6.tgz", "integrity": "sha512-WU4bjoKOzJ8CQE32Pbyq+YshTMcLJf2aJuvVtSLv1BQPwDUGa38m2Vr8GGxf0GZ0luCQcfxlhZeHKu6nmTBvrw==", "dev": true, + "license": "MIT", "dependencies": { "graphql": "^14.5.3" } @@ -3747,6 +3266,7 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-14.7.0.tgz", "integrity": "sha512-l0xWZpoPKpppFzMfvVyFmp9vLN7w/ZZJPefUicMCepfJeQ8sMcztloGYY9DfjVPo6tIUDzU5Hw3MUbIjj9AVVA==", "dev": true, + "license": "MIT", "dependencies": { "iterall": "^1.2.2" }, @@ -3755,129 +3275,144 @@ } }, "node_modules/@types/http-errors": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", - "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "license": "MIT" }, "node_modules/@types/js-yaml": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.7.tgz", - "integrity": "sha512-RJZP9WAMMr1514KbdSXkLRrKvYQacjr1+HWnY8pui/uBTBoSgD9ZGR17u/d4nb9NpERp0FkdLBe7hq8NIPBgkg==", - "dev": true + "version": "4.0.9", + "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", + "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", + "dev": true, + "license": "MIT" }, "node_modules/@types/json-schema": { - "version": "7.0.12", - "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.12.tgz", - "integrity": "sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA==", - "dev": true - }, - "node_modules/@types/json-stable-stringify": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/@types/json-stable-stringify/-/json-stable-stringify-1.0.34.tgz", - "integrity": "sha512-s2cfwagOQAS8o06TcwKfr9Wx11dNGbH2E9vJz1cqV+a/LOyhWNLUNd6JSRYNzvB4d29UuJX2M0Dj9vE1T8fRXw==", - "dev": true + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/long": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/long/-/long-4.0.2.tgz", - "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==" + "integrity": "sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==", + "license": "MIT" }, "node_modules/@types/mime": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", - "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==" + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", + "license": "MIT" }, "node_modules/@types/ms": { - "version": "0.7.31", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.31.tgz", - "integrity": "sha512-iiUgKzV9AuaEkZqkOLDIvlQiL6ltuZd9tGcW3gwpnX8JbuiuhFlEGmmFXEXkN50Cvq7Os88IY2v0dkDqXYWVgA==" + "version": "0.7.34", + "resolved": "https://registry.npmjs.org/@types/ms/-/ms-0.7.34.tgz", + "integrity": "sha512-nG96G3Wp6acyAgJqGasjODb+acrI7KltPiRxzHPXnP3NgI28bpQDRv53olbqGXbfcgF5aiiHmO3xpwEpS5Ld9g==", + "license": "MIT" }, "node_modules/@types/node": { - "version": "20.5.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz", - "integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA==" + "version": "20.14.9", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.14.9.tgz", + "integrity": "sha512-06OCtnTXtWOZBJlRApleWndH4JsRVs1pDCc8dLSQp+7PpUpX3ePdHyeNSFTeSe7FtKyQkrlPvHwJOW3SLd8Oyg==", + "license": "MIT", + "dependencies": { + "undici-types": "~5.26.4" + } }, "node_modules/@types/node-fetch": { - "version": "2.6.4", - "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.4.tgz", - "integrity": "sha512-1ZX9fcN4Rvkvgv4E6PAY5WXUFWFcRWxZa3EW83UjycOB9ljJCedb2CupIP4RZMEwF/M3eTcCihbBRgwtGbg5Rg==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==", + "license": "MIT", "dependencies": { "@types/node": "*", - "form-data": "^3.0.0" + "form-data": "^4.0.0" } }, "node_modules/@types/prettier": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/qs": { - "version": "6.9.8", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.8.tgz", - "integrity": "sha512-u95svzDlTysU5xecFNTgfFG5RUWu1A9P0VzgpcIiGZA9iraHOdSzcxMxQ55DyeRaGCSxQi7LxXDI4rzq/MYfdg==" + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.15.tgz", + "integrity": "sha512-uXHQKES6DQKKCLh441Xv/dwxOq1TVS3JPUMlEqoEglvlhR6Mxnlew/Xq/LRVHpLyk7iK3zODe1qYHIMltO7XGg==", + "license": "MIT" }, "node_modules/@types/range-parser": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", - "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==" + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" }, "node_modules/@types/semver": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.1.tgz", - "integrity": "sha512-cJRQXpObxfNKkFAZbJl2yjWtJCqELQIdShsogr1d2MilP8dKD9TE/nEKHkJgUNHdGKCQaf9HbIynuV2csLGVLg==", - "dev": true + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true, + "license": "MIT" }, "node_modules/@types/send": { - "version": "0.17.1", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", - "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "license": "MIT", "dependencies": { "@types/mime": "^1", "@types/node": "*" } }, "node_modules/@types/serve-static": { - "version": "1.15.2", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", - "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", + "license": "MIT", "dependencies": { "@types/http-errors": "*", - "@types/mime": "*", - "@types/node": "*" + "@types/node": "*", + "@types/send": "*" } }, "node_modules/@types/validator": { - "version": "13.11.1", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.1.tgz", - "integrity": "sha512-d/MUkJYdOeKycmm75Arql4M5+UuXmf4cHdHKsyw1GcvnNgL6s77UkgSgJ8TE/rI5PYsnwYq5jkcWBLuN/MpQ1A==" + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-nH45Lk7oPIJ1RVOF6JgFI6Dy0QpHEzq4QecZhvguxYPDwT8c93prCMqAtiIttm39voZ+DDR+qkNnMpJmMBRqag==", + "license": "MIT" }, "node_modules/@types/ws": { - "version": "8.5.7", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.7.tgz", - "integrity": "sha512-6UrLjiDUvn40CMrAubXuIVtj2PEfKDffJS7ychvnPU44j+KVeXmdHHTgqcM/dxLUTHxlXHiFM8Skmb8ozGdTnQ==", + "version": "8.5.10", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz", + "integrity": "sha512-vmQSUcfalpIq0R9q7uTo2lXs6eGIpt9wtnLdMv9LVpIjCA/+ufZRozlVoVelIYixx1ugCBKDhn89vnsEGOCx9A==", "dev": true, + "license": "MIT", "dependencies": { "@types/node": "*" } }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.5.0.tgz", - "integrity": "sha512-2pktILyjvMaScU6iK3925uvGU87E+N9rh372uGZgiMYwafaw9SXq86U04XPq3UH6tzRvNgBsub6x2DacHc33lw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "6.5.0", - "@typescript-eslint/type-utils": "6.5.0", - "@typescript-eslint/utils": "6.5.0", - "@typescript-eslint/visitor-keys": "6.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "graphemer": "^1.4.0", "ignore": "^5.2.4", @@ -3902,16 +3437,30 @@ } } }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/parser": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.5.0.tgz", - "integrity": "sha512-LMAVtR5GN8nY0G0BadkG0XIe4AcNMeyEy3DyhKGAh9k4pLSMBO7rF29JvDBpZGCmp5Pgz5RLHP6eCpSYZJQDuQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/scope-manager": "6.5.0", - "@typescript-eslint/types": "6.5.0", - "@typescript-eslint/typescript-estree": "6.5.0", - "@typescript-eslint/visitor-keys": "6.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4" }, "engines": { @@ -3931,13 +3480,14 @@ } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.5.0.tgz", - "integrity": "sha512-A8hZ7OlxURricpycp5kdPTH3XnjG85UpJS6Fn4VzeoH4T388gQJ/PGP4ole5NfKt4WDVhmLaQ/dBLNDC4Xl/Kw==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.5.0", - "@typescript-eslint/visitor-keys": "6.5.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, "engines": { "node": "^16.0.0 || >=18.0.0" @@ -3948,13 +3498,14 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.5.0.tgz", - "integrity": "sha512-f7OcZOkRivtujIBQ4yrJNIuwyCQO1OjocVqntl9dgSIZAdKqicj3xFDqDOzHDlGCZX990LqhLQXWRnQvsapq8A==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "6.5.0", - "@typescript-eslint/utils": "6.5.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", "debug": "^4.3.4", "ts-api-utils": "^1.0.1" }, @@ -3975,10 +3526,11 @@ } }, "node_modules/@typescript-eslint/types": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.5.0.tgz", - "integrity": "sha512-eqLLOEF5/lU8jW3Bw+8auf4lZSbbljHR2saKnYqON12G/WsJrGeeDHWuQePoEf9ro22+JkbPfWQwKEC5WwLQ3w==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, + "license": "MIT", "engines": { "node": "^16.0.0 || >=18.0.0" }, @@ -3988,16 +3540,18 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.5.0.tgz", - "integrity": "sha512-q0rGwSe9e5Kk/XzliB9h2LBc9tmXX25G0833r7kffbl5437FPWb2tbpIV9wAATebC/018pGa9fwPDuvGN+LxWQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "@typescript-eslint/types": "6.5.0", - "@typescript-eslint/visitor-keys": "6.5.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", + "minimatch": "9.0.3", "semver": "^7.5.4", "ts-api-utils": "^1.0.1" }, @@ -4014,18 +3568,32 @@ } } }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/utils": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.5.0.tgz", - "integrity": "sha512-9nqtjkNykFzeVtt9Pj6lyR9WEdd8npPhhIPM992FWVkZuS6tmxHfGVnlUcjpUP2hv8r4w35nT33mlxd+Be1ACQ==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.4.0", "@types/json-schema": "^7.0.12", "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "6.5.0", - "@typescript-eslint/types": "6.5.0", - "@typescript-eslint/typescript-estree": "6.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", "semver": "^7.5.4" }, "engines": { @@ -4039,13 +3607,27 @@ "eslint": "^7.0.0 || ^8.0.0" } }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.5.0.tgz", - "integrity": "sha512-yCB/2wkbv3hPsh02ZS8dFQnij9VVQXJMN/gbQsaaY+zxALkZnxa/wagvLEFsAWMPv7d7lxQmNsIzGU1w/T/WyA==", + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "6.5.0", + "@typescript-eslint/types": "6.21.0", "eslint-visitor-keys": "^3.4.1" }, "engines": { @@ -4056,17 +3638,26 @@ "url": "https://opencollective.com/typescript-eslint" } }, + "node_modules/@ungap/structured-clone": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", + "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", + "dev": true, + "license": "ISC" + }, "node_modules/@whatwg-node/events": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/@whatwg-node/events/-/events-0.0.3.tgz", "integrity": "sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@whatwg-node/fetch": { "version": "0.8.8", "resolved": "https://registry.npmjs.org/@whatwg-node/fetch/-/fetch-0.8.8.tgz", "integrity": "sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg==", "dev": true, + "license": "MIT", "dependencies": { "@peculiar/webcrypto": "^1.4.0", "@whatwg-node/node-fetch": "^0.3.6", @@ -4080,6 +3671,7 @@ "resolved": "https://registry.npmjs.org/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz", "integrity": "sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA==", "dev": true, + "license": "MIT", "dependencies": { "@whatwg-node/events": "^0.0.3", "busboy": "^1.6.0", @@ -4088,16 +3680,11 @@ "tslib": "^2.3.1" } }, - "node_modules/abbrev": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", - "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", - "dev": true - }, "node_modules/accepts": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", "dependencies": { "mime-types": "~2.1.34", "negotiator": "0.6.3" @@ -4107,10 +3694,11 @@ } }, "node_modules/acorn": { - "version": "8.10.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.10.0.tgz", - "integrity": "sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==", + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -4123,30 +3711,23 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/acorn-walk": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", - "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.4.0" - } - }, "node_modules/aes-js": { "version": "4.0.0-beta.5", "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-4.0.0-beta.5.tgz", - "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==" + "integrity": "sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==", + "license": "MIT" }, "node_modules/agent-base": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.0.tgz", - "integrity": "sha512-o/zjMZRhJxny7OyEF+Op8X+efiELC7k7yOjMzgfzVqOzXqkBkWI79YoTdOtsuWd5BWhAGAuOY/Xa6xpiaWXiNg==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^4.3.4" }, @@ -4159,6 +3740,7 @@ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, + "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" @@ -4168,16 +3750,17 @@ } }, "node_modules/ajv": { - "version": "8.12.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", - "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.16.0.tgz", + "integrity": "sha512-F0twR8U1ZU67JIEtekUcLkXkoO5mMMmgGD8sK/xUFzJ805jxHQl92hImFAqqXMyMYjSPOyUPAwHYhB72g5sTXw==", "dev": true, + "license": "MIT", "optional": true, "dependencies": { - "fast-deep-equal": "^3.1.1", + "fast-deep-equal": "^3.1.3", "json-schema-traverse": "^1.0.0", "require-from-string": "^2.0.2", - "uri-js": "^4.2.2" + "uri-js": "^4.4.1" }, "funding": { "type": "github", @@ -4189,6 +3772,7 @@ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", "dev": true, + "license": "MIT", "dependencies": { "type-fest": "^0.21.3" }, @@ -4199,37 +3783,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ansi-escapes/node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", - "dev": true, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^1.9.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=4" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/anymatch": { @@ -4237,6 +3814,7 @@ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", "dev": true, + "license": "ISC", "dependencies": { "normalize-path": "^3.0.0", "picomatch": "^2.0.4" @@ -4245,36 +3823,35 @@ "node": ">= 8" } }, - "node_modules/arg": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", - "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", - "dev": true, - "optional": true - }, "node_modules/argparse": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true + "dev": true, + "license": "Python-2.0" }, "node_modules/array-back": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/array-back/-/array-back-3.1.0.tgz", "integrity": "sha512-TkuxA4UCOvxuDK6NZYXCalszEzj+TLszyASooky+i742l9TqsOdYCMJJupxRic61hwquNtppB3hgcuq9SVSH1Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4283,18 +3860,21 @@ "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", - "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", + "license": "MIT" }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", "is-string": "^1.0.7" }, "engines": { @@ -4309,21 +3889,24 @@ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz", + "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4333,14 +3916,15 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz", + "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -4351,14 +3935,15 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz", + "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", "es-shim-unscopables": "^1.0.0" }, "engines": { @@ -4369,16 +3954,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.1.tgz", - "integrity": "sha512-09x0ZWFEjj4WD8PDbykUwo3t9arLn8NIzmmYEJFpYekOAQjpkGSyrQhNoRTcwwcFRu+ycWF78QZ63oWTqSjBcw==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", "is-shared-array-buffer": "^1.0.2" }, "engines": { @@ -4392,6 +3980,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -4400,13 +3989,15 @@ "version": "2.0.6", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz", "integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/asn1js": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.5.tgz", "integrity": "sha512-FVnvrKJwpt9LP2lAMl8qZswRNm3T4q9CON+bxldk2iwk3FFpuwhx2FfinyitizWHsVYyaY+y5JzDR0rCMV5yTQ==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "pvtsutils": "^1.3.2", "pvutils": "^1.1.3", @@ -4421,6 +4012,7 @@ "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -4429,6 +4021,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/async-retry/-/async-retry-1.3.3.tgz", "integrity": "sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==", + "license": "MIT", "dependencies": { "retry": "0.13.1" } @@ -4436,13 +4029,15 @@ "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" }, "node_modules/at-least-node": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", "dev": true, + "license": "ISC", "engines": { "node": ">= 4.0.0" } @@ -4452,6 +4047,7 @@ "resolved": "https://registry.npmjs.org/auto-bind/-/auto-bind-4.0.0.tgz", "integrity": "sha512-Hdw8qdNiqdJ8LqT0iK0sVzkFbzg6fhnQqqfWhBDxcHZvU75+B+ayzTy8x+k5Ix0Y92XOhOUlx74ps+bA6BeYMQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -4460,10 +4056,14 @@ } }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -4475,13 +4075,15 @@ "version": "7.0.0-beta.0", "resolved": "https://registry.npmjs.org/babel-plugin-syntax-trailing-function-commas/-/babel-plugin-syntax-trailing-function-commas-7.0.0-beta.0.tgz", "integrity": "sha512-Xj9XuRuz3nTSbaTXWv3itLOcxyF4oPD8douBBmj7U9BBC6nEBYfyOJYQMf/8PJAFotC62UY5dFfIGEPr7WswzQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/babel-preset-fbjs": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/babel-preset-fbjs/-/babel-preset-fbjs-3.4.0.tgz", "integrity": "sha512-9ywCsCvo1ojrw0b+XYk7aFvTH6D9064t0RIL1rtMf3nsa02Xw41MS7sZw216Im35xj/UY0PDBQsa1brUDDF1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/plugin-proposal-object-rest-spread": "^7.0.0", @@ -4519,7 +4121,8 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/base64-js": { "version": "1.5.1", @@ -4539,15 +4142,20 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/bl": { @@ -4555,6 +4163,7 @@ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "dev": true, + "license": "MIT", "dependencies": { "buffer": "^5.5.0", "inherits": "^2.0.4", @@ -4565,6 +4174,7 @@ "version": "1.20.2", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "content-type": "~1.0.5", @@ -4588,6 +4198,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -4595,34 +4206,36 @@ "node_modules/body-parser/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, + "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "balanced-match": "^1.0.0" } }, "node_modules/braces": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", - "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, + "license": "MIT", "dependencies": { - "fill-range": "^7.0.1" + "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.1.tgz", - "integrity": "sha512-FEVc202+2iuClEhZhrWy6ZiAcRLvNMyYcxZ8raemul1DYVOVdFsbqckWLdsixQZCpJlwe77Z3UTalE7jsjnKfQ==", + "version": "4.23.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.1.tgz", + "integrity": "sha512-TUfofFo/KsK/bWZ9TWQ5O26tsWW4Uhmt8IYklbnUa70udB6P2wA7w7o4PY4muaEPBQaAX+CEnmmIA41NVHtPVw==", "dev": true, "funding": [ { @@ -4638,11 +4251,12 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001541", - "electron-to-chromium": "^1.4.535", - "node-releases": "^2.0.13", - "update-browserslist-db": "^1.0.13" + "caniuse-lite": "^1.0.30001629", + "electron-to-chromium": "^1.4.796", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.16" }, "bin": { "browserslist": "cli.js" @@ -4656,6 +4270,7 @@ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz", "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==", "dev": true, + "license": "Apache-2.0", "dependencies": { "node-int64": "^0.4.0" } @@ -4679,19 +4294,12 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "base64-js": "^1.3.1", "ieee754": "^1.1.13" } }, - "node_modules/buffer-writer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/buffer-writer/-/buffer-writer-2.0.0.tgz", - "integrity": "sha512-a7ZpuTZU1TRtnwyCNW3I5dc0wWNC3VR9S++Ewyk2HHZdrO3CQJqSpd+95Us590V6AL7JqUAH2IwZ/398PmNFgw==", - "engines": { - "node": ">=4" - } - }, "node_modules/busboy": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", @@ -4708,6 +4316,7 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -4717,17 +4326,25 @@ "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.3.0.tgz", "integrity": "sha512-A+Fezp4zxnit6FanDmv9EqXNAi3vt9DWp51/71UEhXukb7QUuvtv9344h91dyAxuTLoSYJFU299qzR3tzwPAhw==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/call-bind": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4738,6 +4355,7 @@ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4747,6 +4365,7 @@ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz", "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==", "dev": true, + "license": "MIT", "dependencies": { "pascal-case": "^3.1.2", "tslib": "^2.0.3" @@ -4757,14 +4376,15 @@ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/caniuse-lite": { - "version": "1.0.30001547", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001547.tgz", - "integrity": "sha512-W7CrtIModMAxobGhz8iXmDfuJiiKg1WADMO/9x7/CLNin5cpSbuBjooyoIUVB5eyCc36QuTVlkVa1iB2S5+/eA==", + "version": "1.0.30001640", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001640.tgz", + "integrity": "sha512-lA4VMpW0PSUrFnkmVuEKBUovSWKhj7puyCg8StBChgu298N1AtuF1sKWEvfDuimSEDbhlb/KqPKC3fs1HbuQUA==", "dev": true, "funding": [ { @@ -4779,13 +4399,15 @@ "type": "github", "url": "https://github.com/sponsors/ai" } - ] + ], + "license": "CC-BY-4.0" }, "node_modules/capital-case": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/capital-case/-/capital-case-1.0.4.tgz", "integrity": "sha512-ds37W8CytHgwnhGGTi88pcPyR15qoNkOpYwmMMfnWqqWgESapLqvDx6huFjQ5vqWSn2Z06173XNA7LtMOeUh1A==", "dev": true, + "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -4793,17 +4415,20 @@ } }, "node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=4" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/change-case": { @@ -4811,6 +4436,7 @@ "resolved": "https://registry.npmjs.org/change-case/-/change-case-4.1.2.tgz", "integrity": "sha512-bSxY2ws9OtviILG1EiY5K7NNxkqg/JnRnFxLtKQ96JaviiIxi7djMrSd0ECT9AC+lttClmYwKw53BWpOMblo7A==", "dev": true, + "license": "MIT", "dependencies": { "camel-case": "^4.1.2", "capital-case": "^1.0.4", @@ -4831,6 +4457,7 @@ "resolved": "https://registry.npmjs.org/change-case-all/-/change-case-all-1.0.15.tgz", "integrity": "sha512-3+GIFhk3sNuvFAJKU46o26OdzudQlPNBCu1ZQi3cMeMHhty1bhDxu2WrEilVNYaGvqUtR1VSigFcJOiS13dRhQ==", "dev": true, + "license": "MIT", "dependencies": { "change-case": "^4.1.2", "is-lower-case": "^2.0.2", @@ -4848,19 +4475,15 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], + "license": "MIT", "dependencies": { "anymatch": "~3.1.2", "braces": "~3.0.2", @@ -4873,6 +4496,9 @@ "engines": { "node": ">= 8.10.0" }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, "optionalDependencies": { "fsevents": "~2.3.2" } @@ -4882,6 +4508,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -4894,6 +4521,7 @@ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -4903,6 +4531,7 @@ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, + "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, @@ -4911,10 +4540,11 @@ } }, "node_modules/cli-spinners": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.0.tgz", - "integrity": "sha512-4/aL9X3Wh0yiMQlE+eeRhWP6vclO3QRtw1JHKIT0FFUs5FjpFmESqtMvYZ0+lbzBw900b95mS0hohy+qn2VK/g==", + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" }, @@ -4927,6 +4557,7 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", "dev": true, + "license": "MIT", "dependencies": { "slice-ansi": "^3.0.0", "string-width": "^4.2.0" @@ -4943,6 +4574,7 @@ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", "dev": true, + "license": "ISC", "engines": { "node": ">= 10" } @@ -4952,6 +4584,7 @@ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", "strip-ansi": "^6.0.1", @@ -4961,40 +4594,66 @@ "node": ">=12" } }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/clone": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8" } }, "node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "dev": true, + "license": "MIT", "dependencies": { - "color-name": "1.1.3" + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" } }, "node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "license": "MIT", "dependencies": { "delayed-stream": "~1.0.0" }, @@ -5007,6 +4666,7 @@ "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.2.1.tgz", "integrity": "sha512-H4UfQhZyakIjC74I9d34fGYDwk3XpSr17QhEd0Q3I9Xq1CETHo4Hcuo87WyWHpAF1aSLjLRf5lD9ZGX2qStUvg==", "dev": true, + "license": "MIT", "dependencies": { "array-back": "^3.1.0", "find-replace": "^3.0.0", @@ -5022,6 +4682,7 @@ "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-6.1.3.tgz", "integrity": "sha512-sH5ZSPr+7UStsloltmDh7Ce5fb8XPlHyoPzTpyyMuYCtervL65+ubVZ6Q61cFtFl62UyJlc8/JwERRbAFPUqgw==", "dev": true, + "license": "MIT", "dependencies": { "array-back": "^4.0.2", "chalk": "^2.4.2", @@ -5032,20 +4693,100 @@ "node": ">=8.0.0" } }, + "node_modules/command-line-usage/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/command-line-usage/node_modules/array-back": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, + "node_modules/command-line-usage/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/command-line-usage/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/command-line-usage/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/command-line-usage/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/command-line-usage/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/command-line-usage/node_modules/typical": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -5055,6 +4796,7 @@ "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.3.0.tgz", "integrity": "sha512-H0iNtClNEhT0fotHvGV3E9tDejDeS04sN1veIebsKYGMuGscFaswRoYJKmT3eW85eIJAs0F28bG2+a/9wCOfPw==", "dev": true, + "license": "MIT", "dependencies": { "cachedir": "2.3.0", "cz-conventional-changelog": "3.3.0", @@ -5080,11 +4822,57 @@ "node": ">= 12" } }, + "node_modules/commitizen/node_modules/inquirer": { + "version": "8.2.5", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", + "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/commitizen/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/common-tags": { "version": "1.8.2", "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } @@ -5093,19 +4881,22 @@ "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/confusing-browser-globals": { "version": "1.0.11", "resolved": "https://registry.npmjs.org/confusing-browser-globals/-/confusing-browser-globals-1.0.11.tgz", "integrity": "sha512-JsPKdmh8ZkmnHxDk55FZ1TqVLvEQTvoByJZRN9jzI0UjxK/QgAmsphz7PGtqgPieQZ/CQcHWXCR7ATDNhGe+YA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/constant-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/constant-case/-/constant-case-3.0.4.tgz", "integrity": "sha512-I2hSBi7Vvs7BEuJDr5dDHfzb/Ruj3FyvFyh7KLilAjNQw3Be+xgqUBA2W6scVEcL0hL1dwPRtIqEPVUCKkSsyQ==", "dev": true, + "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -5116,6 +4907,7 @@ "version": "0.5.4", "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "license": "MIT", "dependencies": { "safe-buffer": "5.2.1" }, @@ -5127,6 +4919,7 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5135,18 +4928,21 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/convert-source-map": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/cookie": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", - "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -5154,12 +4950,14 @@ "node_modules/cookie-signature": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", + "license": "MIT" }, "node_modules/cors": { "version": "2.8.5", "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "license": "MIT", "dependencies": { "object-assign": "^4", "vary": "^1" @@ -5169,14 +4967,15 @@ } }, "node_modules/cosmiconfig": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz", - "integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==", + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", "dev": true, + "license": "MIT", "dependencies": { - "import-fresh": "^3.2.1", + "import-fresh": "^3.3.0", "js-yaml": "^4.1.0", - "parse-json": "^5.0.0", + "parse-json": "^5.2.0", "path-type": "^4.0.0" }, "engines": { @@ -5184,89 +4983,244 @@ }, "funding": { "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, "node_modules/cosmiconfig-typescript-loader": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-4.4.0.tgz", - "integrity": "sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-5.0.0.tgz", + "integrity": "sha512-+8cK7jRAReYkMwMiG+bxhcNKiHJDM6bR9FD/nGBXOWdMLuYawjF5cGrtLilJ+LGd3ZjCXnJjR5DkfWPoIVlqJA==", "dev": true, + "license": "MIT", "optional": true, + "dependencies": { + "jiti": "^1.19.1" + }, "engines": { - "node": ">=v14.21.3" + "node": ">=v16" }, "peerDependencies": { "@types/node": "*", - "cosmiconfig": ">=7", - "ts-node": ">=10", + "cosmiconfig": ">=8.2", "typescript": ">=4" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "dev": true, - "optional": true - }, "node_modules/cross-fetch": { "version": "3.1.8", "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.8.tgz", "integrity": "sha512-cvA+JwZoU0Xq+h6WkMvAUqPEYy92Obet6UdKLfW60qn99ftItKjB5T+BkyWOFWe2pUyfQ+IJHmpOTznqk1M6Kg==", "dev": true, + "license": "MIT", + "dependencies": { + "node-fetch": "^2.6.12" + } + }, + "node_modules/cross-inspect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cross-inspect/-/cross-inspect-1.0.0.tgz", + "integrity": "sha512-4PFfn4b5ZN6FMNGSZlyb7wUhuN8wvj8t/VQHZdM4JsDcruGJ8L2kf9zao98QIrBPFCpdk27qst/AGTl7pL3ypQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cz-conventional-changelog": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", + "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" + } + }, + "node_modules/cz-conventional-changelog/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/cz-conventional-changelog/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "dev": true, + "license": "MIT" + }, + "node_modules/cz-conventional-changelog/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/cz-conventional-changelog/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/cz-conventional-changelog/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", + "dev": true, + "license": "MIT", "dependencies": { - "node-fetch": "^2.6.12" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, + "license": "MIT", "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cz-conventional-changelog": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.3.0.tgz", - "integrity": "sha512-U466fIzU5U22eES5lTNiNbZ+d8dfcHcssH4o7QsdWaCcRs/feIPCxKYSWkYBNs5mny7MvEfwpTLWjvbm94hecw==", + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, + "license": "MIT", "dependencies": { - "chalk": "^2.4.1", - "commitizen": "^4.0.3", - "conventional-commit-types": "^3.0.0", - "lodash.map": "^4.5.1", - "longest": "^2.0.1", - "word-wrap": "^1.0.3" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": ">= 10" + "node": ">= 0.4" }, - "optionalDependencies": { - "@commitlint/load": ">6.1.1" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/dataloader": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/dataloader/-/dataloader-2.2.2.tgz", - "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==" + "integrity": "sha512-8YnDaaf7N3k/q5HnTJVuzSyLETjoZjVmHc4AeKAzOvKHEFQKcn64OKBfzHYtE9zGjctNM7V9I0MfnUVLpi7M5g==", + "license": "MIT" }, "node_modules/debounce": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz", "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "license": "MIT", "dependencies": { "ms": "2.1.2" }, @@ -5284,6 +5238,7 @@ "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5292,13 +5247,15 @@ "version": "0.7.0", "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/deep-extend": { "version": "0.6.0", "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4.0.0" } @@ -5307,13 +5264,15 @@ "version": "0.1.4", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/defaults": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", "dev": true, + "license": "MIT", "dependencies": { "clone": "^1.0.2" }, @@ -5321,12 +5280,31 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -5341,6 +5319,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { "node": ">=0.4.0" } @@ -5349,6 +5328,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -5358,6 +5338,7 @@ "resolved": "https://registry.npmjs.org/dependency-graph/-/dependency-graph-0.11.0.tgz", "integrity": "sha512-JeMq7fEshyepOWDfcfHK06N3MhyPhz++vtqWhMT5O9A3K42rdsEDpfdVqjaqaAhsw6a+ZqeDvQVtD0hFHQWrzg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.6.0" } @@ -5366,6 +5347,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { "node": ">= 0.8", "npm": "1.2.8000 || >= 1.4.16" @@ -5376,6 +5358,7 @@ "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", "integrity": "sha512-DtCOLG98P007x7wiiOmfI0fi3eIKyWiLTGJ2MDnVi/E04lWGbf+JzrRHMm0rgIIZJGtHpKpbVgLWHrv8xXpc3Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -5385,25 +5368,17 @@ "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.1.0.tgz", "integrity": "sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, - "node_modules/diff": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", - "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", - "dev": true, - "optional": true, - "engines": { - "node": ">=0.3.1" - } - }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, + "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, @@ -5416,6 +5391,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -5428,32 +5404,36 @@ "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz", "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==", "dev": true, + "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" } }, "node_modules/dotenv": { - "version": "16.3.1", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", - "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "version": "16.4.5", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.5.tgz", + "integrity": "sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==", + "license": "BSD-2-Clause", "engines": { "node": ">=12" }, "funding": { - "url": "https://github.com/motdotla/dotenv?sponsor=1" + "url": "https://dotenvx.com" } }, "node_modules/dottie": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.6.tgz", - "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==" + "integrity": "sha512-iGCHkfUc5kFekGiqhe8B/mdaurD+lakO9txNnTvKtA6PISrw86LgqHvRzWYPyoE2Ph5aMIrCw9/uko6XHTKCwA==", + "license": "MIT" }, "node_modules/dset": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.2.tgz", - "integrity": "sha512-g/M9sqy3oHe477Ar4voQxWtaPIFw1jTdKZuomOjhCcBx9nHUNn0pu6NopuFFrTh/TRZIKEj+76vLWFu9BNKk+Q==", + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.3.tgz", + "integrity": "sha512-20TuZZHCEZ2O71q9/+8BwKwZ0QtD9D8ObhrihJPr+vLLYlSuAU3/zL4cSlgbfeoGHTjCSJBa7NGcrF9/Bx/WJQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -5461,82 +5441,106 @@ "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", - "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" }, "node_modules/electron-to-chromium": { - "version": "1.4.551", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.551.tgz", - "integrity": "sha512-/Ng/W/kFv7wdEHYzxdK7Cv0BHEGSkSB3M0Ssl8Ndr1eMiYeas/+Mv4cNaDqamqWx6nd2uQZfPz6g25z25M/sdw==", - "dev": true + "version": "1.4.816", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.816.tgz", + "integrity": "sha512-EKH5X5oqC6hLmiS7/vYtZHZFTNdhsYG5NVPRN6Yn0kQHNBlT59+xSM8HBy66P5fxWpKgZbPqb+diC64ng295Jw==", + "dev": true, + "license": "ISC" }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/encodeurl": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } + }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, + "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-abstract": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.1.tgz", - "integrity": "sha512-ioRRcXMO6OFyRpyzV3kE1IIBd4WG5/kltnzdxSCqoP8CMGs/Li+M1uF5o7lOkZVFjDs+NLesthnF66Pg/0q0Lw==", - "dev": true, - "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.1", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.5", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", "globalthis": "^1.0.3", "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", + "is-shared-array-buffer": "^1.0.3", "is-string": "^1.0.7", - "is-typed-array": "^1.1.10", + "is-typed-array": "^1.1.13", "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "object-inspect": "^1.13.1", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.0", - "safe-array-concat": "^1.0.0", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.7", - "string.prototype.trimend": "^1.0.6", - "string.prototype.trimstart": "^1.0.6", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.10" + "which-typed-array": "^1.1.15" }, "engines": { "node": ">= 0.4" @@ -5545,27 +5549,63 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz", + "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.0" } }, "node_modules/es-to-primitive": { @@ -5573,6 +5613,7 @@ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -5586,10 +5627,11 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -5597,30 +5639,37 @@ "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", - "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" }, "node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, + "license": "MIT", "engines": { - "node": ">=0.8.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/eslint": { - "version": "8.48.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.48.0.tgz", - "integrity": "sha512-sb6DLeIuRXxeM1YljSe1KEx9/YYeZFQWcV8Rq9HfigmdDEugjLEVEa1ozDjL6YDjBpQHPJxJzze+alxi4T3OLg==", + "version": "8.57.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", + "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", "dev": true, + "license": "MIT", "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.2", - "@eslint/js": "8.48.0", - "@humanwhocodes/config-array": "^0.11.10", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.0", + "@humanwhocodes/config-array": "^0.11.14", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", "ajv": "^6.12.4", "chalk": "^4.0.0", "cross-spawn": "^7.0.2", @@ -5667,6 +5716,7 @@ "resolved": "https://registry.npmjs.org/eslint-config-airbnb-base/-/eslint-config-airbnb-base-15.0.0.tgz", "integrity": "sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==", "dev": true, + "license": "MIT", "dependencies": { "confusing-browser-globals": "^1.0.10", "object.assign": "^4.1.2", @@ -5681,20 +5731,12 @@ "eslint-plugin-import": "^2.25.2" } }, - "node_modules/eslint-config-airbnb-base/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/eslint-config-airbnb-typescript": { "version": "17.1.0", "resolved": "https://registry.npmjs.org/eslint-config-airbnb-typescript/-/eslint-config-airbnb-typescript-17.1.0.tgz", "integrity": "sha512-GPxI5URre6dDpJ0CtcthSZVBAfI+Uw7un5OYNVxP2EYi3H81Jw701yFP7AU+/vCE7xBtFmjge7kfhhk4+RAiig==", "dev": true, + "license": "MIT", "dependencies": { "eslint-config-airbnb-base": "^15.0.0" }, @@ -5706,10 +5748,11 @@ } }, "node_modules/eslint-config-prettier": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.0.0.tgz", - "integrity": "sha512-IcJsTkJae2S35pRsRAwoCE+925rJJStOdkKnLVgtE+tEpqU0EVVM7OqrwxqgptKdX29NUwC82I5pXsGFIgSevw==", + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz", + "integrity": "sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==", "dev": true, + "license": "MIT", "bin": { "eslint-config-prettier": "bin/cli.js" }, @@ -5722,6 +5765,7 @@ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", "is-core-module": "^2.13.0", @@ -5733,15 +5777,17 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.1.tgz", + "integrity": "sha512-rXDXR3h7cs7dy9RNpUlQf80nX31XWJEyGq1tRMo+6GsO5VmTe4UTwtmonAD4ZkAsrfMVDA2wlGJ3790Ys+D49Q==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -5759,33 +5805,35 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz", + "integrity": "sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "array-includes": "^3.1.7", + "array.prototype.findlastindex": "^1.2.3", + "array.prototype.flat": "^1.3.2", + "array.prototype.flatmap": "^1.3.2", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", + "eslint-import-resolver-node": "^0.3.9", "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "hasown": "^2.0.0", + "is-core-module": "^2.13.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.7", + "object.groupby": "^1.0.1", + "object.values": "^1.1.7", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" @@ -5794,11 +5842,23 @@ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" } }, + "node_modules/eslint-plugin-import/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/eslint-plugin-import/node_modules/debug": { "version": "3.2.7", "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -5808,6 +5868,7 @@ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", "dev": true, + "license": "Apache-2.0", "dependencies": { "esutils": "^2.0.2" }, @@ -5815,13 +5876,17 @@ "node": ">=0.10.0" } }, - "node_modules/eslint-plugin-import/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "node_modules/eslint-plugin-import/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "bin": { - "semver": "bin/semver.js" + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, "node_modules/eslint-scope": { @@ -5829,6 +5894,7 @@ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" @@ -5845,6 +5911,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -5857,6 +5924,7 @@ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -5868,60 +5936,59 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/eslint/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "node_modules/eslint/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/eslint/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" + "type-fest": "^0.20.2" }, "engines": { - "node": ">=10" + "node": ">=8" }, "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", "dependencies": { - "color-name": "~1.1.4" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=7.0.0" + "node": "*" } }, - "node_modules/eslint/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/eslint/node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/eslint/node_modules/type-fest": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -5929,38 +5996,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/eslint/node_modules/json-schema-traverse": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", - "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", - "dev": true - }, - "node_modules/eslint/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/espree": { "version": "9.6.1", "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "acorn": "^8.9.0", "acorn-jsx": "^5.3.2", @@ -5978,6 +6019,7 @@ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -5990,6 +6032,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -6002,6 +6045,7 @@ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } @@ -6011,6 +6055,7 @@ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", "dev": true, + "license": "BSD-2-Clause", "engines": { "node": ">=0.10.0" } @@ -6019,14 +6064,15 @@ "version": "1.8.1", "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/ethers": { - "version": "6.7.1", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.7.1.tgz", - "integrity": "sha512-qX5kxIFMfg1i+epfgb0xF4WM7IqapIIu50pOJ17aebkxxa4BacW5jFrQRmCJpDEg2ZK2oNtR5QjrQ1WDBF29dA==", + "version": "6.13.1", + "resolved": "https://registry.npmjs.org/ethers/-/ethers-6.13.1.tgz", + "integrity": "sha512-hdJ2HOxg/xx97Lm9HdCWk949BfYqYWpyw4//78SiwOLgASyfrNszfMUNB2joKjvGUdwhHfaiMMFFwacVVoLR9A==", "funding": [ { "type": "individual", @@ -6037,14 +6083,15 @@ "url": "https://www.buymeacoffee.com/ricmoo" } ], + "license": "MIT", "dependencies": { - "@adraffy/ens-normalize": "1.9.2", - "@noble/hashes": "1.1.2", - "@noble/secp256k1": "1.7.1", + "@adraffy/ens-normalize": "1.10.1", + "@noble/curves": "1.2.0", + "@noble/hashes": "1.3.2", "@types/node": "18.15.13", "aes-js": "4.0.0-beta.5", "tslib": "2.4.0", - "ws": "8.5.0" + "ws": "8.17.1" }, "engines": { "node": ">=14.0.0" @@ -6053,18 +6100,42 @@ "node_modules/ethers/node_modules/@types/node": { "version": "18.15.13", "resolved": "https://registry.npmjs.org/@types/node/-/node-18.15.13.tgz", - "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==" + "integrity": "sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==", + "license": "MIT" }, "node_modules/ethers/node_modules/tslib": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.4.0.tgz", - "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==" + "integrity": "sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==", + "license": "0BSD" + }, + "node_modules/ethers/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } }, "node_modules/expand-tilde": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", "integrity": "sha512-A5EmesHW6rfnZ9ysHQjPdJRni0SRar0tjtG5MNtm9n5TUvsYU8oozprtRD4AqHxcZWWlVuAmQo2nWKfN9oyjTw==", "dev": true, + "license": "MIT", "dependencies": { "homedir-polyfill": "^1.0.1" }, @@ -6073,16 +6144,17 @@ } }, "node_modules/express": { - "version": "4.18.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", - "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "version": "4.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "license": "MIT", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "1.20.1", + "body-parser": "1.20.2", "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "0.5.0", + "cookie": "0.6.0", "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", @@ -6114,46 +6186,25 @@ } }, "node_modules/express-rate-limit": { - "version": "7.1.5", - "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.1.5.tgz", - "integrity": "sha512-/iVogxu7ueadrepw1bS0X0kaRC/U0afwiYRSLg68Ts+p4Dc85Q5QKsOnPS/QUjPMHvOJQtBDrZgvkOzf8ejUYw==", + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.3.1.tgz", + "integrity": "sha512-BbaryvkY4wEgDqLgD18/NSy2lDO2jTuT9Y8c1Mpx0X63Yz0sYd5zN6KPe7UvpuSVvV33T6RaE1o1IVZQjHMYgw==", + "license": "MIT", "engines": { "node": ">= 16" }, "funding": { "url": "https://github.com/sponsors/express-rate-limit" }, - "peerDependencies": { - "express": "4 || 5 || ^5.0.0-beta.1" - } - }, - "node_modules/express/node_modules/body-parser": { - "version": "1.20.1", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", - "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", - "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.4", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.11.0", - "raw-body": "2.5.1", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "peerDependencies": { + "express": "4 || 5 || ^5.0.0-beta.1" } }, "node_modules/express/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -6161,27 +6212,15 @@ "node_modules/express/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" - }, - "node_modules/express/node_modules/raw-body": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", - "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", - "dependencies": { - "bytes": "3.1.2", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8" - } + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/external-editor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", "dev": true, + "license": "MIT", "dependencies": { "chardet": "^0.7.0", "iconv-lite": "^0.4.24", @@ -6196,6 +6235,7 @@ "resolved": "https://registry.npmjs.org/extract-files/-/extract-files-11.0.0.tgz", "integrity": "sha512-FuoE1qtbJ4bBVvv94CC7s0oTnKUGvQs+Rjf1L2SJFfS+HTVVjhPFtehPdQ0JiGPqVNfSSZvL5yzHHQq2Z4WNhQ==", "dev": true, + "license": "MIT", "engines": { "node": "^12.20 || >= 14.13" }, @@ -6207,19 +6247,22 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz", "integrity": "sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-glob": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.1.tgz", - "integrity": "sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", @@ -6236,6 +6279,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -6247,19 +6291,22 @@ "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-levenshtein": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/fast-querystring": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/fast-querystring/-/fast-querystring-1.1.2.tgz", "integrity": "sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg==", "dev": true, + "license": "MIT", "dependencies": { "fast-decode-uri-component": "^1.0.1" } @@ -6269,21 +6316,17 @@ "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", "integrity": "sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ==", "dev": true, + "license": "MIT", "dependencies": { "punycode": "^1.3.2" } }, - "node_modules/fast-url-parser/node_modules/punycode": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", - "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", - "dev": true - }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } @@ -6293,6 +6336,7 @@ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz", "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==", "dev": true, + "license": "Apache-2.0", "dependencies": { "bser": "2.1.1" } @@ -6302,6 +6346,7 @@ "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-3.0.5.tgz", "integrity": "sha512-ztsSx77JBtkuMrEypfhgc3cI0+0h+svqeie7xHbh1k/IKdcydnvadp/mUaGgjAOXQmQSxsqgaRhS3q9fy+1kxg==", "dev": true, + "license": "MIT", "dependencies": { "cross-fetch": "^3.1.5", "fbjs-css-vars": "^1.0.0", @@ -6316,13 +6361,15 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/fbjs-css-vars/-/fbjs-css-vars-1.0.2.tgz", "integrity": "sha512-b2XGFAFdWZWg0phtAWLHCk836A1Xann+I+Dgd3Gk64MHKZO44FfoD1KxyvbSh0qZsIoXQGGlVztIY+oitJPpRQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/figures": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", "dev": true, + "license": "MIT", "dependencies": { "escape-string-regexp": "^1.0.5" }, @@ -6333,11 +6380,22 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/figures/node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, "node_modules/file-entry-cache": { "version": "6.0.1", "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, + "license": "MIT", "dependencies": { "flat-cache": "^3.0.4" }, @@ -6346,10 +6404,11 @@ } }, "node_modules/fill-range": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", - "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, + "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -6361,6 +6420,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "encodeurl": "~1.0.2", @@ -6378,6 +6438,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -6385,13 +6446,15 @@ "node_modules/finalhandler/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/find-node-modules": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.3.tgz", "integrity": "sha512-UC2I2+nx1ZuOBclWVNdcnbDR5dlrOdVb7xNjmT/lHE+LsgztWks3dG7boJ37yTS/venXw84B/mAW9uHVoC5QRg==", "dev": true, + "license": "MIT", "dependencies": { "findup-sync": "^4.0.0", "merge": "^2.1.1" @@ -6402,6 +6465,7 @@ "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-3.0.0.tgz", "integrity": "sha512-6Tb2myMioCAgv5kfvP5/PkZZ/ntTpVK39fHY7WkWBgvbeE+VHd/tZuZ4mrC+bxh4cfOZeYKVPaJIZtZXV7GNCQ==", "dev": true, + "license": "MIT", "dependencies": { "array-back": "^3.0.1" }, @@ -6413,13 +6477,15 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/find-up": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", "dev": true, + "license": "MIT", "dependencies": { "locate-path": "^6.0.0", "path-exists": "^4.0.0" @@ -6436,6 +6502,7 @@ "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", "dev": true, + "license": "MIT", "dependencies": { "detect-file": "^1.0.0", "is-glob": "^4.0.0", @@ -6447,38 +6514,42 @@ } }, "node_modules/flat-cache": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.1.0.tgz", - "integrity": "sha512-OHx4Qwrrt0E4jEIcI5/Xb+f+QmJYNj2rrK8wiIdQOIrB9WrrJL8cjZvXdXuBTkkEwEqLycb5BeZDV1o2i9bTew==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.2.7", + "flatted": "^3.2.9", "keyv": "^4.5.3", "rimraf": "^3.0.2" }, "engines": { - "node": ">=12.0.0" + "node": "^10.12.0 || >=12.0.0" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", - "dev": true + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", + "dev": true, + "license": "ISC" }, "node_modules/for-each": { "version": "0.3.3", "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", "dev": true, + "license": "MIT", "dependencies": { "is-callable": "^1.1.3" } }, "node_modules/form-data": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-3.0.1.tgz", - "integrity": "sha512-RHkBKtLWUVwd7SqRIvCZMEvAMoGUp0XU+seQiZejj0COz3RI3hWP4sCv3gZWWLjJTd7rGwcsF5eKZGii0r/hbg==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "license": "MIT", "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", @@ -6492,6 +6563,7 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6500,6 +6572,7 @@ "version": "0.5.2", "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -6509,6 +6582,7 @@ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", "dev": true, + "license": "MIT", "dependencies": { "at-least-node": "^1.0.0", "graceful-fs": "^4.2.0", @@ -6523,7 +6597,8 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/fsevents": { "version": "2.3.3", @@ -6531,6 +6606,7 @@ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "optional": true, "os": [ "darwin" @@ -6540,15 +6616,20 @@ } }, "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } }, "node_modules/function.prototype.name": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "define-properties": "^1.2.0", @@ -6567,6 +6648,7 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -6576,6 +6658,7 @@ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.9.0" } @@ -6585,32 +6668,40 @@ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" }, "engines": { "node": ">= 0.4" @@ -6623,7 +6714,9 @@ "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -6644,6 +6737,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.3" }, @@ -6651,17 +6745,45 @@ "node": ">=10.13.0" } }, - "node_modules/global-dirs": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", - "integrity": "sha512-NknMLn7F2J7aflwFOlGdNIuCDpN3VGoSoB+aap3KABFWbHVn1TCgFC+np23J8W2BiZbjfEw3BFBycSMv1AFblg==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-directory": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/global-directory/-/global-directory-4.0.1.tgz", + "integrity": "sha512-wHTUcDUoZ1H5/0iVqEudYW4/kAlN5cZ3j/bXn0Dpbizl9iaUVeWSHqiOjsgk6OW2bkLclbBjzewBz6weQ1zA2Q==", + "dev": true, + "license": "MIT", "optional": true, "dependencies": { - "ini": "^1.3.4" + "ini": "4.1.1" }, "engines": { - "node": ">=4" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/global-modules": { @@ -6669,6 +6791,7 @@ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", "dev": true, + "license": "MIT", "dependencies": { "global-prefix": "^1.0.1", "is-windows": "^1.0.1", @@ -6683,6 +6806,7 @@ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", "integrity": "sha512-5lsx1NUDHtSjfg0eHlmYvZKv8/nVqX4ckFbM+FrGcQ+04KWcWFo9P5MxPZYSzUvyzmdTbI7Eix8Q4IbELDqzKg==", "dev": true, + "license": "MIT", "dependencies": { "expand-tilde": "^2.0.2", "homedir-polyfill": "^1.0.1", @@ -6694,11 +6818,19 @@ "node": ">=0.10.0" } }, + "node_modules/global-prefix/node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true, + "license": "ISC" + }, "node_modules/global-prefix/node_modules/which": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -6707,27 +6839,24 @@ } }, "node_modules/globals": { - "version": "13.21.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.21.0.tgz", - "integrity": "sha512-ybyme3s4yy/t/3s35bewwXKOf7cvzfreG2lH0lZl0JB7I4GxRP2ghxOK/Nb9EkRXdbBXZLfq/p/0W2JUONB/Gg==", + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, - "dependencies": { - "type-fest": "^0.20.2" - }, + "license": "MIT", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=4" } }, "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { - "define-properties": "^1.1.3" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -6741,6 +6870,7 @@ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", "dev": true, + "license": "MIT", "dependencies": { "array-union": "^2.1.0", "dir-glob": "^3.0.1", @@ -6760,7 +6890,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, + "license": "MIT", "dependencies": { "get-intrinsic": "^1.1.3" }, @@ -6772,18 +6902,21 @@ "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/graphql": { - "version": "16.8.1", - "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.8.1.tgz", - "integrity": "sha512-59LZHPdGZVh695Ud9lRzPBVTtlX9ZCV150Er2W43ro37wVof0ctenSaskPPjN7lVTIN8mSZt8PHUNKZuNQUuxw==", + "version": "16.9.0", + "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.9.0.tgz", + "integrity": "sha512-GGTKBX4SD7Wdb8mqeDLni2oaRGYQWjWHGKPQ24ZMnUtKfcsVoiv4uX8+LJr1K6U5VW2Lu1BwJnj7uiori0YtRw==", + "license": "MIT", "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -6793,6 +6926,7 @@ "resolved": "https://registry.npmjs.org/graphql-config/-/graphql-config-5.0.3.tgz", "integrity": "sha512-BNGZaoxIBkv9yy6Y7omvsaBUHOzfFcII3UN++tpH8MGOKFPFkCPZuwx09ggANMt8FgyWP1Od8SWPmrUEZca4NQ==", "dev": true, + "license": "MIT", "dependencies": { "@graphql-tools/graphql-file-loader": "^8.0.0", "@graphql-tools/json-file-loader": "^8.0.0", @@ -6820,12 +6954,13 @@ } }, "node_modules/graphql-config/node_modules/@graphql-tools/merge": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.0.tgz", - "integrity": "sha512-J7/xqjkGTTwOJmaJQJ2C+VDBDOWJL3lKrHJN4yMaRLAJH3PosB7GiPRaSDZdErs0+F77sH2MKs2haMMkywzx7Q==", + "version": "9.0.4", + "resolved": "https://registry.npmjs.org/@graphql-tools/merge/-/merge-9.0.4.tgz", + "integrity": "sha512-MivbDLUQ+4Q8G/Hp/9V72hbn810IJDEZQ57F01sHnlrrijyadibfVhaQfW/pNH+9T/l8ySZpaR/DpL5i+ruZ+g==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-tools/utils": "^10.0.0", + "@graphql-tools/utils": "^10.0.13", "tslib": "^2.4.0" }, "engines": { @@ -6835,21 +6970,15 @@ "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" } }, - "node_modules/graphql-config/node_modules/@graphql-tools/utils": { - "version": "10.0.7", - "resolved": "https://registry.npmjs.org/@graphql-tools/utils/-/utils-10.0.7.tgz", - "integrity": "sha512-KOdeMj6Hd/MENDaqPbws3YJl3wVy0DeYnL7PyUms5Skyf7uzI9INynDwPMhLXfSb0/ph6BXTwMd5zBtWbF8tBQ==", + "node_modules/graphql-config/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, + "license": "MIT", "dependencies": { - "@graphql-typed-document-node/core": "^3.1.1", - "dset": "^3.1.2", - "tslib": "^2.4.0" - }, - "engines": { - "node": ">=16.0.0" - }, - "peerDependencies": { - "graphql": "^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, "node_modules/graphql-config/node_modules/minimatch": { @@ -6857,6 +6986,7 @@ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-4.2.3.tgz", "integrity": "sha512-lIUdtK5hdofgCTu3aT0sOaHsYR37viUuIc0rwnnDXImbwFRcumyLMeZaM0t0I/fgxS6s6JMfu0rLD1Wz9pv1ng==", "dev": true, + "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, @@ -6868,6 +6998,7 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/graphql-depth-limit/-/graphql-depth-limit-1.1.0.tgz", "integrity": "sha512-+3B2BaG8qQ8E18kzk9yiSdAa75i/hnnOwgSeAxVJctGQPvmeiLtqKOYF6HETCyRjiF7Xfsyal0HbLlxCQkgkrw==", + "license": "MIT", "dependencies": { "arrify": "^1.0.1" }, @@ -6883,6 +7014,7 @@ "resolved": "https://registry.npmjs.org/graphql-request/-/graphql-request-6.1.0.tgz", "integrity": "sha512-p+XPfS4q7aIpKVcgmnZKhMNqhltk20hfXtkaIkTfjjmiKMJ5xrt5c743cL03y/K7y1rg3WrIC49xGiEQ4mxdNw==", "dev": true, + "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.2.0", "cross-fetch": "^3.1.5" @@ -6895,6 +7027,7 @@ "version": "2.12.6", "resolved": "https://registry.npmjs.org/graphql-tag/-/graphql-tag-2.12.6.tgz", "integrity": "sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==", + "license": "MIT", "dependencies": { "tslib": "^2.1.0" }, @@ -6906,10 +7039,14 @@ } }, "node_modules/graphql-ws": { - "version": "5.14.1", - "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.14.1.tgz", - "integrity": "sha512-aqkls1espsygP1PfkAuuLIV96IbztQ6EaADse97pw8wRIMT3+AL/OYfS8V2iCRkc0gzckitoDRGCQEdnySggiA==", + "version": "5.16.0", + "resolved": "https://registry.npmjs.org/graphql-ws/-/graphql-ws-5.16.0.tgz", + "integrity": "sha512-Ju2RCU2dQMgSKtArPbEtsK5gNLnsQyTNIo/T7cZNp96niC1x0KdJNZV0TIoilceBPQwfb5itrGl8pkFeOUMl4A==", "dev": true, + "license": "MIT", + "workspaces": [ + "website" + ], "engines": { "node": ">=10" }, @@ -6917,51 +7054,43 @@ "graphql": ">=0.11 <=16" } }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", - "dev": true, + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -6973,6 +7102,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -6981,12 +7111,13 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -6995,11 +7126,24 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/header-case": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/header-case/-/header-case-2.0.4.tgz", "integrity": "sha512-H/vuk5TEEVZwrR0lp2zed9OCo1uAILMlx0JEMgC26rzyJJ3N1v6XkwHHXJQdR2doSjcGPM6OKPYoJgf0plJ11Q==", "dev": true, + "license": "MIT", "dependencies": { "capital-case": "^1.0.4", "tslib": "^2.0.3" @@ -7010,6 +7154,7 @@ "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", "dev": true, + "license": "MIT", "dependencies": { "parse-passwd": "^1.0.0" }, @@ -7021,6 +7166,7 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", "dependencies": { "depd": "2.0.0", "inherits": "2.0.4", @@ -7033,10 +7179,11 @@ } }, "node_modules/http-proxy-agent": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.0.tgz", - "integrity": "sha512-+ZT+iBxVUQ1asugqnD6oWoRiS25AkjNfG085dKJGtGxkdwLQrMKU5wJr2bOOFAXzKcTuqq+7fZlTMgG3SRfIYQ==", + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", + "integrity": "sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.1.0", "debug": "^4.3.4" @@ -7046,10 +7193,11 @@ } }, "node_modules/https-proxy-agent": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.2.tgz", - "integrity": "sha512-NmLNjm6ucYwtcUmL7JQC1ZQ57LmHP4lT15FQ8D61nak1rO6DH+fz5qNK2Ap5UN4ZapYICE3/0KodcLYSPsPbaA==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "dev": true, + "license": "MIT", "dependencies": { "agent-base": "^7.0.2", "debug": "4" @@ -7063,6 +7211,7 @@ "resolved": "https://registry.npmjs.org/husky/-/husky-8.0.3.tgz", "integrity": "sha512-+dQSyqPh4x1hlO1swXBiNb2HzTDN1I2IGLQx1GrBuiqFJfoMrnZWwVmatvSiO+Iz8fBUnf+lekwNo4c2LlXItg==", "dev": true, + "license": "MIT", "bin": { "husky": "lib/bin.js" }, @@ -7077,6 +7226,7 @@ "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "license": "MIT", "dependencies": { "safer-buffer": ">= 2.1.2 < 3" }, @@ -7102,13 +7252,15 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "BSD-3-Clause" }, "node_modules/ignore": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.2.4.tgz", - "integrity": "sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ==", + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.1.tgz", + "integrity": "sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4" } @@ -7117,13 +7269,15 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/immutable": { "version": "3.7.6", "resolved": "https://registry.npmjs.org/immutable/-/immutable-3.7.6.tgz", "integrity": "sha512-AizQPcaofEtO11RZhPPHBOJRdo/20MKQF9mBLnVkBoyHi1/zXK8fzVdnEpSV9gxqtnh6Qomfp3F0xT5qP/vThw==", "dev": true, + "license": "BSD-3-Clause", "engines": { "node": ">=0.8.0" } @@ -7133,6 +7287,7 @@ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, + "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" @@ -7149,6 +7304,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -7158,6 +7314,7 @@ "resolved": "https://registry.npmjs.org/import-from/-/import-from-4.0.0.tgz", "integrity": "sha512-P9J71vT5nLlDeV8FHs5nNxaLbrpfAV5cF5srvbZfpwpcJoM/xZR3hiv+q+SAnuSmuGbXMWud063iIMx/V/EWZQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=12.2" }, @@ -7165,11 +7322,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/import-meta-resolve": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.1.0.tgz", + "integrity": "sha512-I6fiaX09Xivtk+THaMfAwnA3MVA5Big1WHF1Dfx9hFuvNIWpXnorlkzhcQf6ehrqQiiZECRt1poOAkPmer3ruw==", + "dev": true, + "license": "MIT", + "optional": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wooorm" + } + }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.8.19" } @@ -7179,6 +7349,7 @@ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -7189,13 +7360,16 @@ "integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==", "engines": [ "node >= 0.4.0" - ] + ], + "license": "MIT" }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, + "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" @@ -7204,19 +7378,26 @@ "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "license": "ISC" }, "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.1.tgz", + "integrity": "sha512-QQnnxNyfvmHFIsj7gkPcYymR8Jdw/o7mp5ZFihxn6h8Ci6fh3Dx4E1gPjpQEpIuPo9XVNY/ZUwh4BPMjGyL01g==", + "dev": true, + "license": "ISC", + "optional": true, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } }, "node_modules/inquirer": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.5.tgz", - "integrity": "sha512-QAgPDQMEgrDssk1XiwwHoOGYF9BAbUcc1+j+FhEvaOt8/cKRqyLn0U5qA6F74fGhTMGxf92pOvPBeh29jQJDTQ==", + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^4.2.1", "chalk": "^4.1.1", @@ -7232,90 +7413,21 @@ "string-width": "^4.1.0", "strip-ansi": "^6.0.0", "through": "^2.3.6", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/inquirer/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/inquirer/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/inquirer/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/inquirer/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/inquirer/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" + "wrap-ansi": "^6.0.1" }, "engines": { - "node": ">=8" + "node": ">=12.0.0" } }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", + "es-errors": "^1.3.0", + "hasown": "^2.0.0", "side-channel": "^1.0.4" }, "engines": { @@ -7327,6 +7439,7 @@ "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", "dev": true, + "license": "MIT", "dependencies": { "loose-envify": "^1.0.0" } @@ -7335,6 +7448,7 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -7344,6 +7458,7 @@ "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-1.0.0.tgz", "integrity": "sha512-dOWoqflvcydARa360Gvv18DZ/gRuHKi2NU/wU5X1ZFzdYfH29nkiNZsF3mp4OJ3H4yo9Mx8A/uAGNzpzPN3yBA==", "dev": true, + "license": "MIT", "dependencies": { "is-relative": "^1.0.0", "is-windows": "^1.0.1" @@ -7353,14 +7468,17 @@ } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "get-intrinsic": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7370,13 +7488,15 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-bigint": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", "dev": true, + "license": "MIT", "dependencies": { "has-bigints": "^1.0.1" }, @@ -7389,6 +7509,7 @@ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", "dev": true, + "license": "MIT", "dependencies": { "binary-extensions": "^2.0.0" }, @@ -7401,6 +7522,7 @@ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -7417,6 +7539,7 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7425,12 +7548,32 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.14.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.14.0.tgz", + "integrity": "sha512-a5dFJih5ZLYlRtDc0dZWP7RiKr6xIKzmn/oAYCDvdLThadVgyJwlaoQPmRtMSpz+rk0OGAgIu+TcM9HUF0fk1A==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7441,6 +7584,7 @@ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -7456,6 +7600,7 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7465,6 +7610,7 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -7474,6 +7620,7 @@ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, + "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, @@ -7486,6 +7633,7 @@ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -7495,15 +7643,17 @@ "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz", "integrity": "sha512-bVcMJy4X5Og6VZfdOZstSexlEy20Sr0k/p/b2IlQJlfdKAQuMpiv5w2Ccxb8sKdRUNAG1PnHVHjFSdRDVS6NlQ==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -7516,6 +7666,7 @@ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -7525,6 +7676,7 @@ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -7540,6 +7692,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -7549,6 +7702,7 @@ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-tostringtag": "^1.0.0" @@ -7565,6 +7719,7 @@ "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", "integrity": "sha512-Kw/ReK0iqwKeu0MITLFuj0jbPAmEiOsIwyIXvvbfa6QfmN9pkD1M+8pdk7Rl/dTKbH34/XBFMbgD4iMJhLQbGA==", "dev": true, + "license": "MIT", "dependencies": { "is-unc-path": "^1.0.0" }, @@ -7573,12 +7728,16 @@ } }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -7589,6 +7748,7 @@ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, + "license": "MIT", "dependencies": { "has-tostringtag": "^1.0.0" }, @@ -7604,6 +7764,7 @@ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, + "license": "MIT", "dependencies": { "has-symbols": "^1.0.2" }, @@ -7615,12 +7776,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -7634,6 +7796,7 @@ "resolved": "https://registry.npmjs.org/is-unc-path/-/is-unc-path-1.0.0.tgz", "integrity": "sha512-mrGpVd0fs7WWLfVsStvgF6iEJnbjDFZh9/emhRDcGWTduTfNHd9CHeUwH3gYIjdbwo4On6hunkztwOaAw0yllQ==", "dev": true, + "license": "MIT", "dependencies": { "unc-path-regex": "^0.1.2" }, @@ -7646,6 +7809,7 @@ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -7658,6 +7822,7 @@ "resolved": "https://registry.npmjs.org/is-upper-case/-/is-upper-case-2.0.2.tgz", "integrity": "sha512-44pxmxAvnnAOwBg4tHPnkfvgjPwbc5QIsSstNU+YcJ1ovxVzCWpSGosPJOZh/a1tdl81fbgnLc9LLv+x2ywbPQ==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } @@ -7666,13 +7831,15 @@ "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/is-weakref": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2" }, @@ -7685,6 +7852,7 @@ "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -7693,19 +7861,22 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/isomorphic-ws": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", "dev": true, + "license": "MIT", "peerDependencies": { "ws": "*" } @@ -7714,22 +7885,25 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/jiti": { - "version": "1.20.0", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.20.0.tgz", - "integrity": "sha512-3TV69ZbrvV6U5DfQimop50jE9Dl6J8O1ja1dvBbMba/sZ3YBEQqJ2VZRoQPVnhlzjNtU1vaXRZVrVjU4qtm8yA==", + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", "dev": true, + "license": "MIT", "bin": { "jiti": "bin/jiti.js" } }, "node_modules/jose": { - "version": "4.15.3", - "resolved": "https://registry.npmjs.org/jose/-/jose-4.15.3.tgz", - "integrity": "sha512-RZJdL9Qjd1sqNdyiVteRGV/bnWtik/+PJh1JP4kT6+x1QQMn+7ryueRys5BEueuayvSVY8CWGCisCDazeRLTuw==", + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/jose/-/jose-5.6.3.tgz", + "integrity": "sha512-1Jh//hEEwMhNYPDDLwXHa2ePWgWiFNNUadVmguAAw2IJ6sj9mNxV5tGXJNqlMkJAybF6Lgw1mISDxTePP/187g==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/panva" } @@ -7738,19 +7912,22 @@ "version": "0.8.0", "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", "dev": true, + "license": "MIT", "dependencies": { "argparse": "^2.0.1" }, @@ -7763,6 +7940,7 @@ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -7774,44 +7952,37 @@ "version": "3.0.1", "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", "dev": true, + "license": "MIT", "optional": true }, - "node_modules/json-stable-stringify": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.0.2.tgz", - "integrity": "sha512-eunSSaEnxV12z+Z73y/j5N37/In40GK4GmsSy+tEHJMxknvqnA7/djeYtAgW0GsWHUfg+847WJjKaEylk2y09g==", - "dev": true, - "dependencies": { - "jsonify": "^0.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/json-to-pretty-yaml": { "version": "1.2.2", "resolved": "https://registry.npmjs.org/json-to-pretty-yaml/-/json-to-pretty-yaml-1.2.2.tgz", "integrity": "sha512-rvm6hunfCcqegwYaG5T4yKJWxc9FXFgBVrcTZ4XfSVRwa5HA/Xs+vB/Eo9treYYHCeNM0nrSUr82V/M31Urc7A==", "dev": true, + "license": "Apache-2.0", "dependencies": { "remedial": "^1.0.7", "remove-trailing-spaces": "^1.0.6" @@ -7821,15 +7992,16 @@ } }, "node_modules/json5": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", - "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, - "dependencies": { - "minimist": "^1.2.0" - }, + "license": "MIT", "bin": { "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" } }, "node_modules/jsonfile": { @@ -7837,6 +8009,7 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", "dev": true, + "license": "MIT", "dependencies": { "universalify": "^2.0.0" }, @@ -7844,20 +8017,12 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/jsonify": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz", - "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==", - "dev": true, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/keyv": { - "version": "4.5.3", - "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.3.tgz", - "integrity": "sha512-QCiSav9WaX1PgETJ+SpNnx2PRRapJ/oRSXM4VO5OGYGSjrxbKPVFVhB3l2OCbLCk329N8qyAtsJjSjvVBWzEug==", + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", "dev": true, + "license": "MIT", "dependencies": { "json-buffer": "3.0.1" } @@ -7867,6 +8032,7 @@ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1", "type-check": "~0.4.0" @@ -7879,13 +8045,15 @@ "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/listr2": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/listr2/-/listr2-4.0.5.tgz", "integrity": "sha512-juGHV1doQdpNT3GSTs9IUN43QJb7KHdF9uqg7Vufs/tG9VTzpFphqF4pm/ICdAABGQxsyNn9CiYA3StkI6jpwA==", "dev": true, + "license": "MIT", "dependencies": { "cli-truncate": "^2.1.0", "colorette": "^2.0.16", @@ -7908,11 +8076,30 @@ } } }, + "node_modules/listr2/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, + "license": "MIT", "dependencies": { "p-locate": "^5.0.0" }, @@ -7926,50 +8113,58 @@ "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "license": "MIT" }, "node_modules/lodash.camelcase": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/lodash.map": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", "integrity": "sha512-worNHGKLDetmcEYDvh2stPCrrQRkP20E4l0iIS7F8EvzMqBBi7ltvFN5m1HvTf1P7Jk1txKhvFcmYsCr8O2F1Q==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/lodash.mergewith": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.2.tgz", "integrity": "sha512-GK3g5RPZWTRSeLSpgP8Xhra+pnjBC56q9FZYe1d5RN3TJ35dbkGy3YqBSMbyCrlbi+CM9Z3Jk5yTL7RCsqboyQ==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/lodash.sortby": { "version": "4.7.0", "resolved": "https://registry.npmjs.org/lodash.sortby/-/lodash.sortby-4.7.0.tgz", - "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==" + "integrity": "sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==", + "license": "MIT" }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true, + "license": "MIT", "optional": true }, "node_modules/log-symbols": { @@ -7977,6 +8172,7 @@ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", "dev": true, + "license": "MIT", "dependencies": { "chalk": "^4.1.0", "is-unicode-supported": "^0.1.0" @@ -7988,81 +8184,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-symbols/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/log-symbols/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-symbols/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/log-symbols/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/log-symbols/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/log-update": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", "dev": true, + "license": "MIT", "dependencies": { "ansi-escapes": "^4.3.0", "cli-cursor": "^3.1.0", @@ -8076,44 +8203,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/log-update/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/log-update/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/log-update/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/log-update/node_modules/slice-ansi": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -8126,24 +8221,11 @@ "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/loglevel": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.1.tgz", - "integrity": "sha512-tCRIJM51SHjAayKwC+QAg8hT8vg6z7GSgLJKGvzuPb1Wc+hLzqtuVLxp6/HzSPOozuK+8ErAhy7U/sVzw8Dgfg==", + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.9.1.tgz", + "integrity": "sha512-hP3I3kCrDIMuRwAwHltphhDM1r8i55H33GgqjXbrisuJhF4kRhW1dNuxsRklp4bXl8DSdLaNLuiL4A/LWRfxvg==", + "license": "MIT", "engines": { "node": ">= 0.6.0" }, @@ -8155,13 +8237,15 @@ "node_modules/long": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", - "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "license": "Apache-2.0" }, "node_modules/longest": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", "integrity": "sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8171,6 +8255,7 @@ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", "dev": true, + "license": "MIT", "dependencies": { "js-tokens": "^3.0.0 || ^4.0.0" }, @@ -8183,6 +8268,7 @@ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz", "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } @@ -8192,33 +8278,26 @@ "resolved": "https://registry.npmjs.org/lower-case-first/-/lower-case-first-2.0.2.tgz", "integrity": "sha512-EVm/rR94FJTZi3zefZ82fLWab+GX14LJN4HrWBcuo6Evmsl9hEfnqxgcHCKb9q+mNf6EVdsjx/qucYFIIB84pg==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } }, "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, - "node_modules/make-error": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", - "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", - "dev": true, - "optional": true - }, "node_modules/map-cache": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz", "integrity": "sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8227,6 +8306,7 @@ "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8235,18 +8315,21 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/merge-descriptors": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", - "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==", + "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -8256,6 +8339,7 @@ "resolved": "https://registry.npmjs.org/meros/-/meros-1.3.0.tgz", "integrity": "sha512-2BNGOimxEz5hmjUG2FwoxCt5HN7BXdaWyFqEwxPTrJzVdABtrL4TiHTcsWSFAxPQ/tOnEaQEJh3qWq71QRMY+w==", "dev": true, + "license": "MIT", "engines": { "node": ">=13" }, @@ -8272,17 +8356,19 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/micromatch": { - "version": "4.0.5", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", - "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.7.tgz", + "integrity": "sha512-LPP/3KorzCwBxfeUuZmaR6bG2kdeHSbe0P2tY3FLRU4vYrjYz5hI4QZwV0njUx3jeuKe67YukQ1LSPZBKDqO/Q==", "dev": true, + "license": "MIT", "dependencies": { - "braces": "^3.0.2", + "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { @@ -8293,6 +8379,7 @@ "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", "bin": { "mime": "cli.js" }, @@ -8304,6 +8391,7 @@ "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8312,6 +8400,7 @@ "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, @@ -8324,20 +8413,25 @@ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { @@ -8345,6 +8439,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.7.tgz", "integrity": "sha512-bzfL1YUZsP41gmu/qjrEk0Q6i2ix/cVeAhbCbqH9u3zYutS1cLg00qhrD0M2MVdCcx4Sc0UpP2eBWo9rotpq6g==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8354,6 +8449,7 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, + "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, @@ -8362,17 +8458,19 @@ } }, "node_modules/moment": { - "version": "2.29.4", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz", - "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==", + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "license": "MIT", "engines": { "node": "*" } }, "node_modules/moment-timezone": { - "version": "0.5.43", - "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz", - "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==", + "version": "0.5.45", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.45.tgz", + "integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==", + "license": "MIT", "dependencies": { "moment": "^2.29.4" }, @@ -8383,24 +8481,28 @@ "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "license": "MIT" }, "node_modules/mute-stream": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/negotiator": { "version": "0.6.3", "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -8410,6 +8512,7 @@ "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==", "dev": true, + "license": "MIT", "dependencies": { "lower-case": "^2.0.2", "tslib": "^2.0.3" @@ -8418,12 +8521,14 @@ "node_modules/node-abort-controller": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -8443,22 +8548,25 @@ "version": "0.4.0", "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.13.tgz", - "integrity": "sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==", - "dev": true + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", + "dev": true, + "license": "MIT" }, "node_modules/nodemon": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.1.tgz", - "integrity": "sha512-g9AZ7HmkhQkqXkRc20w+ZfQ73cHLbE8hnPbtaFbFtCumZsjyMhKk9LajQ07U5Ux28lvFjZ5X7HvWR1xzU8jHVw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.1.4.tgz", + "integrity": "sha512-wjPBbFhtpJwmIeY2yP7QF+UKzPfltVGtfce1g/bB15/8vCGZj8uxD62b/b9M9/WVgme0NZudpownKN+c0plXlQ==", "dev": true, + "license": "MIT", "dependencies": { "chokidar": "^3.5.2", - "debug": "^3.2.7", + "debug": "^4", "ignore-by-default": "^1.0.1", "minimatch": "^3.1.2", "pstree.remy": "^1.1.8", @@ -8474,33 +8582,69 @@ "engines": { "node": ">=10" }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/nodemon" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/nodemon/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/nodemon/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" } }, - "node_modules/nodemon/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/nodemon/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "dev": true, - "dependencies": { - "ms": "^2.1.1" + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" } }, - "node_modules/nopt": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", - "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "node_modules/nodemon/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, + "license": "MIT", "dependencies": { - "abbrev": "1" - }, - "bin": { - "nopt": "bin/nopt.js" + "has-flag": "^3.0.0" }, "engines": { - "node": "*" + "node": ">=4" } }, "node_modules/normalize-path": { @@ -8508,6 +8652,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8516,20 +8661,26 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -8539,18 +8690,20 @@ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, @@ -8562,28 +8715,31 @@ } }, "node_modules/object.entries": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.7.tgz", - "integrity": "sha512-jCBs/0plmPsOnrKAfFQXRG2NFjlhZgjjcBLSmTnEhU8U6vVTsVe8ANeQJCHTl3gSsI4J+0emOoCgoKlmQPMgmA==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -8593,26 +8749,30 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.7.tgz", - "integrity": "sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz", + "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -8625,6 +8785,7 @@ "version": "2.4.1", "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", "dependencies": { "ee-first": "1.1.1" }, @@ -8637,6 +8798,7 @@ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, + "license": "ISC", "dependencies": { "wrappy": "1" } @@ -8646,6 +8808,7 @@ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, + "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, @@ -8657,17 +8820,18 @@ } }, "node_modules/optionator": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", - "integrity": "sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg==", + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", "dev": true, + "license": "MIT", "dependencies": { - "@aashutoshrathi/word-wrap": "^1.2.3", "deep-is": "^0.1.3", "fast-levenshtein": "^2.0.6", "levn": "^0.4.1", "prelude-ls": "^1.2.1", - "type-check": "^0.4.0" + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" }, "engines": { "node": ">= 0.8.0" @@ -8678,6 +8842,7 @@ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", "dev": true, + "license": "MIT", "dependencies": { "bl": "^4.1.0", "chalk": "^4.1.0", @@ -8696,81 +8861,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/ora/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ora/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ora/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ora/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ora/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ora/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/os-tmpdir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8780,6 +8876,7 @@ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, + "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, @@ -8795,6 +8892,7 @@ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, + "license": "MIT", "dependencies": { "p-limit": "^3.0.2" }, @@ -8810,6 +8908,7 @@ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, + "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, @@ -8825,20 +8924,17 @@ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, - "node_modules/packet-reader": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/packet-reader/-/packet-reader-1.0.0.tgz", - "integrity": "sha512-HAKu/fG3HpHFO0AA8WE8q2g+gBJaZ9MG7fcKk+IJPLTGAD6Psw4443l+9DGRbOIh3/aXr7Phy0TjilYivJo5XQ==" - }, "node_modules/param-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz", "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==", "dev": true, + "license": "MIT", "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -8849,6 +8945,7 @@ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, + "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, @@ -8861,6 +8958,7 @@ "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha512-FwdRXKCohSVeXqwtYonZTXtbGJKrn+HNyWDYVcp5yuJlesTwNH4rsmRZ+GrKAPJ5bLpRxESMeS+Rl0VCHRvB2Q==", "dev": true, + "license": "MIT", "dependencies": { "is-absolute": "^1.0.0", "map-cache": "^0.2.0", @@ -8875,6 +8973,7 @@ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, + "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", @@ -8893,6 +8992,7 @@ "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", "integrity": "sha512-1Y1A//QUXEZK7YKz+rD9WydcE1+EuPr6ZBgKecAB8tmoW6UFv0NREVJe1p+jRxtThkcbbKkfwIbWJe/IeE6m2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8901,6 +9001,7 @@ "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -8910,6 +9011,7 @@ "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz", "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==", "dev": true, + "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3" @@ -8920,6 +9022,7 @@ "resolved": "https://registry.npmjs.org/path-case/-/path-case-3.0.4.tgz", "integrity": "sha512-qO4qCFjXqVTrcbPt/hQfhTQ+VhFsqNKOPtytgNKkKxSoEp3XPUQ8ObFuePylOIok5gjn69ry8XiULxCwot3Wfg==", "dev": true, + "license": "MIT", "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -8930,6 +9033,7 @@ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8939,6 +9043,7 @@ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8948,6 +9053,7 @@ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -8956,13 +9062,15 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-root": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/path-root/-/path-root-0.1.1.tgz", "integrity": "sha512-QLcPegTHF11axjfojBIoDygmS2E3Lf+8+jI6wOVmNVenrKSo3mFdSGiIgdSHenczw3wPtlVMQaFVwGmM7BJdtg==", "dev": true, + "license": "MIT", "dependencies": { "path-root-regex": "^0.1.0" }, @@ -8975,6 +9083,7 @@ "resolved": "https://registry.npmjs.org/path-root-regex/-/path-root-regex-0.1.2.tgz", "integrity": "sha512-4GlJ6rZDhQZFE0DPVKh0e9jmZ5egZfxTkp7bcRDuPlJXbAwhxcl2dINPUAsjLdejqaLsCeg8axcLjIbvBjN4pQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -8982,27 +9091,28 @@ "node_modules/path-to-regexp": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", - "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==", + "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/pg": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/pg/-/pg-8.11.3.tgz", - "integrity": "sha512-+9iuvG8QfaaUrrph+kpF24cXkH1YOOUeArRNYIxq1viYHZagBxrTno7cecY1Fa44tJeZvaoG+Djpkc3JwehN5g==", - "dependencies": { - "buffer-writer": "2.0.0", - "packet-reader": "1.0.0", - "pg-connection-string": "^2.6.2", - "pg-pool": "^3.6.1", - "pg-protocol": "^1.6.0", + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/pg/-/pg-8.12.0.tgz", + "integrity": "sha512-A+LHUSnwnxrnL/tZ+OLfqR1SxLN3c/pgDztZ47Rpbsd4jUytsTtwQo/TLPRzPJMp/1pbhYVhH9cuSZLAajNfjQ==", + "license": "MIT", + "dependencies": { + "pg-connection-string": "^2.6.4", + "pg-pool": "^3.6.2", + "pg-protocol": "^1.6.1", "pg-types": "^2.1.0", "pgpass": "1.x" }, @@ -9025,38 +9135,44 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.1.1.tgz", "integrity": "sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==", + "license": "MIT", "optional": true }, "node_modules/pg-connection-string": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", - "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==" + "version": "2.6.4", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.4.tgz", + "integrity": "sha512-v+Z7W/0EO707aNMaAEfiGnGL9sxxumwLl2fJvCQtMn9Fxsg+lPpPkdcyBSv/KFgpGdYkMfn+EI1Or2EHjpgLCA==", + "license": "MIT" }, "node_modules/pg-int8": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz", "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==", + "license": "ISC", "engines": { "node": ">=4.0.0" } }, "node_modules/pg-pool": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.1.tgz", - "integrity": "sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==", + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.6.2.tgz", + "integrity": "sha512-Htjbg8BlwXqSBQ9V8Vjtc+vzf/6fVUuak/3/XXKA9oxZprwW3IMDQTGHP+KDmVL7rtd+R1QjbnCFPuTHm3G4hg==", + "license": "MIT", "peerDependencies": { "pg": ">=8.0" } }, "node_modules/pg-protocol": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.0.tgz", - "integrity": "sha512-M+PDm637OY5WM307051+bsDia5Xej6d9IR4GwJse1qA1DIhiKlksvrneZOYQq42OM+spubpcNYEo2FcKQrDk+Q==" + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.6.1.tgz", + "integrity": "sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==", + "license": "MIT" }, "node_modules/pg-types": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz", "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==", + "license": "MIT", "dependencies": { "pg-int8": "1.0.1", "postgres-array": "~2.0.0", @@ -9072,21 +9188,24 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz", "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==", + "license": "MIT", "dependencies": { "split2": "^4.1.0" } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==", + "dev": true, + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, + "license": "MIT", "engines": { "node": ">=8.6" }, @@ -9094,10 +9213,21 @@ "url": "https://github.com/sponsors/jonschlinkert" } }, + "node_modules/possible-typed-array-names": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", + "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/postgres-array": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz", "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==", + "license": "MIT", "engines": { "node": ">=4" } @@ -9106,6 +9236,7 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz", "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9114,6 +9245,7 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz", "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==", + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9122,6 +9254,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz", "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==", + "license": "MIT", "dependencies": { "xtend": "^4.0.0" }, @@ -9134,15 +9267,17 @@ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.8.0" } }, "node_modules/prettier": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.0.3.tgz", - "integrity": "sha512-L/4pUDMxcNa8R/EthV08Zt42WBO4h1rarVtK0K+QJG0X187OLo7l699jWw0GKuwzkPQ//jMFA/8Xm6Fh3J/DAg==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.3.2.tgz", + "integrity": "sha512-rAVeHYMcv8ATV5d508CFdn+8/pHPpXeIid1DdrPwXnaAdH7cqjVbpJaT5eq4yRAFU/lsbwYwSF/n5iNrdJHPQA==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin/prettier.cjs" }, @@ -9158,6 +9293,7 @@ "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.1.tgz", "integrity": "sha512-nolQXZ/4L+bP/UGlkfaIujX9BKxGwmQ9OT4mOt5yvy8iK1h3wqTEJCijzGANTCCl9nWjY41juyAn2K3Q1hLLTg==", "dev": true, + "license": "MIT", "dependencies": { "asap": "~2.0.3" } @@ -9166,6 +9302,7 @@ "version": "2.0.7", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz", "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==", + "license": "MIT", "dependencies": { "forwarded": "0.2.0", "ipaddr.js": "1.9.1" @@ -9178,22 +9315,22 @@ "version": "1.1.8", "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/punycode": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", - "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==", "dev": true, - "engines": { - "node": ">=6" - } + "license": "MIT" }, "node_modules/pvtsutils": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.5.tgz", "integrity": "sha512-ARvb14YB9Nm2Xi6nBq1ZX6dAM0FsJnuk+31aUp4TrcZEdKUlSqOqsxJHUPJDNE3qiIp+iUPEIeR6Je/tgV7zsA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.6.1" } @@ -9203,6 +9340,7 @@ "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.3.tgz", "integrity": "sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=6.0.0" } @@ -9211,6 +9349,7 @@ "version": "6.11.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "license": "BSD-3-Clause", "dependencies": { "side-channel": "^1.0.4" }, @@ -9239,12 +9378,14 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", "engines": { "node": ">= 0.6" } @@ -9253,6 +9394,7 @@ "version": "2.5.2", "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "license": "MIT", "dependencies": { "bytes": "3.1.2", "http-errors": "2.0.0", @@ -9268,6 +9410,7 @@ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, + "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", @@ -9282,6 +9425,7 @@ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", "dev": true, + "license": "MIT", "dependencies": { "picomatch": "^2.2.1" }, @@ -9294,25 +9438,29 @@ "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-2.0.0.tgz", "integrity": "sha512-EJ4UNY/U1t2P/2k6oqotuX2Cc3T6nxJwsM0N0asT7dhrtH1ltUxDn4NalSYmPE2rCkVpcf/X6R0wDwcFpzhd4w==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/regenerator-runtime": { - "version": "0.14.0", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.0.tgz", - "integrity": "sha512-srw17NI0TUWHuGa5CFGGmhfNIeja30WMBfbslPNhf6JrqQlLN5gcrvig1oqPxiVaXb0oW0XRKtH6Nngs5lKCIA==", - "dev": true + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "dev": true, + "license": "MIT" }, "node_modules/regexp.prototype.flags": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.0.tgz", - "integrity": "sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==", + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.2.tgz", + "integrity": "sha512-NcDiDkTLuPR+++OCKB0nWafEmhg/Da8aUPLPMQbK+bxKKCm1/S5he+AqYa4PlMCVBalb4/yxIRub6qkEx5yJbw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.6", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "set-function-name": "^2.0.1" }, "engines": { "node": ">= 0.4" @@ -9326,6 +9474,7 @@ "resolved": "https://registry.npmjs.org/relay-runtime/-/relay-runtime-12.0.0.tgz", "integrity": "sha512-QU6JKr1tMsry22DXNy9Whsq5rmvwr3LSZiiWV/9+DFpuTWvp+WFhobWMc8TC4OjKFfNhEZy7mOiqUAn5atQtug==", "dev": true, + "license": "MIT", "dependencies": { "@babel/runtime": "^7.0.0", "fbjs": "^3.0.0", @@ -9337,6 +9486,7 @@ "resolved": "https://registry.npmjs.org/remedial/-/remedial-1.0.8.tgz", "integrity": "sha512-/62tYiOe6DzS5BqVsNpH/nkGlX45C/Sp6V+NtiN6JQNS1Viay7cWkazmRkrQrdFj2eshDe96SIQNIoMxqhzBOg==", "dev": true, + "license": "(MIT OR Apache-2.0)", "engines": { "node": "*" } @@ -9345,19 +9495,22 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", "integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/remove-trailing-spaces": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/remove-trailing-spaces/-/remove-trailing-spaces-1.0.8.tgz", "integrity": "sha512-O3vsMYfWighyFbTd8hk8VaSj9UAGENxAtX+//ugIst2RMk5e03h6RoIS+0ylsFxY1gvmPuAY/PO4It+gPEeySA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -9367,6 +9520,7 @@ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", "dev": true, + "license": "MIT", "optional": true, "engines": { "node": ">=0.10.0" @@ -9376,13 +9530,15 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/resolve": { - "version": "1.22.4", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.4.tgz", - "integrity": "sha512-PXNdCiPqDqeUou+w1C2eTQbNfxKSuMxqTCuvlmmMsk1NWHL5fRrhY6Pl0qEYYc6+QqGClco1Qj8XnjPego4wfg==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, + "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", @@ -9400,6 +9556,7 @@ "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", "integrity": "sha512-R7uiTjECzvOsWSfdM0QKFNBVFcK27aHOUwdvK53BcW8zqnGdYp0Fbj82cy54+2A4P2tFM22J5kRfe1R+lM/1yg==", "dev": true, + "license": "MIT", "dependencies": { "expand-tilde": "^2.0.0", "global-modules": "^1.0.0" @@ -9413,19 +9570,7 @@ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-global": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", - "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", - "dev": true, - "optional": true, - "dependencies": { - "global-dirs": "^0.1.1" - }, + "license": "MIT", "engines": { "node": ">=8" } @@ -9435,6 +9580,7 @@ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, + "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" @@ -9447,6 +9593,7 @@ "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==", + "license": "MIT", "engines": { "node": ">= 4" } @@ -9454,29 +9601,34 @@ "node_modules/retry-as-promised": { "version": "7.0.4", "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.0.4.tgz", - "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==" + "integrity": "sha512-XgmCoxKWkDofwH8WddD0w85ZfqYz+ZHlr5yo+3YUCfycWawU56T5ckWXsScsj5B8tqUcIG67DxXByo3VUgiAdA==", + "license": "MIT" }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, + "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rfdc": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", - "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==", - "dev": true + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", + "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", + "dev": true, + "license": "MIT" }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "glob": "^7.1.3" }, @@ -9492,6 +9644,7 @@ "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -9515,6 +9668,7 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } @@ -9524,18 +9678,20 @@ "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", "dev": true, + "license": "Apache-2.0", "dependencies": { "tslib": "^2.1.0" } }, "node_modules/safe-array-concat": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.0.tgz", - "integrity": "sha512-9dVEFruWIsnie89yym+xWTAYASdpw3CJV7Li/6zBewGf9z2i1j31rP6jnY0pHEO4QZh6N0K11bFjWmdR8UGdPQ==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", "has-symbols": "^1.0.3", "isarray": "^2.0.5" }, @@ -9563,18 +9719,23 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/safe-regex-test": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", "is-regex": "^1.1.4" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -9582,32 +9743,31 @@ "node_modules/safer-buffer": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", - "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "license": "MIT" }, "node_modules/scuid": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz", "integrity": "sha512-MuCAyrGZcTLfQoH2XoBlQ8C6bzwN88XT/0slOGz0pn8+gIP85BOAfYa44ZXQUTOwRwPU0QvgU+V+OSajl/59Xg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" } }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "license": "MIT", "dependencies": { "debug": "2.6.9", "depd": "2.0.0", @@ -9631,6 +9791,7 @@ "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { "ms": "2.0.0" } @@ -9638,18 +9799,21 @@ "node_modules/send/node_modules/debug/node_modules/ms": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, "node_modules/send/node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" }, "node_modules/sentence-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", "integrity": "sha512-8LS0JInaQMCRoQ7YUytAo/xUu5W2XnQxV2HI/6uM6U7CITS1RqPElr30V6uIqyMKM9lJGRVFy5/4CuzcixNYSg==", "dev": true, + "license": "MIT", "dependencies": { "no-case": "^3.0.4", "tslib": "^2.0.3", @@ -9657,27 +9821,28 @@ } }, "node_modules/sequelize": { - "version": "6.32.1", - "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.32.1.tgz", - "integrity": "sha512-3Iv0jruv57Y0YvcxQW7BE56O7DC1BojcfIrqh6my+IQwde+9u/YnuYHzK+8kmZLhLvaziRT1eWu38nh9yVwn/g==", + "version": "6.37.3", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.3.tgz", + "integrity": "sha512-V2FTqYpdZjPy3VQrZvjTPnOoLm0KudCRXfGWp48QwhyPPp2yW8z0p0sCYZd/em847Tl2dVxJJ1DR+hF+O77T7A==", "funding": [ { "type": "opencollective", "url": "https://opencollective.com/sequelize" } ], + "license": "MIT", "dependencies": { "@types/debug": "^4.1.8", "@types/validator": "^13.7.17", "debug": "^4.3.4", - "dottie": "^2.0.4", + "dottie": "^2.0.6", "inflection": "^1.13.4", "lodash": "^4.17.21", "moment": "^2.29.4", "moment-timezone": "^0.5.43", - "pg-connection-string": "^2.6.0", + "pg-connection-string": "^2.6.1", "retry-as-promised": "^7.0.4", - "semver": "^7.5.1", + "semver": "^7.5.4", "sequelize-pool": "^7.1.0", "toposort-class": "^1.0.1", "uuid": "^8.3.2", @@ -9721,14 +9886,28 @@ "version": "7.1.0", "resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz", "integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==", + "license": "MIT", "engines": { "node": ">= 10.0.0" } }, + "node_modules/sequelize/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/sequelize/node_modules/uuid": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } @@ -9737,6 +9916,7 @@ "version": "1.15.0", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "license": "MIT", "dependencies": { "encodeurl": "~1.0.2", "escape-html": "~1.0.3", @@ -9751,23 +9931,60 @@ "version": "2.0.0", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true + "dev": true, + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", "integrity": "sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", - "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" }, "node_modules/sha.js": { "version": "2.4.11", "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "license": "(MIT AND BSD-3-Clause)", "dependencies": { "inherits": "^2.0.1", "safe-buffer": "^5.0.1" @@ -9781,6 +9998,7 @@ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, + "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, @@ -9793,6 +10011,7 @@ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9802,18 +10021,24 @@ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -9823,19 +10048,22 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/signedsource": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/signedsource/-/signedsource-1.0.0.tgz", "integrity": "sha512-6+eerH9fEnNmi/hyM1DXcRK3pWdoMQtlkQ+ns0ntzunjKqp5i3sKCc80ym8Fib3iaYhdJUOPdhlJWj1tvge2Ww==", - "dev": true + "dev": true, + "license": "BSD-3-Clause" }, "node_modules/simple-update-notifier": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", "dev": true, + "license": "MIT", "dependencies": { "semver": "^7.5.3" }, @@ -9843,11 +10071,25 @@ "node": ">=10" } }, + "node_modules/simple-update-notifier/node_modules/semver": { + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -9857,6 +10099,7 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "astral-regex": "^2.0.0", @@ -9866,44 +10109,12 @@ "node": ">=8" } }, - "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/slice-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/slice-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/snake-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/snake-case/-/snake-case-3.0.4.tgz", "integrity": "sha512-LAOh4z89bGQvl9pFfNF8V146i7o7/CqFPbqzYgP+yYzDIDeS9HaNFtXABamRW+AQzEVODcvE79ljJ+8a9YSdMg==", "dev": true, + "license": "MIT", "dependencies": { "dot-case": "^3.0.4", "tslib": "^2.0.3" @@ -9913,6 +10124,7 @@ "version": "4.2.0", "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz", "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==", + "license": "ISC", "engines": { "node": ">= 10.x" } @@ -9922,6 +10134,7 @@ "resolved": "https://registry.npmjs.org/sponge-case/-/sponge-case-1.0.1.tgz", "integrity": "sha512-dblb9Et4DAtiZ5YSUZHLl4XhH4uK80GhAZrVXdN4O2P4gQ40Wa5UIOPUHlA/nFd2PLblBZWUioLMMAVrgpoYcA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } @@ -9930,6 +10143,7 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -9948,6 +10162,7 @@ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, + "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } @@ -9956,19 +10171,22 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string-env-interpolation/-/string-env-interpolation-1.0.1.tgz", "integrity": "sha512-78lwMoCcn0nNu8LszbP1UA7g55OeE4v7rCeWnM5B453rnNr4aq+5it3FEYtZrSEiMvHZOZ9Jlqb0OD0M2VInqg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/string-format": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==", - "dev": true + "dev": true, + "license": "WTFPL OR MIT" }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", "dev": true, + "license": "MIT", "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -9979,14 +10197,16 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.7.tgz", - "integrity": "sha512-p6TmeT1T3411M8Cgg9wBTMRtY2q9+PNy9EV1i2lIXUN/btt763oIfxwN3RR8VU6wHX8j/1CFy0L+YuThm6bgOg==", + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -9996,28 +10216,33 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.6.tgz", - "integrity": "sha512-JySq+4mrPf9EsDBEDYMOb/lM7XQLulwg5R/m1r0PXEFqrV0qHvl58sdTilSXtKOflCsK2E8jxf+GKC0T07RWwQ==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.6.tgz", - "integrity": "sha512-omqjMDaY92pbn5HOX7f9IccLA+U1tA9GvtU4JrodiXFfYB7jPzzHpRzpglLAjtUV6bB557zwClJezTqnAiYnQA==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -10028,6 +10253,7 @@ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", "dev": true, + "license": "MIT", "dependencies": { "ansi-regex": "^5.0.1" }, @@ -10040,6 +10266,7 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10049,6 +10276,7 @@ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" }, @@ -10057,15 +10285,16 @@ } }, "node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, + "license": "MIT", "dependencies": { - "has-flag": "^3.0.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=4" + "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { @@ -10073,6 +10302,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -10085,6 +10315,7 @@ "resolved": "https://registry.npmjs.org/swap-case/-/swap-case-2.0.2.tgz", "integrity": "sha512-kc6S2YS/2yXbtkSMunBtKdah4VFETZ8Oh6ONSmSd9bRxhqTrtARUCBUiWXH3xVPpvR7tz2CSnkuXVE42EcGnMw==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } @@ -10094,6 +10325,7 @@ "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-1.0.2.tgz", "integrity": "sha512-qd/R7n5rQTRFi+Zf2sk5XVVd9UQl6ZkduPFC3S7WEGJAmetDTjY3qPN50eSKzwuzEyQKy5TN2TiZdkIjos2L6A==", "dev": true, + "license": "MIT", "dependencies": { "array-back": "^4.0.1", "deep-extend": "~0.6.0", @@ -10109,6 +10341,7 @@ "resolved": "https://registry.npmjs.org/array-back/-/array-back-4.0.2.tgz", "integrity": "sha512-NbdMezxqf94cnNfWLL7V/im0Ub+Anbb0IoZhvzie8+4HJ4nMQuzHuy49FkGYCJK2yAloZ3meiB6AVMClbrI1vg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10118,6 +10351,7 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -10126,19 +10360,22 @@ "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/through": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/title-case": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/title-case/-/title-case-3.0.3.tgz", "integrity": "sha512-e1zGYRvbffpcHIrnuqT0Dh+gEJtDaxDSoG4JAIpq4oDFyooziLBIiYQv0GBT4FUAnUop5uZ1hiIAj7oAF6sOCA==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } @@ -10148,6 +10385,7 @@ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, + "license": "MIT", "dependencies": { "os-tmpdir": "~1.0.2" }, @@ -10160,6 +10398,7 @@ "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } @@ -10169,6 +10408,7 @@ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, + "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -10180,6 +10420,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", "engines": { "node": ">=0.6" } @@ -10187,16 +10428,15 @@ "node_modules/toposort-class": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", - "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==" + "integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==", + "license": "MIT" }, "node_modules/touch": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", - "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.1.tgz", + "integrity": "sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==", "dev": true, - "dependencies": { - "nopt": "~1.0.10" - }, + "license": "ISC", "bin": { "nodetouch": "bin/nodetouch.js" } @@ -10204,15 +10444,17 @@ "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", - "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==" + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" }, "node_modules/ts-api-utils": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.2.tgz", - "integrity": "sha512-Cbu4nIqnEdd+THNEsBdkolnOXhg0I8XteoHaEKgvsxpsbWda4IsUut2c187HxywQCvveojow0Dgw/amxtSKVkQ==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16.13.0" + "node": ">=16" }, "peerDependencies": { "typescript": ">=4.2.0" @@ -10223,6 +10465,7 @@ "resolved": "https://registry.npmjs.org/ts-command-line-args/-/ts-command-line-args-2.5.1.tgz", "integrity": "sha512-H69ZwTw3rFHb5WYpQya40YAX2/w7Ut75uUECbgBIsLmM+BNuYnxsltfyyLMxy6sEeKxgijLTnQtLd0nKd6+IYw==", "dev": true, + "license": "ISC", "dependencies": { "chalk": "^4.1.0", "command-line-args": "^5.1.1", @@ -10233,81 +10476,12 @@ "write-markdown": "dist/write-markdown.js" } }, - "node_modules/ts-command-line-args/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/ts-command-line-args/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/ts-command-line-args/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/ts-command-line-args/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, - "node_modules/ts-command-line-args/node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/ts-command-line-args/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/ts-essentials": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-7.0.3.tgz", "integrity": "sha512-8+gr5+lqO3G84KdiTSMRLtuyJ+nTBVRKuCrK4lidMPdVeEp0uqC875uE5NMcaA7YYMN7XsNiFQuMvasF8HT/xQ==", "dev": true, + "license": "MIT", "peerDependencies": { "typescript": ">=3.7.0" } @@ -10316,57 +10490,15 @@ "version": "2.2.5", "resolved": "https://registry.npmjs.org/ts-log/-/ts-log-2.2.5.tgz", "integrity": "sha512-PGcnJoTBnVGy6yYNFxWVNkdcAuAMstvutN9MgDJIV6L0oG8fB+ZNNy1T+wJzah8RPGor1mZuPQkVfXNDpy9eHA==", - "dev": true - }, - "node_modules/ts-node": { - "version": "10.9.1", - "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.1.tgz", - "integrity": "sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw==", "dev": true, - "optional": true, - "dependencies": { - "@cspotcode/source-map-support": "^0.8.0", - "@tsconfig/node10": "^1.0.7", - "@tsconfig/node12": "^1.0.7", - "@tsconfig/node14": "^1.0.0", - "@tsconfig/node16": "^1.0.2", - "acorn": "^8.4.1", - "acorn-walk": "^8.1.1", - "arg": "^4.1.0", - "create-require": "^1.1.0", - "diff": "^4.0.1", - "make-error": "^1.1.1", - "v8-compile-cache-lib": "^3.0.1", - "yn": "3.1.1" - }, - "bin": { - "ts-node": "dist/bin.js", - "ts-node-cwd": "dist/bin-cwd.js", - "ts-node-esm": "dist/bin-esm.js", - "ts-node-script": "dist/bin-script.js", - "ts-node-transpile-only": "dist/bin-transpile.js", - "ts-script": "dist/bin-script-deprecated.js" - }, - "peerDependencies": { - "@swc/core": ">=1.2.50", - "@swc/wasm": ">=1.2.50", - "@types/node": "*", - "typescript": ">=2.7" - }, - "peerDependenciesMeta": { - "@swc/core": { - "optional": true - }, - "@swc/wasm": { - "optional": true - } - } + "license": "MIT" }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -10374,25 +10506,41 @@ "strip-bom": "^3.0.0" } }, + "node_modules/tsconfig-paths/node_modules/json5": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", + "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "minimist": "^1.2.0" + }, + "bin": { + "json5": "lib/cli.js" + } + }, "node_modules/tsconfig-paths/node_modules/strip-bom": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/tslib": { - "version": "2.6.2", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", - "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.3.tgz", + "integrity": "sha512-xNvxJEOUiWPGhUuUdQgAJPKOOJfGnIyKySOc09XkKsgdUV/3E2zvwZYdejjmRgPCgcym1juLH3226yA7sEFJKQ==", + "license": "0BSD" }, "node_modules/type-check": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", "dev": true, + "license": "MIT", "dependencies": { "prelude-ls": "^1.2.1" }, @@ -10401,10 +10549,11 @@ } }, "node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -10416,6 +10565,7 @@ "version": "1.6.18", "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", "dependencies": { "media-typer": "0.3.0", "mime-types": "~2.1.24" @@ -10429,6 +10579,7 @@ "resolved": "https://registry.npmjs.org/typechain/-/typechain-8.3.2.tgz", "integrity": "sha512-x/sQYr5w9K7yv3es7jo4KTX05CLxOf7TRWwoHlrjRh8H82G64g+k7VuWPJlgMo6qrjfCulOdfBjiaDtmhFYD/Q==", "dev": true, + "license": "MIT", "dependencies": { "@types/prettier": "^2.1.1", "debug": "^4.3.1", @@ -10448,11 +10599,23 @@ "typescript": ">=4.3.0" } }, + "node_modules/typechain/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, "node_modules/typechain/node_modules/fs-extra": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", "dev": true, + "license": "MIT", "dependencies": { "graceful-fs": "^4.1.2", "jsonfile": "^4.0.0", @@ -10466,7 +10629,9 @@ "version": "7.1.7", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.7.tgz", "integrity": "sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, + "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", @@ -10487,15 +10652,30 @@ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, + "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } }, + "node_modules/typechain/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/typechain/node_modules/prettier": { "version": "2.8.8", "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", "dev": true, + "license": "MIT", "bin": { "prettier": "bin-prettier.js" }, @@ -10511,34 +10691,38 @@ "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -10548,16 +10732,18 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -10567,24 +10753,32 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/typescript": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", - "integrity": "sha512-mI4WrpHsbCIcwT9cF4FZvr80QUeKvsUsUvKDoR+X/7XHQH98xYD8YHZg7ANtz2GtZt/CBq2QJ0thkGJMHfqc1w==", + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz", + "integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==", "dev": true, + "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -10598,14 +10792,15 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-4.0.0.tgz", "integrity": "sha512-VAH4IvQ7BDFYglMd7BPRDfLgxZZX4O4TFcRDA6EN5X7erNJJq+McIEp8np9aVtxrCJ6qx4GTYVfOWNjcqwZgRw==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/ua-parser-js": { - "version": "1.0.36", - "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.36.tgz", - "integrity": "sha512-znuyCIXzl8ciS3+y3fHJI/2OhQIXbXw9MWC/o3qwyR+RGppjZHrM27CGFSKCJXi2Kctiz537iOu2KnXs1lMQhw==", + "version": "1.0.38", + "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz", + "integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==", "dev": true, "funding": [ { @@ -10621,6 +10816,7 @@ "url": "https://github.com/sponsors/faisalman" } ], + "license": "MIT", "engines": { "node": "*" } @@ -10630,6 +10826,7 @@ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", "dev": true, + "license": "MIT", "dependencies": { "call-bind": "^1.0.2", "has-bigints": "^1.0.2", @@ -10645,6 +10842,7 @@ "resolved": "https://registry.npmjs.org/unc-path-regex/-/unc-path-regex-0.1.2.tgz", "integrity": "sha512-eXL4nmJT7oCpkZsHZUOJo8hcX3GbsiDOa0Qu9F646fi8dT3XuSVopVqAcEiVzSKKH7UoDti23wNX3qGFxcW5Qg==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10653,13 +10851,21 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", - "dev": true + "dev": true, + "license": "MIT" + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", + "license": "MIT" }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 10.0.0" } @@ -10669,6 +10875,7 @@ "resolved": "https://registry.npmjs.org/unixify/-/unixify-1.0.0.tgz", "integrity": "sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==", "dev": true, + "license": "MIT", "dependencies": { "normalize-path": "^2.1.1" }, @@ -10681,6 +10888,7 @@ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", "integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==", "dev": true, + "license": "MIT", "dependencies": { "remove-trailing-separator": "^1.0.1" }, @@ -10692,14 +10900,15 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", "engines": { "node": ">= 0.8" } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { @@ -10715,9 +10924,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -10731,6 +10941,7 @@ "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-2.0.2.tgz", "integrity": "sha512-KgdgDGJt2TpuwBUIjgG6lzw2GWFRCW9Qkfkiv0DxqHHLYJHmtmdUIKcZd8rHgFSjopVTlw6ggzCm1b8MFQwikg==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } @@ -10740,6 +10951,7 @@ "resolved": "https://registry.npmjs.org/upper-case-first/-/upper-case-first-2.0.2.tgz", "integrity": "sha512-514ppYHBaKwfJRK/pNC6c/OxfGa0obSnAl106u97Ed0I625Nin96KAjttZF6ZL3e1XLtphxnqrOi9iWgm+u+bg==", "dev": true, + "license": "MIT", "dependencies": { "tslib": "^2.0.3" } @@ -10749,49 +10961,62 @@ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, + "node_modules/uri-js/node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/urlpattern-polyfill": { "version": "8.0.2", "resolved": "https://registry.npmjs.org/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz", "integrity": "sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/utils-merge": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", "engines": { "node": ">= 0.4.0" } }, "node_modules/uuid": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.0.tgz", - "integrity": "sha512-MXcSTerfPa4uqyzStbRoTgt5XIe3x5+42+q1sDuy3R5MDk66URdLMOZe5aPX/SQd+kuYAh0FdP/pO28IkQyTeg==", + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", "bin": { "uuid": "dist/bin/uuid" } }, - "node_modules/v8-compile-cache-lib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", - "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", - "dev": true, - "optional": true - }, "node_modules/validator": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", - "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", + "license": "MIT", "engines": { "node": ">= 0.10" } @@ -10800,6 +11025,7 @@ "version": "1.0.12", "resolved": "https://registry.npmjs.org/value-or-promise/-/value-or-promise-1.0.12.tgz", "integrity": "sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==", + "license": "MIT", "engines": { "node": ">=12" } @@ -10808,6 +11034,7 @@ "version": "1.1.2", "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", "engines": { "node": ">= 0.8" } @@ -10817,41 +11044,46 @@ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", "dev": true, + "license": "MIT", "dependencies": { "defaults": "^1.0.3" } }, "node_modules/web-streams-polyfill": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz", - "integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz", + "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/webcrypto-core": { - "version": "1.7.7", - "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.7.7.tgz", - "integrity": "sha512-7FjigXNsBfopEj+5DV2nhNpfic2vumtjjgPmeDKk45z+MJwXKKfhPB7118Pfzrmh4jqOMST6Ch37iPAHoImg5g==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.0.tgz", + "integrity": "sha512-kR1UQNH8MD42CYuLzvibfakG5Ew5seG85dMMoAM/1LqvckxaF6pUiidLuraIu4V+YCIFabYecUZAW0TuxAoaqw==", "dev": true, + "license": "MIT", "dependencies": { - "@peculiar/asn1-schema": "^2.3.6", + "@peculiar/asn1-schema": "^2.3.8", "@peculiar/json-schema": "^1.1.12", "asn1js": "^3.0.1", - "pvtsutils": "^1.3.2", - "tslib": "^2.4.0" + "pvtsutils": "^1.3.5", + "tslib": "^2.6.2" } }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", - "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==" + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" }, "node_modules/whatwg-mimetype": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", + "license": "MIT", "engines": { "node": ">=12" } @@ -10860,6 +11092,7 @@ "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", "dependencies": { "tr46": "~0.0.3", "webidl-conversions": "^3.0.0" @@ -10870,6 +11103,7 @@ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, + "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, @@ -10885,6 +11119,7 @@ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", "dev": true, + "license": "MIT", "dependencies": { "is-bigint": "^1.0.1", "is-boolean-object": "^1.1.0", @@ -10900,19 +11135,21 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -10925,6 +11162,7 @@ "version": "0.5.0", "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz", "integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==", + "license": "MIT", "dependencies": { "@types/node": "*" } @@ -10934,6 +11172,7 @@ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } @@ -10943,6 +11182,7 @@ "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-4.0.1.tgz", "integrity": "sha512-kKlNACbvHrkpIw6oPeYDSmdCTu2hdMHoyXLTcUKala++lx5Y+wjJ/e474Jqv5abnVmwxw08DiTuHmw69lJGksA==", "dev": true, + "license": "MIT", "dependencies": { "reduce-flatten": "^2.0.0", "typical": "^5.2.0" @@ -10956,76 +11196,45 @@ "resolved": "https://registry.npmjs.org/typical/-/typical-5.2.0.tgz", "integrity": "sha512-dvdQgNDNJo+8B2uBQoqdb11eUCE1JQXhvjC/CZtgvZseVd5TYMXnq0+vuUemXbd/Se29cTaUuPX3YIc2xgbvIg==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", "strip-ansi": "^6.0.0" }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "dependencies": { - "color-convert": "^2.0.1" - }, "engines": { "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/wrap-ansi/node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" } }, - "node_modules/wrap-ansi/node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true - }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true + "dev": true, + "license": "ISC" }, "node_modules/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-BWX0SWVgLPzYwF8lTzEy1egjhS4S4OEAHfsO8o65WOVsrnSRGaSiUaa9e0ggGlkMTtBlmOpEXiie9RUcBO86qg==", + "version": "8.18.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", + "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "dev": true, + "license": "MIT", "engines": { "node": ">=10.0.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": "^5.0.2" + "utf-8-validate": ">=5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -11040,6 +11249,7 @@ "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", "engines": { "node": ">=0.4" } @@ -11049,20 +11259,27 @@ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" }, "node_modules/yaml": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.2.tgz", - "integrity": "sha512-N/lyzTPaJasoDmfV7YTrYCI0G/3ivm/9wdG0aHuheKowWQwGTsK0Eoiw6utmzAnI6pkJa0DUVygvp3spqqEKXg==", + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, "engines": { "node": ">= 14" } @@ -11071,13 +11288,15 @@ "version": "0.0.43", "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz", "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==", - "dev": true + "dev": true, + "license": "Apache-2.0" }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { "cliui": "^8.0.1", "escalade": "^3.1.1", @@ -11096,25 +11315,17 @@ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, + "license": "ISC", "engines": { "node": ">=12" } }, - "node_modules/yn": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", - "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", - "dev": true, - "optional": true, - "engines": { - "node": ">=6" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=10" }, @@ -11123,9 +11334,10 @@ } }, "node_modules/zod": { - "version": "3.23.4", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.4.tgz", - "integrity": "sha512-/AtWOKbBgjzEYYQRNfoGKHObgfAZag6qUJX1VbHo2PRBgS+wfWagEY2mizjfyAPcGesrJOcx/wcl0L9WnVrHFw==", + "version": "3.23.8", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz", + "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==", + "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/src/schema.ts b/src/schema.ts index 9615ea6..3ab32aa 100644 --- a/src/schema.ts +++ b/src/schema.ts @@ -27,10 +27,7 @@ const rootTypeDef = gql` ): MintedTokens! userById(accountId: ID!, chains: [SupportedChain!]): User! userByAddress(address: String!, chains: [SupportedChain!]): User! - streams( - where: StreamWhereInput - chains: [SupportedChain!] - ): [StreamChainData!]! + streams(where: StreamWhereInput, chains: [SupportedChain!]): [Stream!]! } `; diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index 0d82fe7..cd6f419 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -6,7 +6,7 @@ import { Driver } from '../generated/graphql'; import type { Context } from '../server'; import toResolverUser from '../user/userUtils'; import type { ProtoStream } from '../utils/buildAssetConfigs'; -import { chainToDbSchema } from '../utils/chainSchemaMappings'; +import { chainToDbSchema, dbSchemaToChain } from '../utils/chainSchemaMappings'; import shouldNeverHappen from '../utils/shouldNeverHappen'; import verifyStreamsInput from './streamValidators'; @@ -28,10 +28,12 @@ const streamResolvers = { where, ); - return Object.entries(streamsByChain).map(([chain, streams]) => ({ - chain, - data: streams, - })); + return Object.values(streamsByChain) + .flat() + .map((s) => ({ + ...s, + chain: dbSchemaToChain[s.chain], + })); }, }, Stream: { diff --git a/src/stream/streamTypeDef.ts b/src/stream/streamTypeDef.ts index b60edee..74fab73 100644 --- a/src/stream/streamTypeDef.ts +++ b/src/stream/streamTypeDef.ts @@ -38,11 +38,7 @@ const streamTypeDef = gql` timeline: [TimelineItem!]! createdAt: Date! endsAt: Date - } - - type StreamChainData { chain: SupportedChain! - data: [Stream!]! } input StreamWhereInput { From bb53668d8b693f66b6e5e4d489655460e1606442 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 5 Jul 2024 15:43:12 +0200 Subject: [PATCH 27/37] refactor: add base sepolia support --- src/common/commonTypeDef.ts | 5 +++-- src/common/constants.ts | 1 + src/common/dripsContracts.ts | 9 +++++++-- src/utils/chainSchemaMappings.ts | 2 ++ 4 files changed, 13 insertions(+), 4 deletions(-) diff --git a/src/common/commonTypeDef.ts b/src/common/commonTypeDef.ts index 2bcca8d..71e7e56 100644 --- a/src/common/commonTypeDef.ts +++ b/src/common/commonTypeDef.ts @@ -114,13 +114,13 @@ const commonTypeDef = gql` } union SupportItem = - DripListSupport + | DripListSupport | ProjectSupport | OneTimeDonationSupport | StreamSupport union Support = - DripListSupport + | DripListSupport | ProjectSupport | OneTimeDonationSupport | StreamSupport @@ -135,6 +135,7 @@ const commonTypeDef = gql` SEPOLIA OPTIMISM_SEPOLIA POLYGON_AMOY + BASE_SEPOLIA } type WithdrawableBalance { diff --git a/src/common/constants.ts b/src/common/constants.ts index 13ac75a..b1b2233 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -35,4 +35,5 @@ export const DB_SCHEMAS = [ 'sepolia', 'optimism_sepolia', 'polygon_amoy', + 'base_sepolia', ] as const; diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts index d4cb640..f151eb8 100644 --- a/src/common/dripsContracts.ts +++ b/src/common/dripsContracts.ts @@ -45,6 +45,11 @@ const chainConfigs: Record< addressDriverAddress: '0x004310a6d47893Dd6e443cbE471c24aDA1e6c619', repoDriverAddress: '0x54372850Db72915Fd9C5EC745683EB607b4a8642', }, + BASE_SEPOLIA: { + dripsAddress: '0xeebCd570e50fa31bcf6eF10f989429C87C3A6981', + addressDriverAddress: '0x004310a6d47893Dd6e443cbE471c24aDA1e6c619', + repoDriverAddress: '0x54372850Db72915Fd9C5EC745683EB607b4a8642', + }, }; const { rpcUrls } = appSettings; @@ -60,8 +65,8 @@ Object.values(SupportedChain).forEach((network) => { const provider = rpcUrl.startsWith('http') ? new JsonRpcProvider(rpcUrl) : rpcUrl.startsWith('wss') - ? new WebSocketProvider(rpcUrl) - : shouldNeverHappen(`Invalid RPC URL: ${rpcUrl}`); + ? new WebSocketProvider(rpcUrl) + : shouldNeverHappen(`Invalid RPC URL: ${rpcUrl}`); providers[network] = provider; } }); diff --git a/src/utils/chainSchemaMappings.ts b/src/utils/chainSchemaMappings.ts index 3583c09..4160409 100644 --- a/src/utils/chainSchemaMappings.ts +++ b/src/utils/chainSchemaMappings.ts @@ -6,6 +6,7 @@ export const dbSchemaToChain: Record = { sepolia: SupportedChain.SEPOLIA, optimism_sepolia: SupportedChain.OPTIMISM_SEPOLIA, polygon_amoy: SupportedChain.POLYGON_AMOY, + base_sepolia: SupportedChain.BASE_SEPOLIA, }; export const chainToDbSchema: Record = { @@ -13,4 +14,5 @@ export const chainToDbSchema: Record = { [SupportedChain.SEPOLIA]: 'sepolia', [SupportedChain.OPTIMISM_SEPOLIA]: 'optimism_sepolia', [SupportedChain.POLYGON_AMOY]: 'polygon_amoy', + [SupportedChain.BASE_SEPOLIA]: 'base_sepolia', }; From da6cc6e8c03fbccd7b02f576a31a0c5c321016e5 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 11 Jul 2024 13:32:05 +0200 Subject: [PATCH 28/37] fix: wrong identification of claimed projects and stream chain return type --- src/project/projectResolvers.ts | 8 ++++++-- src/stream/streamResolvers.ts | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 0288263..0e1584c 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -10,7 +10,7 @@ import { toResolverProjects, } from './projectUtils'; import shouldNeverHappen from '../utils/shouldNeverHappen'; -import { Driver } from '../generated/graphql'; +import { Driver, ProjectVerificationStatus } from '../generated/graphql'; import type { Source, RepoDriverAccount, @@ -139,7 +139,11 @@ const projectResolvers = { }, ProjectData: { __resolveType(parent: ProjectData) { - if ('claimedAt' in parent && !!parent.claimedAt) { + if ( + 'claimedAt' in parent && + !!parent.claimedAt && + parent.verificationStatus === ProjectVerificationStatus.Claimed + ) { return 'ClaimedProjectData'; } diff --git a/src/stream/streamResolvers.ts b/src/stream/streamResolvers.ts index cd6f419..51923df 100644 --- a/src/stream/streamResolvers.ts +++ b/src/stream/streamResolvers.ts @@ -32,11 +32,11 @@ const streamResolvers = { .flat() .map((s) => ({ ...s, - chain: dbSchemaToChain[s.chain], })); }, }, Stream: { + chain: ({ chain }: ProtoStream) => dbSchemaToChain[chain], receiver: async ( { chain, receiver }: ProtoStream, _: {}, From b5dff7818a7d526965d6b7c7eb3911d4a91e712a Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 11 Jul 2024 17:41:17 +0200 Subject: [PATCH 29/37] fix: correctly resolve user latest ipfs hash --- src/drip-list/dripListResolvers.ts | 4 ++-- src/project/projectResolvers.ts | 4 ++-- src/user/userResolvers.ts | 17 ++++++----------- src/utils/getLatestAccountMetadata.ts | 10 +++++++--- 4 files changed, 17 insertions(+), 18 deletions(-) diff --git a/src/drip-list/dripListResolvers.ts b/src/drip-list/dripListResolvers.ts index 95dd8c5..4df540f 100644 --- a/src/drip-list/dripListResolvers.ts +++ b/src/drip-list/dripListResolvers.ts @@ -23,7 +23,7 @@ import type { DripListDataValues } from './DripListModel'; import { resolveTotalEarned } from '../common/commonResolverLogic'; import { toResolverProject } from '../project/projectUtils'; import { chainToDbSchema } from '../utils/chainSchemaMappings'; -import { getLatestMetadataHash } from '../utils/getLatestAccountMetadata'; +import { getLatestMetadataHashOnChain } from '../utils/getLatestAccountMetadata'; const dripListResolvers = { Query: { @@ -295,7 +295,7 @@ const dripListResolvers = { latestMetadataIpfsHash: async ({ parentDripListInfo: { dripListChain, dripListId }, }: ResolverDripListData) => - getLatestMetadataHash(dripListId, [dripListChain]), + getLatestMetadataHashOnChain(dripListId, dripListChain), }, }; diff --git a/src/project/projectResolvers.ts b/src/project/projectResolvers.ts index 0e1584c..a9b4f37 100644 --- a/src/project/projectResolvers.ts +++ b/src/project/projectResolvers.ts @@ -34,7 +34,7 @@ import { resolveTotalEarned } from '../common/commonResolverLogic'; import { validateChainsQueryArg } from '../utils/commonInputValidators'; import { toResolverDripList } from '../drip-list/dripListUtils'; import { chainToDbSchema } from '../utils/chainSchemaMappings'; -import { getLatestMetadataHash } from '../utils/getLatestAccountMetadata'; +import { getLatestMetadataHashOnChain } from '../utils/getLatestAccountMetadata'; import getWithdrawableBalancesOnChain from '../utils/getWithdrawableBalances'; const projectResolvers = { @@ -378,7 +378,7 @@ const projectResolvers = { latestMetadataIpfsHash: async ({ parentProjectInfo: { projectId, projectChain }, }: ResolverUnClaimedProjectData) => - getLatestMetadataHash(projectId, [projectChain]), + getLatestMetadataHashOnChain(projectId, projectChain), }, UnClaimedProjectData: { verificationStatus: (projectData: ResolverUnClaimedProjectData) => diff --git a/src/user/userResolvers.ts b/src/user/userResolvers.ts index e5b155e..d26f2b3 100644 --- a/src/user/userResolvers.ts +++ b/src/user/userResolvers.ts @@ -19,7 +19,7 @@ import type { } from '../generated/graphql'; import { Driver } from '../generated/graphql'; import type { Context } from '../server'; -import assert, { isAddressDriverId } from '../utils/assert'; +import assert, { isAccountId, isAddressDriverId } from '../utils/assert'; import getAssetConfigs from '../utils/getAssetConfigs'; import getUserAddress from '../utils/getUserAddress'; import queryableChains from '../common/queryableChains'; @@ -28,7 +28,9 @@ import { toResolverDripList, toResolverDripLists, } from '../drip-list/dripListUtils'; -import getLatestAccountMetadataOnChain from '../utils/getLatestAccountMetadata'; +import getLatestAccountMetadataOnChain, { + getLatestMetadataHashOnChain, +} from '../utils/getLatestAccountMetadata'; import { validateChainsQueryArg } from '../utils/commonInputValidators'; import toResolverUser from './userUtils'; import { getCrossChainAddressDriverAccountIdByAddress } from '../common/dripsContracts'; @@ -47,7 +49,7 @@ const userResolvers = { chains, }: { accountId: AddressDriverId; chains?: SupportedChain[] }, ): ResolverUser => { - assert(isAddressDriverId(accountId)); + assert(isAccountId(accountId)); if (chains?.length) { validateChainsQueryArg(chains); } @@ -265,14 +267,7 @@ const userResolvers = { }, latestMetadataIpfsHash: async ({ parentUserInfo: { accountId, userChain }, - }: ResolverUserData) => { - const chainMetadata = await getLatestAccountMetadataOnChain( - [userChain], - accountId as AddressDriverId, - ); - - return chainMetadata[userChain]?.ipfsHash; - }, + }: ResolverUserData) => getLatestMetadataHashOnChain(accountId, userChain), }, UserStreams: { outgoing: async ( diff --git a/src/utils/getLatestAccountMetadata.ts b/src/utils/getLatestAccountMetadata.ts index 412f2ea..9c96670 100644 --- a/src/utils/getLatestAccountMetadata.ts +++ b/src/utils/getLatestAccountMetadata.ts @@ -61,12 +61,16 @@ export default async function getLatestAccountMetadataOnChain( return response; } -export async function getLatestMetadataHash( +export async function getLatestMetadataHashOnChain( accountId: AccountId, - chains: DbSchema[], + chain: DbSchema, ): Promise { + // Ordered by blockNumber and logIndex. const latestAccountMetadataEmittedEvent = - await accountMetadataEmittedEventsQueries.getByAccountId(chains, accountId); + await accountMetadataEmittedEventsQueries.getByAccountId( + [chain], + accountId, + ); if (!latestAccountMetadataEmittedEvent.length) { return undefined; From 96d2a163d745c28172054cb12e7c64f369718da8 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 11 Jul 2024 17:50:57 +0200 Subject: [PATCH 30/37] refactor: return non existing projects in DB as unclaimed --- src/dataLoaders/ProjectsDataSource.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 907ba37..06a0039 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -6,7 +6,10 @@ import type { ProjectId, ProjectMultiChainKey, } from '../common/types'; -import { toApiProject } from '../project/projectUtils'; +import { + toApiProject, + toFakeUnclaimedProjectFromUrl, +} from '../project/projectUtils'; import type { ProjectSortInput, ProjectWhereInput, @@ -92,7 +95,7 @@ export default class ProjectsDataSource { const dbProjects = await projectsQueries.getByUrl(chains, url); if (!dbProjects?.length) { - return null; + return [await toFakeUnclaimedProjectFromUrl(url)]; } if (dbProjects.some((p) => p.id !== dbProjects[0].id)) { From 4fb863722e57646357305b093e165e93551bfec4 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Tue, 20 Aug 2024 18:01:31 +0200 Subject: [PATCH 31/37] feat: add support for filecoin --- .gitignore | 1 + package.json | 5 +--- src/common/appSettings.ts | 35 +++++++++++++++++++----- src/common/commonTypeDef.ts | 1 + src/common/constants.ts | 1 + src/common/dripsContracts.ts | 47 +++++++++++++++++++++++++------- src/common/queryableChains.ts | 2 +- src/environment.d.ts | 20 +++++++++++--- src/utils/chainSchemaMappings.ts | 2 ++ 9 files changed, 88 insertions(+), 26 deletions(-) diff --git a/.gitignore b/.gitignore index 1ab05f7..ff5623f 100644 --- a/.gitignore +++ b/.gitignore @@ -79,6 +79,7 @@ web_modules/ .yarn-integrity # dotenv environment variable files +.env .env.* !.env.template diff --git a/package.json b/package.json index 7cc3d75..ceccdae 100644 --- a/package.json +++ b/package.json @@ -13,10 +13,7 @@ "build:graphql": "graphql-codegen", "build:contracts": "typechain --target=ethers-v6 --out-dir ./src/generated/contracts ./src/abi/**.json", "build": "npm run build:contracts && npm run build:graphql && tsc", - "start:local": "ENV=local npx nodemon", - "start:goerli": "ENV=goerli npx nodemon", - "start:sepolia": "ENV=sepolia npx nodemon", - "start:mainnet": "export ENV=mainnet && npm run build && node dist/index.js", + "dev": "npx nodemon", "start": "npm run build && node dist/index.js", "check": "tsc --noEmit" }, diff --git a/src/common/appSettings.ts b/src/common/appSettings.ts index 190990c..935946c 100644 --- a/src/common/appSettings.ts +++ b/src/common/appSettings.ts @@ -1,16 +1,37 @@ import dotenv from 'dotenv'; import type { SupportedChain } from '../generated/graphql'; -dotenv.config({ path: `.env.${process.env.ENV}` }); +dotenv.config(); + +type RpcConfig = { + url: string; + accessToken?: string; +}; export default { port: (process.env.PORT || 8080) as number, - rpcUrls: { - MAINNET: process.env.RPC_URL_MAINNET, - SEPOLIA: process.env.RPC_URL_SEPOLIA, - OPTIMISM_SEPOLIA: process.env.RPC_URL_OPTIMISM_SEPOLIA, - POLYGON_AMOY: process.env.RPC_URL_POLYGON_AMOY, - } as Record, + rpcConfigs: { + MAINNET: { + url: process.env.RPC_URL_MAINNET, + accessToken: process.env.RPC_ACCESS_TOKEN_MAINNET, + }, + SEPOLIA: { + url: process.env.RPC_URL_SEPOLIA, + accessToken: process.env.RPC_ACCESS_TOKEN_SEPOLIA, + }, + OPTIMISM_SEPOLIA: { + url: process.env.RPC_URL_OPTIMISM_SEPOLIA, + accessToken: process.env.RPC_ACCESS_TOKEN_OPTIMISM_SEPOLIA, + }, + POLYGON_AMOY: { + url: process.env.RPC_URL_POLYGON_AMOY, + accessToken: process.env.RPC_ACCESS_TOKEN_POLYGON_AMOY, + }, + FILECOIN: { + url: process.env.RPC_URL_FILECOIN, + accessToken: process.env.RPC_ACCESS_TOKEN_FILECOIN, + }, + } as Record, publicApiKeys: process.env.PUBLIC_API_KEYS?.split(',') || [], dripsApiKey: process.env.DRIPS_API_KEY, postgresConnectionString: process.env.POSTGRES_CONNECTION_STRING, diff --git a/src/common/commonTypeDef.ts b/src/common/commonTypeDef.ts index 71e7e56..dea1b26 100644 --- a/src/common/commonTypeDef.ts +++ b/src/common/commonTypeDef.ts @@ -136,6 +136,7 @@ const commonTypeDef = gql` OPTIMISM_SEPOLIA POLYGON_AMOY BASE_SEPOLIA + FILECOIN } type WithdrawableBalance { diff --git a/src/common/constants.ts b/src/common/constants.ts index b1b2233..c7dadcd 100644 --- a/src/common/constants.ts +++ b/src/common/constants.ts @@ -36,4 +36,5 @@ export const DB_SCHEMAS = [ 'optimism_sepolia', 'polygon_amoy', 'base_sepolia', + 'filecoin', ] as const; diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts index f151eb8..a0f64e8 100644 --- a/src/common/dripsContracts.ts +++ b/src/common/dripsContracts.ts @@ -1,4 +1,9 @@ -import { JsonRpcProvider, WebSocketProvider, ethers } from 'ethers'; +import { + FetchRequest, + JsonRpcProvider, + WebSocketProvider, + ethers, +} from 'ethers'; import appSettings from './appSettings'; import type { AddressDriver, Drips, RepoDriver } from '../generated/contracts'; import { @@ -50,23 +55,45 @@ const chainConfigs: Record< addressDriverAddress: '0x004310a6d47893Dd6e443cbE471c24aDA1e6c619', repoDriverAddress: '0x54372850Db72915Fd9C5EC745683EB607b4a8642', }, + FILECOIN: { + dripsAddress: '0x29252acF5a3dA105CB3aC245B7758F6e50281ba7', + addressDriverAddress: '0xE13A4f3671ee451F81Df3aa1AEb6653e4c33D5e0', + repoDriverAddress: '0x249e35aC49ccC4B1F0688Bc4c0bFA866a1b1E3fE', + }, }; -const { rpcUrls } = appSettings; +const { rpcConfigs } = appSettings; const providers: { [network in SupportedChain]?: JsonRpcProvider | WebSocketProvider; } = {}; +function createAuthFetchRequest(rpcUrl: string, token: string): FetchRequest { + const fetchRequest = new FetchRequest(rpcUrl); + fetchRequest.method = 'POST'; + fetchRequest.setHeader('Content-Type', 'application/json'); + fetchRequest.setHeader('Authorization', `Bearer ${token}`); + return fetchRequest; +} + Object.values(SupportedChain).forEach((network) => { - const rpcUrl = rpcUrls[network]; - if (rpcUrl) { - // eslint-disable-next-line no-nested-ternary - const provider = rpcUrl.startsWith('http') - ? new JsonRpcProvider(rpcUrl) - : rpcUrl.startsWith('wss') - ? new WebSocketProvider(rpcUrl) - : shouldNeverHappen(`Invalid RPC URL: ${rpcUrl}`); + const rpcConfig = rpcConfigs[network]; + + if (rpcConfig?.url) { + const rpcUrl = rpcConfig.url; + + let provider: JsonRpcProvider | WebSocketProvider | null = null; + + if (rpcUrl.startsWith('http')) { + provider = rpcConfig?.url + ? new JsonRpcProvider(createAuthFetchRequest(rpcUrl, rpcConfig?.url)) + : new JsonRpcProvider(rpcUrl); + } else if (rpcUrl.startsWith('wss')) { + provider = new WebSocketProvider(rpcUrl); + } else { + shouldNeverHappen(`Invalid RPC URL: ${rpcUrl}`); + } + providers[network] = provider; } }); diff --git a/src/common/queryableChains.ts b/src/common/queryableChains.ts index e8ae9cb..b512cff 100644 --- a/src/common/queryableChains.ts +++ b/src/common/queryableChains.ts @@ -7,7 +7,7 @@ import appSettings from './appSettings'; const queryableChains: SupportedChain[] = []; Object.keys(SupportedChain).forEach((chain) => { - if (appSettings.rpcUrls[chain as SupportedChain]) { + if (appSettings.rpcConfigs[chain as SupportedChain]) { queryableChains.push(chain as SupportedChain); } }); diff --git a/src/environment.d.ts b/src/environment.d.ts index c1d28b4..b98572b 100644 --- a/src/environment.d.ts +++ b/src/environment.d.ts @@ -4,10 +4,22 @@ declare global { namespace NodeJS { interface ProcessEnv { PORT: string; - RPC_URL_MAINNET: string; - RPC_URL_SEPOLIA: string; - RPC_URL_OPTIMISM_SEPOLIA: string; - RPC_URL_POLYGON_AMOY: string; + + RPC_URL_MAINNET: string | undefined; + RPC_ACCESS_TOKEN_MAINNET: string | undefined; + + RPC_URL_SEPOLIA: string | undefined; + RPC_ACCESS_TOKEN_SEPOLIA: string | undefined; + + RPC_URL_OPTIMISM_SEPOLIA: string | undefined; + RPC_ACCESS_TOKEN_OPTIMISM_SEPOLIA: string | undefined; + + RPC_URL_POLYGON_AMOY: string | undefined; + RPC_ACCESS_TOKEN_POLYGON_AMOY: string | undefined; + + RPC_URL_FILECOIN: string | undefined; + RPC_ACCESS_TOKEN_FILECOIN: string | undefined; + PUBLIC_API_KEYS: string; DRIPS_API_KEY: string; NODE_ENV: 'development' | 'production'; diff --git a/src/utils/chainSchemaMappings.ts b/src/utils/chainSchemaMappings.ts index 4160409..9c855d2 100644 --- a/src/utils/chainSchemaMappings.ts +++ b/src/utils/chainSchemaMappings.ts @@ -7,6 +7,7 @@ export const dbSchemaToChain: Record = { optimism_sepolia: SupportedChain.OPTIMISM_SEPOLIA, polygon_amoy: SupportedChain.POLYGON_AMOY, base_sepolia: SupportedChain.BASE_SEPOLIA, + filecoin: SupportedChain.FILECOIN, }; export const chainToDbSchema: Record = { @@ -15,4 +16,5 @@ export const chainToDbSchema: Record = { [SupportedChain.OPTIMISM_SEPOLIA]: 'optimism_sepolia', [SupportedChain.POLYGON_AMOY]: 'polygon_amoy', [SupportedChain.BASE_SEPOLIA]: 'base_sepolia', + [SupportedChain.FILECOIN]: 'filecoin', }; From 2871329ca288b7202883573c3579aa8817ef7089 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Tue, 20 Aug 2024 18:10:33 +0200 Subject: [PATCH 32/37] refactor: update the env template --- .env.template | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.env.template b/.env.template index e45c1df..ee22dde 100644 --- a/.env.template +++ b/.env.template @@ -4,9 +4,15 @@ NETWORK=string # Required. The network to connect to. See `SupportedChains` in # You should provide at least one of the following RPC URLs: RPC_URL_MAINNET=string # The RPC URL for the Mainnet provider. +RPC_ACCESS_TOKEN_MAINNET=string # Optional. The access token to use for the RPC. If specified, it will be used as a bearer token in the `Authorization` header. RPC_URL_SEPOLIA=string # The RPC URL for the Sepolia provider. +RPC_ACCESS_TOKEN_SEPOLIA=string # Optional. The access token to use for the RPC. If specified, it will be used as a bearer token in the `Authorization` header. RPC_URL_OPTIMISM_SEPOLIA=string # The RPC URL for the Optimism Sepolia provider. +RPC_ACCESS_TOKEN_OPTIMISM_SEPOLIA=string # Optional. The access token to use for the RPC. If specified, it will be used as a bearer token in the `Authorization` header. RPC_URL_POLYGON_AMOY=string # The RPC URL for the Polygon Amoy provider. +RPC_ACCESS_TOKEN_POLYGON_AMOY=string # Optional. The access token to use for the RPC. If specified, it will be used as a bearer token in the `Authorization` header. +RPC_URL_FILECOIN=string # The RPC URL for the Filecoin provider. +RPC_ACCESS_TOKEN_FILECOIN=string # Optional. The access token to use for the RPC. If specified, it will be used as a bearer token in the `Authorization` header. PUBLIC_API_KEYS=string # Required. Comma-separated list of strings API keys that rate limit is applied to. DRIPS_API_KEY=string # Required. API key withouth rate limit. From a6c9bcaa03c417076244885621e264d8088a41c9 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Wed, 21 Aug 2024 12:05:53 +0200 Subject: [PATCH 33/37] fix: wrong provider creation logic --- src/common/dripsContracts.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts index a0f64e8..c08af12 100644 --- a/src/common/dripsContracts.ts +++ b/src/common/dripsContracts.ts @@ -85,8 +85,10 @@ Object.values(SupportedChain).forEach((network) => { let provider: JsonRpcProvider | WebSocketProvider | null = null; if (rpcUrl.startsWith('http')) { - provider = rpcConfig?.url - ? new JsonRpcProvider(createAuthFetchRequest(rpcUrl, rpcConfig?.url)) + provider = rpcConfig?.accessToken + ? new JsonRpcProvider( + createAuthFetchRequest(rpcUrl, rpcConfig.accessToken), + ) : new JsonRpcProvider(rpcUrl); } else if (rpcUrl.startsWith('wss')) { provider = new WebSocketProvider(rpcUrl); From d5e43ea1428896d546691699bbd5582aa8877b9e Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Wed, 21 Aug 2024 15:07:11 +0200 Subject: [PATCH 34/37] fix: wrong project status calculation --- src/dataLoaders/ProjectsDataSource.ts | 10 ++++++++-- src/project/projectUtils.ts | 13 +++++++------ 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/src/dataLoaders/ProjectsDataSource.ts b/src/dataLoaders/ProjectsDataSource.ts index 06a0039..b2c847e 100644 --- a/src/dataLoaders/ProjectsDataSource.ts +++ b/src/dataLoaders/ProjectsDataSource.ts @@ -7,8 +7,9 @@ import type { ProjectMultiChainKey, } from '../common/types'; import { + doesRepoExists, toApiProject, - toFakeUnclaimedProjectFromUrl, + toProjectRepresentationFromUrl, } from '../project/projectUtils'; import type { ProjectSortInput, @@ -92,10 +93,15 @@ export default class ProjectsDataSource { chains: DbSchema[], ): Promise { // TODO: To Data Loader. + + if (!doesRepoExists(url)) { + return null; + } + const dbProjects = await projectsQueries.getByUrl(chains, url); if (!dbProjects?.length) { - return [await toFakeUnclaimedProjectFromUrl(url)]; + return [await toProjectRepresentationFromUrl(url)]; } if (dbProjects.some((p) => p.id !== dbProjects[0].id)) { diff --git a/src/project/projectUtils.ts b/src/project/projectUtils.ts index ecb63eb..4488084 100644 --- a/src/project/projectUtils.ts +++ b/src/project/projectUtils.ts @@ -55,7 +55,7 @@ export function toApiProject(project: ProjectDataValues) { return project; } - return toFakeUnclaimedProject(project); + return toProjectRepresentation(project); } function toForge(forge: string): Forge { @@ -69,7 +69,7 @@ function toForge(forge: string): Forge { } } -export async function toFakeUnclaimedProjectFromUrl(url: string) { +export async function toProjectRepresentationFromUrl(url: string) { const pattern = /^(?:https?:\/\/)?(?:www\.)?(github|gitlab)\.com\/([^\/]+)\/([^\/]+)/; // eslint-disable-line no-useless-escape const match = url.match(pattern); @@ -104,7 +104,7 @@ function toUrl(forge: Forge, projectName: string): string { } } -export async function toFakeUnclaimedProject( +export async function toProjectRepresentation( project: ProjectDataValues, ): Promise { const { name, forge } = project; @@ -116,7 +116,8 @@ export async function toFakeUnclaimedProject( name, forge, url: toUrl(forge, name), - verificationStatus: ProjectVerificationStatus.Unclaimed, + verificationStatus: + project.verificationStatus ?? ProjectVerificationStatus.Unclaimed, isValid: true, chain: project.chain, } as ProjectDataValues; @@ -214,7 +215,7 @@ export async function toResolverProjects( if (project.chain === chain) { return mapClaimedProjectChainData(project, chain, chains); } - const fakeUnclaimedProject = await toFakeUnclaimedProject(project); + const fakeUnclaimedProject = await toProjectRepresentation(project); return mapUnClaimedProjectChainData( fakeUnclaimedProject, @@ -275,7 +276,7 @@ export async function mergeProjects( ); } else { if (!projectOnChain) { - projectOnChain = await toFakeUnclaimedProjectFromUrl( + projectOnChain = await toProjectRepresentationFromUrl( projectBase.url!, ); } From f60f9058a88940efe57030fb6a779e017aa69db6 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Fri, 27 Sep 2024 17:22:49 +0300 Subject: [PATCH 35/37] fix: logic error when trying to get cross chain property --- src/common/dripsContracts.ts | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts index c08af12..bcd8799 100644 --- a/src/common/dripsContracts.ts +++ b/src/common/dripsContracts.ts @@ -137,7 +137,15 @@ export async function getCrossChainAddressDriverAccountIdByAddress( address: Address, ): Promise { // AddressDriver account IDs are the same across all chains. - const { addressDriver } = dripsContracts[queryableChains[0]]!; + const availableChain = queryableChains.find( + (chain) => dripsContracts[chain] && dripsContracts[chain]!.addressDriver, + ); + + if (!availableChain) { + throw new Error('No available chain with initialized contracts.'); + } + + const { addressDriver } = dripsContracts[availableChain]!; const accountId = (await addressDriver.calcAccountId(address)).toString(); @@ -149,7 +157,15 @@ export async function getCrossChainRepoDriverAccountIdByAddress( project: string, ): Promise { // RepoDriver account IDs are the same across all chains. - const { repoDriver } = dripsContracts[queryableChains[0]]!; + const availableChain = queryableChains.find( + (chain) => dripsContracts[chain] && dripsContracts[chain]!.repoDriver, + ); + + if (!availableChain) { + throw new Error('No available chain with initialized contracts.'); + } + + const { repoDriver } = dripsContracts[availableChain]!; const nameAsBytesLike = ethers.toUtf8Bytes(project); From 05b38247a0e544aac3e8eefabedad657ec4a5d00 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Thu, 3 Oct 2024 16:25:45 +0200 Subject: [PATCH 36/37] refactor: update Filecoin contract addresses --- src/common/dripsContracts.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/common/dripsContracts.ts b/src/common/dripsContracts.ts index bcd8799..bd6db99 100644 --- a/src/common/dripsContracts.ts +++ b/src/common/dripsContracts.ts @@ -56,9 +56,9 @@ const chainConfigs: Record< repoDriverAddress: '0x54372850Db72915Fd9C5EC745683EB607b4a8642', }, FILECOIN: { - dripsAddress: '0x29252acF5a3dA105CB3aC245B7758F6e50281ba7', - addressDriverAddress: '0xE13A4f3671ee451F81Df3aa1AEb6653e4c33D5e0', - repoDriverAddress: '0x249e35aC49ccC4B1F0688Bc4c0bFA866a1b1E3fE', + dripsAddress: '0x0B71C2a08d27E86d3841A6772332DEde0bc8DCa5', + addressDriverAddress: '0xEFcd912a5a67C3a7Cc70a2Fb9aa17781bf1cE68F', + repoDriverAddress: '0xf3aE6ADDeEE195e91380F5F9Ce73698460BAdf79', }, }; From fa82875a5a44e0d694cb94f49a0253b8cdfb6f66 Mon Sep 17 00:00:00 2001 From: Ioannis Tourkogiorgis Date: Mon, 7 Oct 2024 17:04:40 +0300 Subject: [PATCH 37/37] fix: rpc endpoint validation --- src/common/queryableChains.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/common/queryableChains.ts b/src/common/queryableChains.ts index b512cff..ea7efe2 100644 --- a/src/common/queryableChains.ts +++ b/src/common/queryableChains.ts @@ -7,7 +7,7 @@ import appSettings from './appSettings'; const queryableChains: SupportedChain[] = []; Object.keys(SupportedChain).forEach((chain) => { - if (appSettings.rpcConfigs[chain as SupportedChain]) { + if (appSettings.rpcConfigs[chain as SupportedChain]?.url) { queryableChains.push(chain as SupportedChain); } });