diff --git a/.cursorignore b/.cursorignore new file mode 100644 index 0000000..ac3f1b9 --- /dev/null +++ b/.cursorignore @@ -0,0 +1,6 @@ +# Add directories or file patterns to ignore during indexing (e.g. foo/ or *.csv) + +node_modules +dist +.next +.turbo diff --git a/.npmrc b/.npmrc index 347ae0d..3ad8959 100644 --- a/.npmrc +++ b/.npmrc @@ -1,2 +1,3 @@ +@cerc-io:registry=https://git.vdb.to/api/packages/cerc-io/npm/ legacy-peer-deps=true strict-peer-dependencies=false \ No newline at end of file diff --git a/apps/.gitignore b/apps/.gitignore new file mode 100644 index 0000000..39b2403 --- /dev/null +++ b/apps/.gitignore @@ -0,0 +1,41 @@ +# Dependencies +node_modules +.pnp +.pnp.js + +# Build outputs +dist +build +.next +out + +# Testing +coverage + +# Debug logs +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* + +# Environment +.env +.env.local +.env.development.local +.env.test.local +.env.production.local + +# IDE +.idea +.vscode/* +!.vscode/extensions.json +!.vscode/settings.json +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? + +# OS +.DS_Store +Thumbs.db \ No newline at end of file diff --git a/apps/backend/README.md b/apps/backend/README.md new file mode 100644 index 0000000..7fb3c8e --- /dev/null +++ b/apps/backend/README.md @@ -0,0 +1,76 @@ +# backend + +This backend is a [node.js](https://nodejs.org/) [express.js](https://expressjs.com/) [apollo server](https://www.apollographql.com/docs/apollo-server/) project in a [yarn workspace](https://yarnpkg.com/features/workspaces). + +## Getting Started + +### Install dependencies + +In the root of the project, run: + +```zsh +yarn +``` + +### Build backend + +```zsh +yarn build --ignore frontend +``` + +### Environment variables + +#### Local + +Copy the `environments/local.toml.example` file to `environments/local.toml`: + +```zsh +cp environments/local.toml.example environments/local.toml +``` + +#### Staging environment variables + +In the deployment repository, update staging [staging/configmaps/config/prod.toml](https://git.vdb.to/cerc-io/snowballtools-base-api-deployments/src/commit/318c2bc09f334dca79c3501838512749f9431bf1/deployments/staging/configmaps/config/prod.toml) + +#### Production environment variables + +In the deployment repository, update production [production/configmaps/config/prod.toml](https://git.vdb.to/cerc-io/snowballtools-base-api-deployments/src/commit/318c2bc09f334dca79c3501838512749f9431bf1/deployments/production/configmaps/config/prod.toml) + +### Run development server + +```zsh +yarn start +``` + +## Deployment + +Clone the [deployer repository](https://git.vdb.to/cerc-io/snowballtools-base-api-deployments): + +```zsh +git clone git@git.vdb.to:cerc-io/snowballtools-base-api-deployments.git +``` + +### Staging + +```zsh +echo trigger >> .gitea/workflows/triggers/staging-deploy +git commit -a -m "Deploy v0.0.8" # replace with version number +git push +``` + +### Production + +```zsh +echo trigger >> .gitea/workflows/triggers/production-deploy +git commit -a -m "Deploy v0.0.8" # replace with version number +git push +``` + +### Deployment status + +Dumb for now + +- [Staging](https://snowballtools-base-api.staging.apps.snowballtools.com/staging/version) +- [Production](https://snowballtools-base-api.apps.snowballtools.com/staging/version) + +Update version number manually in [routes/staging.ts](/packages/backend/src/routes/staging.ts) diff --git a/apps/backend/biome.json b/apps/backend/biome.json new file mode 100644 index 0000000..dd2cde3 --- /dev/null +++ b/apps/backend/biome.json @@ -0,0 +1,32 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.9.4/schema.json", + "formatter": { + "enabled": true, + "indentStyle": "space", + "indentWidth": 2, + "lineWidth": 80 + }, + "linter": { + "enabled": true, + "rules": { + "recommended": true, + "suspicious": { + "noExplicitAny": "off" + }, + "style": { + "noNonNullAssertion": "off" + } + } + }, + "javascript": { + "formatter": { + "enabled": true, + "quoteStyle": "single", + "trailingCommas": "none", + "semicolons": "asNeeded" + } + }, + "files": { + "ignore": ["dist/**/*", "node_modules/**/*", ".turbo/**/*"] + } +} diff --git a/apps/backend/environments/local.toml.example b/apps/backend/environments/local.toml.example new file mode 100644 index 0000000..233d495 --- /dev/null +++ b/apps/backend/environments/local.toml.example @@ -0,0 +1,43 @@ +[server] + host = "127.0.0.1" + port = 8000 + gqlPath = "/graphql" + [server.session] + secret = "" + # Frontend webapp URL origin + appOriginUrl = "http://localhost:3000" + # Set to true if server running behind proxy + trustProxy = false + # Backend URL hostname + domain = "localhost" + +[database] + dbPath = "db/snowball" + +[gitHub] + webhookUrl = "" + [gitHub.oAuth] + clientId = "" + clientSecret = "" + +[registryConfig] + fetchDeploymentRecordDelay = 5000 + checkAuctionStatusDelay = 5000 + restEndpoint = "http://localhost:1317" + gqlEndpoint = "http://localhost:9473/api" + chainId = "laconic_9000-1" + privateKey = "" + bondId = "" + authority = "" + [registryConfig.fee] + gas = "" + fees = "" + gasPrice = "1alnt" + +# Durations are set to 2 mins as deployers may take time with ongoing deployments and auctions +[auction] + commitFee = "100000" + commitsDuration = "120s" + revealFee = "100000" + revealsDuration = "120s" + denom = "alnt" diff --git a/apps/backend/package.json b/apps/backend/package.json new file mode 100644 index 0000000..fbf128c --- /dev/null +++ b/apps/backend/package.json @@ -0,0 +1,68 @@ +{ + "name": "@qwrk/backend", + "license": "UNLICENSED", + "version": "1.0.0", + "private": true, + "main": "./dist/index.js", + "types": "./dist/index.d.ts", + "dependencies": { + "@cerc-io/registry-sdk": "^0.2.11", + "@cosmjs/stargate": "^0.33.0", + "@graphql-tools/schema": "^10.0.2", + "@graphql-tools/utils": "^10.0.12", + "@octokit/oauth-app": "^6.1.0", + "@turnkey/sdk-server": "^0.1.0", + "@types/debug": "^4.1.5", + "@types/node": "^20.11.0", + "@types/semver": "^7.5.8", + "apollo-server-core": "^3.13.0", + "apollo-server-express": "^3.13.0", + "cookie-session": "^2.1.0", + "cors": "^2.8.5", + "debug": "^4.3.1", + "express": "^4.18.2", + "express-async-errors": "^3.1.1", + "express-session": "^1.18.0", + "fs-extra": "^11.2.0", + "graphql": "^16.8.1", + "luxon": "^3.5.0", + "nanoid": "3", + "nanoid-dictionary": "^5.0.0-beta.1", + "octokit": "^3.1.2", + "openpgp": "^6.0.1", + "reflect-metadata": "^0.2.1", + "semver": "^7.6.0", + "siwe": "^3.0.0", + "toml": "^3.0.0", + "ts-node": "^10.9.2", + "typeorm": "^0.3.19", + "typescript": "^5.3.3" + }, + "scripts": { + "start": "DEBUG=snowball:* node --enable-source-maps ./dist/index.js", + "start:dev": "DEBUG=snowball:* ts-node ./src/index.ts", + "copy-assets": "copyfiles -u 1 src/**/*.gql dist/", + "clean": "rm -rf ./dist", + "build": "pnpm clean && tsc && pnpm copy-assets", + "format": "biome format .", + "format:check": "biome format --check .", + "lint": "biome check .", + "test:registry:init": "DEBUG=snowball:* ts-node ./test/initialize-registry.ts", + "test:registry:publish-deploy-records": "DEBUG=snowball:* ts-node ./test/publish-deploy-records.ts", + "test:registry:publish-deployment-removal-records": "DEBUG=snowball:* ts-node ./test/publish-deployment-removal-records.ts", + "test:db:load:fixtures": "DEBUG=snowball:* ts-node ./test/initialize-db.ts", + "test:db:delete": "DEBUG=snowball:* ts-node ./test/delete-db.ts" + }, + "devDependencies": { + "@biomejs/biome": "1.9.4", + "@types/cookie-session": "^2.0.49", + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/express-session": "^1.17.10", + "@types/fs-extra": "^11.0.4", + "better-sqlite3": "^9.2.2", + "copyfiles": "^2.4.1", + "prettier": "^3.1.1", + "workspace": "^0.0.1-preview.1" + } +} diff --git a/apps/backend/src/config.ts b/apps/backend/src/config.ts new file mode 100644 index 0000000..53a071a --- /dev/null +++ b/apps/backend/src/config.ts @@ -0,0 +1,66 @@ +export interface SessionConfig { + secret: string + appOriginUrl: string + trustProxy: boolean + domain: string +} + +export interface ServerConfig { + host: string + port: number + gqlPath?: string + sessionSecret: string + appOriginUrl: string + isProduction: boolean + session: SessionConfig +} + +export interface DatabaseConfig { + dbPath: string +} + +export interface GitHubConfig { + webhookUrl: string + oAuth: { + clientId: string + clientSecret: string + } +} + +export interface RegistryConfig { + restEndpoint: string + gqlEndpoint: string + chainId: string + privateKey: string + bondId: string + fetchDeploymentRecordDelay: number + checkAuctionStatusDelay: number + authority: string + fee: { + gas: string + fees: string + gasPrice: string + } +} + +export interface AuctionConfig { + commitFee: string + commitsDuration: string + revealFee: string + revealsDuration: string + denom: string +} + +export interface Config { + server: ServerConfig + database: DatabaseConfig + gitHub: GitHubConfig + registryConfig: RegistryConfig + auction: AuctionConfig + turnkey: { + apiBaseUrl: string + apiPublicKey: string + apiPrivateKey: string + defaultOrganizationId: string + } +} diff --git a/apps/backend/src/constants.ts b/apps/backend/src/constants.ts new file mode 100644 index 0000000..be2a86e --- /dev/null +++ b/apps/backend/src/constants.ts @@ -0,0 +1,7 @@ +import process from 'node:process' + +export const DEFAULT_CONFIG_FILE_PATH = + process.env.SNOWBALL_BACKEND_CONFIG_FILE_PATH || + 'apps/backend/environments/local.toml' + +export const DEFAULT_GQL_PATH = '/graphql' diff --git a/apps/backend/src/database.ts b/apps/backend/src/database.ts new file mode 100644 index 0000000..6528bfe --- /dev/null +++ b/apps/backend/src/database.ts @@ -0,0 +1,694 @@ +import assert from 'node:assert' +import path from 'node:path' +import debug from 'debug' +import { customAlphabet } from 'nanoid' +import { lowercase, numbers } from 'nanoid-dictionary' +import { + DataSource, + type DeepPartial, + type FindManyOptions, + type FindOneOptions, + type FindOptionsWhere, + IsNull, + Not +} from 'typeorm' + +import type { DatabaseConfig } from './config' +import { Deployer } from './entity/Deployer' +import { Deployment, DeploymentStatus } from './entity/Deployment' +import { Domain } from './entity/Domain' +import { EnvironmentVariable } from './entity/EnvironmentVariable' +import { Organization } from './entity/Organization' +import { Project } from './entity/Project' +import { ProjectMember } from './entity/ProjectMember' +import { User } from './entity/User' +import { UserOrganization } from './entity/UserOrganization' +import type { DNSRecordAttributes } from './types' +import { getEntities, loadAndSaveData } from './utils' + +const ORGANIZATION_DATA_PATH = '../test/fixtures/organizations.json' + +const log = debug('snowball:database') + +const nanoid = customAlphabet(lowercase + numbers, 8) + +// TODO: Fix order of methods +export class Database { + private dataSource: DataSource + + constructor({ dbPath }: DatabaseConfig) { + this.dataSource = new DataSource({ + type: 'better-sqlite3', + database: dbPath, + entities: [path.join(__dirname, '/entity/*')], + synchronize: true, + logging: false + }) + } + + async init(): Promise { + await this.dataSource.initialize() + log('database initialized') + + let organizations = await this.getOrganizations({}) + + // Load an organization if none exist + if (!organizations.length) { + const orgEntities = await getEntities( + path.resolve(__dirname, ORGANIZATION_DATA_PATH) + ) + organizations = await loadAndSaveData(Organization, this.dataSource, [ + orgEntities[0] + ]) + } + + // Hotfix for updating old DB data + if (organizations[0].slug === 'snowball-tools-1') { + const [orgEntity] = await getEntities( + path.resolve(__dirname, ORGANIZATION_DATA_PATH) + ) + + await this.updateOrganization(organizations[0].id, { + slug: orgEntity.slug as string, + name: orgEntity.name as string + }) + } + } + + async getUser(options: FindOneOptions): Promise { + const userRepository = this.dataSource.getRepository(User) + const user = await userRepository.findOne(options) + + return user + } + + async addUser(data: DeepPartial): Promise { + const userRepository = this.dataSource.getRepository(User) + const user = await userRepository.save(data) + + return user + } + + async updateUser(user: User, data: DeepPartial): Promise { + const userRepository = this.dataSource.getRepository(User) + const updateResult = await userRepository.update({ id: user.id }, data) + assert(updateResult.affected) + + return updateResult.affected > 0 + } + + async getOrganizations( + options: FindManyOptions + ): Promise { + const organizationRepository = this.dataSource.getRepository(Organization) + const organizations = await organizationRepository.find(options) + + return organizations + } + + async getOrganization( + options: FindOneOptions + ): Promise { + const organizationRepository = this.dataSource.getRepository(Organization) + const organization = await organizationRepository.findOne(options) + + return organization + } + + async getOrganizationsByUserId(userId: string): Promise { + const organizationRepository = this.dataSource.getRepository(Organization) + + const userOrgs = await organizationRepository.find({ + where: { + userOrganizations: { + member: { + id: userId + } + } + } + }) + + return userOrgs + } + + async addUserOrganization( + data: DeepPartial + ): Promise { + const userOrganizationRepository = + this.dataSource.getRepository(UserOrganization) + const newUserOrganization = await userOrganizationRepository.save(data) + + return newUserOrganization + } + + async updateOrganization( + organizationId: string, + data: DeepPartial + ): Promise { + const organizationRepository = this.dataSource.getRepository(Organization) + const updateResult = await organizationRepository.update( + { id: organizationId }, + data + ) + assert(updateResult.affected) + + return updateResult.affected > 0 + } + + async getProjects(options: FindManyOptions): Promise { + const projectRepository = this.dataSource.getRepository(Project) + const projects = await projectRepository.find(options) + + return projects + } + + async getProjectById(projectId: string): Promise { + const projectRepository = this.dataSource.getRepository(Project) + + const project = await projectRepository + .createQueryBuilder('project') + .leftJoinAndSelect( + 'project.deployments', + 'deployments', + 'deployments.isCurrent = true AND deployments.isCanonical = true' + ) + .leftJoinAndSelect('deployments.createdBy', 'user') + .leftJoinAndSelect('deployments.deployer', 'deployer') + .leftJoinAndSelect('project.owner', 'owner') + .leftJoinAndSelect('project.deployers', 'deployers') + .leftJoinAndSelect('project.organization', 'organization') + .where('project.id = :projectId', { + projectId + }) + .getOne() + + return project + } + + async allProjectsWithoutDeployments(): Promise { + const allProjects = await this.getProjects({ + where: { + auctionId: Not(IsNull()) + }, + relations: ['deployments'], + withDeleted: true + }) + + const projects = allProjects.filter((project) => { + if (project.deletedAt !== null) return false + + return project.deployments.length === 0 + }) + + return projects + } + + async getProjectsInOrganization( + userId: string, + organizationSlug: string + ): Promise { + const projectRepository = this.dataSource.getRepository(Project) + + const projects = await projectRepository + .createQueryBuilder('project') + .leftJoinAndSelect( + 'project.deployments', + 'deployments', + 'deployments.isCurrent = true AND deployments.isCanonical = true' + ) + .leftJoin('project.projectMembers', 'projectMembers') + .leftJoin('project.organization', 'organization') + .where( + '(project.ownerId = :userId OR projectMembers.userId = :userId) AND organization.slug = :organizationSlug', + { + userId, + organizationSlug + } + ) + .getMany() + + return projects + } + + /** + * Get deployments with specified filter + */ + async getDeployments( + options: FindManyOptions + ): Promise { + const deploymentRepository = this.dataSource.getRepository(Deployment) + const deployments = await deploymentRepository.find(options) + + return deployments + } + + async getDeploymentsByProjectId(projectId: string): Promise { + return this.getDeployments({ + relations: { + project: true, + createdBy: true, + deployer: true + }, + where: { + project: { + id: projectId + } + }, + order: { + createdAt: 'DESC' + } + }) + } + + async getNonCanonicalDeploymentsByProjectId( + projectId: string + ): Promise { + return this.getDeployments({ + relations: { + project: true, + createdBy: true, + deployer: true + }, + where: { + project: { + id: projectId + }, + isCanonical: false + }, + order: { + createdAt: 'DESC' + } + }) + } + + async getDeployment( + options: FindOneOptions + ): Promise { + const deploymentRepository = this.dataSource.getRepository(Deployment) + const deployment = await deploymentRepository.findOne(options) + + return deployment + } + + async getDomains(options: FindManyOptions): Promise { + const domainRepository = this.dataSource.getRepository(Domain) + const domains = await domainRepository.find(options) + + return domains + } + + async addDeployment(data: DeepPartial): Promise { + const deploymentRepository = this.dataSource.getRepository(Deployment) + + const id = nanoid() + + const updatedData = { + ...data, + id + } + const deployment = await deploymentRepository.save(updatedData) + + return deployment + } + + async getProjectMembersByProjectId( + projectId: string + ): Promise { + const projectMemberRepository = this.dataSource.getRepository(ProjectMember) + + const projectMembers = await projectMemberRepository.find({ + relations: { + project: true, + member: true + }, + where: { + project: { + id: projectId + } + } + }) + + return projectMembers + } + + async getEnvironmentVariablesByProjectId( + projectId: string, + filter?: FindOptionsWhere + ): Promise { + const environmentVariableRepository = + this.dataSource.getRepository(EnvironmentVariable) + + const environmentVariables = await environmentVariableRepository.find({ + where: { + project: { + id: projectId + }, + ...filter + } + }) + + return environmentVariables + } + + async removeProjectMemberById(projectMemberId: string): Promise { + const projectMemberRepository = this.dataSource.getRepository(ProjectMember) + + const deleteResult = await projectMemberRepository.delete({ + id: projectMemberId + }) + + if (deleteResult.affected) { + return deleteResult.affected > 0 + } + + return false + } + + async updateProjectMemberById( + projectMemberId: string, + data: DeepPartial + ): Promise { + const projectMemberRepository = this.dataSource.getRepository(ProjectMember) + const updateResult = await projectMemberRepository.update( + { id: projectMemberId }, + data + ) + + return Boolean(updateResult.affected) + } + + async addProjectMember( + data: DeepPartial + ): Promise { + const projectMemberRepository = this.dataSource.getRepository(ProjectMember) + const newProjectMember = await projectMemberRepository.save(data) + + return newProjectMember + } + + async addEnvironmentVariables( + data: DeepPartial[] + ): Promise { + const environmentVariableRepository = + this.dataSource.getRepository(EnvironmentVariable) + const savedEnvironmentVariables = + await environmentVariableRepository.save(data) + + return savedEnvironmentVariables + } + + async updateEnvironmentVariable( + environmentVariableId: string, + data: DeepPartial + ): Promise { + const environmentVariableRepository = + this.dataSource.getRepository(EnvironmentVariable) + const updateResult = await environmentVariableRepository.update( + { id: environmentVariableId }, + data + ) + + return Boolean(updateResult.affected) + } + + async deleteEnvironmentVariable( + environmentVariableId: string + ): Promise { + const environmentVariableRepository = + this.dataSource.getRepository(EnvironmentVariable) + const deleteResult = await environmentVariableRepository.delete({ + id: environmentVariableId + }) + + if (deleteResult.affected) { + return deleteResult.affected > 0 + } + + return false + } + + async getProjectMemberById(projectMemberId: string): Promise { + const projectMemberRepository = this.dataSource.getRepository(ProjectMember) + + const projectMemberWithProject = await projectMemberRepository.find({ + relations: { + project: { + owner: true + }, + member: true + }, + where: { + id: projectMemberId + } + }) + + if (projectMemberWithProject.length === 0) { + throw new Error('Member does not exist') + } + + return projectMemberWithProject[0] + } + + async getProjectsBySearchText( + userId: string, + searchText: string + ): Promise { + const projectRepository = this.dataSource.getRepository(Project) + + const projects = await projectRepository + .createQueryBuilder('project') + .leftJoinAndSelect('project.organization', 'organization') + .leftJoin('project.projectMembers', 'projectMembers') + .where( + '(project.owner = :userId OR projectMembers.member.id = :userId) AND project.name LIKE :searchText', + { + userId, + searchText: `%${searchText}%` + } + ) + .getMany() + + return projects + } + + async updateDeploymentById( + deploymentId: string, + data: DeepPartial + ): Promise { + return this.updateDeployment({ id: deploymentId }, data) + } + + async updateDeployment( + criteria: FindOptionsWhere, + data: DeepPartial + ): Promise { + const deploymentRepository = this.dataSource.getRepository(Deployment) + const updateResult = await deploymentRepository.update(criteria, data) + + return Boolean(updateResult.affected) + } + + async updateDeploymentsByProjectIds( + projectIds: string[], + data: DeepPartial + ): Promise { + const deploymentRepository = this.dataSource.getRepository(Deployment) + + const updateResult = await deploymentRepository + .createQueryBuilder() + .update(Deployment) + .set(data) + .where('projectId IN (:...projectIds)', { projectIds }) + .execute() + + return Boolean(updateResult.affected) + } + + async deleteDeploymentById(deploymentId: string): Promise { + const deploymentRepository = this.dataSource.getRepository(Deployment) + const deployment = await deploymentRepository.findOneOrFail({ + where: { + id: deploymentId + } + }) + + const deleteResult = await deploymentRepository.softRemove(deployment) + + return Boolean(deleteResult) + } + + async addProject( + user: User, + organizationId: string, + data: DeepPartial + ): Promise { + const projectRepository = this.dataSource.getRepository(Project) + + // TODO: Check if organization exists + const newProject = projectRepository.create(data) + // TODO: Set default empty array for webhooks in TypeORM + newProject.webhooks = [] + // TODO: Set icon according to framework + newProject.icon = '' + + newProject.owner = user + + newProject.organization = Object.assign(new Organization(), { + id: organizationId + }) + + return projectRepository.save(newProject) + } + + async saveProject(project: Project): Promise { + const projectRepository = this.dataSource.getRepository(Project) + + return projectRepository.save(project) + } + + async updateProjectById( + projectId: string, + data: DeepPartial + ): Promise { + const projectRepository = this.dataSource.getRepository(Project) + const updateResult = await projectRepository.update({ id: projectId }, data) + + return Boolean(updateResult.affected) + } + + async deleteProjectById(projectId: string): Promise { + const projectRepository = this.dataSource.getRepository(Project) + const project = await projectRepository.findOneOrFail({ + where: { + id: projectId + }, + relations: { + projectMembers: true + } + }) + + const deleteResult = await projectRepository.softRemove(project) + + return Boolean(deleteResult) + } + + async deleteDomainById(domainId: string): Promise { + const domainRepository = this.dataSource.getRepository(Domain) + + const deleteResult = await domainRepository.softDelete({ id: domainId }) + + if (deleteResult.affected) { + return deleteResult.affected > 0 + } + + return false + } + + async addDomain(data: DeepPartial): Promise { + const domainRepository = this.dataSource.getRepository(Domain) + const newDomain = await domainRepository.save(data) + + return newDomain + } + + async getDomain(options: FindOneOptions): Promise { + const domainRepository = this.dataSource.getRepository(Domain) + const domain = await domainRepository.findOne(options) + + return domain + } + + async updateDomainById( + domainId: string, + data: DeepPartial + ): Promise { + const domainRepository = this.dataSource.getRepository(Domain) + const updateResult = await domainRepository.update({ id: domainId }, data) + + return Boolean(updateResult.affected) + } + + async getDomainsByProjectId( + projectId: string, + filter?: FindOptionsWhere + ): Promise { + const domainRepository = this.dataSource.getRepository(Domain) + + const domains = await domainRepository.find({ + relations: { + redirectTo: true + }, + where: { + project: { + id: projectId + }, + ...filter + } + }) + + return domains + } + + async getOldestDomainByProjectId(projectId: string): Promise { + const domainRepository = this.dataSource.getRepository(Domain) + + const domain = await domainRepository.findOne({ + where: { + project: { + id: projectId + } + }, + order: { + createdAt: 'ASC' + } + }) + + return domain + } + + async getLatestDNSRecordByProjectId( + projectId: string + ): Promise { + const deploymentRepository = this.dataSource.getRepository(Deployment) + + const deployment = await deploymentRepository.findOne({ + where: { + project: { + id: projectId + }, + status: DeploymentStatus.Ready + }, + order: { + createdAt: 'DESC' + } + }) + + if (deployment === null) { + throw new Error(`No deployment found for project ${projectId}`) + } + + return deployment.dnsRecordData + } + + async addDeployer(data: DeepPartial): Promise { + const deployerRepository = this.dataSource.getRepository(Deployer) + const newDomain = await deployerRepository.save(data) + + return newDomain + } + + async getDeployers(): Promise { + const deployerRepository = this.dataSource.getRepository(Deployer) + const deployers = await deployerRepository.find() + return deployers + } + + async getDeployerByLRN(deployerLrn: string): Promise { + const deployerRepository = this.dataSource.getRepository(Deployer) + const deployer = await deployerRepository.findOne({ + where: { deployerLrn } + }) + + return deployer + } +} diff --git a/apps/backend/src/entity/Deployer.ts b/apps/backend/src/entity/Deployer.ts new file mode 100644 index 0000000..95feb76 --- /dev/null +++ b/apps/backend/src/entity/Deployer.ts @@ -0,0 +1,32 @@ +import { Column, Entity, ManyToMany, PrimaryColumn } from 'typeorm' +import { Project } from './Project' + +@Entity() +export class Deployer { + @PrimaryColumn('varchar') + deployerLrn!: string + + @Column('varchar') + deployerId!: string + + @Column('varchar') + deployerApiUrl!: string + + @Column('varchar') + baseDomain!: string + + @Column('varchar', { nullable: true }) + publicKey!: string | null + + @Column('varchar', { nullable: true }) + minimumPayment!: string | null + + @Column('varchar', { nullable: true }) + paymentAddress!: string | null + + @ManyToMany( + () => Project, + (project) => project.deployers + ) + projects!: Project[] +} diff --git a/apps/backend/src/entity/Deployment.ts b/apps/backend/src/entity/Deployment.ts new file mode 100644 index 0000000..5e02678 --- /dev/null +++ b/apps/backend/src/entity/Deployment.ts @@ -0,0 +1,159 @@ +import { + Column, + CreateDateColumn, + DeleteDateColumn, + Entity, + JoinColumn, + ManyToOne, + PrimaryColumn, + UpdateDateColumn +} from 'typeorm' + +import type { + AppDeploymentRecordAttributes, + AppDeploymentRemovalRecordAttributes, + DNSRecordAttributes +} from '../types' +import { Deployer } from './Deployer' +import { Project } from './Project' +import { User } from './User' + +export enum Environment { + Production = 'Production', + Preview = 'Preview', + Development = 'Development' +} + +export enum DeploymentStatus { + Building = 'Building', + Ready = 'Ready', + Error = 'Error', + Deleting = 'Deleting' +} + +export interface ApplicationDeploymentRequest { + type: string + version: string + name: string + application: string + lrn?: string + auction?: string + config: string + meta: string + payment?: string + dns?: string +} + +export interface ApplicationDeploymentRemovalRequest { + type: string + version: string + deployment: string + auction?: string + payment?: string +} + +export interface ApplicationRecord { + type: string + version: string + name: string + description?: string + homepage?: string + license?: string + author?: string + repository?: string[] + app_version?: string + repository_ref: string + app_type: string +} + +@Entity() +export class Deployment { + // TODO: set custom generated id + @PrimaryColumn('varchar') + id!: string + + @Column() + projectId!: string + + @ManyToOne(() => Project, { onDelete: 'CASCADE' }) + @JoinColumn({ name: 'projectId' }) + project!: Project + + @Column('varchar') + branch!: string + + @Column('varchar') + commitHash!: string + + @Column('varchar') + commitMessage!: string + + @Column('varchar', { nullable: true }) + url!: string | null + + @Column('varchar') + applicationRecordId!: string + + @Column('simple-json') + applicationRecordData!: ApplicationRecord + + @Column('varchar', { nullable: true }) + applicationDeploymentRequestId!: string | null + + @Column('simple-json', { nullable: true }) + applicationDeploymentRequestData!: ApplicationDeploymentRequest | null + + @Column('varchar', { nullable: true }) + applicationDeploymentRecordId!: string | null + + @Column('simple-json', { nullable: true }) + applicationDeploymentRecordData!: AppDeploymentRecordAttributes | null + + @Column('varchar', { nullable: true }) + applicationDeploymentRemovalRequestId!: string | null + + @Column('simple-json', { nullable: true }) + applicationDeploymentRemovalRequestData!: ApplicationDeploymentRemovalRequest | null + + @Column('varchar', { nullable: true }) + applicationDeploymentRemovalRecordId!: string | null + + @Column('simple-json', { nullable: true }) + applicationDeploymentRemovalRecordData!: AppDeploymentRemovalRecordAttributes | null + + @Column('simple-json', { nullable: true }) + dnsRecordData!: DNSRecordAttributes | null + + @ManyToOne(() => Deployer) + @JoinColumn({ name: 'deployerLrn' }) + deployer!: Deployer + + @Column({ + enum: Environment + }) + environment!: Environment + + @Column('boolean', { default: false }) + isCurrent!: boolean + + @Column('boolean', { default: false }) + isCanonical!: boolean + + @Column({ + enum: DeploymentStatus + }) + status!: DeploymentStatus + + @ManyToOne(() => User) + @JoinColumn({ name: 'createdBy' }) + createdBy!: User + + @CreateDateColumn() + createdAt!: Date + + @UpdateDateColumn() + updatedAt!: Date + + @DeleteDateColumn() + deletedAt!: Date | null +} diff --git a/apps/backend/src/entity/Domain.ts b/apps/backend/src/entity/Domain.ts new file mode 100644 index 0000000..93a263f --- /dev/null +++ b/apps/backend/src/entity/Domain.ts @@ -0,0 +1,59 @@ +import { + Column, + CreateDateColumn, + DeleteDateColumn, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, + UpdateDateColumn +} from 'typeorm' + +import { Project } from './Project' + +export enum Status { + Live = 'Live', + Pending = 'Pending' +} + +@Entity() +export class Domain { + @PrimaryGeneratedColumn('uuid') + id!: string + + @Column('varchar') + projectId!: string + + @ManyToOne(() => Project, { onDelete: 'CASCADE' }) + @JoinColumn({ name: 'projectId' }) + project!: Project + + @Column('varchar', { length: 255, default: 'main' }) + branch!: string + + @Column('varchar', { length: 255 }) + name!: string + + @Column('string', { nullable: true }) + redirectToId!: string | null + + @ManyToOne(() => Domain) + @JoinColumn({ name: 'redirectToId' }) + // eslint-disable-next-line no-use-before-define + redirectTo!: Domain | null + + @Column({ + enum: Status, + default: Status.Pending + }) + status!: Status + + @CreateDateColumn() + createdAt!: Date + + @UpdateDateColumn() + updatedAt!: Date + + @DeleteDateColumn() + deletedAt!: Date | null +} diff --git a/apps/backend/src/entity/EnvironmentVariable.ts b/apps/backend/src/entity/EnvironmentVariable.ts new file mode 100644 index 0000000..45ef5eb --- /dev/null +++ b/apps/backend/src/entity/EnvironmentVariable.ts @@ -0,0 +1,44 @@ +import { + Column, + CreateDateColumn, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, + UpdateDateColumn +} from 'typeorm' + +import { Project } from './Project' + +enum Environment { + Production = 'Production', + Preview = 'Preview', + Development = 'Development' +} + +@Entity() +export class EnvironmentVariable { + @PrimaryGeneratedColumn('uuid') + id!: string + + @ManyToOne(() => Project, { onDelete: 'CASCADE' }) + @JoinColumn({ name: 'projectId' }) + project!: Project + + @Column({ + enum: Environment + }) + environment!: Environment + + @Column('varchar') + key!: string + + @Column('varchar') + value!: string + + @CreateDateColumn() + createdAt!: Date + + @UpdateDateColumn() + updatedAt!: Date +} diff --git a/apps/backend/src/entity/Organization.ts b/apps/backend/src/entity/Organization.ts new file mode 100644 index 0000000..b2fe727 --- /dev/null +++ b/apps/backend/src/entity/Organization.ts @@ -0,0 +1,38 @@ +import { + Column, + CreateDateColumn, + Entity, + OneToMany, + PrimaryGeneratedColumn, + Unique, + UpdateDateColumn +} from 'typeorm' +import { UserOrganization } from './UserOrganization' + +@Entity() +@Unique(['slug']) +export class Organization { + @PrimaryGeneratedColumn('uuid') + id!: string + + @Column('varchar', { length: 255 }) + name!: string + + @Column('varchar') + slug!: string + + @CreateDateColumn() + createdAt!: Date + + @UpdateDateColumn() + updatedAt!: Date + + @OneToMany( + () => UserOrganization, + (userOrganization) => userOrganization.organization, + { + cascade: ['soft-remove'] + } + ) + userOrganizations!: UserOrganization[] +} diff --git a/apps/backend/src/entity/Project.ts b/apps/backend/src/entity/Project.ts new file mode 100644 index 0000000..7de2418 --- /dev/null +++ b/apps/backend/src/entity/Project.ts @@ -0,0 +1,111 @@ +import { + Column, + CreateDateColumn, + DeleteDateColumn, + Entity, + JoinColumn, + JoinTable, + ManyToMany, + ManyToOne, + OneToMany, + PrimaryGeneratedColumn, + UpdateDateColumn +} from 'typeorm' + +import { Deployer } from './Deployer' +import { Deployment } from './Deployment' +import { Organization } from './Organization' +import { ProjectMember } from './ProjectMember' +import { User } from './User' + +@Entity() +export class Project { + @PrimaryGeneratedColumn('uuid') + id!: string + + @ManyToOne(() => User) + @JoinColumn({ name: 'ownerId' }) + owner!: User + + @Column({ nullable: false }) + ownerId!: string + + @ManyToOne(() => Organization, { nullable: true }) + @JoinColumn({ name: 'organizationId' }) + organization!: Organization | null + + @Column('varchar') + organizationId!: string + + @Column('varchar') + name!: string + + @Column('varchar') + repository!: string + + @Column('varchar', { length: 255, default: 'main' }) + prodBranch!: string + + @Column('text', { default: '' }) + description!: string + + @Column('varchar', { nullable: true }) + auctionId!: string | null + + // Tx hash for sending coins from snowball to deployer + @Column('varchar', { nullable: true }) + txHash!: string | null + + @ManyToMany( + () => Deployer, + (deployer) => deployer.projects + ) + @JoinTable() + deployers!: Deployer[] + + @Column('boolean', { default: false, nullable: true }) + fundsReleased!: boolean + + // TODO: Compute template & framework in import repository + @Column('varchar', { nullable: true }) + template!: string | null + + @Column('varchar', { nullable: true }) + framework!: string | null + + // Address of the user who created the project i.e. requested deployments + @Column('varchar') + paymentAddress!: string + + @Column({ + type: 'simple-array' + }) + webhooks!: string[] + + @Column('varchar') + icon!: string + + @CreateDateColumn() + createdAt!: Date + + @UpdateDateColumn() + updatedAt!: Date + + @DeleteDateColumn() + deletedAt!: Date | null + + @OneToMany( + () => Deployment, + (deployment) => deployment.project + ) + deployments!: Deployment[] + + @OneToMany( + () => ProjectMember, + (projectMember) => projectMember.project, + { + cascade: ['soft-remove'] + } + ) + projectMembers!: ProjectMember[] +} diff --git a/apps/backend/src/entity/ProjectMember.ts b/apps/backend/src/entity/ProjectMember.ts new file mode 100644 index 0000000..0e75ee0 --- /dev/null +++ b/apps/backend/src/entity/ProjectMember.ts @@ -0,0 +1,57 @@ +import { + Column, + CreateDateColumn, + DeleteDateColumn, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, + Unique, + UpdateDateColumn +} from 'typeorm' + +import { Project } from './Project' +import { User } from './User' + +export enum Permission { + View = 'View', + Edit = 'Edit' +} + +@Entity() +@Unique(['project', 'member']) +export class ProjectMember { + @PrimaryGeneratedColumn('uuid') + id!: string + + @ManyToOne( + () => User, + (user) => user.projectMembers + ) + @JoinColumn({ name: 'userId' }) + member!: User + + @ManyToOne( + () => Project, + (project) => project.projectMembers + ) + @JoinColumn({ name: 'projectId' }) + project!: Project + + @Column({ + type: 'simple-array' + }) + permissions!: Permission[] + + @Column('boolean', { default: false }) + isPending!: boolean + + @CreateDateColumn() + createdAt!: Date + + @UpdateDateColumn() + updatedAt!: Date + + @DeleteDateColumn() + deletedAt!: Date | null +} diff --git a/apps/backend/src/entity/User.ts b/apps/backend/src/entity/User.ts new file mode 100644 index 0000000..86cdc76 --- /dev/null +++ b/apps/backend/src/entity/User.ts @@ -0,0 +1,65 @@ +import { + Column, + CreateDateColumn, + Entity, + OneToMany, + PrimaryGeneratedColumn, + Unique +} from 'typeorm' + +import { ProjectMember } from './ProjectMember' +import { UserOrganization } from './UserOrganization' + +@Entity() +@Unique(['email']) +@Unique(['ethAddress']) +export class User { + @PrimaryGeneratedColumn('uuid') + id!: string + + // TODO: Set ethAddress as ID + @Column() + ethAddress!: string + + @Column('varchar', { length: 255, nullable: true }) + name!: string | null + + @Column() + email!: string + + @Column('varchar', { nullable: true }) + gitHubToken!: string | null + + @Column('boolean', { default: false }) + isVerified!: boolean + + @CreateDateColumn() + createdAt!: Date + + @CreateDateColumn() + updatedAt!: Date + + @Column() + subOrgId!: string + + @Column() + turnkeyWalletId!: string + + @OneToMany( + () => ProjectMember, + (projectMember) => projectMember.project, + { + cascade: ['soft-remove'] + } + ) + projectMembers!: ProjectMember[] + + @OneToMany( + () => UserOrganization, + (UserOrganization) => UserOrganization.member, + { + cascade: ['soft-remove'] + } + ) + userOrganizations!: UserOrganization[] +} diff --git a/apps/backend/src/entity/UserOrganization.ts b/apps/backend/src/entity/UserOrganization.ts new file mode 100644 index 0000000..2f34491 --- /dev/null +++ b/apps/backend/src/entity/UserOrganization.ts @@ -0,0 +1,47 @@ +import { + Column, + CreateDateColumn, + DeleteDateColumn, + Entity, + JoinColumn, + ManyToOne, + PrimaryGeneratedColumn, + UpdateDateColumn +} from 'typeorm' + +import { Organization } from './Organization' +import { User } from './User' + +export enum Role { + Owner = 'Owner', + Maintainer = 'Maintainer', + Reader = 'Reader' +} + +@Entity() +export class UserOrganization { + @PrimaryGeneratedColumn('uuid') + id!: string + + @ManyToOne(() => User) + @JoinColumn({ name: 'userId' }) + member!: User + + @ManyToOne(() => Organization) + @JoinColumn({ name: 'organizationId' }) + organization!: Organization + + @Column({ + enum: Role + }) + role!: Role + + @CreateDateColumn() + createdAt!: Date + + @UpdateDateColumn() + updatedAt!: Date + + @DeleteDateColumn() + deletedAt!: Date | null +} diff --git a/apps/backend/src/index.ts b/apps/backend/src/index.ts new file mode 100644 index 0000000..5195e9b --- /dev/null +++ b/apps/backend/src/index.ts @@ -0,0 +1,53 @@ +import 'express-async-errors' +import 'reflect-metadata' +import fs from 'node:fs' +import path from 'node:path' +import debug from 'debug' + +import { OAuthApp } from '@octokit/oauth-app' + +import { Database } from './database' +import { Registry } from './registry' +import { createResolvers } from './resolvers' +import { createAndStartServer } from './server' +import { Service } from './service' +import { getConfig } from './utils' + +const log = debug('snowball:server') +const OAUTH_CLIENT_TYPE = 'oauth-app' + +export const main = async (): Promise => { + const { server, database, gitHub, registryConfig } = await getConfig() + + const app = new OAuthApp({ + clientType: OAUTH_CLIENT_TYPE, + clientId: gitHub.oAuth.clientId, + clientSecret: gitHub.oAuth.clientSecret + }) + + const db = new Database(database) + await db.init() + + const registry = new Registry(registryConfig) + const service = new Service( + { gitHubConfig: gitHub, registryConfig }, + db, + app, + registry + ) + + const typeDefs = fs + .readFileSync(path.join(__dirname, 'schema.gql')) + .toString() + const resolvers = await createResolvers(service) + + await createAndStartServer(server, typeDefs, resolvers, service) +} + +main() + .then(() => { + log('Starting server...') + }) + .catch((err) => { + log(err) + }) diff --git a/apps/backend/src/registry.ts b/apps/backend/src/registry.ts new file mode 100644 index 0000000..b74ce8b --- /dev/null +++ b/apps/backend/src/registry.ts @@ -0,0 +1,624 @@ +import assert from 'node:assert' +import debug from 'debug' +import { DateTime } from 'luxon' +import type { Octokit } from 'octokit' +import * as openpgp from 'openpgp' +import { inc as semverInc } from 'semver' +import type { DeepPartial } from 'typeorm' + +import { + Account, + DEFAULT_GAS_ESTIMATION_MULTIPLIER, + Registry as LaconicRegistry, + getGasPrice, + parseGasAndFees +} from '@cerc-io/registry-sdk' +import type { DeliverTxResponse, IndexedTx } from '@cosmjs/stargate' + +import type { RegistryConfig } from './config' +import type { + ApplicationDeploymentRemovalRequest, + ApplicationDeploymentRequest, + ApplicationRecord, + Deployment +} from './entity/Deployment' +import type { + AppDeploymentRecord, + AppDeploymentRemovalRecord, + AuctionParams, + DeployerRecord, + RegistryRecord +} from './types' +import { + getConfig, + getRepoDetails, + registryTransactionWithRetry, + sleep +} from './utils' + +const log = debug('snowball:registry') + +const APP_RECORD_TYPE = 'ApplicationRecord' +const APP_DEPLOYMENT_AUCTION_RECORD_TYPE = 'ApplicationDeploymentAuction' +const APP_DEPLOYMENT_REQUEST_TYPE = 'ApplicationDeploymentRequest' +const APP_DEPLOYMENT_REMOVAL_REQUEST_TYPE = + 'ApplicationDeploymentRemovalRequest' +const APP_DEPLOYMENT_RECORD_TYPE = 'ApplicationDeploymentRecord' +const APP_DEPLOYMENT_REMOVAL_RECORD_TYPE = 'ApplicationDeploymentRemovalRecord' +const WEBAPP_DEPLOYER_RECORD_TYPE = 'WebappDeployer' +const SLEEP_DURATION = 1000 + +// TODO: Move registry code to registry-sdk/watcher-ts +export class Registry { + private registry: LaconicRegistry + private registryConfig: RegistryConfig + + constructor(registryConfig: RegistryConfig) { + this.registryConfig = registryConfig + + const gasPrice = getGasPrice(registryConfig.fee.gasPrice) + + this.registry = new LaconicRegistry( + registryConfig.gqlEndpoint, + registryConfig.restEndpoint, + { chainId: registryConfig.chainId, gasPrice } + ) + } + + async createApplicationRecord({ + octokit, + repository, + commitHash, + appType + }: { + octokit: Octokit + repository: string + commitHash: string + appType: string + }): Promise<{ + applicationRecordId: string + applicationRecordData: ApplicationRecord + }> { + const { repo, repoUrl, packageJSON } = await getRepoDetails( + octokit, + repository, + commitHash + ) + // Use registry-sdk to publish record + // Reference: https://git.vdb.to/cerc-io/test-progressive-web-app/src/branch/main/scripts/publish-app-record.sh + // Fetch previous records + const records = await this.registry.queryRecords( + { + type: APP_RECORD_TYPE, + name: packageJSON.name + }, + true + ) + + // Get next version of record + const bondRecords = records.filter( + (record: any) => record.bondId === this.registryConfig.bondId + ) + const [latestBondRecord] = bondRecords.sort( + (a: any, b: any) => + new Date(b.createTime).getTime() - new Date(a.createTime).getTime() + ) + const nextVersion = semverInc( + latestBondRecord?.attributes.version ?? '0.0.0', + 'patch' + ) + + assert(nextVersion, 'Application record version not valid') + + // Create record of type ApplicationRecord and publish + const applicationRecord = { + type: APP_RECORD_TYPE, + version: nextVersion, + repository_ref: commitHash, + repository: [repoUrl], + app_type: appType, + name: repo, + ...(packageJSON.description && { description: packageJSON.description }), + ...(packageJSON.homepage && { homepage: packageJSON.homepage }), + ...(packageJSON.license && { license: packageJSON.license }), + ...(packageJSON.author && { + author: + typeof packageJSON.author === 'object' + ? JSON.stringify(packageJSON.author) + : packageJSON.author + }), + ...(packageJSON.version && { app_version: packageJSON.version }) + } + + const result = await this.publishRecord(applicationRecord) + + log(`Published application record ${result.id}`) + log('Application record data:', applicationRecord) + + // TODO: Discuss computation of LRN + const lrn = this.getLrn(repo) + log(`Setting name: ${lrn} for record ID: ${result.id}`) + + const fee = parseGasAndFees( + this.registryConfig.fee.gas, + this.registryConfig.fee.fees + ) + + await sleep(SLEEP_DURATION) + await registryTransactionWithRetry(() => + this.registry.setName( + { + cid: result.id, + lrn + }, + this.registryConfig.privateKey, + fee + ) + ) + + await sleep(SLEEP_DURATION) + await registryTransactionWithRetry(() => + this.registry.setName( + { + cid: result.id, + lrn: `${lrn}@${applicationRecord.app_version}` + }, + this.registryConfig.privateKey, + fee + ) + ) + + await sleep(SLEEP_DURATION) + await registryTransactionWithRetry(() => + this.registry.setName( + { + cid: result.id, + lrn: `${lrn}@${applicationRecord.repository_ref}` + }, + this.registryConfig.privateKey, + fee + ) + ) + + return { + applicationRecordId: result.id, + applicationRecordData: applicationRecord + } + } + + async createApplicationDeploymentAuction( + appName: string, + octokit: Octokit, + auctionParams: AuctionParams, + data: DeepPartial + ): Promise<{ + applicationDeploymentAuctionId: string + }> { + assert(data.project?.repository, 'Project repository not found') + + await this.createApplicationRecord({ + octokit, + repository: data.project.repository, + appType: data.project!.template!, + commitHash: data.commitHash! + }) + + const lrn = this.getLrn(appName) + const config = await getConfig() + const auctionConfig = config.auction + + const fee = parseGasAndFees( + this.registryConfig.fee.gas, + this.registryConfig.fee.fees + ) + const auctionResult = await registryTransactionWithRetry(() => + this.registry.createProviderAuction( + { + commitFee: auctionConfig.commitFee, + commitsDuration: auctionConfig.commitsDuration, + revealFee: auctionConfig.revealFee, + revealsDuration: auctionConfig.revealsDuration, + denom: auctionConfig.denom, + maxPrice: auctionParams.maxPrice, + numProviders: auctionParams.numProviders + }, + this.registryConfig.privateKey, + fee + ) + ) + + if (!auctionResult.auction) { + throw new Error('Error creating auction') + } + + // Create record of type applicationDeploymentAuction and publish + const applicationDeploymentAuction = { + application: lrn, + auction: auctionResult.auction.id, + type: APP_DEPLOYMENT_AUCTION_RECORD_TYPE + } + + const result = await this.publishRecord(applicationDeploymentAuction) + + log(`Application deployment auction created: ${auctionResult.auction.id}`) + log(`Application deployment auction record published: ${result.id}`) + log('Application deployment auction data:', applicationDeploymentAuction) + + return { + applicationDeploymentAuctionId: auctionResult.auction.id + } + } + + async createApplicationDeploymentRequest(data: { + deployment: Deployment + appName: string + repository: string + auctionId?: string | null + lrn: string + apiUrl: string + environmentVariables: { [key: string]: string } + dns: string + requesterAddress: string + publicKey: string + payment?: string | null + }): Promise<{ + applicationDeploymentRequestId: string + applicationDeploymentRequestData: ApplicationDeploymentRequest + }> { + const lrn = this.getLrn(data.appName) + const records = await this.registry.resolveNames([lrn]) + const applicationRecord = records[0] + + if (!applicationRecord) { + throw new Error(`No record found for ${lrn}`) + } + + let hash: string | undefined + if (Object.keys(data.environmentVariables).length !== 0) { + hash = await this.generateConfigHash( + data.environmentVariables, + data.requesterAddress, + data.publicKey, + data.apiUrl + ) + } + + // Create record of type ApplicationDeploymentRequest and publish + const applicationDeploymentRequest = { + type: APP_DEPLOYMENT_REQUEST_TYPE, + version: '1.0.0', + name: `${applicationRecord.attributes.name}@${applicationRecord.attributes.app_version}`, + application: `${lrn}@${applicationRecord.attributes.app_version}`, + dns: data.dns, + + // https://git.vdb.to/cerc-io/laconic-registry-cli/commit/129019105dfb93bebcea02fde0ed64d0f8e5983b + config: JSON.stringify(hash ? { ref: hash } : {}), + meta: JSON.stringify({ + note: `Added by Snowball @ ${DateTime.utc().toFormat( + "EEE LLL dd HH:mm:ss 'UTC' yyyy" + )}`, + repository: data.repository, + repository_ref: data.deployment.commitHash + }), + deployer: data.lrn, + ...(data.auctionId && { auction: data.auctionId }), + ...(data.payment && { payment: data.payment }) + } + + await sleep(SLEEP_DURATION) + + const result = await this.publishRecord(applicationDeploymentRequest) + + log(`Application deployment request record published: ${result.id}`) + log('Application deployment request data:', applicationDeploymentRequest) + + return { + applicationDeploymentRequestId: result.id, + applicationDeploymentRequestData: applicationDeploymentRequest + } + } + + async getAuctionWinningDeployerRecords( + auctionId: string + ): Promise { + const records = await this.registry.getAuctionsByIds([auctionId]) + const auctionResult = records[0] + + const deployerRecords = [] + const { winnerAddresses } = auctionResult + + for (const auctionWinner of winnerAddresses) { + const records = await this.getDeployerRecordsByFilter({ + paymentAddress: auctionWinner + }) + + const newRecords = records.filter((record) => { + return record.names !== null && record.names.length > 0 + }) + + for (const record of newRecords) { + if (record.id) { + deployerRecords.push(record) + break + } + } + } + + return deployerRecords + } + + async releaseDeployerFunds(auctionId: string): Promise { + const fee = parseGasAndFees( + this.registryConfig.fee.gas, + this.registryConfig.fee.fees + ) + const auction = await registryTransactionWithRetry(() => + this.registry.releaseFunds( + { + auctionId + }, + this.registryConfig.privateKey, + fee + ) + ) + + return auction + } + + /** + * Fetch ApplicationDeploymentRecords for deployments + */ + async getDeploymentRecords( + deployments: Deployment[] + ): Promise { + // Fetch ApplicationDeploymentRecords for corresponding ApplicationRecord set in deployments + // TODO: Implement Laconicd GQL query to filter records by multiple values for an attribute + const records = await this.registry.queryRecords( + { + type: APP_DEPLOYMENT_RECORD_TYPE + }, + true + ) + + // Filter records with ApplicationDeploymentRequestId ID + return records.filter((record: AppDeploymentRecord) => + deployments.some( + (deployment) => + deployment.applicationDeploymentRequestId === + record.attributes.request + ) + ) + } + + /** + * Fetch WebappDeployer Records by filter + */ + async getDeployerRecordsByFilter(filter: { [key: string]: any }): Promise< + DeployerRecord[] + > { + return this.registry.queryRecords( + { + type: WEBAPP_DEPLOYER_RECORD_TYPE, + ...filter + }, + true + ) + } + + /** + * Fetch ApplicationDeploymentRecords by filter + */ + async getDeploymentRecordsByFilter(filter: { [key: string]: any }): Promise< + AppDeploymentRecord[] + > { + return this.registry.queryRecords( + { + type: APP_DEPLOYMENT_RECORD_TYPE, + ...filter + }, + true + ) + } + + /** + * Fetch ApplicationDeploymentRemovalRecords for deployments + */ + async getDeploymentRemovalRecords( + deployments: Deployment[] + ): Promise { + // Fetch ApplicationDeploymentRemovalRecords for corresponding ApplicationDeploymentRecord set in deployments + const records = await this.registry.queryRecords( + { + type: APP_DEPLOYMENT_REMOVAL_RECORD_TYPE + }, + true + ) + + // Filter records with ApplicationDeploymentRecord and ApplicationDeploymentRemovalRequest IDs + return records.filter((record: AppDeploymentRemovalRecord) => + deployments.some( + (deployment) => + deployment.applicationDeploymentRemovalRequestId === + record.attributes.request && + deployment.applicationDeploymentRecordId === + record.attributes.deployment + ) + ) + } + + /** + * Fetch record by Id + */ + async getRecordById(id: string): Promise { + const [record] = await this.registry.getRecordsByIds([id]) + return record ?? null + } + + async createApplicationDeploymentRemovalRequest(data: { + deploymentId: string + deployerLrn: string + auctionId?: string | null + payment?: string | null + }): Promise<{ + applicationDeploymentRemovalRequestId: string + applicationDeploymentRemovalRequestData: ApplicationDeploymentRemovalRequest + }> { + const applicationDeploymentRemovalRequest = { + type: APP_DEPLOYMENT_REMOVAL_REQUEST_TYPE, + version: '1.0.0', + deployment: data.deploymentId, + deployer: data.deployerLrn, + ...(data.auctionId && { auction: data.auctionId }), + ...(data.payment && { payment: data.payment }) + } + + const result = await this.publishRecord(applicationDeploymentRemovalRequest) + + log(`Application deployment removal request record published: ${result.id}`) + log( + 'Application deployment removal request data:', + applicationDeploymentRemovalRequest + ) + + return { + applicationDeploymentRemovalRequestId: result.id, + applicationDeploymentRemovalRequestData: + applicationDeploymentRemovalRequest + } + } + + async getCompletedAuctionIds(auctionIds: string[]): Promise { + if (auctionIds.length === 0) { + return [] + } + + const auctions = await this.registry.getAuctionsByIds(auctionIds) + + const completedAuctions = auctions + .filter( + (auction: { id: string; status: string }) => + auction.status === 'completed' + ) + .map((auction: { id: string; status: string }) => auction.id) + + return completedAuctions + } + + async publishRecord(recordData: any): Promise { + const fee = parseGasAndFees( + this.registryConfig.fee.gas, + this.registryConfig.fee.fees + ) + + const result = await registryTransactionWithRetry(() => + this.registry.setRecord( + { + privateKey: this.registryConfig.privateKey, + record: recordData, + bondId: this.registryConfig.bondId + }, + this.registryConfig.privateKey, + fee + ) + ) + + return result + } + + async getRecordsByName(name: string): Promise { + return this.registry.resolveNames([name]) + } + + async getAuctionData(auctionId: string): Promise { + return this.registry.getAuctionsByIds([auctionId]) + } + + async sendTokensToAccount( + receiverAddress: string, + amount: string + ): Promise { + const fee = parseGasAndFees( + this.registryConfig.fee.gas, + this.registryConfig.fee.fees + ) + const account = await this.getAccount() + const laconicClient = await this.registry.getLaconicClient(account) + const txResponse: DeliverTxResponse = await registryTransactionWithRetry( + () => + laconicClient.sendTokens( + account.address, + receiverAddress, + [ + { + denom: 'alnt', + amount + } + ], + fee || DEFAULT_GAS_ESTIMATION_MULTIPLIER + ) + ) + + return txResponse + } + + async getAccount(): Promise { + const account = new Account( + Buffer.from(this.registryConfig.privateKey, 'hex') + ) + await account.init() + + return account + } + + async getTxResponse(txHash: string): Promise { + const account = await this.getAccount() + const laconicClient = await this.registry.getLaconicClient(account) + const txResponse: IndexedTx | null = await laconicClient.getTx(txHash) + + return txResponse + } + + getLrn(appName: string): string { + assert(this.registryConfig.authority, "Authority doesn't exist") + return `lrn://${this.registryConfig.authority}/applications/${appName}` + } + + async generateConfigHash( + environmentVariables: { [key: string]: string }, + requesterAddress: string, + pubKey: string, + url: string + ): Promise { + // Config to be encrypted + const config = { + authorized: [requesterAddress], + config: { env: environmentVariables } + } + + // Serialize the config + const serialized = JSON.stringify(config, null, 2) + + const armoredKey = `-----BEGIN PGP PUBLIC KEY BLOCK-----\n\n${pubKey}\n\n-----END PGP PUBLIC KEY BLOCK-----` + const publicKey = await openpgp.readKey({ armoredKey }) + + // Encrypt the config + const encrypted = await openpgp.encrypt({ + message: await openpgp.createMessage({ text: serialized }), + encryptionKeys: publicKey, + format: 'binary' + }) + + // Get the hash after uploading encrypted config + const response = await fetch(`${url}/upload/config`, { + method: 'POST', + headers: { + 'Content-Type': 'application/octet-stream' + }, + body: encrypted + }) + + const configHash = await response.json() + + return configHash.id + } +} diff --git a/apps/backend/src/resolvers.ts b/apps/backend/src/resolvers.ts new file mode 100644 index 0000000..38a4a31 --- /dev/null +++ b/apps/backend/src/resolvers.ts @@ -0,0 +1,413 @@ +import debug from 'debug' +import type { DeepPartial, FindOptionsWhere } from 'typeorm' + +import type { Domain } from './entity/Domain' +import type { EnvironmentVariable } from './entity/EnvironmentVariable' +import type { Project } from './entity/Project' +import type { Permission } from './entity/ProjectMember' +import type { Service } from './service' +import type { + AddProjectFromTemplateInput, + AuctionParams, + EnvironmentVariables +} from './types' + +const log = debug('snowball:resolver') + +export const createResolvers = async (service: Service): Promise => { + return { + Query: { + // TODO: add custom type for context + user: (_: any, __: any, context: any) => { + return context.user + }, + + organizations: async (_: any, __: any, context: any) => { + return service.getOrganizationsByUserId(context.user) + }, + + project: async ( + _: any, + { projectId }: { projectId: string }, + context: any + ) => { + return service.getProjectById(context.user, projectId) + }, + + projectsInOrganization: async ( + _: any, + { organizationSlug }: { organizationSlug: string }, + context: any + ) => { + return service.getProjectsInOrganization(context.user, organizationSlug) + }, + + deployments: async (_: any, { projectId }: { projectId: string }) => { + return service.getNonCanonicalDeploymentsByProjectId(projectId) + }, + + environmentVariables: async ( + _: any, + { projectId }: { projectId: string } + ) => { + return service.getEnvironmentVariablesByProjectId(projectId) + }, + + projectMembers: async (_: any, { projectId }: { projectId: string }) => { + return service.getProjectMembersByProjectId(projectId) + }, + + searchProjects: async ( + _: any, + { searchText }: { searchText: string }, + context: any + ) => { + return service.searchProjects(context.user, searchText) + }, + + domains: async ( + _: any, + { + projectId, + filter + }: { projectId: string; filter?: FindOptionsWhere } + ) => { + return service.getDomainsByProjectId(projectId, filter) + }, + + getAuctionData: async (_: any, { auctionId }: { auctionId: string }) => { + return service.getAuctionData(auctionId) + }, + + deployers: async (_: any, __: any) => { + return service.getDeployers() + }, + + address: async (_: any, __: any) => { + return service.getAddress() + }, + + verifyTx: async ( + _: any, + { + txHash, + amount, + senderAddress + }: { txHash: string; amount: string; senderAddress: string } + ) => { + return service.verifyTx(txHash, amount, senderAddress) + }, + + latestDNSRecord: async (_: any, { projectId }: { projectId: string }) => { + return service.getLatestDNSRecordByProjectId(projectId) + } + }, + + // TODO: Return error in GQL response + Mutation: { + removeProjectMember: async ( + _: any, + { projectMemberId }: { projectMemberId: string }, + context: any + ) => { + try { + return await service.removeProjectMember( + context.user, + projectMemberId + ) + } catch (err) { + log(err) + return false + } + }, + + updateProjectMember: async ( + _: any, + { + projectMemberId, + data + }: { + projectMemberId: string + data: { + permissions: Permission[] + } + } + ) => { + try { + return await service.updateProjectMember(projectMemberId, data) + } catch (err) { + log(err) + return false + } + }, + + addProjectMember: async ( + _: any, + { + projectId, + data + }: { + projectId: string + data: { + email: string + permissions: Permission[] + } + } + ) => { + try { + return Boolean(await service.addProjectMember(projectId, data)) + } catch (err) { + log(err) + return false + } + }, + + addEnvironmentVariables: async ( + _: any, + { + projectId, + data + }: { + projectId: string + data: { environments: string[]; key: string; value: string }[] + } + ) => { + try { + return Boolean(await service.addEnvironmentVariables(projectId, data)) + } catch (err) { + log(err) + return false + } + }, + + updateEnvironmentVariable: async ( + _: any, + { + environmentVariableId, + data + }: { + environmentVariableId: string + data: DeepPartial + } + ) => { + try { + return await service.updateEnvironmentVariable( + environmentVariableId, + data + ) + } catch (err) { + log(err) + return false + } + }, + + removeEnvironmentVariable: async ( + _: any, + { environmentVariableId }: { environmentVariableId: string } + ) => { + try { + return await service.removeEnvironmentVariable(environmentVariableId) + } catch (err) { + log(err) + return false + } + }, + + updateDeploymentToProd: async ( + _: any, + { deploymentId }: { deploymentId: string }, + context: any + ) => { + try { + return Boolean( + await service.updateDeploymentToProd(context.user, deploymentId) + ) + } catch (err) { + log(err) + return false + } + }, + + addProjectFromTemplate: async ( + _: any, + { + organizationSlug, + data, + lrn, + auctionParams, + environmentVariables + }: { + organizationSlug: string + data: AddProjectFromTemplateInput + lrn: string + auctionParams: AuctionParams + environmentVariables: EnvironmentVariables[] + }, + context: any + ) => { + try { + return await service.addProjectFromTemplate( + context.user, + organizationSlug, + data, + lrn, + auctionParams, + environmentVariables + ) + } catch (err) { + log(err) + throw err + } + }, + + addProject: async ( + _: any, + { + organizationSlug, + data, + lrn, + auctionParams, + environmentVariables + }: { + organizationSlug: string + data: DeepPartial + lrn: string + auctionParams: AuctionParams + environmentVariables: EnvironmentVariables[] + }, + context: any + ) => { + try { + return await service.addProject( + context.user, + organizationSlug, + data, + lrn, + auctionParams, + environmentVariables + ) + } catch (err) { + log(err) + throw err + } + }, + + updateProject: async ( + _: any, + { projectId, data }: { projectId: string; data: DeepPartial } + ) => { + try { + return await service.updateProject(projectId, data) + } catch (err) { + log(err) + return false + } + }, + + redeployToProd: async ( + _: any, + { deploymentId }: { deploymentId: string }, + context: any + ) => { + try { + return Boolean( + await service.redeployToProd(context.user, deploymentId) + ) + } catch (err) { + log(err) + return false + } + }, + + deleteProject: async (_: any, { projectId }: { projectId: string }) => { + try { + return await service.deleteProject(projectId) + } catch (err) { + log(err) + return false + } + }, + + deleteDomain: async (_: any, { domainId }: { domainId: string }) => { + try { + return await service.deleteDomain(domainId) + } catch (err) { + log(err) + return false + } + }, + + rollbackDeployment: async ( + _: any, + { projectId, deploymentId }: { deploymentId: string; projectId: string } + ) => { + try { + return await service.rollbackDeployment(projectId, deploymentId) + } catch (err) { + log(err) + return false + } + }, + + deleteDeployment: async ( + _: any, + { deploymentId }: { deploymentId: string } + ) => { + try { + return await service.deleteDeployment(deploymentId) + } catch (err) { + log(err) + return false + } + }, + + addDomain: async ( + _: any, + { projectId, data }: { projectId: string; data: { name: string } } + ) => { + try { + return Boolean(await service.addDomain(projectId, data)) + } catch (err) { + log(err) + return false + } + }, + + updateDomain: async ( + _: any, + { domainId, data }: { domainId: string; data: DeepPartial } + ) => { + try { + return await service.updateDomain(domainId, data) + } catch (err) { + log(err) + return false + } + }, + + authenticateGitHub: async ( + _: any, + { code }: { code: string }, + context: any + ) => { + try { + return await service.authenticateGitHub(code, context.user) + } catch (err) { + log(err) + return false + } + }, + + unauthenticateGitHub: async (_: any, __: object, context: any) => { + try { + return service.unauthenticateGitHub(context.user, { + gitHubToken: null + }) + } catch (err) { + log(err) + return false + } + } + } + } +} diff --git a/apps/backend/src/routes/auth.ts b/apps/backend/src/routes/auth.ts new file mode 100644 index 0000000..3d2ff5d --- /dev/null +++ b/apps/backend/src/routes/auth.ts @@ -0,0 +1,97 @@ +import { Router } from 'express' +import { SiweMessage } from 'siwe' +import type { Service } from '../service' +import { authenticateUser, createUser } from '../turnkey-backend' + +const router: Router = Router() + +// +// Turnkey +// +router.get('/registration/:email', async (req, res) => { + const service: Service = req.app.get('service') + const user = await service.getUserByEmail(req.params.email) + if (user) { + return res.send({ subOrganizationId: user?.subOrgId }) + } + + return res.sendStatus(204) +}) + +router.post('/register', async (req, res) => { + console.log('Register', req.body) + const { email, challenge, attestation } = req.body + const user = await createUser(req.app.get('service'), { + challenge, + attestation, + userEmail: email, + userName: email.split('@')[0] + }) + req.session.address = user.id + res.sendStatus(200) +}) + +router.post('/authenticate', async (req, res) => { + console.log('Authenticate', req.body) + const { signedWhoamiRequest } = req.body + const user = await authenticateUser( + req.app.get('service'), + signedWhoamiRequest + ) + if (user) { + req.session.address = user.id + res.sendStatus(200) + } else { + res.sendStatus(401) + } +}) + +// +// SIWE Auth +// +router.post('/validate', async (req, res) => { + const { message, signature } = req.body + const { success, data } = await new SiweMessage(message).verify({ + signature + }) + + if (!success) { + return res.send({ success }) + } + const service: Service = req.app.get('service') + const user = await service.getUserByEthAddress(data.address) + + if (!user) { + const newUser = await service.createUser({ + ethAddress: data.address, + email: `${data.address}@example.com`, + subOrgId: '', + turnkeyWalletId: '' + }) + + // SIWESession from the web3modal library requires both address and chain ID + req.session.address = newUser.id + req.session.chainId = data.chainId + } else { + req.session.address = user.id + req.session.chainId = data.chainId + } + + res.send({ success }) +}) + +// +// General +// +router.get('/session', (req, res) => { + if (req.session.address && req.session.chainId) { + res.send({ + address: req.session.address, + chainId: req.session.chainId + }) + } else { + res.status(401).send({ error: 'Unauthorized: No active session' }) + } +}) + +export default router diff --git a/apps/backend/src/routes/github.ts b/apps/backend/src/routes/github.ts new file mode 100644 index 0000000..a64f023 --- /dev/null +++ b/apps/backend/src/routes/github.ts @@ -0,0 +1,26 @@ +import debug from 'debug' +import { Router } from 'express' + +import type { Service } from '../service' + +const log = debug('snowball:routes-github') +const router: Router = Router() + +/* POST GitHub webhook handler */ +// https://docs.github.com/en/webhooks/using-webhooks/handling-webhook-deliveries#javascript-example +router.post('/webhook', async (req, res) => { + // Server should respond with a 2XX response within 10 seconds of receiving a webhook delivery + // If server takes longer than that to respond, then GitHub terminates the connection and considers the delivery a failure + res.status(202).send('Accepted') + + const service = req.app.get('service') as Service + const githubEvent = req.headers['x-github-event'] + log(`Received GitHub webhook for event ${githubEvent}`) + + if (githubEvent === 'push') { + // Create deployments using push event data + await service.handleGitHubPush(req.body) + } +}) + +export default router diff --git a/apps/backend/src/routes/staging.ts b/apps/backend/src/routes/staging.ts new file mode 100644 index 0000000..e6cbd0b --- /dev/null +++ b/apps/backend/src/routes/staging.ts @@ -0,0 +1,9 @@ +import { Router } from 'express' + +const router: Router = Router() + +router.get('/version', async (_req, res) => { + return res.send({ version: '0.0.9' }) +}) + +export default router diff --git a/apps/backend/src/schema.gql b/apps/backend/src/schema.gql new file mode 100644 index 0000000..4dbff1d --- /dev/null +++ b/apps/backend/src/schema.gql @@ -0,0 +1,337 @@ +enum Role { + Owner + Maintainer + Reader +} + +enum Permission { + View + Edit +} + +enum Environment { + Production + Preview + Development +} + +enum DeploymentStatus { + Building + Ready + Error + Deleting +} + +enum AuctionStatus { + completed + reveal + commit + expired +} + +enum DomainStatus { + Live + Pending +} + +type User { + id: String! + name: String + email: String! + organizations: [Organization!] + projects: [Project!] + isVerified: Boolean! + createdAt: String! + updatedAt: String! + gitHubToken: String +} + +type Organization { + id: String! + name: String! + slug: String! + projects: [Project!] + createdAt: String! + updatedAt: String! + members: [OrganizationMember!] +} + +type OrganizationMember { + id: String! + member: User! + role: Role! + createdAt: String! + updatedAt: String! +} + +type Project { + id: String! + owner: User! + deployments: [Deployment!] + name: String! + repository: String! + prodBranch: String! + description: String + deployers: [Deployer!] + auctionId: String + fundsReleased: Boolean + template: String + framework: String + paymentAddress: String! + txHash: String! + webhooks: [String!] + members: [ProjectMember!] + environmentVariables: [EnvironmentVariable!] + createdAt: String! + updatedAt: String! + organization: Organization! + icon: String + baseDomains: [String!] +} + +type ProjectMember { + id: String! + member: User! + permissions: [Permission!]! + isPending: Boolean! + createdAt: String! + updatedAt: String! +} + +type Deployment { + id: String! + branch: String! + commitHash: String! + commitMessage: String! + url: String + environment: Environment! + deployer: Deployer + applicationDeploymentRequestId: String + applicationDeploymentRecordData: AppDeploymentRecordAttributes + isCurrent: Boolean! + baseDomain: String + status: DeploymentStatus! + createdAt: String! + updatedAt: String! + createdBy: User! +} + +type Domain { + id: String! + branch: String! + name: String! + redirectTo: Domain + status: DomainStatus! + createdAt: String! + updatedAt: String! +} + +type EnvironmentVariable { + id: String! + environment: Environment! + key: String! + value: String! + createdAt: String! + updatedAt: String! +} + +type Deployer { + deployerLrn: String! + deployerId: String! + deployerApiUrl: String! + minimumPayment: String + paymentAddress: String + createdAt: String! + updatedAt: String! + baseDomain: String +} + +type AuthResult { + token: String! +} + +input AddEnvironmentVariableInput { + environments: [Environment!]! + key: String! + value: String! +} + +input AddProjectFromTemplateInput { + templateOwner: String! + templateRepo: String! + owner: String! + name: String! + isPrivate: Boolean! + paymentAddress: String! + txHash: String! +} + +input AddProjectInput { + name: String! + repository: String! + prodBranch: String! + template: String + paymentAddress: String! + txHash: String! +} + +input UpdateProjectInput { + name: String + description: String + prodBranch: String + organizationId: String + webhooks: [String!] +} + +input AddDomainInput { + name: String! +} + +input UpdateDomainInput { + name: String + branch: String + redirectToId: String +} + +input UpdateEnvironmentVariableInput { + key: String + value: String +} + +input AddProjectMemberInput { + email: String! + permissions: [Permission!] +} + +input UpdateProjectMemberInput { + permissions: [Permission] +} + +input FilterDomainsInput { + branch: String + status: DomainStatus +} + +type Fee { + type: String! + quantity: String! +} + +type Bid { + auctionId: String! + bidderAddress: String! + status: String! + commitHash: String! + commitTime: String + commitFee: Fee + revealTime: String + revealFee: Fee + bidAmount: Fee +} + +type Auction { + id: String! + kind: String! + status: String! + ownerAddress: String! + createTime: String! + commitsEndTime: String! + revealsEndTime: String! + commitFee: Fee! + revealFee: Fee! + minimumBid: Fee + winnerAddresses: [String!]! + winnerBids: [Fee!] + winnerPrice: Fee + maxPrice: Fee + numProviders: Int! + fundsReleased: Boolean! + bids: [Bid!]! +} + +type DNSRecordAttributes { + name: String + value: String + request: String + resourceType: String + version: String +} + +type AppDeploymentRecordAttributes { + application: String + auction: String + deployer: String + dns: String + meta: String + name: String + request: String + type: String + url: String + version: String +} + +input AuctionParams { + maxPrice: String + numProviders: Int +} + +type Query { + user: User! + organizations: [Organization!] + projects: [Project!] + projectsInOrganization(organizationSlug: String!): [Project!] + project(projectId: String!): Project + deployments(projectId: String!): [Deployment!] + environmentVariables(projectId: String!): [EnvironmentVariable!] + projectMembers(projectId: String!): [ProjectMember!] + searchProjects(searchText: String!): [Project!] + getAuctionData(auctionId: String!): Auction! + latestDNSRecord(projectId: String!): DNSRecordAttributes + domains(projectId: String!, filter: FilterDomainsInput): [Domain] + deployers: [Deployer] + address: String! + verifyTx(txHash: String!, amount: String!, senderAddress: String!): Boolean! +} + +type Mutation { + addProjectMember(projectId: String!, data: AddProjectMemberInput): Boolean! + updateProjectMember( + projectMemberId: String! + data: UpdateProjectMemberInput + ): Boolean! + removeProjectMember(projectMemberId: String!): Boolean! + addEnvironmentVariables( + projectId: String! + data: [AddEnvironmentVariableInput!] + ): Boolean! + updateEnvironmentVariable( + environmentVariableId: String! + data: UpdateEnvironmentVariableInput! + ): Boolean! + removeEnvironmentVariable(environmentVariableId: String!): Boolean! + updateDeploymentToProd(deploymentId: String!): Boolean! + addProjectFromTemplate( + organizationSlug: String! + data: AddProjectFromTemplateInput + lrn: String + auctionParams: AuctionParams + environmentVariables: [AddEnvironmentVariableInput!] + ): Project! + addProject( + organizationSlug: String! + data: AddProjectInput! + lrn: String + auctionParams: AuctionParams + environmentVariables: [AddEnvironmentVariableInput!] + ): Project! + updateProject(projectId: String!, data: UpdateProjectInput): Boolean! + redeployToProd(deploymentId: String!): Boolean! + deleteProject(projectId: String!): Boolean! + deleteDomain(domainId: String!): Boolean! + rollbackDeployment(projectId: String!, deploymentId: String!): Boolean! + deleteDeployment(deploymentId: String!): Boolean! + addDomain(projectId: String!, data: AddDomainInput!): Boolean! + updateDomain(domainId: String!, data: UpdateDomainInput!): Boolean! + authenticateGitHub(code: String!): AuthResult! + unauthenticateGitHub: Boolean! +} diff --git a/apps/backend/src/server.ts b/apps/backend/src/server.ts new file mode 100644 index 0000000..50a7c3d --- /dev/null +++ b/apps/backend/src/server.ts @@ -0,0 +1,131 @@ +import { createServer } from 'node:http' +import { + ApolloServerPluginDrainHttpServer, + ApolloServerPluginLandingPageLocalDefault, + AuthenticationError +} from 'apollo-server-core' +import { ApolloServer } from 'apollo-server-express' +import cors from 'cors' +import debug from 'debug' +import express from 'express' +import session from 'express-session' + +import { makeExecutableSchema } from '@graphql-tools/schema' +import type { TypeSource } from '@graphql-tools/utils' + +import type { ServerConfig } from './config' +import { DEFAULT_GQL_PATH } from './constants' +import authRouter from './routes/auth' +import githubRouter from './routes/github' +import stagingRouter from './routes/staging' +import type { Service } from './service' + +const log = debug('snowball:server') + +// Set cookie expiration to 1 month in milliseconds +const COOKIE_MAX_AGE = 30 * 24 * 60 * 60 * 1000 + +declare module 'express-session' { + interface SessionData { + address: string + chainId: number + } +} + +export const createAndStartServer = async ( + serverConfig: ServerConfig, + typeDefs: TypeSource, + resolvers: any, + service: Service +): Promise => { + const { host, port, gqlPath = DEFAULT_GQL_PATH } = serverConfig + const { appOriginUrl, secret, domain, trustProxy } = serverConfig.session + + const app = express() + + // Create HTTP server + const httpServer = createServer(app) + + // Create the schema + const schema = makeExecutableSchema({ + typeDefs, + resolvers + }) + + const server = new ApolloServer({ + schema, + csrfPrevention: true, + context: async ({ req }) => { + // https://www.apollographql.com/docs/apollo-server/v3/security/authentication#api-wide-authorization + + const { address } = req.session + + if (!address) { + throw new AuthenticationError('Unauthorized: No active session') + } + + const user = await service.getUser(address) + return { user } + }, + plugins: [ + // Proper shutdown for the HTTP server + ApolloServerPluginDrainHttpServer({ httpServer }), + ApolloServerPluginLandingPageLocalDefault({ embed: true }) + ] + }) + + await server.start() + + app.use( + cors({ + origin: appOriginUrl, + credentials: true + }) + ) + + const sessionOptions: session.SessionOptions = { + secret: secret, + resave: false, + saveUninitialized: true, + cookie: { + secure: new URL(appOriginUrl).protocol === 'https:', + maxAge: COOKIE_MAX_AGE, + domain: domain || undefined, + sameSite: new URL(appOriginUrl).protocol === 'https:' ? 'none' : 'lax' + } + } + + if (trustProxy) { + // trust first proxy + app.set('trust proxy', 1) + } + + app.use(session(sessionOptions)) + + server.applyMiddleware({ + app: app as any, + path: gqlPath, + cors: { + origin: [appOriginUrl], + credentials: true + } + }) + + app.use(express.json()) + + app.set('service', service) + app.use('/auth', authRouter) + app.use('/api/github', githubRouter) + app.use('/staging', stagingRouter) + + app.use((err: any, _req: any, res: any, _next: any) => { + console.error(err) + res.status(500).json({ error: err.message }) + }) + + httpServer.listen(port, host, () => { + log(`Server is listening on ${host}:${port}${server.graphqlPath}`) + }) + + return server +} diff --git a/apps/backend/src/service.ts b/apps/backend/src/service.ts new file mode 100644 index 0000000..d7c1f26 --- /dev/null +++ b/apps/backend/src/service.ts @@ -0,0 +1,1783 @@ +import assert from 'node:assert' +import debug from 'debug' +import { DateTime } from 'luxon' + +import { Octokit, RequestError } from 'octokit' +import type { DeepPartial, FindOptionsWhere } from 'typeorm' + +import type { OAuthApp } from '@octokit/oauth-app' + +import type { GitHubConfig, RegistryConfig } from './config' +import type { Database } from './database' +import { Deployer } from './entity/Deployer' +import { + type ApplicationRecord, + type Deployment, + DeploymentStatus, + Environment +} from './entity/Deployment' +import type { Domain } from './entity/Domain' +import type { EnvironmentVariable } from './entity/EnvironmentVariable' +import type { Organization } from './entity/Organization' +import { Project } from './entity/Project' +import type { Permission, ProjectMember } from './entity/ProjectMember' +import { User } from './entity/User' +import { Role } from './entity/UserOrganization' +import type { Registry } from './registry' +import type { + AddProjectFromTemplateInput, + AppDeploymentRecord, + AppDeploymentRemovalRecord, + AuctionParams, + DNSRecord, + DNSRecordAttributes, + DeployerRecord, + EnvironmentVariables, + GitPushEventPayload +} from './types' +import { getRepoDetails } from './utils' + +const log = debug('snowball:service') + +const GITHUB_UNIQUE_WEBHOOK_ERROR = 'Hook already exists on this repository' + +// Define a constant for an hour in milliseconds +const HOUR = 1000 * 60 * 60 + +interface Config { + gitHubConfig: GitHubConfig + registryConfig: RegistryConfig +} + +export class Service { + private db: Database + private oauthApp: OAuthApp + private laconicRegistry: Registry + private config: Config + + private deployRecordCheckTimeout?: NodeJS.Timeout + private auctionStatusCheckTimeout?: NodeJS.Timeout + + constructor(config: Config, db: Database, app: OAuthApp, registry: Registry) { + this.db = db + this.oauthApp = app + this.laconicRegistry = registry + this.config = config + this.init() + } + + /** + * Initialize services + */ + init(): void { + // Start check for ApplicationDeploymentRecords asynchronously + this.checkDeployRecordsAndUpdate() + // Start check for ApplicationDeploymentRemovalRecords asynchronously + this.checkDeploymentRemovalRecordsAndUpdate() + // Start check for Deployment Auctions asynchronously + this.checkAuctionStatus() + } + + /** + * Destroy services + */ + destroy(): void { + clearTimeout(this.deployRecordCheckTimeout) + clearTimeout(this.auctionStatusCheckTimeout) + } + + /** + * Checks for ApplicationDeploymentRecord and update corresponding deployments + * Continues check in loop after a delay of registryConfig.fetchDeploymentRecordDelay + */ + async checkDeployRecordsAndUpdate(): Promise { + // Fetch deployments in building state + const deployments = await this.db.getDeployments({ + where: { + status: DeploymentStatus.Building + } + }) + + if (deployments.length) { + log( + `Found ${deployments.length} deployments in ${DeploymentStatus.Building} state` + ) + + // Calculate a timestamp for one hour ago + const anHourAgo = Date.now() - HOUR + + // Filter out deployments started more than an hour ago and mark them as Error + const oldDeploymentsToUpdate = deployments + .filter((deployment) => Number(deployment.updatedAt) < anHourAgo) + .map((deployment) => { + return this.db.updateDeploymentById(deployment.id, { + status: DeploymentStatus.Error, + isCurrent: false + }) + }) + + // If there are old deployments to update, log and perform the updates + if (oldDeploymentsToUpdate.length > 0) { + log( + `Cleaning up ${oldDeploymentsToUpdate.length} deployments stuck in ${DeploymentStatus.Building} state for over an hour` + ) + await Promise.all(oldDeploymentsToUpdate) + } + + // Fetch ApplicationDeploymentRecord for deployments + const records = + await this.laconicRegistry.getDeploymentRecords(deployments) + log(`Found ${records.length} ApplicationDeploymentRecords`) + + // Update deployments for which ApplicationDeploymentRecords were returned + if (records.length) { + await this.updateDeploymentsWithRecordData(records) + } + } + + this.deployRecordCheckTimeout = setTimeout(() => { + this.checkDeployRecordsAndUpdate() + }, this.config.registryConfig.fetchDeploymentRecordDelay) + } + + /** + * Checks for ApplicationDeploymentRemovalRecord and remove corresponding deployments + * Continues check in loop after a delay of registryConfig.fetchDeploymentRecordDelay + */ + async checkDeploymentRemovalRecordsAndUpdate(): Promise { + // Fetch deployments in deleting state + const deployments = await this.db.getDeployments({ + where: { + status: DeploymentStatus.Deleting + } + }) + + if (deployments.length) { + log( + `Found ${deployments.length} deployments in ${DeploymentStatus.Deleting} state` + ) + + // Fetch ApplicationDeploymentRemovalRecords for deployments + const records = + await this.laconicRegistry.getDeploymentRemovalRecords(deployments) + log(`Found ${records.length} ApplicationDeploymentRemovalRecords`) + + // Update deployments for which ApplicationDeploymentRemovalRecords were returned + if (records.length) { + await this.deleteDeploymentsWithRecordData(records, deployments) + } + } + + this.deployRecordCheckTimeout = setTimeout(() => { + this.checkDeploymentRemovalRecordsAndUpdate() + }, this.config.registryConfig.fetchDeploymentRecordDelay) + } + + /** + * Update deployments with ApplicationDeploymentRecord data + * Deployments that are completed but not updated in DB + */ + async updateDeploymentsWithRecordData( + records: AppDeploymentRecord[] + ): Promise { + // Fetch the deployments to be updated using deployment requestId + const deployments = await this.db.getDeployments({ + where: records.map((record) => ({ + applicationDeploymentRequestId: record.attributes.request + })), + relations: { + deployer: true, + project: true + }, + order: { + createdAt: 'DESC' + } + }) + + const recordToDeploymentsMap = deployments.reduce( + (acc: { [key: string]: Deployment }, deployment) => { + if (deployment.applicationDeploymentRequestId) { + acc[deployment.applicationDeploymentRequestId] = deployment + } + return acc + }, + {} + ) + + // Update deployment data for ApplicationDeploymentRecords + const deploymentUpdatePromises = records.map(async (record) => { + const deployment = recordToDeploymentsMap[record.attributes.request] + + if (!deployment.project) { + log(`Project ${deployment.projectId} not found`) + return + } + + const registryRecord = await this.laconicRegistry.getRecordById( + record.attributes.dns + ) + + if (!registryRecord) { + log(`DNS record not found for deployment ${deployment.id}`) + return + } + + const dnsRecord = registryRecord as DNSRecord + + const dnsRecordData: DNSRecordAttributes = { + name: dnsRecord.attributes.name, + request: dnsRecord.attributes.request, + resourceType: dnsRecord.attributes.resource_type, + value: dnsRecord.attributes.value, + version: dnsRecord.attributes.version + } + + deployment.applicationDeploymentRecordId = record.id + deployment.applicationDeploymentRecordData = record.attributes + deployment.url = record.attributes.url + deployment.status = DeploymentStatus.Ready + deployment.isCurrent = deployment.environment === Environment.Production + deployment.dnsRecordData = dnsRecordData + + if (deployment.isCanonical) { + const previousCanonicalDeployment = await this.db.getDeployment({ + where: { + projectId: deployment.project.id, + deployer: deployment.deployer, + isCanonical: true, + isCurrent: true + }, + relations: { + project: true, + deployer: true + } + }) + + if (previousCanonicalDeployment) { + // Send removal request for the previous canonical deployment and delete DB entry + if (previousCanonicalDeployment.url !== deployment.url) { + await this.laconicRegistry.createApplicationDeploymentRemovalRequest( + { + deploymentId: + previousCanonicalDeployment.applicationDeploymentRecordId!, + deployerLrn: previousCanonicalDeployment.deployer.deployerLrn, + auctionId: previousCanonicalDeployment.project.auctionId, + payment: previousCanonicalDeployment.project.txHash + } + ) + } + + await this.db.deleteDeploymentById(previousCanonicalDeployment.id) + } + } + + await this.db.updateDeploymentById(deployment.id, deployment) + + // Release deployer funds on successful deployment + if (!deployment.project.fundsReleased) { + const fundsReleased = await this.releaseDeployerFundsByProjectId( + deployment.projectId + ) + + // Return remaining amount to owner + await this.returnUserFundsByProjectId(deployment.projectId, true) + + await this.db.updateProjectById(deployment.projectId, { + fundsReleased + }) + } + + log( + `Updated deployment ${deployment.id} with URL ${record.attributes.url}` + ) + }) + + await Promise.all(deploymentUpdatePromises) + + // Get deployments that are in production environment + const prodDeployments = Object.values(recordToDeploymentsMap).filter( + (deployment) => deployment.isCurrent + ) + // Set the isCurrent state to false for the old deployments + for (const deployment of prodDeployments) { + const projectDeployments = await this.db.getDeploymentsByProjectId( + deployment.projectId + ) + + const oldDeployments = projectDeployments.filter( + (projectDeployment) => + projectDeployment.deployer.deployerLrn === + deployment.deployer.deployerLrn && + projectDeployment.id !== deployment.id && + projectDeployment.isCanonical === deployment.isCanonical + ) + for (const oldDeployment of oldDeployments) { + await this.db.updateDeployment( + { id: oldDeployment.id }, + { isCurrent: false } + ) + } + } + } + + /** + * Delete deployments with ApplicationDeploymentRemovalRecord data + */ + async deleteDeploymentsWithRecordData( + records: AppDeploymentRemovalRecord[], + deployments: Deployment[] + ): Promise { + const removedApplicationDeploymentRecordIds = records.map( + (record) => record.attributes.deployment + ) + + // Get removed deployments for ApplicationDeploymentRecords + const removedDeployments = deployments.filter((deployment) => + removedApplicationDeploymentRecordIds.includes( + deployment.applicationDeploymentRecordId! + ) + ) + + const recordToDeploymentsMap = removedDeployments.reduce( + (acc: { [key: string]: Deployment }, deployment) => { + if (deployment.applicationDeploymentRecordId) { + acc[deployment.applicationDeploymentRecordId] = deployment + } + return acc + }, + {} + ) + + // Update deployment data for ApplicationDeploymentRecords and delete + const deploymentUpdatePromises = records.map(async (record) => { + const deployment = recordToDeploymentsMap[record.attributes.deployment] + + await this.db.updateDeploymentById(deployment.id, { + applicationDeploymentRemovalRecordId: record.id, + applicationDeploymentRemovalRecordData: record.attributes + }) + + log( + `Updated deployment ${deployment.id} with ApplicationDeploymentRemovalRecord ${record.id}` + ) + + await this.db.deleteDeploymentById(deployment.id) + }) + + await Promise.all(deploymentUpdatePromises) + } + + /** + * Checks the status for all ongoing auctions + * Calls the createDeploymentFromAuction method for deployments with completed auctions + */ + async checkAuctionStatus(): Promise { + const projects = await this.db.allProjectsWithoutDeployments() + + const validAuctionIds = projects + .map((project) => project.auctionId) + .filter((id): id is string => Boolean(id)) + const completedAuctionIds = + await this.laconicRegistry.getCompletedAuctionIds(validAuctionIds) + + const projectsToBedeployed = projects.filter( + (project) => + project.auctionId && completedAuctionIds.includes(project.auctionId) + ) + + for (const project of projectsToBedeployed) { + const deployerRecords = + await this.laconicRegistry.getAuctionWinningDeployerRecords( + project!.auctionId! + ) + + if (!deployerRecords) { + log(`No winning deployer for auction ${project!.auctionId}`) + + // Return all funds to the owner + await this.returnUserFundsByProjectId(project.id, false) + } else { + const deployers = + await this.saveDeployersByDeployerRecords(deployerRecords) + for (const deployer of deployers) { + log(`Creating deployment for deployer ${deployer.deployerLrn}`) + await this.createDeploymentFromAuction(project, deployer) + // Update project with deployer + await this.updateProjectWithDeployer(project.id, deployer) + } + } + } + + this.auctionStatusCheckTimeout = setTimeout(() => { + this.checkAuctionStatus() + }, this.config.registryConfig.checkAuctionStatusDelay) + } + + async getUser(userId: string): Promise { + return this.db.getUser({ + where: { + id: userId + } + }) + } + + async getUserByEmail(email: string): Promise { + return await this.db.getUser({ + where: { + email + } + }) + } + + async getUserBySubOrgId(subOrgId: string): Promise { + return await this.db.getUser({ + where: { + subOrgId + } + }) + } + + async getUserByEthAddress(ethAddress: string): Promise { + return await this.db.getUser({ + where: { + ethAddress + } + }) + } + + async createUser(params: { + name?: string + email: string + subOrgId: string + ethAddress: string + turnkeyWalletId: string + }): Promise { + const [org] = await this.db.getOrganizations({}) + assert(org, 'No organizations exists in database') + + // Create user with new address + const user = await this.db.addUser({ + email: params.email, + name: params.name, + subOrgId: params.subOrgId, + ethAddress: params.ethAddress, + isVerified: true, + turnkeyWalletId: params.turnkeyWalletId + }) + + await this.db.addUserOrganization({ + member: user, + organization: org, + role: Role.Owner + }) + + return user + } + + async getOctokit(userId: string): Promise { + const user = await this.db.getUser({ where: { id: userId } }) + assert( + user?.gitHubToken, + 'User needs to be authenticated with GitHub token' + ) + + return new Octokit({ auth: user.gitHubToken }) + } + + async getOrganizationsByUserId(user: User): Promise { + const dbOrganizations = await this.db.getOrganizationsByUserId(user.id) + return dbOrganizations + } + + async getProjectById(user: User, projectId: string): Promise { + const dbProject = await this.db.getProjectById(projectId) + + if (dbProject && dbProject.owner.id !== user.id) { + return null + } + + return dbProject + } + + async getProjectsInOrganization( + user: User, + organizationSlug: string + ): Promise { + const dbProjects = await this.db.getProjectsInOrganization( + user.id, + organizationSlug + ) + return dbProjects + } + + async getNonCanonicalDeploymentsByProjectId( + projectId: string + ): Promise { + const nonCanonicalDeployments = + await this.db.getNonCanonicalDeploymentsByProjectId(projectId) + return nonCanonicalDeployments + } + + async getLatestDNSRecordByProjectId( + projectId: string + ): Promise { + const dnsRecord = await this.db.getLatestDNSRecordByProjectId(projectId) + return dnsRecord + } + + async getEnvironmentVariablesByProjectId( + projectId: string + ): Promise { + const dbEnvironmentVariables = + await this.db.getEnvironmentVariablesByProjectId(projectId) + return dbEnvironmentVariables + } + + async getProjectMembersByProjectId( + projectId: string + ): Promise { + const dbProjectMembers = + await this.db.getProjectMembersByProjectId(projectId) + return dbProjectMembers + } + + async searchProjects(user: User, searchText: string): Promise { + const dbProjects = await this.db.getProjectsBySearchText( + user.id, + searchText + ) + return dbProjects + } + + async getDomainsByProjectId( + projectId: string, + filter?: FindOptionsWhere + ): Promise { + const dbDomains = await this.db.getDomainsByProjectId(projectId, filter) + return dbDomains + } + + async updateProjectMember( + projectMemberId: string, + data: { permissions: Permission[] } + ): Promise { + return this.db.updateProjectMemberById(projectMemberId, data) + } + + async addProjectMember( + projectId: string, + data: { + email: string + permissions: Permission[] + } + ): Promise { + // TODO: Send invitation + let user = await this.db.getUser({ + where: { + email: data.email + } + }) + + if (!user) { + user = await this.db.addUser({ + email: data.email + }) + } + + const newProjectMember = await this.db.addProjectMember({ + project: { + id: projectId + }, + permissions: data.permissions, + isPending: true, + member: { + id: user.id + } + }) + + return newProjectMember + } + + async removeProjectMember( + user: User, + projectMemberId: string + ): Promise { + const member = await this.db.getProjectMemberById(projectMemberId) + + if (String(member.member.id) === user.id) { + throw new Error('Invalid operation: cannot remove self') + } + + const memberProject = member.project + assert(memberProject) + + if (String(user.id) === String(memberProject.owner.id)) { + return this.db.removeProjectMemberById(projectMemberId) + } + + throw new Error('Invalid operation: not authorized') + } + + async addEnvironmentVariables( + projectId: string, + data: { environments: string[]; key: string; value: string }[] + ): Promise { + const formattedEnvironmentVariables = data.flatMap( + (environmentVariable) => { + return environmentVariable.environments.map((environment) => { + return { + key: environmentVariable.key, + value: environmentVariable.value, + environment: environment as Environment, + project: Object.assign(new Project(), { + id: projectId + }) + } + }) + } + ) + + const savedEnvironmentVariables = await this.db.addEnvironmentVariables( + formattedEnvironmentVariables + ) + return savedEnvironmentVariables + } + + async updateEnvironmentVariable( + environmentVariableId: string, + data: DeepPartial + ): Promise { + return this.db.updateEnvironmentVariable(environmentVariableId, data) + } + + async removeEnvironmentVariable( + environmentVariableId: string + ): Promise { + return this.db.deleteEnvironmentVariable(environmentVariableId) + } + + async updateDeploymentToProd( + user: User, + deploymentId: string + ): Promise { + const oldDeployment = await this.db.getDeployment({ + where: { id: deploymentId }, + relations: { + project: true, + deployer: true + } + }) + + if (!oldDeployment) { + throw new Error('Deployment does not exist') + } + + const octokit = await this.getOctokit(user.id) + + const newDeployment = await this.createDeployment(user.id, octokit, { + project: oldDeployment.project, + branch: oldDeployment.branch, + environment: Environment.Production, + commitHash: oldDeployment.commitHash, + commitMessage: oldDeployment.commitMessage, + deployer: oldDeployment.deployer + }) + + return newDeployment + } + + async createDeployment( + userId: string, + octokit: Octokit, + data: DeepPartial, + deployerLrn?: string + ): Promise { + assert(data.project?.repository, 'Project repository not found') + log( + `Creating deployment in project ${data.project.name} from branch ${data.branch}` + ) + + // TODO: Set environment variables for each deployment (environment variables can`t be set in application record) + const { applicationRecordId, applicationRecordData } = + await this.laconicRegistry.createApplicationRecord({ + octokit, + repository: data.project.repository, + appType: data.project!.template!, + commitHash: data.commitHash! + }) + + let deployer: Deployer | undefined + if (deployerLrn) { + const found = await this.db.getDeployerByLRN(deployerLrn) + deployer = found || undefined + } else { + deployer = data.deployer as Deployer + } + + const deployment = await this.createDeploymentFromData( + userId, + data, + deployer!.deployerLrn!, + applicationRecordId, + applicationRecordData, + false + ) + + const address = await this.getAddress() + const { repo, repoUrl } = await getRepoDetails( + octokit, + data.project.repository, + data.commitHash + ) + const environmentVariablesObj = await this.getEnvVariables( + data.project!.id! + ) + + // To set project DNS + if (data.environment === Environment.Production) { + const canonicalDeployment = await this.createDeploymentFromData( + userId, + data, + deployer!.deployerLrn!, + applicationRecordId, + applicationRecordData, + true + ) + // If a custom domain is present then use that as the DNS in the deployment request + const customDomain = await this.db.getOldestDomainByProjectId( + data.project!.id! + ) + + // On deleting deployment later, project canonical deployment is also deleted + // So publish project canonical deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later + const { + applicationDeploymentRequestData, + applicationDeploymentRequestId + } = await this.laconicRegistry.createApplicationDeploymentRequest({ + deployment: canonicalDeployment, + appName: repo, + repository: repoUrl, + environmentVariables: environmentVariablesObj, + dns: customDomain?.name ?? `${canonicalDeployment.project.name}`, + lrn: deployer!.deployerLrn!, + apiUrl: deployer!.deployerApiUrl!, + payment: data.project.txHash, + auctionId: data.project.auctionId, + requesterAddress: address, + publicKey: deployer!.publicKey! + }) + + await this.db.updateDeploymentById(canonicalDeployment.id, { + applicationDeploymentRequestId, + applicationDeploymentRequestData + }) + } + + const { applicationDeploymentRequestId, applicationDeploymentRequestData } = + await this.laconicRegistry.createApplicationDeploymentRequest({ + deployment: deployment, + appName: repo, + repository: repoUrl, + lrn: deployer!.deployerLrn!, + apiUrl: deployer!.deployerApiUrl!, + environmentVariables: environmentVariablesObj, + dns: `${deployment.project.name}-${deployment.id}`, + payment: data.project.txHash, + auctionId: data.project.auctionId, + requesterAddress: address, + publicKey: deployer!.publicKey! + }) + + await this.db.updateDeploymentById(deployment.id, { + applicationDeploymentRequestId, + applicationDeploymentRequestData + }) + + return deployment + } + + async createDeploymentFromAuction( + project: DeepPartial, + deployer: Deployer + ): Promise { + const octokit = await this.getOctokit(project.ownerId!) + const [owner, repo] = project.repository!.split('/') + + const repoUrl = ( + await octokit.rest.repos.get({ + owner, + repo + }) + ).data.html_url + + const { + data: [latestCommit] + } = await octokit.rest.repos.listCommits({ + owner, + repo, + sha: project.prodBranch, + per_page: 1 + }) + + const lrn = this.laconicRegistry.getLrn(repo) + const [record] = await this.laconicRegistry.getRecordsByName(lrn) + const applicationRecordId = record.id + const applicationRecordData = record.attributes + + const deployerLrn = deployer!.deployerLrn + + // Create deployment with prod branch and latest commit + const deploymentData = { + project, + branch: project.prodBranch, + environment: Environment.Production, + domain: null, + commitHash: latestCommit.sha, + commitMessage: latestCommit.commit.message + } + + const deployment = await this.createDeploymentFromData( + project.ownerId!, + deploymentData, + deployerLrn, + applicationRecordId, + applicationRecordData, + false + ) + const address = await this.getAddress() + + const environmentVariablesObj = await this.getEnvVariables(project!.id!) + // To set project DNS + if (deploymentData.environment === Environment.Production) { + const canonicalDeployment = await this.createDeploymentFromData( + project.ownerId!, + deploymentData, + deployerLrn, + applicationRecordId, + applicationRecordData, + true + ) + // If a custom domain is present then use that as the DNS in the deployment request + const customDomain = await this.db.getOldestDomainByProjectId( + project!.id! + ) + + // On deleting deployment later, project canonical deployment is also deleted + // So publish project canonical deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later + const { + applicationDeploymentRequestId, + applicationDeploymentRequestData + } = await this.laconicRegistry.createApplicationDeploymentRequest({ + deployment: canonicalDeployment, + appName: repo, + repository: repoUrl, + environmentVariables: environmentVariablesObj, + dns: customDomain?.name ?? `${canonicalDeployment.project.name}`, + auctionId: project.auctionId!, + lrn: deployerLrn, + apiUrl: deployer!.deployerApiUrl!, + requesterAddress: address, + publicKey: deployer!.publicKey! + }) + + await this.db.updateDeploymentById(canonicalDeployment.id, { + applicationDeploymentRequestId, + applicationDeploymentRequestData + }) + } + + const { applicationDeploymentRequestId, applicationDeploymentRequestData } = + // Create requests for all the deployers + await this.laconicRegistry.createApplicationDeploymentRequest({ + deployment: deployment, + appName: repo, + repository: repoUrl, + auctionId: project.auctionId!, + lrn: deployerLrn, + apiUrl: deployer!.deployerApiUrl!, + environmentVariables: environmentVariablesObj, + dns: `${deployment.project.name}-${deployment.id}`, + requesterAddress: address, + publicKey: deployer!.publicKey! + }) + + await this.db.updateDeploymentById(deployment.id, { + applicationDeploymentRequestId, + applicationDeploymentRequestData + }) + + return deployment + } + + async createDeploymentFromData( + userId: string, + data: DeepPartial, + deployerLrn: string, + applicationRecordId: string, + applicationRecordData: ApplicationRecord, + isCanonical: boolean + ): Promise { + const newDeployment = await this.db.addDeployment({ + project: data.project, + branch: data.branch, + commitHash: data.commitHash, + commitMessage: data.commitMessage, + environment: data.environment, + status: DeploymentStatus.Building, + applicationRecordId, + applicationRecordData, + createdBy: Object.assign(new User(), { + id: userId + }), + deployer: Object.assign(new Deployer(), { + deployerLrn + }), + isCanonical + }) + + log(`Created deployment ${newDeployment.id}`) + + return newDeployment + } + + async updateProjectWithDeployer( + projectId: string, + deployer: Deployer + ): Promise { + const deploymentProject = await this.db.getProjects({ + where: { id: projectId }, + relations: ['deployers'] + }) + + if (!deploymentProject[0].deployers) { + deploymentProject[0].deployers = [] + } + + deploymentProject[0].deployers.push(deployer) + + await this.db.saveProject(deploymentProject[0]) + + return deployer + } + + async addProjectFromTemplate( + user: User, + organizationSlug: string, + data: AddProjectFromTemplateInput, + lrn?: string, + auctionParams?: AuctionParams, + environmentVariables?: EnvironmentVariables[] + ): Promise { + try { + const octokit = await this.getOctokit(user.id) + + const gitRepo = await octokit?.rest.repos.createUsingTemplate({ + template_owner: data.templateOwner, + template_repo: data.templateRepo, + owner: data.owner, + name: data.name, + include_all_branches: false, + private: data.isPrivate + }) + + if (!gitRepo) { + throw new Error('Failed to create repository from template') + } + + const createdTemplateRepo = await octokit.rest.repos.get({ + owner: data.owner, + repo: data.name + }) + + const prodBranch = createdTemplateRepo.data.default_branch ?? 'main' + + const project = await this.addProject( + user, + organizationSlug, + { + name: `${gitRepo.data.owner!.login}-${gitRepo.data.name}`, + prodBranch, + repository: gitRepo.data.full_name, + // TODO: Set selected template + template: 'webapp', + paymentAddress: data.paymentAddress, + txHash: data.txHash + }, + lrn, + auctionParams, + environmentVariables + ) + + if (!project || !project.id) { + throw new Error('Failed to create project from template') + } + + return project + } catch (error) { + console.error('Error creating project from template:', error) + throw error + } + } + + async addProject( + user: User, + organizationSlug: string, + data: DeepPartial, + lrn?: string, + auctionParams?: AuctionParams, + environmentVariables?: EnvironmentVariables[] + ): Promise { + const organization = await this.db.getOrganization({ + where: { + slug: organizationSlug + } + }) + + if (!organization) { + throw new Error('Organization does not exist') + } + + const project = await this.db.addProject(user, organization.id, data) + + if (environmentVariables) { + await this.addEnvironmentVariables(project.id, environmentVariables) + } + + const octokit = await this.getOctokit(user.id) + const [owner, repo] = project.repository.split('/') + + const { + data: [latestCommit] + } = await octokit.rest.repos.listCommits({ + owner, + repo, + sha: project.prodBranch, + per_page: 1 + }) + + if (auctionParams) { + // Create deployment with prod branch and latest commit + const deploymentData = { + project, + branch: project.prodBranch, + environment: Environment.Production, + domain: null, + commitHash: latestCommit.sha, + commitMessage: latestCommit.commit.message + } + const { applicationDeploymentAuctionId } = + await this.laconicRegistry.createApplicationDeploymentAuction( + repo, + octokit, + auctionParams!, + deploymentData + ) + await this.updateProject(project.id, { + auctionId: applicationDeploymentAuctionId + }) + } else { + const deployer = await this.db.getDeployerByLRN(lrn!) + + if (!deployer) { + log('Invalid deployer LRN') + return + } + + if (deployer.minimumPayment && project.txHash) { + const amountToBePaid = deployer?.minimumPayment + .replace(/\D/g, '') + .toString() + + const txResponse = await this.laconicRegistry.sendTokensToAccount( + deployer?.paymentAddress!, + amountToBePaid + ) + + const txHash = txResponse.transactionHash + if (txHash) { + await this.updateProject(project.id, { txHash }) + project.txHash = txHash + log('Funds transferrend to deployer') + } + } + + const deploymentData = { + project, + branch: project.prodBranch, + environment: Environment.Production, + domain: null, + commitHash: latestCommit.sha, + commitMessage: latestCommit.commit.message, + deployer + } + + const newDeployment = await this.createDeployment( + user.id, + octokit, + deploymentData + ) + // Update project with deployer + await this.updateProjectWithDeployer( + newDeployment.projectId, + newDeployment.deployer + ) + } + + await this.createRepoHook(octokit, project) + + return project + } + + async createRepoHook(octokit: Octokit, project: Project): Promise { + try { + const [owner, repo] = project.repository.split('/') + await octokit.rest.repos.createWebhook({ + owner, + repo, + config: { + url: new URL( + 'api/github/webhook', + this.config.gitHubConfig.webhookUrl + ).href, + content_type: 'json' + }, + events: ['push'] + }) + } catch (err) { + // https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook--status-codes + if ( + !( + err instanceof RequestError && + err.status === 422 && + (err.response?.data as any).errors.some( + (err: any) => err.message === GITHUB_UNIQUE_WEBHOOK_ERROR + ) + ) + ) { + throw err + } + + log(GITHUB_UNIQUE_WEBHOOK_ERROR) + } + } + + async handleGitHubPush(data: GitPushEventPayload): Promise { + const { repository, ref, head_commit: headCommit, deleted } = data + + if (deleted) { + log(`Branch ${ref} deleted for project ${repository.full_name}`) + return + } + + log( + `Handling GitHub push event from repository: ${repository.full_name}, branch: ${ref}` + ) + const projects = await this.db.getProjects({ + where: { repository: repository.full_name }, + relations: { + deployers: true + } + }) + + if (!projects.length) { + log(`No projects found for repository ${repository.full_name}`) + } + + // The `ref` property contains the full reference, including the branch name + // For example, "refs/heads/main" or "refs/heads/feature-branch" + const branch = ref.split('/').pop() + + for await (const project of projects) { + const octokit = await this.getOctokit(project.ownerId) + + const deployers = project.deployers + if (!deployers) { + log(`No deployer present for project ${project.id}`) + return + } + + for (const deployer of deployers) { + // Create deployment with branch and latest commit in GitHub data + await this.createDeployment(project.ownerId, octokit, { + project, + branch, + environment: + project.prodBranch === branch + ? Environment.Production + : Environment.Preview, + commitHash: headCommit.id, + commitMessage: headCommit.message, + deployer: deployer + }) + } + } + } + + async updateProject( + projectId: string, + data: DeepPartial + ): Promise { + return this.db.updateProjectById(projectId, data) + } + + async deleteProject(projectId: string): Promise { + // TODO: Remove GitHub repo hook + return this.db.deleteProjectById(projectId) + } + + async deleteDomain(domainId: string): Promise { + const domainsRedirectedFrom = await this.db.getDomains({ + where: { + redirectToId: domainId + } + }) + + if (domainsRedirectedFrom.length > 0) { + throw new Error( + 'Cannot delete domain since it has redirects from other domains' + ) + } + + return this.db.deleteDomainById(domainId) + } + + async redeployToProd(user: User, deploymentId: string): Promise { + const oldDeployment = await this.db.getDeployment({ + relations: { + project: true, + deployer: true, + createdBy: true + }, + where: { + id: deploymentId + } + }) + + if (oldDeployment === null) { + throw new Error('Deployment not found') + } + + const octokit = await this.getOctokit(user.id) + + let newDeployment: Deployment + + if (oldDeployment.project.auctionId) { + newDeployment = await this.createDeploymentFromAuction( + oldDeployment.project, + oldDeployment.deployer + ) + } else { + newDeployment = await this.createDeployment(user.id, octokit, { + project: oldDeployment.project, + // TODO: Put isCurrent field in project + branch: oldDeployment.branch, + environment: Environment.Production, + commitHash: oldDeployment.commitHash, + commitMessage: oldDeployment.commitMessage, + deployer: oldDeployment.deployer + }) + } + + return newDeployment + } + + async rollbackDeployment( + projectId: string, + deploymentId: string + ): Promise { + // TODO: Implement transactions + const oldCurrentDeployment = await this.db.getDeployment({ + relations: { + project: true, + deployer: true + }, + where: { + project: { + id: projectId + }, + isCurrent: true, + isCanonical: false + } + }) + + if (!oldCurrentDeployment) { + throw new Error('Current deployment does not exist') + } + + const oldCurrentDeploymentUpdate = await this.db.updateDeploymentById( + oldCurrentDeployment.id, + { isCurrent: false } + ) + + const newCurrentDeploymentUpdate = await this.db.updateDeploymentById( + deploymentId, + { isCurrent: true } + ) + + if (!newCurrentDeploymentUpdate || !oldCurrentDeploymentUpdate) { + return false + } + + const newCurrentDeployment = await this.db.getDeployment({ + where: { id: deploymentId }, + relations: { project: true, deployer: true } + }) + + if (!newCurrentDeployment) { + throw new Error(`Deployment with Id ${deploymentId} not found`) + } + + const applicationDeploymentRequestData = + newCurrentDeployment.applicationDeploymentRequestData + + const customDomain = await this.db.getOldestDomainByProjectId(projectId) + + if (customDomain && applicationDeploymentRequestData) { + applicationDeploymentRequestData.dns = customDomain.name + } + + // Create a canonical deployment for the new current deployment + const canonicalDeployment = await this.createDeploymentFromData( + newCurrentDeployment.project.ownerId, + newCurrentDeployment, + newCurrentDeployment.deployer!.deployerLrn!, + newCurrentDeployment.applicationRecordId, + newCurrentDeployment.applicationRecordData, + true + ) + + applicationDeploymentRequestData!.meta = JSON.stringify({ + ...JSON.parse(applicationDeploymentRequestData!.meta), + note: `Updated by Snowball @ ${DateTime.utc().toFormat( + "EEE LLL dd HH:mm:ss 'UTC' yyyy" + )}` + }) + + const result = await this.laconicRegistry.publishRecord( + applicationDeploymentRequestData + ) + + log(`Application deployment request record published: ${result.id}`) + + const updateResult = await this.db.updateDeploymentById( + canonicalDeployment.id, + { + applicationDeploymentRequestId: result.id, + applicationDeploymentRequestData + } + ) + + return updateResult + } + + async deleteDeployment(deploymentId: string): Promise { + const deployment = await this.db.getDeployment({ + where: { + id: deploymentId + }, + relations: { + project: true, + deployer: true + } + }) + + if (deployment?.applicationDeploymentRecordId) { + // If deployment is current, remove deployment for project subdomain as well + if (deployment.isCurrent) { + const canonicalDeployment = await this.db.getDeployment({ + where: { + projectId: deployment.project.id, + deployer: deployment.deployer, + isCanonical: true + }, + relations: { + project: true, + deployer: true + } + }) + + // If the canonical deployment is not present then query the chain for the deployment record for backward compatibility + if (!canonicalDeployment) { + log( + `Canonical deployment for deployment with id ${deployment.id} not found, querying the chain..` + ) + const currentDeploymentURL = `https://${(deployment.project.name).toLowerCase()}.${deployment.deployer.baseDomain}` + + const deploymentRecords = + await this.laconicRegistry.getDeploymentRecordsByFilter({ + application: deployment.applicationRecordId, + url: currentDeploymentURL + }) + + if (!deploymentRecords.length) { + log( + `No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}` + ) + + return false + } + + // Multiple records are fetched, take the latest record + const latestRecord = deploymentRecords.sort( + (a, b) => + new Date(b.createTime).getTime() - + new Date(a.createTime).getTime() + )[0] + + await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ + deploymentId: latestRecord.id, + deployerLrn: deployment.deployer.deployerLrn, + auctionId: deployment.project.auctionId, + payment: deployment.project.txHash + }) + } else { + // If canonical deployment is found in the DB, then send the removal request with that deployment record Id + const result = + await this.laconicRegistry.createApplicationDeploymentRemovalRequest( + { + deploymentId: + canonicalDeployment.applicationDeploymentRecordId!, + deployerLrn: canonicalDeployment.deployer.deployerLrn, + auctionId: canonicalDeployment.project.auctionId, + payment: canonicalDeployment.project.txHash + } + ) + + await this.db.updateDeploymentById(canonicalDeployment.id, { + status: DeploymentStatus.Deleting, + applicationDeploymentRemovalRequestId: + result.applicationDeploymentRemovalRequestId, + applicationDeploymentRemovalRequestData: + result.applicationDeploymentRemovalRequestData + }) + } + } + + const result = + await this.laconicRegistry.createApplicationDeploymentRemovalRequest({ + deploymentId: deployment.applicationDeploymentRecordId, + deployerLrn: deployment.deployer.deployerLrn, + auctionId: deployment.project.auctionId, + payment: deployment.project.txHash + }) + + await this.db.updateDeploymentById(deployment.id, { + status: DeploymentStatus.Deleting, + applicationDeploymentRemovalRequestId: + result.applicationDeploymentRemovalRequestId, + applicationDeploymentRemovalRequestData: + result.applicationDeploymentRemovalRequestData + }) + + return result !== undefined || result !== null + } + + return false + } + + async addDomain( + projectId: string, + data: { name: string } + ): Promise<{ + primaryDomain: Domain + // redirectedDomain: Domain; + }> { + const currentProject = await this.db.getProjectById(projectId) + + if (currentProject === null) { + throw new Error(`Project with ${projectId} not found`) + } + + const primaryDomainDetails = { + ...data, + branch: currentProject.prodBranch, + project: currentProject + } + + const savedPrimaryDomain = await this.db.addDomain(primaryDomainDetails) + + // const domainArr = data.name.split('www.'); + + // const redirectedDomainDetails = { + // name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`, + // branch: currentProject.prodBranch, + // project: currentProject, + // redirectTo: savedPrimaryDomain, + // }; + + // const savedRedirectedDomain = await this.db.addDomain( + // redirectedDomainDetails, + // ); + + return { + primaryDomain: savedPrimaryDomain + // redirectedDomain: savedRedirectedDomain, + } + } + + async updateDomain( + domainId: string, + data: DeepPartial + ): Promise { + const domain = await this.db.getDomain({ + where: { + id: domainId + } + }) + + if (domain === null) { + throw new Error(`Error finding domain with id ${domainId}`) + } + + const newDomain = { + ...data + } + + const domainsRedirectedFrom = await this.db.getDomains({ + where: { + project: { + id: domain.projectId + }, + redirectToId: domain.id + } + }) + + // If there are domains redirecting to current domain, only branch of current domain can be updated + if (domainsRedirectedFrom.length > 0 && data.branch === domain.branch) { + throw new Error('Remove all redirects to this domain before updating') + } + + if (data.redirectToId) { + const redirectedDomain = await this.db.getDomain({ + where: { + id: data.redirectToId + } + }) + + if (redirectedDomain === null) { + throw new Error('Could not find Domain to redirect to') + } + + if (redirectedDomain.redirectToId) { + throw new Error( + 'Unable to redirect to the domain because it is already redirecting elsewhere. Redirects cannot be chained.' + ) + } + + newDomain.redirectTo = redirectedDomain + } + + const updateResult = await this.db.updateDomainById(domainId, newDomain) + + return updateResult + } + + async authenticateGitHub( + code: string, + user: User + ): Promise<{ token: string }> { + const { + authentication: { token } + } = await this.oauthApp.createToken({ + code + }) + + await this.db.updateUser(user, { gitHubToken: token }) + + return { token } + } + + async unauthenticateGitHub( + user: User, + data: DeepPartial + ): Promise { + return this.db.updateUser(user, data) + } + + async getEnvVariables(projectId: string): Promise<{ [key: string]: string }> { + const environmentVariables = + await this.db.getEnvironmentVariablesByProjectId(projectId, { + environment: Environment.Production + }) + + const environmentVariablesObj = environmentVariables.reduce( + (acc, env) => { + acc[env.key] = env.value + return acc + }, + {} as { [key: string]: string } + ) + + return environmentVariablesObj + } + + async getAuctionData(auctionId: string): Promise { + const auctions = await this.laconicRegistry.getAuctionData(auctionId) + return auctions[0] + } + + async releaseDeployerFundsByProjectId(projectId: string): Promise { + const project = await this.db.getProjectById(projectId) + + if (!project || !project.auctionId) { + log( + `Project ${projectId} ${!project ? 'not found' : 'does not have an auction'}` + ) + + return false + } + + const auction = await this.laconicRegistry.releaseDeployerFunds( + project.auctionId + ) + + if (auction.auction.fundsReleased) { + log(`Funds released for auction ${project.auctionId}`) + await this.db.updateProjectById(projectId, { fundsReleased: true }) + + return true + } + + log(`Error releasing funds for auction ${project.auctionId}`) + + return false + } + + async returnUserFundsByProjectId( + projectId: string, + winningDeployersPresent: boolean + ) { + const project = await this.db.getProjectById(projectId) + + if (!project || !project.auctionId) { + log( + `Project ${projectId} ${!project ? 'not found' : 'does not have an auction'}` + ) + + return false + } + + const auction = await this.getAuctionData(project.auctionId) + const totalAuctionPrice = + Number(auction.maxPrice.quantity) * auction.numProviders + + let amountToBeReturned: number + if (winningDeployersPresent) { + amountToBeReturned = + totalAuctionPrice - + auction.winnerAddresses.length * Number(auction.winnerPrice.quantity) + } else { + amountToBeReturned = totalAuctionPrice + } + + if (amountToBeReturned !== 0) { + await this.laconicRegistry.sendTokensToAccount( + project.paymentAddress, + amountToBeReturned.toString() + ) + } + } + + async getDeployers(): Promise { + const dbDeployers = await this.db.getDeployers() + + if (dbDeployers.length > 0) { + // Call asynchronously to fetch the records from the registry and update the DB + this.updateDeployersFromRegistry() + return dbDeployers + } + + // Fetch from the registry and populate empty DB + return await this.updateDeployersFromRegistry() + } + + async updateDeployersFromRegistry(): Promise { + const deployerRecords = + await this.laconicRegistry.getDeployerRecordsByFilter({}) + await this.saveDeployersByDeployerRecords(deployerRecords) + + return await this.db.getDeployers() + } + + async saveDeployersByDeployerRecords( + deployerRecords: DeployerRecord[] + ): Promise { + const deployers: Deployer[] = [] + + for (const record of deployerRecords) { + if (record.names && record.names.length > 0) { + const deployerId = record.id + const deployerLrn = record.names[0] + const deployerApiUrl = record.attributes.apiUrl + const minimumPayment = record.attributes.minimumPayment + const paymentAddress = record.attributes.paymentAddress + const publicKey = record.attributes.publicKey + const baseDomain = deployerApiUrl.substring( + deployerApiUrl.indexOf('.') + 1 + ) + + const deployerData = { + deployerLrn, + deployerId, + deployerApiUrl, + baseDomain, + minimumPayment, + paymentAddress, + publicKey + } + + // TODO: Update deployers table in a separate job + const deployer = await this.db.addDeployer(deployerData) + deployers.push(deployer) + } + } + + return deployers + } + + async getAddress(): Promise { + const account = await this.laconicRegistry.getAccount() + + return account.address + } + + async verifyTx( + txHash: string, + amountSent: string, + senderAddress: string + ): Promise { + const txResponse = await this.laconicRegistry.getTxResponse(txHash) + if (!txResponse) { + log('Transaction response not found') + return false + } + + const transfer = txResponse.events.find( + (e: any) => + e.type === 'transfer' && + e.attributes.some((a: any) => a.key === 'msg_index') + ) + if (!transfer) { + log('No transfer event found') + return false + } + + const sender = transfer.attributes.find( + (a: any) => a.key === 'sender' + )?.value + const recipient = transfer.attributes.find( + (a: any) => a.key === 'recipient' + )?.value + const amount = transfer.attributes.find( + (a: any) => a.key === 'amount' + )?.value + + const recipientAddress = await this.getAddress() + + return ( + amount === amountSent && + sender === senderAddress && + recipient === recipientAddress + ) + } +} diff --git a/apps/backend/src/turnkey-backend.ts b/apps/backend/src/turnkey-backend.ts new file mode 100644 index 0000000..2336bdd --- /dev/null +++ b/apps/backend/src/turnkey-backend.ts @@ -0,0 +1,130 @@ +import { Turnkey, type TurnkeyApiTypes } from '@turnkey/sdk-server' + +// Default path for the first Ethereum address in a new HD wallet. +// See https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki, paths are in the form: +// m / purpose' / coin_type' / account' / change / address_index +// - Purpose is a constant set to 44' following the BIP43 recommendation. +// - Coin type is set to 60 (ETH) -- see https://github.com/satoshilabs/slips/blob/master/slip-0044.md +// - Account, Change, and Address Index are set to 0 +import { DEFAULT_ETHEREUM_ACCOUNTS } from '@turnkey/sdk-server' +import type { Service } from './service' +import { getConfig } from './utils' + +type TAttestation = TurnkeyApiTypes['v1Attestation'] + +type CreateUserParams = { + userName: string + userEmail: string + challenge: string + attestation: TAttestation +} + +export async function createUser( + service: Service, + { userName, userEmail, challenge, attestation }: CreateUserParams +) { + try { + if (await service.getUserByEmail(userEmail)) { + throw new Error(`User already exists: ${userEmail}`) + } + + const config = await getConfig() + const turnkey = new Turnkey(config.turnkey) + + const apiClient = turnkey.api() + + const walletName = 'Default ETH Wallet' + + const createSubOrgResponse = await apiClient.createSubOrganization({ + subOrganizationName: `Default SubOrg for ${userEmail}`, + rootQuorumThreshold: 1, + rootUsers: [ + { + userName, + userEmail, + apiKeys: [], + authenticators: [ + { + authenticatorName: 'Passkey', + challenge, + attestation + } + ] + } + ], + wallet: { + walletName: walletName, + accounts: DEFAULT_ETHEREUM_ACCOUNTS + } + }) + + const subOrgId = refineNonNull(createSubOrgResponse.subOrganizationId) + const wallet = refineNonNull(createSubOrgResponse.wallet) + + const result = { + id: wallet.walletId, + address: wallet.addresses[0], + subOrgId: subOrgId + } + console.log('Turnkey success', result) + + const user = await service.createUser({ + name: userName, + email: userEmail, + subOrgId, + ethAddress: wallet.addresses[0], + turnkeyWalletId: wallet.walletId + }) + console.log('New user', user) + + return user + } catch (e) { + console.error('Failed to create user:', e) + throw e + } +} + +export async function authenticateUser( + service: Service, + signedWhoamiRequest: { + url: string + body: any + stamp: { + stampHeaderName: string + stampHeaderValue: string + } + } +) { + try { + const tkRes = await fetch(signedWhoamiRequest.url, { + method: 'POST', + body: signedWhoamiRequest.body, + headers: { + [signedWhoamiRequest.stamp.stampHeaderName]: + signedWhoamiRequest.stamp.stampHeaderValue + } + }) + console.log('AUTH RESULT', tkRes.status) + if (tkRes.status !== 200) { + console.log(await tkRes.text()) + return null + } + const orgId = (await tkRes.json()).organizationId + const user = await service.getUserBySubOrgId(orgId) + return user + } catch (e) { + console.error('Failed to authenticate:', e) + throw e + } +} + +function refineNonNull( + input: T | null | undefined, + errorMessage?: string +): T { + if (input == null) { + throw new Error(errorMessage ?? `Unexpected ${JSON.stringify(input)}`) + } + + return input +} diff --git a/apps/backend/src/types.ts b/apps/backend/src/types.ts new file mode 100644 index 0000000..82f6111 --- /dev/null +++ b/apps/backend/src/types.ts @@ -0,0 +1,124 @@ +export interface PackageJSON { + name: string + version: string + author?: string + description?: string + homepage?: string + license?: string + repository?: string +} + +export interface GitRepositoryDetails { + id: number + name: string + full_name: string + visibility?: string + updated_at?: string | null + default_branch?: string +} + +export interface GitPushEventPayload { + repository: GitRepositoryDetails + ref: string + head_commit: { + id: string + message: string + } + deleted: boolean +} + +export interface AppDeploymentRecordAttributes { + application: string + auction: string + deployer: string + dns: string + meta: string + name: string + request: string + type: string + url: string + version: string +} + +export interface DNSRecordAttributes { + name: string + value: string + request: string + resourceType: string + version: string +} + +export interface RegistryDNSRecordAttributes { + name: string + value: string + request: string + resource_type: string + version: string +} + +export interface AppDeploymentRemovalRecordAttributes { + deployment: string + request: string + type: 'ApplicationDeploymentRemovalRecord' + version: string +} + +export interface RegistryRecord { + id: string + names: string[] | null + owners: string[] + bondId: string + createTime: string + expiryTime: string +} + +export interface AppDeploymentRecord extends RegistryRecord { + attributes: AppDeploymentRecordAttributes +} + +export interface AppDeploymentRemovalRecord extends RegistryRecord { + attributes: AppDeploymentRemovalRecordAttributes +} + +export interface DNSRecord extends RegistryRecord { + attributes: RegistryDNSRecordAttributes +} + +export interface AddProjectFromTemplateInput { + templateOwner: string + templateRepo: string + owner: string + name: string + isPrivate: boolean + paymentAddress: string + txHash: string +} + +export interface AuctionParams { + maxPrice: string + numProviders: number +} + +export interface EnvironmentVariables { + environments: string[] + key: string + value: string +} + +export interface DeployerRecord { + id: string + names: string[] + owners: string[] + bondId: string + createTime: string + expiryTime: string + attributes: { + apiUrl: string + minimumPayment: string | null + name: string + paymentAddress: string + publicKey: string + type: string + version: string + } +} diff --git a/apps/backend/src/utils.ts b/apps/backend/src/utils.ts new file mode 100644 index 0000000..f55d79d --- /dev/null +++ b/apps/backend/src/utils.ts @@ -0,0 +1,152 @@ +import assert from 'node:assert' +import path from 'node:path' +import debug from 'debug' +import fs from 'fs-extra' +import type { Octokit } from 'octokit' +import toml from 'toml' +import type { + DataSource, + DeepPartial, + EntityTarget, + ObjectLiteral +} from 'typeorm' + +import type { Config } from './config' +import { DEFAULT_CONFIG_FILE_PATH } from './constants' +import type { PackageJSON } from './types' + +const log = debug('snowball:utils') + +export async function getConfig() { + // TODO: get config path using cli + return await _getConfig(DEFAULT_CONFIG_FILE_PATH) +} + +const _getConfig = async ( + configFile: string +): Promise => { + const configFilePath = path.resolve(configFile) + const fileExists = await fs.pathExists(configFilePath) + if (!fileExists) { + throw new Error(`Config file not found: ${configFilePath}`) + } + + const config = toml.parse(await fs.readFile(configFilePath, 'utf8')) + log('config', JSON.stringify(config, null, 2)) + + return config +} + +export const checkFileExists = async (filePath: string): Promise => { + try { + await fs.access(filePath, fs.constants.F_OK) + return true + } catch (err) { + log(err) + return false + } +} + +export const getEntities = async (filePath: string): Promise => { + const entitiesData = await fs.readFile(filePath, 'utf-8') + const entities = JSON.parse(entitiesData) + return entities +} + +export const loadAndSaveData = async ( + entityType: EntityTarget, + dataSource: DataSource, + entities: any, + relations?: any | undefined +): Promise => { + const entityRepository = dataSource.getRepository(entityType) + + const savedEntity: Entity[] = [] + + for (const entityData of entities) { + let entity = entityRepository.create(entityData as DeepPartial) + + if (relations) { + for (const field in relations) { + const valueIndex = `${field}Index` + + entity = { + ...entity, + [field]: relations[field][entityData[valueIndex]] + } + } + } + const dbEntity = await entityRepository.save(entity) + savedEntity.push(dbEntity) + } + + return savedEntity +} + +export const sleep = async (ms: number): Promise => + new Promise((resolve) => setTimeout(resolve, ms)) + +export const getRepoDetails = async ( + octokit: Octokit, + repository: string, + commitHash: string | undefined +): Promise<{ + repo: string + packageJSON: PackageJSON + repoUrl: string +}> => { + const [owner, repo] = repository.split('/') + const { data: packageJSONData } = await octokit.rest.repos.getContent({ + owner, + repo, + path: 'package.json', + ref: commitHash + }) + + if (!packageJSONData) { + throw new Error('Package.json file not found') + } + + assert(!Array.isArray(packageJSONData) && packageJSONData.type === 'file') + const packageJSON: PackageJSON = JSON.parse(atob(packageJSONData.content)) + + assert(packageJSON.name, "name field doesn't exist in package.json") + + const repoUrl = ( + await octokit.rest.repos.get({ + owner, + repo + }) + ).data.html_url + + return { + repo, + packageJSON, + repoUrl + } +} + +// Wrapper method for registry txs to retry once if 'account sequence mismatch' occurs +export const registryTransactionWithRetry = async ( + txMethod: () => Promise +): Promise => { + try { + return await txMethod() + } catch (error: any) { + if (!error.message.includes('account sequence mismatch')) { + throw error + } + + console.error( + 'Transaction failed due to account sequence mismatch. Retrying...' + ) + + try { + return await txMethod() + } catch (retryError: any) { + throw new Error( + `Transaction failed again after retry: ${retryError.message}` + ) + } + } +} diff --git a/apps/backend/test/delete-db.ts b/apps/backend/test/delete-db.ts new file mode 100644 index 0000000..1872b30 --- /dev/null +++ b/apps/backend/test/delete-db.ts @@ -0,0 +1,19 @@ +import * as fs from 'node:fs/promises' +import debug from 'debug' + +import { getConfig } from '../src/utils' + +const log = debug('snowball:delete-database') + +const deleteFile = async (filePath: string) => { + await fs.unlink(filePath) + log(`File ${filePath} has been deleted.`) +} + +const main = async () => { + const config = await getConfig() + + deleteFile(config.database.dbPath) +} + +main().catch((err) => log(err)) diff --git a/apps/backend/test/fixtures/deployments.json b/apps/backend/test/fixtures/deployments.json new file mode 100644 index 0000000..b73956f --- /dev/null +++ b/apps/backend/test/fixtures/deployments.json @@ -0,0 +1,189 @@ +[ + { + "projectIndex": 0, + "domainIndex": 0, + "createdByIndex": 0, + "id": "ffhae3zq", + "status": "Ready", + "environment": "Production", + "isCurrent": true, + "applicationRecordId": "qbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "xqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "main", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "testProject-ffhae3zq.snowball.xyz" + }, + { + "projectIndex": 0, + "domainIndex": 1, + "createdByIndex": 0, + "id": "vehagei8", + "status": "Ready", + "environment": "Preview", + "isCurrent": false, + "applicationRecordId": "wbafyreihvzya6ovp4yfpkqnddkui2iw7thbhwq74lbqs7bhobvmfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "wqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "test", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "testProject-vehagei8.snowball.xyz" + }, + { + "projectIndex": 0, + "domainIndex": 2, + "createdByIndex": 0, + "id": "qmgekyte", + "status": "Ready", + "environment": "Development", + "isCurrent": false, + "applicationRecordId": "ebafyreihvzya6ovp4yfpkqnddkui2iw7t6bhwq74lbqs7bhobvmfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "kqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "test", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "testProject-qmgekyte.snowball.xyz" + }, + { + "projectIndex": 0, + "domainIndex": null, + "createdByIndex": 0, + "id": "f8wsyim6", + "status": "Ready", + "environment": "Production", + "isCurrent": false, + "applicationRecordId": "rbafyreihvzya6ovp4yfpkqnddkui2iw7t6hbhw74lbqs7bhobvmfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "yqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "prod", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "testProject-f8wsyim6.snowball.xyz" + }, + { + "projectIndex": 1, + "domainIndex": 3, + "createdByIndex": 1, + "id": "eO8cckxk", + "status": "Ready", + "environment": "Production", + "isCurrent": true, + "applicationRecordId": "tbafyreihvzya6ovp4yfpqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "pqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "main", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "testProject-2-eO8cckxk.snowball.xyz" + }, + { + "projectIndex": 1, + "domainIndex": 4, + "createdByIndex": 1, + "id": "yaq0t5yw", + "status": "Ready", + "environment": "Preview", + "isCurrent": false, + "applicationRecordId": "ybafyreihvzya6ovp4yfpkqnddkui2iw7t6bhwq74lbqs7bhobvmfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "tqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "test", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "testProject-2-yaq0t5yw.snowball.xyz" + }, + { + "projectIndex": 1, + "domainIndex": 5, + "createdByIndex": 1, + "id": "hwwr6sbx", + "status": "Ready", + "environment": "Development", + "isCurrent": false, + "applicationRecordId": "ubafyreihvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "eqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "test", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "testProject-2-hwwr6sbx.snowball.xyz" + }, + { + "projectIndex": 2, + "domainIndex": 9, + "createdByIndex": 2, + "id": "ndxje48a", + "status": "Ready", + "environment": "Production", + "isCurrent": true, + "applicationRecordId": "ibayreihvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "dqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "main", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "iglootools-ndxje48a.snowball.xyz" + }, + { + "projectIndex": 2, + "domainIndex": 7, + "createdByIndex": 2, + "id": "gtgpgvei", + "status": "Ready", + "environment": "Preview", + "isCurrent": false, + "applicationRecordId": "obafyreihvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "aqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "test", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "iglootools-gtgpgvei.snowball.xyz" + }, + { + "projectIndex": 2, + "domainIndex": 8, + "createdByIndex": 2, + "id": "b4bpthjr", + "status": "Ready", + "environment": "Development", + "isCurrent": false, + "applicationRecordId": "pbafyreihvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowo", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "uqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "test", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "iglootools-b4bpthjr.snowball.xyz" + }, + { + "projectIndex": 3, + "domainIndex": 6, + "createdByIndex": 2, + "id": "b4bpthjr", + "status": "Ready", + "environment": "Production", + "isCurrent": true, + "applicationRecordId": "pbafyreihvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowo", + "applicationRecordData": {}, + "applicationDeploymentRequestId": "pqbafyrehvzya6ovp4yfpkqnddkui2iw7t6hbhwq74lbqs7bhobvmfhrowoi", + "applicationDeploymentRequestData": {}, + "branch": "test", + "commitHash": "d5dfd7b827226b0d09d897346d291c256e113e00", + "commitMessage": "subscription added", + "url": "iglootools-b4bpthjr.snowball.xyz" + } +] diff --git a/apps/backend/test/fixtures/environment-variables.json b/apps/backend/test/fixtures/environment-variables.json new file mode 100644 index 0000000..2af52b3 --- /dev/null +++ b/apps/backend/test/fixtures/environment-variables.json @@ -0,0 +1,92 @@ +[ + { + "projectIndex": 0, + "key": "ABC", + "value": "ABC", + "environment": "Production" + }, + { + "projectIndex": 0, + "key": "ABC", + "value": "ABC", + "environment": "Preview" + }, + { + "projectIndex": 0, + "key": "XYZ", + "value": "abc3", + "environment": "Preview" + }, + { + "projectIndex": 1, + "key": "ABC", + "value": "ABC", + "environment": "Production" + }, + { + "projectIndex": 1, + "key": "ABC", + "value": "ABC", + "environment": "Preview" + }, + { + "projectIndex": 1, + "key": "XYZ", + "value": "abc3", + "environment": "Preview" + }, + { + "projectIndex": 2, + "key": "ABC", + "value": "ABC", + "environment": "Production" + }, + { + "projectIndex": 2, + "key": "ABC", + "value": "ABC", + "environment": "Preview" + }, + { + "projectIndex": 2, + "key": "XYZ", + "value": "abc3", + "environment": "Preview" + }, + { + "projectIndex": 3, + "key": "ABC", + "value": "ABC", + "environment": "Production" + }, + { + "projectIndex": 3, + "key": "ABC", + "value": "ABC", + "environment": "Preview" + }, + { + "projectIndex": 3, + "key": "XYZ", + "value": "abc3", + "environment": "Preview" + }, + { + "projectIndex": 4, + "key": "ABC", + "value": "ABC", + "environment": "Production" + }, + { + "projectIndex": 4, + "key": "ABC", + "value": "ABC", + "environment": "Preview" + }, + { + "projectIndex": 4, + "key": "XYZ", + "value": "abc3", + "environment": "Preview" + } +] diff --git a/apps/backend/test/fixtures/organizations.json b/apps/backend/test/fixtures/organizations.json new file mode 100644 index 0000000..0d688fb --- /dev/null +++ b/apps/backend/test/fixtures/organizations.json @@ -0,0 +1,7 @@ +[ + { + "id": "2379cf1f-a232-4ad2-ae14-4d881131cc26", + "name": "Deploy Tools", + "slug": "deploy-tools" + } +] diff --git a/apps/backend/test/fixtures/primary-domains.json b/apps/backend/test/fixtures/primary-domains.json new file mode 100644 index 0000000..23e2666 --- /dev/null +++ b/apps/backend/test/fixtures/primary-domains.json @@ -0,0 +1,44 @@ +[ + { + "projectIndex": 0, + "name": "example.snowballtools.xyz", + "status": "Live", + "branch": "main" + }, + { + "projectIndex": 0, + "name": "example.org", + "status": "Pending", + "branch": "test" + }, + { + "projectIndex": 1, + "name": "example.snowballtools.xyz", + "status": "Live", + "branch": "main" + }, + { + "projectIndex": 1, + "name": "example.org", + "status": "Pending", + "branch": "test" + }, + { + "projectIndex": 2, + "name": "example.snowballtools.xyz", + "status": "Live", + "branch": "main" + }, + { + "projectIndex": 2, + "name": "example.org", + "status": "Pending", + "branch": "test" + }, + { + "projectIndex": 3, + "name": "iglootools-2.com", + "status": "Pending", + "branch": "test" + } +] diff --git a/apps/backend/test/fixtures/project-members.json b/apps/backend/test/fixtures/project-members.json new file mode 100644 index 0000000..84029c2 --- /dev/null +++ b/apps/backend/test/fixtures/project-members.json @@ -0,0 +1,56 @@ +[ + { + "memberIndex": 1, + "projectIndex": 0, + "permissions": ["View"], + "isPending": false + }, + { + "memberIndex": 2, + "projectIndex": 0, + "permissions": ["View", "Edit"], + "isPending": false + }, + { + "memberIndex": 2, + "projectIndex": 1, + "permissions": ["View"], + "isPending": false + }, + { + "memberIndex": 0, + "projectIndex": 2, + "permissions": ["View"], + "isPending": false + }, + { + "memberIndex": 1, + "projectIndex": 2, + "permissions": ["View", "Edit"], + "isPending": false + }, + { + "memberIndex": 0, + "projectIndex": 3, + "permissions": ["View"], + "isPending": false + }, + { + "memberIndex": 2, + "projectIndex": 3, + "permissions": ["View", "Edit"], + "isPending": false + }, + { + "memberIndex": 1, + "projectIndex": 4, + "permissions": ["View"], + "isPending": false + }, + { + "memberIndex": 2, + "projectIndex": 4, + "permissions": ["View", "Edit"], + "isPending": false + } +] diff --git a/apps/backend/test/fixtures/projects.json b/apps/backend/test/fixtures/projects.json new file mode 100644 index 0000000..f456464 --- /dev/null +++ b/apps/backend/test/fixtures/projects.json @@ -0,0 +1,67 @@ +[ + { + "ownerIndex": 0, + "organizationIndex": 0, + "name": "testProject", + "repository": "snowball-tools/snowball-ts-framework-template", + "prodBranch": "main", + "description": "test", + "template": "webapp", + "framework": "test", + "webhooks": [], + "icon": "", + "subDomain": "testProject.snowball.xyz" + }, + { + "ownerIndex": 1, + "organizationIndex": 0, + "name": "testProject-2", + "repository": "snowball-tools/snowball-ts-framework-template", + "prodBranch": "main", + "description": "test-2", + "template": "webapp", + "framework": "test-2", + "webhooks": [], + "icon": "", + "subDomain": "testProject-2.snowball.xyz" + }, + { + "ownerIndex": 2, + "organizationIndex": 0, + "name": "iglootools", + "repository": "snowball-tools/snowball-ts-framework-template", + "prodBranch": "main", + "description": "test-3", + "template": "webapp", + "framework": "test-3", + "webhooks": [], + "icon": "", + "subDomain": "iglootools.snowball.xyz" + }, + { + "ownerIndex": 1, + "organizationIndex": 0, + "name": "iglootools-2", + "repository": "snowball-tools/snowball-ts-framework-template", + "prodBranch": "main", + "description": "test-4", + "template": "webapp", + "framework": "test-4", + "webhooks": [], + "icon": "", + "subDomain": "iglootools-2.snowball.xyz" + }, + { + "ownerIndex": 0, + "organizationIndex": 1, + "name": "snowball-2", + "repository": "snowball-tools/snowball-ts-framework-template", + "prodBranch": "main", + "description": "test-5", + "template": "webapp", + "framework": "test-5", + "webhooks": [], + "icon": "", + "subDomain": "snowball-2.snowball.xyz" + } +] diff --git a/apps/backend/test/fixtures/redirected-domains.json b/apps/backend/test/fixtures/redirected-domains.json new file mode 100644 index 0000000..64fa973 --- /dev/null +++ b/apps/backend/test/fixtures/redirected-domains.json @@ -0,0 +1,23 @@ +[ + { + "projectIndex": 0, + "name": "www.example.org", + "status": "Pending", + "redirectToIndex": 1, + "branch": "test" + }, + { + "projectIndex": 1, + "name": "www.example.org", + "status": "Pending", + "redirectToIndex": 3, + "branch": "test" + }, + { + "projectIndex": 2, + "name": "www.example.org", + "status": "Pending", + "redirectToIndex": 5, + "branch": "test" + } +] diff --git a/apps/backend/test/fixtures/user-organizations.json b/apps/backend/test/fixtures/user-organizations.json new file mode 100644 index 0000000..adff4ae --- /dev/null +++ b/apps/backend/test/fixtures/user-organizations.json @@ -0,0 +1,22 @@ +[ + { + "role": "Owner", + "memberIndex": 0, + "organizationIndex": 0 + }, + { + "role": "Maintainer", + "memberIndex": 1, + "organizationIndex": 0 + }, + { + "role": "Owner", + "memberIndex": 2, + "organizationIndex": 0 + }, + { + "role": "Owner", + "memberIndex": 0, + "organizationIndex": 1 + } +] diff --git a/apps/backend/test/fixtures/users.json b/apps/backend/test/fixtures/users.json new file mode 100644 index 0000000..bc1a44d --- /dev/null +++ b/apps/backend/test/fixtures/users.json @@ -0,0 +1,23 @@ +[ + { + "id": "59f4355d-9549-4aac-9b54-eeefceeabef0", + "name": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2", + "email": "snowball@snowballtools.xyz", + "isVerified": true, + "ethAddress": "0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2" + }, + { + "id": "e505b212-8da6-48b2-9614-098225dab34b", + "name": "0xbe0eb53f46cd790cd13851d5eff43d12404d33e8", + "email": "alice@snowballtools.xyz", + "isVerified": true, + "ethAddress": "0xbe0eb53f46cd790cd13851d5eff43d12404d33e8" + }, + { + "id": "cd892fad-9138-4aa2-a62c-414a32776ea7", + "name": "0x8315177ab297ba92a06054ce80a67ed4dbd7ed3a", + "email": "bob@snowballtools.xyz", + "isVerified": true, + "ethAddress": "0x8315177ab297ba92a06054ce80a67ed4dbd7ed3a" + } +] diff --git a/apps/backend/test/initialize-db.ts b/apps/backend/test/initialize-db.ts new file mode 100644 index 0000000..3aff317 --- /dev/null +++ b/apps/backend/test/initialize-db.ts @@ -0,0 +1,176 @@ +import path from 'node:path' +import debug from 'debug' +import { DataSource } from 'typeorm' + +import { Deployment } from '../src/entity/Deployment' +import { Domain } from '../src/entity/Domain' +import { EnvironmentVariable } from '../src/entity/EnvironmentVariable' +import { Organization } from '../src/entity/Organization' +import { Project } from '../src/entity/Project' +import { ProjectMember } from '../src/entity/ProjectMember' +import { User } from '../src/entity/User' +import { UserOrganization } from '../src/entity/UserOrganization' +import { + checkFileExists, + getConfig, + getEntities, + loadAndSaveData +} from '../src/utils' + +const log = debug('snowball:initialize-database') + +const USER_DATA_PATH = './fixtures/users.json' +const PROJECT_DATA_PATH = './fixtures/projects.json' +const ORGANIZATION_DATA_PATH = './fixtures/organizations.json' +const USER_ORGANIZATION_DATA_PATH = './fixtures/user-organizations.json' +const PROJECT_MEMBER_DATA_PATH = './fixtures/project-members.json' +const PRIMARY_DOMAIN_DATA_PATH = './fixtures/primary-domains.json' +const DEPLOYMENT_DATA_PATH = './fixtures/deployments.json' +const ENVIRONMENT_VARIABLE_DATA_PATH = './fixtures/environment-variables.json' +const REDIRECTED_DOMAIN_DATA_PATH = './fixtures/redirected-domains.json' + +const generateTestData = async (dataSource: DataSource) => { + const userEntities = await getEntities( + path.resolve(__dirname, USER_DATA_PATH) + ) + const savedUsers = await loadAndSaveData(User, dataSource, userEntities) + + const orgEntities = await getEntities( + path.resolve(__dirname, ORGANIZATION_DATA_PATH) + ) + const savedOrgs = await loadAndSaveData(Organization, dataSource, orgEntities) + + const projectRelations = { + owner: savedUsers, + organization: savedOrgs + } + + const projectEntities = await getEntities( + path.resolve(__dirname, PROJECT_DATA_PATH) + ) + const savedProjects = await loadAndSaveData( + Project, + dataSource, + projectEntities, + projectRelations + ) + + const domainRepository = dataSource.getRepository(Domain) + + const domainPrimaryRelations = { + project: savedProjects + } + + const primaryDomainsEntities = await getEntities( + path.resolve(__dirname, PRIMARY_DOMAIN_DATA_PATH) + ) + const savedPrimaryDomains = await loadAndSaveData( + Domain, + dataSource, + primaryDomainsEntities, + domainPrimaryRelations + ) + + const domainRedirectedRelations = { + project: savedProjects, + redirectTo: savedPrimaryDomains + } + + const redirectDomainsEntities = await getEntities( + path.resolve(__dirname, REDIRECTED_DOMAIN_DATA_PATH) + ) + await loadAndSaveData( + Domain, + dataSource, + redirectDomainsEntities, + domainRedirectedRelations + ) + + const savedDomains = await domainRepository.find() + + const userOrganizationRelations = { + member: savedUsers, + organization: savedOrgs + } + + const userOrganizationsEntities = await getEntities( + path.resolve(__dirname, USER_ORGANIZATION_DATA_PATH) + ) + await loadAndSaveData( + UserOrganization, + dataSource, + userOrganizationsEntities, + userOrganizationRelations + ) + + const projectMemberRelations = { + member: savedUsers, + project: savedProjects + } + + const projectMembersEntities = await getEntities( + path.resolve(__dirname, PROJECT_MEMBER_DATA_PATH) + ) + await loadAndSaveData( + ProjectMember, + dataSource, + projectMembersEntities, + projectMemberRelations + ) + + const deploymentRelations = { + project: savedProjects, + domain: savedDomains, + createdBy: savedUsers + } + + const deploymentsEntities = await getEntities( + path.resolve(__dirname, DEPLOYMENT_DATA_PATH) + ) + await loadAndSaveData( + Deployment, + dataSource, + deploymentsEntities, + deploymentRelations + ) + + const environmentVariableRelations = { + project: savedProjects + } + + const environmentVariablesEntities = await getEntities( + path.resolve(__dirname, ENVIRONMENT_VARIABLE_DATA_PATH) + ) + await loadAndSaveData( + EnvironmentVariable, + dataSource, + environmentVariablesEntities, + environmentVariableRelations + ) +} + +const main = async () => { + const config = await getConfig() + const isDbPresent = await checkFileExists(config.database.dbPath) + + if (!isDbPresent) { + const dataSource = new DataSource({ + type: 'better-sqlite3', + database: config.database.dbPath, + synchronize: true, + logging: true, + entities: [path.join(__dirname, '../src/entity/*')] + }) + + await dataSource.initialize() + + await generateTestData(dataSource) + log('Data loaded successfully') + } else { + log('WARNING: Database already exists') + } +} + +main().catch((err) => { + log(err) +}) diff --git a/apps/backend/test/initialize-registry.ts b/apps/backend/test/initialize-registry.ts new file mode 100644 index 0000000..27c303d --- /dev/null +++ b/apps/backend/test/initialize-registry.ts @@ -0,0 +1,49 @@ +import debug from 'debug' + +import { Registry, parseGasAndFees } from '@cerc-io/registry-sdk' + +import { getConfig } from '../src/utils' + +const log = debug('snowball:initialize-registry') + +const DENOM = 'alnt' +const BOND_AMOUNT = '1000000000' + +async function main() { + const { registryConfig } = await getConfig() + + // TODO: Get authority names from args + const authorityNames = ['snowballtools', registryConfig.authority] + + const registry = new Registry( + registryConfig.gqlEndpoint, + registryConfig.restEndpoint, + { chainId: registryConfig.chainId } + ) + + const bondId = await registry.getNextBondId(registryConfig.privateKey) + log('bondId:', bondId) + + const fee = parseGasAndFees(registryConfig.fee.gas, registryConfig.fee.fees) + + await registry.createBond( + { denom: DENOM, amount: BOND_AMOUNT }, + registryConfig.privateKey, + fee + ) + + for await (const name of authorityNames) { + await registry.reserveAuthority({ name }, registryConfig.privateKey, fee) + log('Reserved authority name:', name) + await registry.setAuthorityBond( + { name, bondId }, + registryConfig.privateKey, + fee + ) + log(`Bond ${bondId} set for authority ${name}`) + } +} + +main().catch((err) => { + log(err) +}) diff --git a/apps/backend/test/publish-deploy-records.ts b/apps/backend/test/publish-deploy-records.ts new file mode 100644 index 0000000..61d424e --- /dev/null +++ b/apps/backend/test/publish-deploy-records.ts @@ -0,0 +1,100 @@ +import path from 'node:path' +import debug from 'debug' +import { DataSource } from 'typeorm' + +import { Registry, parseGasAndFees } from '@cerc-io/registry-sdk' + +import { + Deployment, + DeploymentStatus, + Environment +} from '../src/entity/Deployment' +import { getConfig } from '../src/utils' + +const log = debug('snowball:publish-deploy-records') + +async function main() { + const { registryConfig, database } = await getConfig() + + const registry = new Registry( + registryConfig.gqlEndpoint, + registryConfig.restEndpoint, + { chainId: registryConfig.chainId } + ) + + const dataSource = new DataSource({ + type: 'better-sqlite3', + database: database.dbPath, + synchronize: true, + entities: [path.join(__dirname, '../src/entity/*')] + }) + + await dataSource.initialize() + + const deploymentRepository = dataSource.getRepository(Deployment) + const deployments = await deploymentRepository.find({ + relations: { + project: true + }, + where: { + status: DeploymentStatus.Building + } + }) + + for await (const deployment of deployments) { + const url = `https://${(deployment.project.name).toLowerCase()}-${deployment.id}.${deployment.deployer.baseDomain}` + + const applicationDeploymentRecord = { + type: 'ApplicationDeploymentRecord', + version: '0.0.1', + name: deployment.applicationRecordData.name, + application: deployment.applicationRecordId, + + // TODO: Create DNS record + dns: 'bafyreihlymqggsgqiqawvehkpr2imt4l3u6q7um7xzjrux5rhsvwnuyewm', + + // Using dummy values + meta: JSON.stringify({ + config: 'da39a3ee5e6b4b0d3255bfef95601890afd80709', + so: '66fcfa49a1664d4cb4ce4f72c1c0e151' + }), + + request: deployment.applicationDeploymentRequestId, + url + } + + const fee = parseGasAndFees(registryConfig.fee.gas, registryConfig.fee.fees) + + const result = await registry.setRecord( + { + privateKey: registryConfig.privateKey, + record: applicationDeploymentRecord, + bondId: registryConfig.bondId + }, + '', + fee + ) + + // Remove deployment for project subdomain if deployment is for production environment + if (deployment.environment === Environment.Production) { + applicationDeploymentRecord.url = `https://${deployment.project.name}.${deployment.deployer.baseDomain}` + + await registry.setRecord( + { + privateKey: registryConfig.privateKey, + record: applicationDeploymentRecord, + bondId: registryConfig.bondId + }, + '', + fee + ) + } + + log('Application deployment record data:', applicationDeploymentRecord) + log(`Application deployment record published: ${result.id}`) + } +} + +main().catch((err) => { + log(err) +}) diff --git a/apps/backend/test/publish-deployment-removal-records.ts b/apps/backend/test/publish-deployment-removal-records.ts new file mode 100644 index 0000000..e902fc7 --- /dev/null +++ b/apps/backend/test/publish-deployment-removal-records.ts @@ -0,0 +1,70 @@ +import path from 'node:path' +import debug from 'debug' +import { DataSource } from 'typeorm' + +import { Registry, parseGasAndFees } from '@cerc-io/registry-sdk' + +import { Deployment, DeploymentStatus } from '../src/entity/Deployment' +import { getConfig } from '../src/utils' + +const log = debug('snowball:publish-deployment-removal-records') + +async function main() { + const { registryConfig, database } = await getConfig() + + const registry = new Registry( + registryConfig.gqlEndpoint, + registryConfig.restEndpoint, + { chainId: registryConfig.chainId } + ) + + const dataSource = new DataSource({ + type: 'better-sqlite3', + database: database.dbPath, + synchronize: true, + entities: [path.join(__dirname, '../src/entity/*')] + }) + + await dataSource.initialize() + + const deploymentRepository = dataSource.getRepository(Deployment) + const deployments = await deploymentRepository.find({ + relations: { + project: true + }, + where: { + status: DeploymentStatus.Deleting + } + }) + + for await (const deployment of deployments) { + const applicationDeploymentRemovalRecord = { + type: 'ApplicationDeploymentRemovalRecord', + version: '1.0.0', + deployment: deployment.applicationDeploymentRecordId, + request: deployment.applicationDeploymentRemovalRequestId + } + + const fee = parseGasAndFees(registryConfig.fee.gas, registryConfig.fee.fees) + + const result = await registry.setRecord( + { + privateKey: registryConfig.privateKey, + record: applicationDeploymentRemovalRecord, + bondId: registryConfig.bondId + }, + '', + fee + ) + + log( + 'Application deployment removal record data:', + applicationDeploymentRemovalRecord + ) + log(`Application deployment removal record published: ${result.id}`) + } +} + +main().catch((err) => { + log(err) +}) diff --git a/apps/backend/tsconfig.json b/apps/backend/tsconfig.json new file mode 100644 index 0000000..d4cfe92 --- /dev/null +++ b/apps/backend/tsconfig.json @@ -0,0 +1,13 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src", + "baseUrl": ".", + "experimentalDecorators": true, + "emitDecoratorMetadata": true, + "resolveJsonModule": true + }, + "include": ["src/**/*"], + "exclude": ["dist", "src/**/*.test.ts"] +} diff --git a/apps/deployer/README.md b/apps/deployer/README.md new file mode 100644 index 0000000..51095c3 --- /dev/null +++ b/apps/deployer/README.md @@ -0,0 +1,64 @@ +# deployer + +- Install dependencies + + ```bash + pnpm install + ``` + + ```bash + brew install jq # if you do not have jq installed already + ``` + +- Run script to deploy app + + - To deploy frontend app to `dashboard.staging.apps.snowballtools.com` + + ```bash + ./deploy-frontend.staging.sh + ``` + + - To deploy frontend app to `dashboard.apps.snowballtools.com` + + ```bash + ./deploy-frontend.sh + ``` + +- Commit the updated [ApplicationRecord](records/application-record.yml) and [ApplicationDeploymentRequest](records/application-deployment-request.yml) files to the repository + +## Notes + +- Any config env can be updated in [records/application-deployment-request.yml](records/application-deployment-request.yml) + + ```yml + record: + ... + config: + env: + LACONIC_HOSTED_CONFIG_app_server_url: https://snowballtools-base-api-001.apps.snowballtools.com + ... + ``` + + - On changing `LACONIC_HOSTED_CONFIG_app_github_clientid`, the GitHub client ID and secret need to be changed in backend config too + +## Troubleshoot + +- Check deployment status in [web-app deployer](https://console.laconic.com/deployer). +- Check records in [registry console app](https://console.laconic.com/#/registry). + +- If deployment fails due to low bond balance + - Check balances + + ```bash + # Account balance + pnpm laconic registry account get + + # Bond balance + pnpm laconic registry bond get --id 99c0e9aec0ac1b8187faa579be3b54f93fafb6060ac1fd29170b860df605be32 + ``` + + - Command to refill bond + + ```bash + pnpm laconic registry bond refill --id 99c0e9aec0ac1b8187faa579be3b54f93fafb6060ac1fd29170b860df605be32 --type alnt --quantity 10000000 + ``` diff --git a/apps/deployer/biome.json b/apps/deployer/biome.json new file mode 100644 index 0000000..08820e9 --- /dev/null +++ b/apps/deployer/biome.json @@ -0,0 +1,6 @@ +{ + "extends": ["../../biome.json"], + "files": { + "ignore": ["dist/**/*", "node_modules/**/*", ".turbo/**/*"] + } +} diff --git a/apps/deployer/config.staging.yml b/apps/deployer/config.staging.yml new file mode 100644 index 0000000..b2c8f7d --- /dev/null +++ b/apps/deployer/config.staging.yml @@ -0,0 +1,10 @@ +services: + registry: + restEndpoint: 'http://console.laconic.com:1317' + gqlEndpoint: 'http://console.laconic.com:9473/api' + userKey: 87d00f66a73e2ca428adeb49ba9164d0ad9a87edc60e33d46ad3031b9c5701fe + bondId: 89c75c7bc5759861d10285aff6f9e7227d6855e446b77ad5d8324822dfec7deb + chainId: laconic_9000-1 + gas: + fees: + gasPrice: 1 diff --git a/apps/deployer/config.yml b/apps/deployer/config.yml new file mode 100644 index 0000000..730022e --- /dev/null +++ b/apps/deployer/config.yml @@ -0,0 +1,8 @@ +services: + registry: + rpcEndpoint: https://laconicd-sapo.laconic.com + gqlEndpoint: https://laconicd-sapo.laconic.com/api + userKey: + bondId: + chainId: laconic-testnet-2 + gasPrice: 0.001alnt diff --git a/apps/deployer/deploy-frontend.sh b/apps/deployer/deploy-frontend.sh new file mode 100755 index 0000000..46ab416 --- /dev/null +++ b/apps/deployer/deploy-frontend.sh @@ -0,0 +1,155 @@ +#!/bin/bash + +source .env +echo "Using REGISTRY_BOND_ID: $REGISTRY_BOND_ID" +echo "Using DEPLOYER_LRN: $DEPLOYER_LRN" +echo "Using AUTHORITY: $AUTHORITY" + +# Repository URL +REPO_URL="https://git.vdb.to/cerc-io/snowballtools-base" + +# Get the latest commit hash for a branch +BRANCH_NAME="main" +LATEST_HASH=$(git ls-remote $REPO_URL refs/heads/$BRANCH_NAME | awk '{print $1}') + +echo "Latest commit hash for branch $BRANCH_NAME: $LATEST_HASH" + +# Extract version from frontend package.json +PACKAGE_VERSION=$(jq -r '.version' ../../apps/deploy-fe/package.json) + +# Current date and time for note +CURRENT_DATE_TIME=$(date -u) + +CONFIG_FILE=config.yml + +# Reference: https://git.vdb.to/cerc-io/test-progressive-web-app/src/branch/main/scripts + +# Get latest version from registry and increment application-record version +NEW_APPLICATION_VERSION=$(pnpm --silent laconic -c $CONFIG_FILE registry record list --type ApplicationRecord --all --name "deploy-frontend" 2>/dev/null | jq -r -s ".[] | sort_by(.createTime) | reverse | [ .[] | select(.bondId == \"$REGISTRY_BOND_ID\") ] | .[0].attributes.version" | awk -F. -v OFS=. '{$NF += 1 ; print}') + +if [ -z "$NEW_APPLICATION_VERSION" ] || [ "1" == "$NEW_APPLICATION_VERSION" ]; then + # Set application-record version if no previous records were found + NEW_APPLICATION_VERSION=0.0.1 +fi + +# Generate application-record.yml with incremented version +cat >./records/application-record.yml <./records/application-deployment-request.yml </dev/null | jq -r -s ".[] | sort_by(.createTime) | reverse | [ .[] | select(.bondId == \"$REGISTRY_BOND_ID\") ] | .[0].attributes.version" | awk -F. -v OFS=. '{$NF += 1 ; print}') + +if [ -z "$NEW_APPLICATION_VERSION" ] || [ "1" == "$NEW_APPLICATION_VERSION" ]; then + # Set application-record version if no previous records were found + NEW_APPLICATION_VERSION=0.0.1 +fi + +# Generate application-record.yml with incremented version +cat >./records/application-record.yml <./records/application-deployment-request.yml < $REMOVAL_REQUEST_RECORD_FILE < (main branch) +- Config used: [../config.yml](../config.yml) +- The script [test-webapp-deployment-undeployment.sh](./test-webapp-deployment-undeployment.sh) performs the following: + - Create / update [`ApplicationRecord`](./records/application-record.yml) and [`ApplicationDeploymentRequest`](./records/application-deployment-request.yml) records with latest meta data from the repo + - Fetch the latest version of `deployment-test-app` from registry and increment `ApplicationRecord` version + - Publish the resulting `ApplicationRecord` record + - Set names to the record and check name resolution + - Publish the `ApplicationDeploymentRequest` record + - Check that the deployment occurs + - Check that a `ApplicationDeploymentRecord` is created + - Check that the deployment record has correct `ApplicationRecord` id + - Check that the URL present in deployment record is active + - Create and publish a [`ApplicationDeploymentRemovalRequest`](./records/application-deployment-removal-request.yml) record + - Check that the deployment is removed + - Check that a `ApplicationDeploymentRemovalRecord` is created + - Check that the deployment URL goes down +- The test script is run in a GitHub CI [workflow](../../../.github/workflows/test-app-deployment.yaml) that: + - Is scheduled to run everyday on the default (`main`) branch or can be triggered manually + - Sends Slack alerts to configured channels on failure diff --git a/apps/deployer/test/records/application-deployment-removal-request.yml b/apps/deployer/test/records/application-deployment-removal-request.yml new file mode 100644 index 0000000..b0082da --- /dev/null +++ b/apps/deployer/test/records/application-deployment-removal-request.yml @@ -0,0 +1,4 @@ +record: + deployment: + type: ApplicationDeploymentRemovalRequest + version: 1.0.0 diff --git a/apps/deployer/test/records/application-deployment-request.yml b/apps/deployer/test/records/application-deployment-request.yml new file mode 100644 index 0000000..2f7df4a --- /dev/null +++ b/apps/deployer/test/records/application-deployment-request.yml @@ -0,0 +1,15 @@ +record: + type: ApplicationDeploymentRequest + version: "1.0.0" + name: deployment-test-app@0.1.24 + application: crn://snowballtools/applications/deployment-test-app@0.1.24 + dns: deployment-ci-test + config: + env: + CERC_TEST_WEBAPP_CONFIG1: "deployment test config 1" + CERC_TEST_WEBAPP_CONFIG2: "deployment test config 2" + CERC_WEBAPP_DEBUG: 0 + meta: + note: Deployment test @ Thu 11 Apr 2024 07:29:19 AM UTC + repository: "https://github.com/snowball-tools/test-progressive-web-app" + repository_ref: 05819619487a0d2dbc5453b6d1ccff3044c0dd26 diff --git a/apps/deployer/test/records/application-record.yml b/apps/deployer/test/records/application-record.yml new file mode 100644 index 0000000..6c599c8 --- /dev/null +++ b/apps/deployer/test/records/application-record.yml @@ -0,0 +1,8 @@ +record: + type: ApplicationRecord + version: 0.0.1 + repository_ref: 05819619487a0d2dbc5453b6d1ccff3044c0dd26 + repository: ["https://github.com/snowball-tools/test-progressive-web-app"] + app_type: webapp + name: deployment-test-app + app_version: 0.1.24 diff --git a/apps/deployer/test/test-webapp-deployment-undeployment.sh b/apps/deployer/test/test-webapp-deployment-undeployment.sh new file mode 100755 index 0000000..6e6fd65 --- /dev/null +++ b/apps/deployer/test/test-webapp-deployment-undeployment.sh @@ -0,0 +1,225 @@ +#!/bin/bash + +# Repository URL +REPO_URL="https://github.com/snowball-tools/test-progressive-web-app" + +# Get the latest commit hash from the repository +LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}') + +# Fetch the package.json file content +# Extract version from package.json content +package_json=$(wget -qO- "$REPO_URL/raw/$LATEST_HASH/package.json") +PACKAGE_VERSION=$(echo "$package_json" | jq -r '.version') + +# Current date and time for note +CURRENT_DATE_TIME=$(date -u) + +CONFIG_FILE=apps/deployer/config.yml +REGISTRY_BOND_ID="99c0e9aec0ac1b8187faa579be3b54f93fafb6060ac1fd29170b860df605be32" + +# Reference: https://git.vdb.to/cerc-io/test-progressive-web-app/src/branch/main/scripts + +APP_NAME=deployment-test-app + +# Get latest version from registry and increment application-record version +NEW_APPLICATION_VERSION=$(pnpm --silent laconic -c $CONFIG_FILE registry record list --type ApplicationRecord --all --name "$APP_NAME" 2>/dev/null | jq -r -s ".[] | sort_by(.createTime) | reverse | [ .[] | select(.bondId == \"$REGISTRY_BOND_ID\") ] | .[0].attributes.version" | awk -F. -v OFS=. '{$NF += 1 ; print}') + +if [ -z "$NEW_APPLICATION_VERSION" ] || [ "1" == "$NEW_APPLICATION_VERSION" ]; then + # Set application-record version if no previous records were found + NEW_APPLICATION_VERSION=0.0.1 +fi + +# Generate application-record.yml with incremented version +RECORD_FILE=apps/deployer/test/records/application-record.yml + +cat >$RECORD_FILE <$REQUEST_RECORD_FILE <$REMOVAL_REQUEST_RECORD_FILE <=10'} + '@apollo/client@3.13.3': + resolution: {integrity: sha512-StozissNsakG9cveM5IYcVjQBiJXXtfybSwIklrJQv3c0CLshWBlUv5OddMrJxKfQ1A+9WqPQZXjkA/HxbflDA==} + peerDependencies: + graphql: ^15.0.0 || ^16.0.0 + graphql-ws: ^5.5.5 || ^6.0.3 + react: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc + react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc + subscriptions-transport-ws: ^0.9.0 || ^0.11.0 + peerDependenciesMeta: + graphql-ws: + optional: true + react: + optional: true + react-dom: + optional: true + subscriptions-transport-ws: + optional: true + + '@apollo/protobufjs@1.2.6': + resolution: {integrity: sha512-Wqo1oSHNUj/jxmsVp4iR3I480p6qdqHikn38lKrFhfzcDJ7lwd7Ck7cHRl4JE81tWNArl77xhnG/OkZhxKBYOw==} + hasBin: true + + '@apollo/protobufjs@1.2.7': + resolution: {integrity: sha512-Lahx5zntHPZia35myYDBRuF58tlwPskwHc5CWBZC/4bMKB6siTBWwtMrkqXcsNwQiFSzSx5hKdRPUmemrEp3Gg==} + hasBin: true + + '@apollo/usage-reporting-protobuf@4.1.1': + resolution: {integrity: sha512-u40dIUePHaSKVshcedO7Wp+mPiZsaU6xjv9J+VyxpoU/zL6Jle+9zWeG98tr/+SZ0nZ4OXhrbb8SNr0rAPpIDA==} + + '@apollo/utils.dropunuseddefinitions@1.1.0': + resolution: {integrity: sha512-jU1XjMr6ec9pPoL+BFWzEPW7VHHulVdGKMkPAMiCigpVIT11VmCbnij0bWob8uS3ODJ65tZLYKAh/55vLw2rbg==} + engines: {node: '>=12.13.0'} + peerDependencies: + graphql: 14.x || 15.x || 16.x + + '@apollo/utils.keyvaluecache@1.0.2': + resolution: {integrity: sha512-p7PVdLPMnPzmXSQVEsy27cYEjVON+SH/Wb7COyW3rQN8+wJgT1nv9jZouYtztWW8ZgTkii5T6tC9qfoDREd4mg==} + + '@apollo/utils.logger@1.0.1': + resolution: {integrity: sha512-XdlzoY7fYNK4OIcvMD2G94RoFZbzTQaNP0jozmqqMudmaGo2I/2Jx71xlDJ801mWA/mbYRihyaw6KJii7k5RVA==} + + '@apollo/utils.printwithreducedwhitespace@1.1.0': + resolution: {integrity: sha512-GfFSkAv3n1toDZ4V6u2d7L4xMwLA+lv+6hqXicMN9KELSJ9yy9RzuEXaX73c/Ry+GzRsBy/fdSUGayGqdHfT2Q==} + engines: {node: '>=12.13.0'} + peerDependencies: + graphql: 14.x || 15.x || 16.x + + '@apollo/utils.removealiases@1.0.0': + resolution: {integrity: sha512-6cM8sEOJW2LaGjL/0vHV0GtRaSekrPQR4DiywaApQlL9EdROASZU5PsQibe2MWeZCOhNrPRuHh4wDMwPsWTn8A==} + engines: {node: '>=12.13.0'} + peerDependencies: + graphql: 14.x || 15.x || 16.x + + '@apollo/utils.sortast@1.1.0': + resolution: {integrity: sha512-VPlTsmUnOwzPK5yGZENN069y6uUHgeiSlpEhRnLFYwYNoJHsuJq2vXVwIaSmts015WTPa2fpz1inkLYByeuRQA==} + engines: {node: '>=12.13.0'} + peerDependencies: + graphql: 14.x || 15.x || 16.x + + '@apollo/utils.stripsensitiveliterals@1.2.0': + resolution: {integrity: sha512-E41rDUzkz/cdikM5147d8nfCFVKovXxKBcjvLEQ7bjZm/cg9zEcXvS6vFY8ugTubI3fn6zoqo0CyU8zT+BGP9w==} + engines: {node: '>=12.13.0'} + peerDependencies: + graphql: 14.x || 15.x || 16.x + + '@apollo/utils.usagereporting@1.0.1': + resolution: {integrity: sha512-6dk+0hZlnDbahDBB2mP/PZ5ybrtCJdLMbeNJD+TJpKyZmSY6bA3SjI8Cr2EM9QA+AdziywuWg+SgbWUF3/zQqQ==} + engines: {node: '>=12.13.0'} + peerDependencies: + graphql: 14.x || 15.x || 16.x + + '@apollographql/apollo-tools@0.5.4': + resolution: {integrity: sha512-shM3q7rUbNyXVVRkQJQseXv6bnYM3BUma/eZhwXR4xsuM+bqWnJKvW7SAfRjP7LuSCocrexa5AXhjjawNHrIlw==} + engines: {node: '>=8', npm: '>=6'} + peerDependencies: + graphql: ^14.2.1 || ^15.0.0 || ^16.0.0 + + '@apollographql/graphql-playground-html@1.6.29': + resolution: {integrity: sha512-xCcXpoz52rI4ksJSdOCxeOCn2DLocxwHf9dVT/Q90Pte1LX+LY+91SFtJF3KXVHH8kEin+g1KKCQPKBjZJfWNA==} + '@babel/runtime-corejs3@7.26.9': resolution: {integrity: sha512-5EVjbTegqN7RSJle6hMWYxO4voo4rI+9krITk+DWR+diJgGrjZjrIBnJhjrHYYQsFgI7j1w1QnrvV7YSKBfYGg==} engines: {node: '>=6.9.0'} @@ -465,6 +697,13 @@ packages: resolution: {tarball: https://codeload.github.com/biomejs/biome/tar.gz/0ce750c5052cc0620af1fb95acb863c1f16b2bce} version: 0.0.0 + '@cerc-io/laconic-registry-cli@0.2.10': + resolution: {integrity: sha512-rwrZhFgYZiMh2k+9E/aiyRhFLApydRUwclATb0f6hsFAkxARuaibHsJNy7eF2N/AQ4d6HAvpkXACJoVrGOppmw==, tarball: https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Flaconic-registry-cli/-/0.2.10/laconic-registry-cli-0.2.10.tgz} + hasBin: true + + '@cerc-io/registry-sdk@0.2.11': + resolution: {integrity: sha512-IipqJzaBQEXMNH6yWFG2E/o0U6IAXw35PBMHx6QIboVu/sMNLIsWy1P8MmR8C8xYsmHOhgXLsC4hYSeFMXrqFw==, tarball: https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fregistry-sdk/-/0.2.11/registry-sdk-0.2.11.tgz} + '@clerk/backend@1.25.1': resolution: {integrity: sha512-VTOg+LGqxY+ydPHxi+hrC+Uc9EIbieiku/+ZxJMhFSzYNhtkwC/UBws4JnFNoz2aLa28Pazf0WIBxwrqZgg69Q==} engines: {node: '>=18.17.0'} @@ -504,6 +743,109 @@ packages: resolution: {integrity: sha512-xB/gqMq6cq6/47ymKs0WaaxKEFPzlvbSgJTLFIfnPMnFSNwYE4WVgVh6geFx6qWr3z588JDDZkJskBHZlgPmQQ==} engines: {node: '>=18.17.0'} + '@confio/ics23@0.6.8': + resolution: {integrity: sha512-wB6uo+3A50m0sW/EWcU64xpV/8wShZ6bMTa7pF8eYsTrSkQA7oLUIJcs/wb8g4y2Oyq701BaGiO6n/ak5WXO1w==} + deprecated: Unmaintained. The codebase for this package was moved to https://github.com/cosmos/ics23 but then the JS implementation was removed in https://github.com/cosmos/ics23/pull/353. Please consult the maintainers of https://github.com/cosmos for further assistance. + + '@cosmjs/amino@0.27.1': + resolution: {integrity: sha512-w56ar/nK9+qlvWDpBPRmD0Blk2wfkkLqRi1COs1x7Ll1LF0AtkIBUjbRKplENLbNovK0T3h+w8bHiFm+GBGQOA==} + + '@cosmjs/amino@0.28.13': + resolution: {integrity: sha512-IHnH2zGwaY69qT4mVAavr/pfzx6YE+ud1NHJbvVePlbGiz68CXTi5LHR+K0lrKB5mQ7E+ZErWz2mw5U/x+V1wQ==} + + '@cosmjs/amino@0.32.4': + resolution: {integrity: sha512-zKYOt6hPy8obIFtLie/xtygCkH9ZROiQ12UHfKsOkWaZfPQUvVbtgmu6R4Kn1tFLI/SRkw7eqhaogmW/3NYu/Q==} + + '@cosmjs/amino@0.33.0': + resolution: {integrity: sha512-a4qnWGzuM2IrlkDTFQmU7bDd+wNIzyvfcRIZ43i00ZHvTEtrCcWopT94rIv/Zy6fdgkhQ3HWrsGVlIPDT/ibRw==} + + '@cosmjs/crypto@0.27.1': + resolution: {integrity: sha512-vbcxwSt99tIYJg8Spp00wc3zx72qx+pY3ozGuBN8gAvySnagK9dQ/jHwtWQWdammmdD6oW+75WfIHZ+gNa+Ybg==} + + '@cosmjs/crypto@0.28.13': + resolution: {integrity: sha512-ynKfM0q/tMBQMHJby6ad8lR3gkgBKaelQhIsCZTjClsnuC7oYT9y3ThSZCUWr7Pa9h0J8ahU2YV2oFWFVWJQzQ==} + + '@cosmjs/crypto@0.32.4': + resolution: {integrity: sha512-zicjGU051LF1V9v7bp8p7ovq+VyC91xlaHdsFOTo2oVry3KQikp8L/81RkXmUIT8FxMwdx1T7DmFwVQikcSDIw==} + + '@cosmjs/crypto@0.33.0': + resolution: {integrity: sha512-kkt06t+cFW2XRGDGUZ0cVf5yoQ2OhZnubwbYbz3QXdyhf1qOXYVPRThfFPsko7dssr+e8Yy4OJKlh5SLA8DXTQ==} + + '@cosmjs/encoding@0.27.1': + resolution: {integrity: sha512-rayLsA0ojHeniaRfWWcqSsrE/T1rl1gl0OXVNtXlPwLJifKBeLEefGbOUiAQaT0wgJ8VNGBazVtAZBpJidfDhw==} + + '@cosmjs/encoding@0.28.13': + resolution: {integrity: sha512-jtXbAYtV77rLHxoIrjGFsvgGjeTKttuHRv6cvuy3toCZzY7JzTclKH5O2g36IIE4lXwD9xwuhGJ2aa6A3dhNkA==} + + '@cosmjs/encoding@0.32.4': + resolution: {integrity: sha512-tjvaEy6ZGxJchiizzTn7HVRiyTg1i4CObRRaTRPknm5EalE13SV+TCHq38gIDfyUeden4fCuaBVEdBR5+ti7Hw==} + + '@cosmjs/encoding@0.33.0': + resolution: {integrity: sha512-9z0g9mM7w5BISVVs8BK1Yp7KSQgNLGz2SBoWYOm4wODB/YcoitODgyRqECcuMZBXtd2sCyy2M1VLs9Z69BPZRQ==} + + '@cosmjs/json-rpc@0.32.4': + resolution: {integrity: sha512-/jt4mBl7nYzfJ2J/VJ+r19c92mUKF0Lt0JxM3MXEJl7wlwW5haHAWtzRujHkyYMXOwIR+gBqT2S0vntXVBRyhQ==} + + '@cosmjs/json-rpc@0.33.0': + resolution: {integrity: sha512-okXjxnT3zhhuYrA1aIDVD8VHt3syWyrJw3cAY6tMNM53bQcAtLGImueMrEoyv7DtLg5R5Tx5PMrQ7UYnpD8OwQ==} + + '@cosmjs/launchpad@0.27.1': + resolution: {integrity: sha512-DcFwGD/z5PK8CzO2sojDxa+Be9EIEtRZb2YawgVnw2Ht/p5FlNv+OVo8qlishpBdalXEN7FvQ1dVeDFEe9TuJw==} + + '@cosmjs/math@0.27.1': + resolution: {integrity: sha512-cHWVjmfIjtRc7f80n7x+J5k8pe+vTVTQ0lA82tIxUgqUvgS6rogPP/TmGtTiZ4+NxWxd11DUISY6gVpr18/VNQ==} + + '@cosmjs/math@0.28.13': + resolution: {integrity: sha512-PDpL8W/kbyeWi0mQ2OruyqE8ZUAdxPs1xCbDX3WXJwy2oU+X2UTbkuweJHVpS9CIqmZulBoWQAmlf6t6zr1N/g==} + + '@cosmjs/math@0.32.4': + resolution: {integrity: sha512-++dqq2TJkoB8zsPVYCvrt88oJWsy1vMOuSOKcdlnXuOA/ASheTJuYy4+oZlTQ3Fr8eALDLGGPhJI02W2HyAQaw==} + + '@cosmjs/math@0.33.0': + resolution: {integrity: sha512-B2uOgM12iuIhJWzGuAxGwO6zO+cI8Q4z7mVu7HgFrGJJTM1HtPTYgb55oMOuUN0OZ352MEEm5uAt8sA9jZQqbA==} + + '@cosmjs/proto-signing@0.32.4': + resolution: {integrity: sha512-QdyQDbezvdRI4xxSlyM1rSVBO2st5sqtbEIl3IX03uJ7YiZIQHyv6vaHVf1V4mapusCqguiHJzm4N4gsFdLBbQ==} + + '@cosmjs/proto-signing@0.33.0': + resolution: {integrity: sha512-UHA92d/Siy3wnce/xhU4iagKrs6r8Ruacc0qeHj3mNrtuUH8f70cD7lzzClzI7wvRLcPprOY0YTeEzqGbPeBFw==} + + '@cosmjs/socket@0.32.4': + resolution: {integrity: sha512-davcyYziBhkzfXQTu1l5NrpDYv0K9GekZCC9apBRvL1dvMc9F/ygM7iemHjUA+z8tJkxKxrt/YPjJ6XNHzLrkw==} + + '@cosmjs/socket@0.33.0': + resolution: {integrity: sha512-a1eHsqVFmG6N5LR53tAB1Xo4XfsZaFlrYA34yC0GnX5m/cJVEe1wkZxMsWJIW2nfCgj7nAvFK6Gx4qj+ZLeqdw==} + + '@cosmjs/stargate@0.32.4': + resolution: {integrity: sha512-usj08LxBSsPRq9sbpCeVdyLx2guEcOHfJS9mHGCLCXpdAPEIEQEtWLDpEUc0LEhWOx6+k/ChXTc5NpFkdrtGUQ==} + + '@cosmjs/stargate@0.33.0': + resolution: {integrity: sha512-Ti/2RRl+LKTNUrOqj6TpGnTRcbmQ5zD4Ujx/PDNPHEexyuwbz+tMcF8Y1kKPWQ1g4wWxLYO4tKY4Gm0J3c5hWA==} + + '@cosmjs/stream@0.32.4': + resolution: {integrity: sha512-Gih++NYHEiP+oyD4jNEUxU9antoC0pFSg+33Hpp0JlHwH0wXhtD3OOKnzSfDB7OIoEbrzLJUpEjOgpCp5Z+W3A==} + + '@cosmjs/stream@0.33.0': + resolution: {integrity: sha512-SmsZW9Xzfk2T2MtWzVkit2WUclL7ZQHhiEhJz39EzKQRAdi4xY8nwefZF4VLQVJ0M33QfRCUzFzb+O/gddMQKA==} + + '@cosmjs/tendermint-rpc@0.32.4': + resolution: {integrity: sha512-MWvUUno+4bCb/LmlMIErLypXxy7ckUuzEmpufYYYd9wgbdCXaTaO08SZzyFM5PI8UJ/0S2AmUrgWhldlbxO8mw==} + + '@cosmjs/tendermint-rpc@0.33.0': + resolution: {integrity: sha512-A5h72fYesFKSjMjB+AMD5thcVVcdfbmWj4atJ1CYmKGyCTCPW8iEIz1ZKR0mUX+gkW6dM1h8flaRj/R14Oc0/A==} + + '@cosmjs/utils@0.27.1': + resolution: {integrity: sha512-VG7QPDiMUzVPxRdJahDV8PXxVdnuAHiIuG56hldV4yPnOz/si/DLNd7VAUUA5923b6jS1Hhev0Hr6AhEkcxBMg==} + + '@cosmjs/utils@0.28.13': + resolution: {integrity: sha512-dVeMBiyg+46x7XBZEfJK8yTihphbCFpjVYmLJVqmTsHfJwymQ65cpyW/C+V/LgWARGK8hWQ/aX9HM5Ao8QmMSg==} + + '@cosmjs/utils@0.32.4': + resolution: {integrity: sha512-D1Yc+Zy8oL/hkUkFUL/bwxvuDBzRGpc4cF7/SkdhxX4iHpSLgdOuTt1mhCh9+kl6NQREy9t7SYZ6xeW5gFe60w==} + + '@cosmjs/utils@0.33.0': + resolution: {integrity: sha512-Y6glwHNlNjcOgwPg8YmNr1PSrNm307EhJVytFt8HmA/G7MRcIA+jIzCL0VlOrWGU4TrAOXvshM+oJZbTIldFRA==} + '@cspotcode/source-map-support@0.8.1': resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} engines: {node: '>=12'} @@ -511,6 +853,246 @@ packages: '@emnapi/runtime@1.3.1': resolution: {integrity: sha512-kEBmG8KyqtxJZv+ygbEim+KCGtIq1fC22Ms3S4ziXmYKm8uyoLX0MHONVKwp+9opg390VaKRNt4a7A9NwmpNhw==} + '@esbuild/aix-ppc64@0.25.0': + resolution: {integrity: sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + + '@esbuild/android-arm64@0.25.0': + resolution: {integrity: sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + + '@esbuild/android-arm@0.25.0': + resolution: {integrity: sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + + '@esbuild/android-x64@0.25.0': + resolution: {integrity: sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + + '@esbuild/darwin-arm64@0.25.0': + resolution: {integrity: sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + + '@esbuild/darwin-x64@0.25.0': + resolution: {integrity: sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + + '@esbuild/freebsd-arm64@0.25.0': + resolution: {integrity: sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + + '@esbuild/freebsd-x64@0.25.0': + resolution: {integrity: sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + + '@esbuild/linux-arm64@0.25.0': + resolution: {integrity: sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + + '@esbuild/linux-arm@0.25.0': + resolution: {integrity: sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + + '@esbuild/linux-ia32@0.25.0': + resolution: {integrity: sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + + '@esbuild/linux-loong64@0.25.0': + resolution: {integrity: sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + + '@esbuild/linux-mips64el@0.25.0': + resolution: {integrity: sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + + '@esbuild/linux-ppc64@0.25.0': + resolution: {integrity: sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + + '@esbuild/linux-riscv64@0.25.0': + resolution: {integrity: sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + + '@esbuild/linux-s390x@0.25.0': + resolution: {integrity: sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + + '@esbuild/linux-x64@0.25.0': + resolution: {integrity: sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + + '@esbuild/netbsd-arm64@0.25.0': + resolution: {integrity: sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + + '@esbuild/netbsd-x64@0.25.0': + resolution: {integrity: sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + + '@esbuild/openbsd-arm64@0.25.0': + resolution: {integrity: sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + + '@esbuild/openbsd-x64@0.25.0': + resolution: {integrity: sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/sunos-x64@0.25.0': + resolution: {integrity: sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + + '@esbuild/win32-arm64@0.25.0': + resolution: {integrity: sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + + '@esbuild/win32-ia32@0.25.0': + resolution: {integrity: sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + + '@esbuild/win32-x64@0.25.0': + resolution: {integrity: sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + + '@ethersproject/abi@5.8.0': + resolution: {integrity: sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==} + + '@ethersproject/abstract-provider@5.8.0': + resolution: {integrity: sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==} + + '@ethersproject/abstract-signer@5.8.0': + resolution: {integrity: sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==} + + '@ethersproject/address@5.8.0': + resolution: {integrity: sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==} + + '@ethersproject/base64@5.8.0': + resolution: {integrity: sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==} + + '@ethersproject/basex@5.8.0': + resolution: {integrity: sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==} + + '@ethersproject/bignumber@5.8.0': + resolution: {integrity: sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==} + + '@ethersproject/bytes@5.8.0': + resolution: {integrity: sha512-vTkeohgJVCPVHu5c25XWaWQOZ4v+DkGoC42/TS2ond+PARCxTJvgTFUNDZovyQ/uAQ4EcpqqowKydcdmRKjg7A==} + + '@ethersproject/constants@5.8.0': + resolution: {integrity: sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==} + + '@ethersproject/contracts@5.8.0': + resolution: {integrity: sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==} + + '@ethersproject/hash@5.8.0': + resolution: {integrity: sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==} + + '@ethersproject/hdnode@5.8.0': + resolution: {integrity: sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==} + + '@ethersproject/json-wallets@5.8.0': + resolution: {integrity: sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==} + + '@ethersproject/keccak256@5.8.0': + resolution: {integrity: sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==} + + '@ethersproject/logger@5.8.0': + resolution: {integrity: sha512-Qe6knGmY+zPPWTC+wQrpitodgBfH7XoceCGL5bJVejmH+yCS3R8jJm8iiWuvWbG76RUmyEG53oqv6GMVWqunjA==} + + '@ethersproject/networks@5.8.0': + resolution: {integrity: sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==} + + '@ethersproject/pbkdf2@5.8.0': + resolution: {integrity: sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==} + + '@ethersproject/properties@5.8.0': + resolution: {integrity: sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==} + + '@ethersproject/providers@5.8.0': + resolution: {integrity: sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==} + + '@ethersproject/random@5.8.0': + resolution: {integrity: sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==} + + '@ethersproject/rlp@5.8.0': + resolution: {integrity: sha512-LqZgAznqDbiEunaUvykH2JAoXTT9NV0Atqk8rQN9nx9SEgThA/WMx5DnW8a9FOufo//6FZOCHZ+XiClzgbqV9Q==} + + '@ethersproject/sha2@5.8.0': + resolution: {integrity: sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==} + + '@ethersproject/signing-key@5.8.0': + resolution: {integrity: sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==} + + '@ethersproject/solidity@5.8.0': + resolution: {integrity: sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==} + + '@ethersproject/strings@5.8.0': + resolution: {integrity: sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==} + + '@ethersproject/transactions@5.8.0': + resolution: {integrity: sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==} + + '@ethersproject/units@5.8.0': + resolution: {integrity: sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==} + + '@ethersproject/wallet@5.8.0': + resolution: {integrity: sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==} + + '@ethersproject/web@5.8.0': + resolution: {integrity: sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==} + + '@ethersproject/wordlists@5.8.0': + resolution: {integrity: sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==} + '@floating-ui/core@1.6.9': resolution: {integrity: sha512-uMXCuQ3BItDUbAMhIXw7UPXRfAlOAvZzdK9BWpE60MCn+Svt3aLn9jsPTi/WNGlRUu2uI0v5S7JiIUsbsvh3fw==} @@ -526,6 +1108,64 @@ packages: '@floating-ui/utils@0.2.9': resolution: {integrity: sha512-MDWhGtE+eHw5JW7lq4qhc5yRLS11ERl1c7Z6Xd0a58DozHES6EnNNwUWbMiG4J9Cgj053Bhk8zvlhFYKVhULwg==} + '@graphql-tools/merge@8.3.1': + resolution: {integrity: sha512-BMm99mqdNZbEYeTPK3it9r9S6rsZsQKtlqJsSBknAclXq2pGEfOxjcIZi+kBSkHZKPKCRrYDd5vY0+rUmIHVLg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/merge@8.4.2': + resolution: {integrity: sha512-XbrHAaj8yDuINph+sAfuq3QCZ/tKblrTLOpirK0+CAgNlZUCHs0Fa+xtMUURgwCVThLle1AF7svJCxFizygLsw==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/merge@9.0.22': + resolution: {integrity: sha512-bjOs9DlTbo1Yz2UzQcJ78Dn9/pKyY2zNaoqNLfRTTSkO56QFkvqhfjQuqJcqu+V3rtaB2o0VMpWaY6JT8ZTvQA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/mock@8.7.20': + resolution: {integrity: sha512-ljcHSJWjC/ZyzpXd5cfNhPI7YljRVvabKHPzKjEs5ElxWu2cdlLGvyNYepApXDsM/OJG/2xuhGM+9GWu5gEAPQ==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/schema@10.0.21': + resolution: {integrity: sha512-AECSlNnD0WNxICwfJs93gYn2oHxPmztn1MYBETIQXrJJcymfD6BoUrDlYPa6F27RzRc+gbPZPHMWL26uujfKBg==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/schema@8.5.1': + resolution: {integrity: sha512-0Esilsh0P/qYcB5DKQpiKeQs/jevzIadNTaT0jeWklPMwNbT7yMX4EqZany7mbeRRlSRwMzNzL5olyFdffHBZg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/schema@9.0.19': + resolution: {integrity: sha512-oBRPoNBtCkk0zbUsyP4GaIzCt8C0aCI4ycIRUL67KK5pOHljKLBBtGT+Jr6hkzA74C8Gco8bpZPe7aWFjiaK2w==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/utils@10.8.4': + resolution: {integrity: sha512-HpHBgcmLIE79jWk1v5Bm0Eb8MaPiwSJT/Iy5xIJ+GMe7yAKpCYrbjf7wb+UMDMkLkfEryvo3syCx8k+TMAZ9bA==} + engines: {node: '>=16.0.0'} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/utils@8.9.0': + resolution: {integrity: sha512-pjJIWH0XOVnYGXCqej8g/u/tsfV4LvLlj0eATKQu5zwnxd/TiTHq7Cg313qUPTFFHZ3PP5wJ15chYVtLDwaymg==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-tools/utils@9.2.1': + resolution: {integrity: sha512-WUw506Ql6xzmOORlriNrD6Ugx+HjVgYxt9KCXD9mHAak+eaXSwuGGPyE60hy9xaDEoXKBsG7SkG69ybitaVl6A==} + peerDependencies: + graphql: ^14.0.0 || ^15.0.0 || ^16.0.0 || ^17.0.0 + + '@graphql-typed-document-node/core@3.2.0': + resolution: {integrity: sha512-mB9oAsNCm9aM3/SOv4YtBMqZbYj10R7dkq8byBqxGY/ncFwhf2oQzMV+LCRlWoDSEBJ3COiR1yeDvMtsoOsuFQ==} + 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 + '@hookform/resolvers@4.1.3': resolution: {integrity: sha512-Jsv6UOWYTrEFJ/01ZrnwVXs7KDvP8XIo115i++5PWvNkNvkrsTfGiLS6w+eJ57CYtUtDQalUWovCZDHFJ8u1VQ==} peerDependencies: @@ -636,10 +1276,19 @@ packages: cpu: [x64] os: [win32] + '@ipld/dag-cbor@7.0.3': + resolution: {integrity: sha512-1VVh2huHsuohdXC1bGJNE8WR72slZ9XE2T3wbBBq31dm7ZBatmKLLxrB+XAqafxfRFjv08RZmj/W/ZqaM13AuA==} + + '@ipld/dag-json@8.0.11': + resolution: {integrity: sha512-Pea7JXeYHTWXRTIhBqBlhw7G53PJ7yta3G/sizGEZyzdeEwhZRr0od5IQ0r2ZxOt1Do+2czddjeEPp+YTxDwCA==} + '@isaacs/cliui@8.0.2': resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} engines: {node: '>=12'} + '@josephg/resolvable@1.0.1': + resolution: {integrity: sha512-CtzORUwWTTOTqfVtHaKRJ0I1kNQd1bpn3sUh8I3nJDVY+5/M/Oe1DnEWzPQvqq/xPIIkzzzIP7mfCoAjFRvDhg==} + '@jridgewell/gen-mapping@0.3.8': resolution: {integrity: sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==} engines: {node: '>=6.0.0'} @@ -661,6 +1310,10 @@ packages: '@jridgewell/trace-mapping@0.3.9': resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + '@metamask/eth-sig-util@4.0.1': + resolution: {integrity: sha512-tghyZKLHZjcdlDqCA3gNZmLeR0XvOE9U1qoQO9ohyAZT6Pya+H9vkBPcsyXytmYLNgVoin7CKCmweo/R43V+tQ==} + engines: {node: '>=12.0.0'} + '@next/env@15.2.1': resolution: {integrity: sha512-JmY0qvnPuS2NCWOz2bbby3Pe0VzdAQ7XpEB6uLIHmtXNfAsAO0KLQLkuAoc42Bxbo3/jMC3dcn9cdf+piCcG2Q==} @@ -712,6 +1365,14 @@ packages: cpu: [x64] os: [win32] + '@noble/curves@1.8.1': + resolution: {integrity: sha512-warwspo+UYUPep0Q+vtdVB4Ugn8GGQj8iyB3gnRWsztmUHTI3S1nhdiWNsPUGL0vud7JlRRk1XEu7Lq1KGTnMQ==} + engines: {node: ^14.21.3 || >=16} + + '@noble/hashes@1.7.1': + resolution: {integrity: sha512-B8XBPsn4vT/KJAGqDzbwztd+6Yte3P4V7iafm24bxgDe/mlRuK6xmWPuCNrKt2vDafZ8MfJLlchDG/vYafQEjQ==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -724,10 +1385,46 @@ packages: resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==} engines: {node: '>= 8'} + '@octetstream/promisify@2.0.2': + resolution: {integrity: sha512-7XHoRB61hxsz8lBQrjC1tq/3OEIgpvGWg6DKAdwi7WRzruwkmsdwmOoUXbU4Dtd4RSOMDwed0SkP3y8UlMt1Bg==} + engines: {node: 6.x || >=8.x} + + '@octokit/app@14.1.0': + resolution: {integrity: sha512-g3uEsGOQCBl1+W1rgfwoRFUIR6PtvB2T1E4RpygeUU5LrLvlOqcxrt5lfykIeRpUPpupreGJUYl70fqMDXdTpw==} + engines: {node: '>= 18'} + + '@octokit/auth-app@6.1.3': + resolution: {integrity: sha512-dcaiteA6Y/beAlDLZOPNReN3FGHu+pARD6OHfh3T9f3EO09++ec+5wt3KtGGSSs2Mp5tI8fQwdMOEnrzBLfgUA==} + engines: {node: '>= 18'} + + '@octokit/auth-oauth-app@7.1.0': + resolution: {integrity: sha512-w+SyJN/b0l/HEb4EOPRudo7uUOSW51jcK1jwLa+4r7PA8FPFpoxEnHBHMITqCsc/3Vo2qqFjgQfz/xUUvsSQnA==} + engines: {node: '>= 18'} + + '@octokit/auth-oauth-device@6.1.0': + resolution: {integrity: sha512-FNQ7cb8kASufd6Ej4gnJ3f1QB5vJitkoV1O0/g6e6lUsQ7+VsSNRHRmFScN2tV4IgKA12frrr/cegUs0t+0/Lw==} + engines: {node: '>= 18'} + + '@octokit/auth-oauth-user@4.1.0': + resolution: {integrity: sha512-FrEp8mtFuS/BrJyjpur+4GARteUCrPeR/tZJzD8YourzoVhRics7u7we/aDcKv+yywRNwNi/P4fRi631rG/OyQ==} + engines: {node: '>= 18'} + + '@octokit/auth-token@4.0.0': + resolution: {integrity: sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==} + engines: {node: '>= 18'} + '@octokit/auth-token@5.1.2': resolution: {integrity: sha512-JcQDsBdg49Yky2w2ld20IHAlwr8d/d8N6NiOXbtuoPCqzbsiJgF633mVUw3x4mo0H5ypataQIX7SFu3yy44Mpw==} engines: {node: '>= 18'} + '@octokit/auth-unauthenticated@5.0.1': + resolution: {integrity: sha512-oxeWzmBFxWd+XolxKTc4zr+h3mt+yofn4r7OfoIkR/Cj/o70eEGmPsFbueyJE2iBAGpjgTnEOKM3pnuEGVmiqg==} + engines: {node: '>= 18'} + + '@octokit/core@5.2.0': + resolution: {integrity: sha512-1LFfa/qnMQvEOAdzlQymH0ulepxbxnCYAKJZfMci/5XJyIHWgEYnDmgnKakbTh7CH2tFQ5O60oYDvns4i9RAIg==} + engines: {node: '>= 18'} + '@octokit/core@6.1.4': resolution: {integrity: sha512-lAS9k7d6I0MPN+gb9bKDt7X8SdxknYqAMh44S5L+lNqIN2NuV8nvv3g8rPp7MuRxcOpxpUIATWprO0C34a8Qmg==} engines: {node: '>= 18'} @@ -736,35 +1433,102 @@ packages: resolution: {integrity: sha512-nBRBMpKPhQUxCsQQeW+rCJ/OPSMcj3g0nfHn01zGYZXuNDvvXudF/TYY6APj5THlurerpFN4a/dQAIAaM6BYhA==} engines: {node: '>= 18'} + '@octokit/endpoint@9.0.6': + resolution: {integrity: sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==} + engines: {node: '>= 18'} + + '@octokit/graphql@7.1.1': + resolution: {integrity: sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==} + engines: {node: '>= 18'} + '@octokit/graphql@8.2.1': resolution: {integrity: sha512-n57hXtOoHrhwTWdvhVkdJHdhTv0JstjDbDRhJfwIRNfFqmSo1DaK/mD2syoNUoLCyqSjBpGAKOG0BuwF392slw==} engines: {node: '>= 18'} + '@octokit/oauth-app@6.1.0': + resolution: {integrity: sha512-nIn/8eUJ/BKUVzxUXd5vpzl1rwaVxMyYbQkNZjHrF7Vk/yu98/YDF/N2KeWO7uZ0g3b5EyiFXFkZI8rJ+DH1/g==} + engines: {node: '>= 18'} + + '@octokit/oauth-authorization-url@6.0.2': + resolution: {integrity: sha512-CdoJukjXXxqLNK4y/VOiVzQVjibqoj/xHgInekviUJV73y/BSIcwvJ/4aNHPBPKcPWFnd4/lO9uqRV65jXhcLA==} + engines: {node: '>= 18'} + + '@octokit/oauth-methods@4.1.0': + resolution: {integrity: sha512-4tuKnCRecJ6CG6gr0XcEXdZtkTDbfbnD5oaHBmLERTjTMZNi2CbfEHZxPU41xXLDG4DfKf+sonu00zvKI9NSbw==} + engines: {node: '>= 18'} + + '@octokit/openapi-types@20.0.0': + resolution: {integrity: sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==} + '@octokit/openapi-types@23.0.1': resolution: {integrity: sha512-izFjMJ1sir0jn0ldEKhZ7xegCTj/ObmEDlEfpFrx4k/JyZSMRHbO3/rBwgE7f3m2DHt+RrNGIVw4wSmwnm3t/g==} + '@octokit/plugin-paginate-graphql@4.0.1': + resolution: {integrity: sha512-R8ZQNmrIKKpHWC6V2gum4x9LG2qF1RxRjo27gjQcG3j+vf2tLsEfE7I/wRWEPzYMaenr1M+qDAtNcwZve1ce1A==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '>=5' + + '@octokit/plugin-paginate-rest@11.3.1': + resolution: {integrity: sha512-ryqobs26cLtM1kQxqeZui4v8FeznirUsksiA+RYemMPJ7Micju0WSkv50dBksTuZks9O5cg4wp+t8fZ/cLY56g==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + '@octokit/plugin-paginate-rest@11.4.3': resolution: {integrity: sha512-tBXaAbXkqVJlRoA/zQVe9mUdb8rScmivqtpv3ovsC5xhje/a+NOCivs7eUhWBwCApJVsR4G5HMeaLbq7PxqZGA==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=6' + '@octokit/plugin-paginate-rest@9.2.2': + resolution: {integrity: sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + '@octokit/plugin-request-log@5.3.1': resolution: {integrity: sha512-n/lNeCtq+9ofhC15xzmJCNKP2BWTv8Ih2TTy+jatNCCq/gQP/V7rK3fjIfuz0pDWDALO/o/4QY4hyOF6TQQFUw==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=6' + '@octokit/plugin-rest-endpoint-methods@13.2.2': + resolution: {integrity: sha512-EI7kXWidkt3Xlok5uN43suK99VWqc8OaIMktY9d9+RNKl69juoTyxmLoWPIZgJYzi41qj/9zU7G/ljnNOJ5AFA==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': ^5 + '@octokit/plugin-rest-endpoint-methods@13.3.1': resolution: {integrity: sha512-o8uOBdsyR+WR8MK9Cco8dCgvG13H1RlM1nWnK/W7TEACQBFux/vPREgKucxUfuDQ5yi1T3hGf4C5ZmZXAERgwQ==} engines: {node: '>= 18'} peerDependencies: '@octokit/core': '>=6' + '@octokit/plugin-retry@6.1.0': + resolution: {integrity: sha512-WrO3bvq4E1Xh1r2mT9w6SDFg01gFmP81nIG77+p/MqW1JeXXgL++6umim3t6x0Zj5pZm3rXAN+0HEjmmdhIRig==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': '5' + + '@octokit/plugin-throttling@8.2.0': + resolution: {integrity: sha512-nOpWtLayKFpgqmgD0y3GqXafMFuKcA4tRPZIfu7BArd2lEZeb1988nhWhwx4aZWmjDmUfdgVf7W+Tt4AmvRmMQ==} + engines: {node: '>= 18'} + peerDependencies: + '@octokit/core': ^5.0.0 + + '@octokit/request-error@5.1.1': + resolution: {integrity: sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==} + engines: {node: '>= 18'} + '@octokit/request-error@6.1.7': resolution: {integrity: sha512-69NIppAwaauwZv6aOzb+VVLwt+0havz9GT5YplkeJv7fG7a40qpLt/yZKyiDxAhgz0EtgNdNcb96Z0u+Zyuy2g==} engines: {node: '>= 18'} + '@octokit/request@8.4.1': + resolution: {integrity: sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==} + engines: {node: '>= 18'} + '@octokit/request@9.2.2': resolution: {integrity: sha512-dZl0ZHx6gOQGcffgm1/Sf6JfEpmh34v3Af2Uci02vzUYz6qEN6zepoRtmybWXIGXFIK8K9ylE3b+duCWqhArtg==} engines: {node: '>= 18'} @@ -773,16 +1537,57 @@ packages: resolution: {integrity: sha512-sTQV7va0IUVZcntzy1q3QqPm/r8rWtDCqpRAmb8eXXnKkjoQEtFe3Nt5GTVsHft+R6jJoHeSiVLcgcvhtue/rg==} engines: {node: '>= 18'} + '@octokit/types@12.6.0': + resolution: {integrity: sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==} + '@octokit/types@13.8.0': resolution: {integrity: sha512-x7DjTIbEpEWXK99DMd01QfWy0hd5h4EN+Q7shkdKds3otGQP+oWE/y0A76i1OvH9fygo4ddvNf7ZvF0t78P98A==} + '@octokit/webhooks-methods@4.1.0': + resolution: {integrity: sha512-zoQyKw8h9STNPqtm28UGOYFE7O6D4Il8VJwhAtMHFt2C4L0VQT1qGKLeefUOqHNs1mNRYSadVv7x0z8U2yyeWQ==} + engines: {node: '>= 18'} + '@octokit/webhooks-types@7.6.1': resolution: {integrity: sha512-S8u2cJzklBC0FgTwWVLaM8tMrDuDMVE4xiTK4EYXM9GntyvrdbSoxqDQa+Fh57CCNApyIpyeqPhhFEmHPfrXgw==} + '@octokit/webhooks@12.3.1': + resolution: {integrity: sha512-BVwtWE3rRXB9IugmQTfKspqjNa8q+ab73ddkV9k1Zok3XbuOxJUi4lTYk5zBZDhfWb/Y2H+RO9Iggm25gsqeow==} + engines: {node: '>= 18'} + '@pkgjs/parseargs@0.11.0': resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} engines: {node: '>=14'} + '@protobufjs/aspromise@1.1.2': + resolution: {integrity: sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==} + + '@protobufjs/base64@1.1.2': + resolution: {integrity: sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==} + + '@protobufjs/codegen@2.0.4': + resolution: {integrity: sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==} + + '@protobufjs/eventemitter@1.1.0': + resolution: {integrity: sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==} + + '@protobufjs/fetch@1.1.0': + resolution: {integrity: sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==} + + '@protobufjs/float@1.0.2': + resolution: {integrity: sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==} + + '@protobufjs/inquire@1.1.0': + resolution: {integrity: sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==} + + '@protobufjs/path@1.1.2': + resolution: {integrity: sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==} + + '@protobufjs/pool@1.1.0': + resolution: {integrity: sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==} + + '@protobufjs/utf8@1.1.0': + resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} + '@radix-ui/number@1.1.0': resolution: {integrity: sha512-V3gRzhVNU1ldS5XhAPTom1fOIo4ccrjjJgmE+LI2h/WaFpHmx0MQApT+KZHnx8abG6Avtfcz4WoEciMnpFT3HQ==} @@ -1377,6 +2182,119 @@ packages: '@radix-ui/rect@1.1.0': resolution: {integrity: sha512-A9+lCBZoaMJlVKcRBz2YByCG+Cp2t6nAnMnNba+XiWxnj6r4JUFqfsgwocMBZU9LPtdxC6wB56ySYpc7LQIoJg==} + '@rollup/rollup-android-arm-eabi@4.34.9': + resolution: {integrity: sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==} + cpu: [arm] + os: [android] + + '@rollup/rollup-android-arm64@4.34.9': + resolution: {integrity: sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==} + cpu: [arm64] + os: [android] + + '@rollup/rollup-darwin-arm64@4.34.9': + resolution: {integrity: sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==} + cpu: [arm64] + os: [darwin] + + '@rollup/rollup-darwin-x64@4.34.9': + resolution: {integrity: sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==} + cpu: [x64] + os: [darwin] + + '@rollup/rollup-freebsd-arm64@4.34.9': + resolution: {integrity: sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==} + cpu: [arm64] + os: [freebsd] + + '@rollup/rollup-freebsd-x64@4.34.9': + resolution: {integrity: sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==} + cpu: [x64] + os: [freebsd] + + '@rollup/rollup-linux-arm-gnueabihf@4.34.9': + resolution: {integrity: sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm-musleabihf@4.34.9': + resolution: {integrity: sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==} + cpu: [arm] + os: [linux] + + '@rollup/rollup-linux-arm64-gnu@4.34.9': + resolution: {integrity: sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-arm64-musl@4.34.9': + resolution: {integrity: sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==} + cpu: [arm64] + os: [linux] + + '@rollup/rollup-linux-loongarch64-gnu@4.34.9': + resolution: {integrity: sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==} + cpu: [loong64] + os: [linux] + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.9': + resolution: {integrity: sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==} + cpu: [ppc64] + os: [linux] + + '@rollup/rollup-linux-riscv64-gnu@4.34.9': + resolution: {integrity: sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==} + cpu: [riscv64] + os: [linux] + + '@rollup/rollup-linux-s390x-gnu@4.34.9': + resolution: {integrity: sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==} + cpu: [s390x] + os: [linux] + + '@rollup/rollup-linux-x64-gnu@4.34.9': + resolution: {integrity: sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-linux-x64-musl@4.34.9': + resolution: {integrity: sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==} + cpu: [x64] + os: [linux] + + '@rollup/rollup-win32-arm64-msvc@4.34.9': + resolution: {integrity: sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==} + cpu: [arm64] + os: [win32] + + '@rollup/rollup-win32-ia32-msvc@4.34.9': + resolution: {integrity: sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==} + cpu: [ia32] + os: [win32] + + '@rollup/rollup-win32-x64-msvc@4.34.9': + resolution: {integrity: sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==} + cpu: [x64] + os: [win32] + + '@spruceid/siwe-parser@3.0.0': + resolution: {integrity: sha512-Y92k63ilw/8jH9Ry4G2e7lQd0jZAvb0d/Q7ssSD0D9mp/Zt2aCXIc3g0ny9yhplpAx1QXHsMz/JJptHK/zDGdw==} + + '@sqltools/formatter@1.2.5': + resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} + + '@stablelib/binary@1.0.1': + resolution: {integrity: sha512-ClJWvmL6UBM/wjkvv/7m5VP3GMr9t0osr4yVgLZsLCOz4hGN9gIAFEqnJ0TsSMAN+n840nf2cHZnA5/KFqHC7Q==} + + '@stablelib/int@1.0.1': + resolution: {integrity: sha512-byr69X/sDtDiIjIV6m4roLVWnNNlRGzsvxw+agj8CIEazqWGOQp2dTYgQhtyVXV9wpO6WyXRQUzLV/JRNumT2w==} + + '@stablelib/random@1.0.2': + resolution: {integrity: sha512-rIsE83Xpb7clHPVRlBj8qNe5L8ISQOzjghYQm/dZ7VaM2KHYwMW5adjQjrzTZCchFnNCNhkwtnOBa9HTMJCI8w==} + + '@stablelib/wipe@1.0.1': + resolution: {integrity: sha512-WfqfX/eXGiAd3RJe4VU2snh/ZPwtSjLG4ynQ/vYzvghTh7dHFcI1wl+nrkWG6lGhukOxOsUHfv8dUXr58D0ayg==} + '@standard-schema/utils@0.3.0': resolution: {integrity: sha512-e7Mew686owMaPJVNNLs55PUvgz371nKgwsc4vxE49zsODpJEnxgxRo2y/OKrqueavXgZNMDVj3DdHFlaSAeU8g==} @@ -1386,81 +2304,96 @@ packages: '@swc/helpers@0.5.15': resolution: {integrity: sha512-JQ5TuMi45Owi4/BIMAJBoSQoOJu12oOk/gADqlcUL9JEdHB8vyjUSsxqeNXnmXHjYKMi2WcYtezGEEhqUI/E2g==} - '@tailwindcss/node@4.0.12': - resolution: {integrity: sha512-a6J11K1Ztdln9OrGfoM75/hChYPcHYGNYimqciMrvKXRmmPaS8XZTHhdvb5a3glz4Kd4ZxE1MnuFE2c0fGGmtg==} + '@tailwindcss/node@4.0.11': + resolution: {integrity: sha512-y1Ko/QaZh6Fv8sSOOPpRztT8nvNKSetvE4CLxsDdyY5kkBS7hKq04D3y3ldelniWe6YqRIzBHTzfAIc1hZ+0FA==} - '@tailwindcss/oxide-android-arm64@4.0.12': - resolution: {integrity: sha512-dAXCaemu3mHLXcA5GwGlQynX8n7tTdvn5i1zAxRvZ5iC9fWLl5bGnjZnzrQqT7ttxCvRwdVf3IHUnMVdDBO/kQ==} + '@tailwindcss/oxide-android-arm64@4.0.11': + resolution: {integrity: sha512-6gGLTOwR3WNh63pUnY6znRY7XiLRVmvyAkQRdyRxPquNIZ7lTeqWlZcxt5Gtlh1VzZXkQ8OWyYte8ZBnulhvwA==} engines: {node: '>= 10'} cpu: [arm64] os: [android] - '@tailwindcss/oxide-darwin-arm64@4.0.12': - resolution: {integrity: sha512-vPNI+TpJQ7sizselDXIJdYkx9Cu6JBdtmRWujw9pVIxW8uz3O2PjgGGzL/7A0sXI8XDjSyRChrUnEW9rQygmJQ==} + '@tailwindcss/oxide-darwin-arm64@4.0.11': + resolution: {integrity: sha512-CM5SF53zzqYqQQGlP6N94zTliUi2FxW4itr223xb2PWgbwf48JTE2P6DNrA5DHOxacIliiCYiBzmKGwKdGMu8w==} engines: {node: '>= 10'} cpu: [arm64] os: [darwin] - '@tailwindcss/oxide-darwin-x64@4.0.12': - resolution: {integrity: sha512-RL/9jM41Fdq4Efr35C5wgLx98BirnrfwuD+zgMFK6Ir68HeOSqBhW9jsEeC7Y/JcGyPd3MEoJVIU4fAb7YLg7A==} + '@tailwindcss/oxide-darwin-x64@4.0.11': + resolution: {integrity: sha512-YB1LJC04O3UugV0egl3jnpXWyJIlcV7oVb0cplcqG0aP6nPYH0SqmD+ysbOrl6Ti1qAVuOHnfJvnAup2hbXMgw==} engines: {node: '>= 10'} cpu: [x64] os: [darwin] - '@tailwindcss/oxide-freebsd-x64@4.0.12': - resolution: {integrity: sha512-7WzWiax+LguJcMEimY0Q4sBLlFXu1tYxVka3+G2M9KmU/3m84J3jAIV4KZWnockbHsbb2XgrEjtlJKVwHQCoRA==} + '@tailwindcss/oxide-freebsd-x64@4.0.11': + resolution: {integrity: sha512-tK63Mi/kbU5GVZFkUH+zLL/G0yiRGY15MU2xFUa3H2q2px4IuWJTWRmv6iPOcZm3kYpsh+0C+dSoz0lDEknENg==} engines: {node: '>= 10'} cpu: [x64] os: [freebsd] - '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.12': - resolution: {integrity: sha512-X9LRC7jjE1QlfIaBbXjY0PGeQP87lz5mEfLSVs2J1yRc9PSg1tEPS9NBqY4BU9v5toZgJgzKeaNltORyTs22TQ==} + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.11': + resolution: {integrity: sha512-vMJPxCQtdhqGGw1MOQnPJ6hyh5BR5EQhRXJk9Ji/1oo2P1chgEaPuGYGZGdZMy9bnFaufnjae0liqk6E3SNTFw==} engines: {node: '>= 10'} cpu: [arm] os: [linux] - '@tailwindcss/oxide-linux-arm64-gnu@4.0.12': - resolution: {integrity: sha512-i24IFNq2402zfDdoWKypXz0ZNS2G4NKaA82tgBlE2OhHIE+4mg2JDb5wVfyP6R+MCm5grgXvurcIcKWvo44QiQ==} + '@tailwindcss/oxide-linux-arm64-gnu@4.0.11': + resolution: {integrity: sha512-5qac6Wps9vCwkQcgyw+VlJvXkdGoOnJp8eK3TaKpZ3fTQozGgvy/AyimV8I7I4ZjU6mTjuQbZe1CPP/cuG+Ldw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-arm64-musl@4.0.12': - resolution: {integrity: sha512-LmOdshJBfAGIBG0DdBWhI0n5LTMurnGGJCHcsm9F//ISfsHtCnnYIKgYQui5oOz1SUCkqsMGfkAzWyNKZqbGNw==} + '@tailwindcss/oxide-linux-arm64-musl@4.0.11': + resolution: {integrity: sha512-hR/Lw7QgODodKLpf37+ohJJZjYEJLg6c+h3nIXJ6eLYDbCZjJ0Z0+jHP0rHXyGab7JL+QlIksNuNbJjj+2qpsw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] - '@tailwindcss/oxide-linux-x64-gnu@4.0.12': - resolution: {integrity: sha512-OSK667qZRH30ep8RiHbZDQfqkXjnzKxdn0oRwWzgCO8CoTxV+MvIkd0BWdQbYtYuM1wrakARV/Hwp0eA/qzdbw==} + '@tailwindcss/oxide-linux-x64-gnu@4.0.11': + resolution: {integrity: sha512-4aCBYzU2SyFUw/dSP3SYAaeo3I7+c6to9acqXAl/Y5XnAO3q6SBrjw2sU2RG7f5Yi+jxevFh4BcOS5ofhhoTIA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-linux-x64-musl@4.0.12': - resolution: {integrity: sha512-uylhWq6OWQ8krV8Jk+v0H/3AZKJW6xYMgNMyNnUbbYXWi7hIVdxRKNUB5UvrlC3RxtgsK5EAV2i1CWTRsNcAnA==} + '@tailwindcss/oxide-linux-x64-musl@4.0.11': + resolution: {integrity: sha512-Y5j5Yp3lRcgyzOF+CY+u54aUUtvZ6OwiVPeILE3wqbsDA6X3UiUpVr8tW2eREERld0gELfXG8TyNAtDsBIOHwA==} engines: {node: '>= 10'} cpu: [x64] os: [linux] - '@tailwindcss/oxide-win32-arm64-msvc@4.0.12': - resolution: {integrity: sha512-XDLnhMoXZEEOir1LK43/gHHwK84V1GlV8+pAncUAIN2wloeD+nNciI9WRIY/BeFTqES22DhTIGoilSO39xDb2g==} + '@tailwindcss/oxide-win32-arm64-msvc@4.0.11': + resolution: {integrity: sha512-ofgW1IugQDJR+fGJUZMniwTzrwHvaw6wpoOE1mIXBFP2wWoDjvNTXUJyMDxF2N6UypXGYCJMDdEohB1CyWf9cg==} engines: {node: '>= 10'} cpu: [arm64] os: [win32] - '@tailwindcss/oxide-win32-x64-msvc@4.0.12': - resolution: {integrity: sha512-I/BbjCLpKDQucvtn6rFuYLst1nfFwSMYyPzkx/095RE+tuzk5+fwXuzQh7T3fIBTcbn82qH/sFka7yPGA50tLw==} + '@tailwindcss/oxide-win32-x64-msvc@4.0.11': + resolution: {integrity: sha512-jUDa1xZNVPuarkEbwxh8aFQ3oagDQRYXcPmfsiDZ2IAxcYnE8YPNbA2HvFxJowppnnu/v/xdWvneN24VBr1Zpw==} engines: {node: '>= 10'} cpu: [x64] os: [win32] - '@tailwindcss/oxide@4.0.12': - resolution: {integrity: sha512-DWb+myvJB9xJwelwT9GHaMc1qJj6MDXRDR0CS+T8IdkejAtu8ctJAgV4r1drQJLPeS7mNwq2UHW2GWrudTf63A==} + '@tailwindcss/oxide@4.0.11': + resolution: {integrity: sha512-vpR3j69boI64ftpDbbC2NPXhbF7LEkBbQ/Ol1mSU9medtdcmabMiEPlN9FtvE2IkoXZpiDM1utSsdutZSka9Cg==} engines: {node: '>= 10'} - '@tailwindcss/postcss@4.0.12': - resolution: {integrity: sha512-r59Sdr8djCW4dL3kvc4aWU8PHdUAVM3O3te2nbYzXsWwKLlHPCuUoZAc9FafXb/YyNDZOMI7sTbKTKFmwOrMjw==} + '@tailwindcss/postcss@4.0.11': + resolution: {integrity: sha512-bhHxHe1NEvh3rKSzJqXYJ8E1MDPAMKc0/5qwRdy+6Ed8PqyicwE1l9zPvt6iZJgIIA1PPX6VF80PDluFe8tyXg==} + + '@tharsis/address-converter@0.1.8': + resolution: {integrity: sha512-z7zdNczV8RIzBNxzIzRFhC5ujiQ3Lt04At9rooo2pL6QONDDMMLxsqH3o28ie80k5DXSXaMJ6gffATeehxwAkw==} + + '@tharsis/eip712@0.2.4': + resolution: {integrity: sha512-tn3zghCpsar2ZDsF8d7eBAfr+Toeqd9uOxFTa8LlCyewXmXE18mPMyoLeNDYX0jU7kTO0TTV9RQf0uNCahzQHA==} + + '@tharsis/proto@0.1.20': + resolution: {integrity: sha512-Ls7Mmw8Oe9uTPpyxcjsjmiREK/MQwrdF4AHwB5J7MsQEjyk7rNFS2lbPDB8hT4bzquIhF9MOTt4Nvh83iyMAAA==} + + '@tharsis/provider@0.2.4': + resolution: {integrity: sha512-gAVKhQfeDmcdp4nCFPfuR0BZkbPaqozMG7wL5gLo+KhuzzeIs4VZvUt4gFCZph1dvsqPy2KLU+4h2/eiWroeMA==} + + '@tharsis/transactions@0.2.6': + resolution: {integrity: sha512-RHDYaLYvDL4UvKveN08vppsRyjTOnJ2eSBBCXmSyRBbeEVXOBG83qhoECx9nrcs3gXzEL5pqU3PUe3p+3hzfDQ==} '@tootallnate/quickjs-emscripten@0.23.0': resolution: {integrity: sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==} @@ -1485,6 +2418,56 @@ packages: resolution: {integrity: sha512-5CK3ZkVskSExf9YaXVMJ04F6Fb18HXKVZw8TMKVP7qOIvHGiBmT6YzWHqsQ3/PMNov2TzJ41ofRKX3zjR3G6Yg==} hasBin: true + '@turnkey/api-key-stamper@0.4.0': + resolution: {integrity: sha512-LyIiAXRuSL5UBa/Y95gHuh7j4uHzVMkI2+sHWM4/UWZat3nCoveU66h6SFXwF1BThA0poGgsKjWjsKNCJ89NPg==} + engines: {node: '>=18.0.0'} + + '@turnkey/encoding@0.1.0': + resolution: {integrity: sha512-aLmLrWtvV1k9UyGzuzMpBFdwleCH8VpzXIriusVMrFLiQp+4uHCS9cwrEG1glg3207ewWFDtvgj31qLoJS29pg==} + engines: {node: '>=18.0.0'} + + '@turnkey/http@2.10.0': + resolution: {integrity: sha512-5I2VwOzxYGxmSy8UOZn8rsV23gmK8v93KqNZ/mjf4GrFQ69q8LCaAFmrH1Zo+/J7eq0/GQdxNqBHfJKLp5iihw==} + engines: {node: '>=16.0.0'} + + '@turnkey/sdk-server@0.1.0': + resolution: {integrity: sha512-INg+r1p955OsS33OkV+AEqkhIhP2QcB20bAhS+oVPskGjin93/02RvfniJvArU30arhYTKOgeHrUHWmI6lVuaw==} + engines: {node: '>=18.0.0'} + + '@turnkey/webauthn-stamper@0.5.0': + resolution: {integrity: sha512-iUbTUwD4f4ibdLy5PWWb7ITEz4S4VAP9/mNjFhoRY3cKVVTDfmykrVTKjPOIHWzDgAmLtgrLvySIIC9ZBVENBw==} + engines: {node: '>=18.0.0'} + + '@types/accepts@1.3.7': + resolution: {integrity: sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==} + + '@types/aws-lambda@8.10.147': + resolution: {integrity: sha512-nD0Z9fNIZcxYX5Mai2CTmFD7wX7UldCkW2ezCF8D1T5hdiLsnTWDGRpfRYntU6VjTdLQjOvyszru7I1c1oCQew==} + + '@types/bn.js@4.11.6': + resolution: {integrity: sha512-pqr857jrp2kPuO9uRjZ3PwnJTjoQy+fcdxvBTvHm6dkmEL9q+hDD/2j/0ELOBPtPnS8LjCX0gI9nbl8lVkadpg==} + + '@types/body-parser@1.19.2': + resolution: {integrity: sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==} + + '@types/body-parser@1.19.5': + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + + '@types/btoa-lite@1.0.2': + resolution: {integrity: sha512-ZYbcE2x7yrvNFJiU7xJGrpF/ihpkM7zKgw8bha3LNJSesvTtUNxbpzaT7WXBIryf6jovisrxTBvymxMeLLj1Mg==} + + '@types/connect@3.4.38': + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + + '@types/cookie-session@2.0.49': + resolution: {integrity: sha512-4E/bBjlqLhU5l4iGPR+NkVJH593hpNsT4dC3DJDr+ODm6Qpe13kZQVkezRIb+TYDXaBMemS3yLQ+0leba3jlkQ==} + + '@types/cors@2.8.12': + resolution: {integrity: sha512-vt+kDhq/M2ayberEtJcIN/hxXy1Pk+59g2FV/ZQceeaTyCtCucjL2Q7FXlFjtWn4n15KCr1NE2lNNFhp0lEThw==} + + '@types/cors@2.8.17': + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + '@types/d3-array@3.2.1': resolution: {integrity: sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==} @@ -1512,36 +2495,145 @@ packages: '@types/d3-timer@3.0.2': resolution: {integrity: sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==} + '@types/debug@4.1.12': + resolution: {integrity: sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==} + + '@types/estree@1.0.6': + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} + + '@types/express-serve-static-core@4.17.31': + resolution: {integrity: sha512-DxMhY+NAsTwMMFHBTtJFNp5qiHKJ7TeqOo23zVEM9alT1Ml27Q3xcTH0xwxn7Q0BbMcVEJOs/7aQtUWupUQN3Q==} + + '@types/express-serve-static-core@4.19.6': + resolution: {integrity: sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==} + + '@types/express-session@1.18.1': + resolution: {integrity: sha512-S6TkD/lljxDlQ2u/4A70luD8/ZxZcrU5pQwI1rVXCiaVIywoFgbA+PIUNDjPhQpPdK0dGleLtYc/y7XWBfclBg==} + + '@types/express@4.17.14': + resolution: {integrity: sha512-TEbt+vaPFQ+xpxFLFssxUDXj5cWCxZJjIcB7Yg0k0GMHGtgtQgpvx/MUQUeAkNbA9AAGrwkAsoeItdTgS7FMyg==} + + '@types/express@4.17.21': + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + + '@types/fs-extra@11.0.4': + resolution: {integrity: sha512-yTbItCNreRooED33qjunPthRcSjERP1r4MqCZc7wv0u2sUkzTFp45tgUfS5+r7FrZPdmCCNflLhVSP/o+SemsQ==} + '@types/glob@7.2.0': resolution: {integrity: sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==} + '@types/google-protobuf@3.15.12': + resolution: {integrity: sha512-40um9QqwHjRS92qnOaDpL7RmDK15NuZYo9HihiJRbYkMQZlWnuH8AdvbMy8/o6lgLmKbDUKa+OALCltHdbOTpQ==} + + '@types/http-errors@2.0.4': + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + '@types/inquirer@6.5.0': resolution: {integrity: sha512-rjaYQ9b9y/VFGOpqBEXRavc3jh0a+e6evAbI31tMda8VlPaSy0AZJfXsvmIe3wklc7W6C3zCSfleuMXR7NOyXw==} + '@types/jsonfile@6.1.4': + resolution: {integrity: sha512-D5qGUYwjvnNNextdU59/+fI+spnwtTFmyQP0h+PfIOSkNfpU6AOICUOkm4i0OnSk+NyjdPJrxCDro0sJsWlRpQ==} + + '@types/jsonwebtoken@9.0.9': + resolution: {integrity: sha512-uoe+GxEuHbvy12OUQct2X9JenKM3qAscquYymuQN4fMWG9DBQtykrQEFcAbVACF7qaLw9BePSodUL0kquqBJpQ==} + + '@types/keygrip@1.0.6': + resolution: {integrity: sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==} + + '@types/long@4.0.2': + resolution: {integrity: sha512-MqTGEo5bj5t157U6fA/BiDynNkn0YknVdh48CMPkTSpFTVmvao5UQmm7uEF6xBEo7qIMAlY/JSleYaE6VOdpaA==} + + '@types/luxon@3.4.2': + resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} + + '@types/mime@1.3.5': + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + '@types/minimatch@5.1.2': resolution: {integrity: sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==} + '@types/ms@2.1.0': + resolution: {integrity: sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==} + + '@types/node@10.12.18': + resolution: {integrity: sha512-fh+pAqt4xRzPfqA6eh3Z2y6fyZavRIumvjhaCL753+TVkGKGhpPeyrJG2JftD0T9q4GF00KjefsQ+PQNDdWQaQ==} + + '@types/node@10.17.60': + resolution: {integrity: sha512-F0KIgDJfy2nA3zMLmWGKxcH2ZVEtCZXHHdOQs2gSaQ27+lNeEfGxzkIw90aXswATX7AZ33tahPbzy6KAfUreVw==} + + '@types/node@17.0.45': + resolution: {integrity: sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==} + '@types/node@20.17.23': resolution: {integrity: sha512-8PCGZ1ZJbEZuYNTMqywO+Sj4vSKjSjT6Ua+6RFOYlEvIvKQABPtrNkoVSLSKDb4obYcMhspVKmsw8Cm10NFRUg==} '@types/node@22.13.9': resolution: {integrity: sha512-acBjXdRJ3A6Pb3tqnw9HZmyR3Fiol3aGxRCK1x3d+6CDAMjl7I649wpSd+yNURCjbOUGu9tqtLKnTGxmK6CyGw==} + '@types/pbkdf2@3.1.2': + resolution: {integrity: sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==} + '@types/prop-types@15.7.14': resolution: {integrity: sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==} + '@types/qs@6.9.18': + resolution: {integrity: sha512-kK7dgTYDyGqS+e2Q4aK9X3D7q234CIZ1Bv0q/7Z5IwRDoADNU81xXJK/YVyLbLTZCoIwUoDoffFeF+p/eIklAA==} + + '@types/range-parser@1.2.7': + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + '@types/react-dom@18.3.1': resolution: {integrity: sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==} '@types/react@18.3.0': resolution: {integrity: sha512-DiUcKjzE6soLyln8NNZmyhcQjVv+WsUIFSqetMN0p8927OztKT4VTfFTqsbAi5oAGIcgOmOajlfBqyptDDjZRw==} + '@types/secp256k1@4.0.6': + resolution: {integrity: sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==} + + '@types/semver@7.5.8': + resolution: {integrity: sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==} + + '@types/send@0.17.4': + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + + '@types/serve-static@1.15.7': + resolution: {integrity: sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==} + '@types/through@0.0.33': resolution: {integrity: sha512-HsJ+z3QuETzP3cswwtzt2vEIiHBk/dCcHGhbmG5X3ecnwFD/lPrMpliGXxSCg03L9AhrdwA4Oz/qfspkDW+xGQ==} '@types/tinycolor2@1.4.6': resolution: {integrity: sha512-iEN8J0BoMnsWBqjVbWH/c0G0Hh7O21lpR2/+PrvAVgWdzL7eexIFm4JN/Wn10PTcmNdtS6U67r499mlWMXOxNw==} + '@whatwg-node/promise-helpers@1.2.4': + resolution: {integrity: sha512-daEUfaHbaMuAcor+FPAVK+pOCSzsAYhK6LN1y81EcakdqQEPQvjm74PTmfwfv8POg8pw4RyCv9LXB1e+mQDwqg==} + engines: {node: '>=16.0.0'} + + '@wolfy1339/lru-cache@11.0.2-patch.1': + resolution: {integrity: sha512-BgYZfL2ADCXKOw2wJtkM3slhHotawWkgIRRxq4wEybnZQPjvAp71SPX35xepMykTw8gXlzWcWPTY31hlbnRsDA==} + engines: {node: 18 >=18.20 || 20 || >=22} + + '@wry/caches@1.0.1': + resolution: {integrity: sha512-bXuaUNLVVkD20wcGBWRyo7j9N3TxePEWFZj2Y+r9OoUzfqmavM84+mFykRicNsBqatba5JLay1t48wxaXaWnlA==} + engines: {node: '>=8'} + + '@wry/context@0.7.4': + resolution: {integrity: sha512-jmT7Sb4ZQWI5iyu3lobQxICu2nC/vbUhP0vIdd6tHC9PTfenmRmuIFqktc6GH9cgi+ZHnsLWPvfSvc4DrYmKiQ==} + engines: {node: '>=8'} + + '@wry/equality@0.5.7': + resolution: {integrity: sha512-BRFORjsTuQv5gxcXsuDXx6oGRhuVsEGwZy6LOzRRfgu+eSfxbhUQ9L9YtSEIuIjY/o7g3iWFjrc5eSY1GXP2Dw==} + engines: {node: '>=8'} + + '@wry/trie@0.5.0': + resolution: {integrity: sha512-FNoYzHawTMk/6KMQoEG5O4PuioX19UbwdQKF44yw0nLfOypfQdjtfZzo/UIJWAJ23sNIFbD1Ug9lbaDGMwbqQA==} + engines: {node: '>=8'} + + accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + acorn-walk@8.3.4: resolution: {integrity: sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==} engines: {node: '>=0.4.0'} @@ -1551,6 +2643,9 @@ packages: engines: {node: '>=0.4.0'} hasBin: true + aes-js@3.0.0: + resolution: {integrity: sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==} + agent-base@7.1.3: resolution: {integrity: sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==} engines: {node: '>= 14'} @@ -1583,6 +2678,10 @@ packages: resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} engines: {node: '>=12'} + ansis@3.17.0: + resolution: {integrity: sha512-0qWUglt9JEqLFr3w1I1pbrChn1grhaiAR2ocX1PP/flRmxgtwTzPFFFnfIlD6aMOLQZgSuCRlidD70lvx8yhzg==} + engines: {node: '>=14'} + any-promise@1.3.0: resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} @@ -1590,12 +2689,72 @@ packages: resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} engines: {node: '>= 8'} + apg-js@4.4.0: + resolution: {integrity: sha512-fefmXFknJmtgtNEXfPwZKYkMFX4Fyeyz+fNF6JWp87biGOPslJbCBVU158zvKRZfHBKnJDy8CMM40oLFGkXT8Q==} + + apollo-datasource@3.3.2: + resolution: {integrity: sha512-L5TiS8E2Hn/Yz7SSnWIVbZw0ZfEIXZCa5VUiVxD9P53JvSrf4aStvsFDlGWPvpIdCR+aly2CfoB79B9/JjKFqg==} + engines: {node: '>=12.0'} + deprecated: The `apollo-datasource` package is part of Apollo Server v2 and v3, which are now end-of-life (as of October 22nd 2023 and October 22nd 2024, respectively). See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details. + + apollo-reporting-protobuf@3.4.0: + resolution: {integrity: sha512-h0u3EbC/9RpihWOmcSsvTW2O6RXVaD/mPEjfrPkxRPTEPWqncsgOoRJw+wih4OqfH3PvTJvoEIf4LwKrUaqWog==} + deprecated: The `apollo-reporting-protobuf` package is part of Apollo Server v2 and v3, which are now end-of-life (as of October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/usage-reporting-protobuf` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details. + + apollo-server-core@3.13.0: + resolution: {integrity: sha512-v/g6DR6KuHn9DYSdtQijz8dLOkP78I5JSVJzPkARhDbhpH74QNwrQ2PP2URAPPEDJ2EeZNQDX8PvbYkAKqg+kg==} + engines: {node: '>=12.0'} + deprecated: The `apollo-server-core` package is part of Apollo Server v2 and v3, which are now end-of-life (as of October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details. + peerDependencies: + graphql: ^15.3.0 || ^16.0.0 + + apollo-server-env@4.2.1: + resolution: {integrity: sha512-vm/7c7ld+zFMxibzqZ7SSa5tBENc4B0uye9LTfjJwGoQFY5xsUPH5FpO5j0bMUDZ8YYNbrF9SNtzc5Cngcr90g==} + engines: {node: '>=12.0'} + deprecated: The `apollo-server-env` package is part of Apollo Server v2 and v3, which are now end-of-life (as of October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/utils.fetcher` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details. + + apollo-server-errors@3.3.1: + resolution: {integrity: sha512-xnZJ5QWs6FixHICXHxUfm+ZWqqxrNuPlQ+kj5m6RtEgIpekOPssH/SD9gf2B4HuWV0QozorrygwZnux8POvyPA==} + engines: {node: '>=12.0'} + deprecated: The `apollo-server-errors` package is part of Apollo Server v2 and v3, which are now end-of-life (as of October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details. + peerDependencies: + graphql: ^15.3.0 || ^16.0.0 + + apollo-server-express@3.13.0: + resolution: {integrity: sha512-iSxICNbDUyebOuM8EKb3xOrpIwOQgKxGbR2diSr4HP3IW8T3njKFOoMce50vr+moOCe1ev8BnLcw9SNbuUtf7g==} + engines: {node: '>=12.0'} + deprecated: The `apollo-server-express` package is part of Apollo Server v2 and v3, which are now end-of-life (as of October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details. + peerDependencies: + express: ^4.17.1 + graphql: ^15.3.0 || ^16.0.0 + + apollo-server-plugin-base@3.7.2: + resolution: {integrity: sha512-wE8dwGDvBOGehSsPTRZ8P/33Jan6/PmL0y0aN/1Z5a5GcbFhDaaJCjK5cav6npbbGL2DPKK0r6MPXi3k3N45aw==} + engines: {node: '>=12.0'} + deprecated: The `apollo-server-plugin-base` package is part of Apollo Server v2 and v3, which are now end-of-life (as of October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details. + peerDependencies: + graphql: ^15.3.0 || ^16.0.0 + + apollo-server-types@3.8.0: + resolution: {integrity: sha512-ZI/8rTE4ww8BHktsVpb91Sdq7Cb71rdSkXELSwdSR0eXu600/sY+1UXhTWdiJvk+Eq5ljqoHLwLbY2+Clq2b9A==} + engines: {node: '>=12.0'} + deprecated: The `apollo-server-types` package is part of Apollo Server v2 and v3, which are now end-of-life (as of October 22nd 2023 and October 22nd 2024, respectively). This package's functionality is now found in the `@apollo/server` package. See https://www.apollographql.com/docs/apollo-server/previous-versions/ for more details. + peerDependencies: + graphql: ^15.3.0 || ^16.0.0 + + app-root-path@3.1.0: + resolution: {integrity: sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==} + engines: {node: '>= 6.0.0'} + arg@4.1.3: resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} + argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + argparse@2.0.1: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} @@ -1603,6 +2762,9 @@ packages: resolution: {integrity: sha512-y+CcFFwelSXpLZk/7fMB2mUbGtX9lKycf1MWJ7CaTIERyitVlyQx6C+sxcROU2BAJ24OiZyK+8wj2i8AlBoS3A==} engines: {node: '>=10'} + array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + array-union@2.1.0: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} @@ -1611,6 +2773,12 @@ packages: resolution: {integrity: sha512-x1FCFnFifvYDDzTaLII71vG5uvDwgtmDTEVWAxrgeiR8VjMONcCXJx7E+USjDtHlwFmt9MysbqgF9b9Vjr6w+w==} engines: {node: '>=4'} + async-retry@1.3.3: + resolution: {integrity: sha512-wfr/jstw9xNi/0teMHrRW7dsz3Lt5ARhYNZ2ewpadnhaIp5mbALhOAP+EAdsC7t4Z6wqsDVv9+W6gm1Dk9mEyw==} + + asynckit@0.4.0: + resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} + autoprefixer@10.4.20: resolution: {integrity: sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==} engines: {node: ^10 || ^12 || >=14} @@ -1618,9 +2786,21 @@ packages: peerDependencies: postcss: ^8.1.0 + axios@0.21.4: + resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==} + + axios@0.26.1: + resolution: {integrity: sha512-fPwcX4EvnSHuInCMItEhAGnaSEXRBjtzh9fOtsE6E1G6p7vl7edEeZe11QHf18+6+9gR5PbKV/sGKNaD8YaMeA==} + + axios@1.8.2: + resolution: {integrity: sha512-ls4GYBm5aig9vWx8AWDSGLpnpDQRtWAfrjU+EuytuODrFBkqesN2RkOQCBzrA1RQNHw1SmRMSDDDSwzNAYQ6Rg==} + balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + base-x@3.0.10: + resolution: {integrity: sha512-7d0s06rR9rYaIWHkpfLIFICM/tkSVdoPC9qYAQRpxn9DdKNWNsKC0uk++akckyLq16Tx2WIinnZ6WRriAt6njQ==} + base64-js@1.5.1: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} @@ -1628,16 +2808,58 @@ packages: resolution: {integrity: sha512-4Bcg1P8xhUuqcii/S0Z9wiHIrQVPMermM1any+MX5GeGD7faD3/msQUDGLol9wOcz4/jbg/WJnGqoJF6LiBdtg==} engines: {node: '>=10.0.0'} + bech32@1.1.4: + resolution: {integrity: sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==} + + bech32@2.0.0: + resolution: {integrity: sha512-LcknSilhIGatDAsY1ak2I8VtGaHNhgMSYVxFrGLXv+xLHytaKZKcaUJJUE7qmBr7h33o5YQwP55pMI0xmkpJwg==} + + before-after-hook@2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + before-after-hook@3.0.2: resolution: {integrity: sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A==} + better-sqlite3@9.6.0: + resolution: {integrity: sha512-yR5HATnqeYNVnkaUTf4bOP2dJSnyhP4puJN/QPRyx4YkBEEUxib422n2XzPqDEHjQQqazoYoADdAm5vE15+dAQ==} + + big-integer@1.6.36: + resolution: {integrity: sha512-t70bfa7HYEA1D9idDbmuv7YbsbVkQ+Hp+8KFSul4aE5e/i1bjCNIRYJZlA8Q8p0r9T8cF/RVvwUgRA//FydEyg==} + engines: {node: '>=0.6'} + binary-extensions@2.3.0: resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} engines: {node: '>=8'} + bindings@1.5.0: + resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==} + + bip32@3.0.1: + resolution: {integrity: sha512-Uhpp9aEx3iyiO7CpbNGFxv9WcMIVdGoHG04doQ5Ln0u60uwDah7jUSc3QMV/fSZGm/Oo01/OeAmYevXV+Gz5jQ==} + engines: {node: '>=6.0.0'} + + bip39@3.1.0: + resolution: {integrity: sha512-c9kiwdk45Do5GL0vJMe7tS95VjCii65mYAH7DfWl3uW8AVzXKQVUm64i3hzVybBDMp9r7j9iNxR85+ul8MdN/A==} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} + blakejs@1.2.1: + resolution: {integrity: sha512-QXUSXI3QVc/gJME0dBpXrag1kbzOqCjCX8/b54ntNyW6sjtoqxqRk3LTmXzaJoh71zMsDCjM+47jS7XiwN/+fQ==} + + bn.js@4.12.1: + resolution: {integrity: sha512-k8TVBiPkPJT9uHLdOKfFpqcfprwBFOAAXXozRubr7R7PfIuKvQlzcI4M0pALeqXN09vdaMbUdUj+pass+uULAg==} + + bn.js@5.2.1: + resolution: {integrity: sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==} + + body-parser@1.20.3: + resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + + bottleneck@2.19.5: + resolution: {integrity: sha512-VHiNCbI1lKdl44tGrhNfU3lup0Tj/ZBMJB5/2ZbNXRCPuRCO7ed2mgcK4r17y+KB2EfuYuRaVlwNbAeaWGSpbw==} + brace-expansion@1.1.11: resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} @@ -1648,18 +2870,64 @@ packages: resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} engines: {node: '>=8'} + brorand@1.1.0: + resolution: {integrity: sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==} + + browserify-aes@1.2.0: + resolution: {integrity: sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==} + browserslist@4.24.4: resolution: {integrity: sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==} engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} hasBin: true + bs58@4.0.1: + resolution: {integrity: sha512-Ok3Wdf5vOIlBrgCvTq96gBkJw+JUEzdBgyaza5HLtPm7yTHkjRy8+JzNyHF7BHa0bNWOQIp3m5YF0nnFcOIKLw==} + + bs58check@2.1.2: + resolution: {integrity: sha512-0TS1jicxdU09dwJMNZtVAfzPi6Q6QeN0pM1Fkzrjn+XYHvzMKPU3pHVpva+769iNVSfIYWf7LJ6WR+BuuMf8cA==} + + btoa-lite@1.0.0: + resolution: {integrity: sha512-gvW7InbIyF8AicrqWoptdW08pUxuhq8BEgowNajy9RhiE86fmGAGl+bLKo6oB8QP0CkqHLowfN0oJdKC/J6LbA==} + + buffer-equal-constant-time@1.0.1: + resolution: {integrity: sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==} + + buffer-xor@1.0.3: + resolution: {integrity: sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==} + buffer@5.7.1: resolution: {integrity: sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==} + buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + + bundle-require@5.1.0: + resolution: {integrity: sha512-3WrrOuZiyaaZPWiEt4G3+IffISVC9HYlWueJEBWED4ZH4aIAC2PnkdnuRrR94M+w6yGWn4AglWtJtBI8YqvgoA==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + peerDependencies: + esbuild: '>=0.18' + busboy@1.6.0: resolution: {integrity: sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==} engines: {node: '>=10.16.0'} + bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + + cac@6.7.14: + resolution: {integrity: sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==} + engines: {node: '>=8'} + + call-bind-apply-helpers@1.0.2: + resolution: {integrity: sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==} + engines: {node: '>= 0.4'} + + call-bound@1.0.4: + resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==} + engines: {node: '>= 0.4'} + camel-case@3.0.0: resolution: {integrity: sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==} @@ -1670,6 +2938,13 @@ packages: caniuse-lite@1.0.30001702: resolution: {integrity: sha512-LoPe/D7zioC0REI5W73PeR1e1MLCipRGq/VkovJnd6Df+QVqT+vT33OXCp8QUd7kA7RZrHWxb1B36OQKI/0gOA==} + canonical-json@0.0.4: + resolution: {integrity: sha512-2sW7x0m/P7dqEnO0O87U7RTVQAaa7MELcd+Jd9FA6CYgYtwJ1TlDWIYMD8nuMkH1KoThsJogqgLyklrt9d/Azw==} + + cborg@1.10.2: + resolution: {integrity: sha512-b3tFPA9pUr2zCUiCfRd2+wok2/LBSNUMKOuRRok+WlvvAgEt/PlbgPTsZUcwCOs53IJvLgTp0eotwtosE6njug==} + hasBin: true + chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1696,6 +2971,17 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + chokidar@4.0.3: + resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==} + engines: {node: '>= 14.16.0'} + + chownr@1.1.4: + resolution: {integrity: sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==} + + cipher-base@1.0.6: + resolution: {integrity: sha512-3Ek9H3X6pj5TgenXYtNWdaBon1tgYCaebd+XPg0keyjEbEfkD4KkmAxkQ/i1vYvxdcT5nscLBfq9VJRmCBcFSw==} + engines: {node: '>= 0.10'} + class-variance-authority@0.7.1: resolution: {integrity: sha512-Ka+9Trutv7G8M6WT6SeiRWz792K5qEqIGEGzXKhAE6xOWAY6pPH8U+9IY3oCMv6kqTmLsv7Xh/2w2RigkePMsg==} @@ -1718,6 +3004,13 @@ packages: client-only@0.0.1: resolution: {integrity: sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA==} + cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + + cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + clone@1.0.4: resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==} engines: {node: '>=0.8'} @@ -1732,6 +3025,10 @@ packages: react: ^18 || ^19 || ^19.0.0-rc react-dom: ^18 || ^19 || ^19.0.0-rc + co@4.6.0: + resolution: {integrity: sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==} + engines: {iojs: '>= 1.0.0', node: '>= 0.12.0'} + color-convert@1.9.3: resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} @@ -1752,10 +3049,17 @@ packages: resolution: {integrity: sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==} engines: {node: '>=12.5.0'} + combined-stream@1.0.8: + resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} + engines: {node: '>= 0.8'} + commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} + commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + commander@4.1.1: resolution: {integrity: sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==} engines: {node: '>= 6'} @@ -1763,23 +3067,87 @@ packages: concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + consola@3.4.0: + resolution: {integrity: sha512-EiPU8G6dQG0GFHNR8ljnZFki/8a+cQwEQ+7wpxdChl02Q8HXlwEZWD5lqAF8vC2sEC3Tehr8hy7vErz88LHyUA==} + engines: {node: ^14.18.0 || >=16.10.0} + constant-case@2.0.0: resolution: {integrity: sha512-eS0N9WwmjTqrOmR3o83F5vW8Z+9R1HnVz3xmzT2PMFug9ly+Au/fxRWlEBSb6LcZwspSsEn9Xs1uw9YgzAg1EQ==} + content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + + content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + + cookie-session@2.1.0: + resolution: {integrity: sha512-u73BDmR8QLGcs+Lprs0cfbcAPKl2HnPcjpwRXT41sEV4DRJ2+W0vJEEZkG31ofkx+HZflA70siRIjiTdIodmOQ==} + engines: {node: '>= 0.10'} + + cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + + cookie-signature@1.0.7: + resolution: {integrity: sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==} + + cookie@0.7.1: + resolution: {integrity: sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==} + engines: {node: '>= 0.6'} + + cookie@0.7.2: + resolution: {integrity: sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==} + engines: {node: '>= 0.6'} + cookie@1.0.2: resolution: {integrity: sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==} engines: {node: '>=18'} + cookies@0.9.1: + resolution: {integrity: sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==} + engines: {node: '>= 0.8'} + + copyfiles@2.4.1: + resolution: {integrity: sha512-fereAvAvxDrQDOXybk3Qu3dPbOoKoysFMWtkY3mv5BsL8//OSZVL5DCLYqgRfY5cWirgRzlC+WSrxp6Bo3eNZg==} + hasBin: true + core-js-pure@3.41.0: resolution: {integrity: sha512-71Gzp96T9YPk63aUvE5Q5qP+DryB4ZloUZPSOebGM88VNw8VNfvdA7z6kGA8iGOTEzAomsRidp4jXSmUIJsL+Q==} + core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + + cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + + cosmjs-types@0.9.0: + resolution: {integrity: sha512-MN/yUe6mkJwHnCFfsNPeCfXVhyxHYW6c/xDUzrSbBycYzw++XvWDMJArXp2pLdgD6FQ8DW79vkPjeNKVrXaHeQ==} + + create-hash@1.2.0: + resolution: {integrity: sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==} + + create-hmac@1.1.7: + resolution: {integrity: sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==} + create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cross-fetch@3.2.0: + resolution: {integrity: sha512-Q+xVJLoGOeIMXZmbUK4HYk+69cQH6LudR0Vu/pRm2YlU/hDV9CiS0gKUMaWY5f2NeUH9C1nV3bsTlCo0FsTV1Q==} + + cross-inspect@1.0.1: + resolution: {integrity: sha512-Pcw1JTvZLSJH83iiGWt6fRcT+BjZlCDRVwYLbUcHzv/CRpB7r0MlSrGbIyQvVSNyGnbt7G4AXuyCiDR3POvZ1A==} + engines: {node: '>=16.0.0'} + cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} + crypto-addr-codec@0.1.8: + resolution: {integrity: sha512-GqAK90iLLgP3FvhNmHbpT3wR6dEdaM8hZyZtLX29SPardh3OA13RFLHDR6sntGCgRWOfiHqW6sIyohpNqOtV/g==} + crypto-js@4.2.0: resolution: {integrity: sha512-KALDyEYgpY+Rlob/iriUtjV6d5Eq+Y191A5g4UqLAi8CyGP9N1+FdVbkc1SxKc2r4YAYqG8JzO2KGL+AizD70Q==} @@ -1788,6 +3156,9 @@ packages: engines: {node: '>=4'} hasBin: true + cssfilter@0.0.10: + resolution: {integrity: sha512-FAaLDaplstoRsDR8XGYH51znUN0UY7nMc6Z9/fvE8EXGwvJE9hu7W2vHwx1+bd6gCYnln9nLbzxFTrcO9YQDZw==} + csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} @@ -1842,6 +3213,25 @@ packages: date-fns@4.1.0: resolution: {integrity: sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==} + dayjs@1.11.13: + resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} + + debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + debug@3.2.7: + resolution: {integrity: sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + debug@4.4.0: resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} @@ -1854,6 +3244,10 @@ packages: decimal.js-light@2.5.1: resolution: {integrity: sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg==} + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + deep-extend@0.6.0: resolution: {integrity: sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==} engines: {node: '>=4.0.0'} @@ -1861,6 +3255,14 @@ packages: defaults@1.0.4: resolution: {integrity: sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==} + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + degenerator@5.0.1: resolution: {integrity: sha512-TllpMR/t0M5sqCXfj85i4XaAzxmS5tVA16dqvdkMwGmzI+dXLXnw3J+3Vdv7VKw+ThlTMboK6i9rnZ6Nntj5CQ==} engines: {node: '>= 14'} @@ -1869,10 +3271,25 @@ packages: resolution: {integrity: sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==} engines: {node: '>=8'} + delayed-stream@1.0.0: + resolution: {integrity: sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==} + engines: {node: '>=0.4.0'} + + depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + + deprecation@2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + dequal@2.0.3: resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==} engines: {node: '>=6'} + destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + detect-libc@2.0.3: resolution: {integrity: sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==} engines: {node: '>=8'} @@ -1907,11 +3324,28 @@ packages: resolution: {integrity: sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==} engines: {node: '>=12'} + dset@3.1.4: + resolution: {integrity: sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==} + engines: {node: '>=4'} + + dunder-proto@1.0.1: + resolution: {integrity: sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==} + engines: {node: '>= 0.4'} + eastasianwidth@0.2.0: resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} - electron-to-chromium@1.5.113: - resolution: {integrity: sha512-wjT2O4hX+wdWPJ76gWSkMhcHAV2PTMX+QetUCPYEdCIe+cxmgzzSSiGRCKW8nuh4mwKZlpv0xvoW7OF2X+wmHg==} + ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + + ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + + electron-to-chromium@1.5.112: + resolution: {integrity: sha512-oen93kVyqSb3l+ziUgzIOlWt/oOuy4zRmpwestMn4rhFWAoFJeFuCVte9F2fASjeZZo7l/Cif9TiyrdW4CwEMA==} + + elliptic@6.6.1: + resolution: {integrity: sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==} embla-carousel-react@8.5.2: resolution: {integrity: sha512-Tmx+uY3MqseIGdwp0ScyUuxpBgx5jX1f7od4Cm5mDwg/dptEiTKf9xp6tw0lZN2VA9JbnVMl/aikmbc53c6QFA==} @@ -1932,14 +3366,49 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + + encodeurl@2.0.0: + resolution: {integrity: sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==} + engines: {node: '>= 0.8'} + + end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + enhanced-resolve@5.18.1: resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==} engines: {node: '>=10.13.0'} + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es-object-atoms@1.1.1: + resolution: {integrity: sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==} + engines: {node: '>= 0.4'} + + es-set-tostringtag@2.1.0: + resolution: {integrity: sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==} + engines: {node: '>= 0.4'} + + esbuild@0.25.0: + resolution: {integrity: sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} + escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + escape-string-regexp@1.0.5: resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} engines: {node: '>=0.8.0'} @@ -1962,13 +3431,54 @@ packages: resolution: {integrity: sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==} engines: {node: '>=0.10.0'} + etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + + ethereum-cryptography@0.1.3: + resolution: {integrity: sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==} + + ethereumjs-abi@0.6.8: + resolution: {integrity: sha512-Tx0r/iXI6r+lRsdvkFDlut0N08jWMnKRZ6Gkq+Nmw75lZe4e6o3EkSnkaBP5NF6+m5PTGAr9JP43N3LyeoglsA==} + deprecated: This library has been deprecated and usage is discouraged. + + ethereumjs-util@6.2.1: + resolution: {integrity: sha512-W2Ktez4L01Vexijrm5EB6w7dg4n/TgpoYU4avuT5T3Vmnw/eCRtiBrJfQYS/DCSvDIOLn2k57GcHdeBcgVxAqw==} + + ethers@5.8.0: + resolution: {integrity: sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==} + + ethjs-util@0.1.6: + resolution: {integrity: sha512-CUnVOQq7gSpDHZVVrQW8ExxUETWrnrvXYvYz55wOU8Uj4VCgw56XC2B/fVqQN+f7gmrnRHSLVnFAwsCuNwji8w==} + engines: {node: '>=6.5.0', npm: '>=3'} + eventemitter3@4.0.7: resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} + evp_bytestokey@1.0.3: + resolution: {integrity: sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==} + execa@5.1.1: resolution: {integrity: sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==} engines: {node: '>=10'} + expand-template@2.0.3: + resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==} + engines: {node: '>=6'} + + express-async-errors@3.1.1: + resolution: {integrity: sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==} + peerDependencies: + express: ^4.16.2 + + express-session@1.18.1: + resolution: {integrity: sha512-a5mtTqEaZvBCL9A9aqkrtfz+3SMDhOVUnjafjo+s7A9Txkq+SVX2DLvSp1Zrv4uCXa3lMSK3viWnh9Gg07PBUA==} + engines: {node: '>= 0.8.0'} + + express@4.21.2: + resolution: {integrity: sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==} + engines: {node: '>= 0.10.0'} + external-editor@3.1.0: resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} engines: {node: '>=4'} @@ -1976,6 +3486,9 @@ packages: fast-content-type-parse@2.0.1: resolution: {integrity: sha512-nGqtvLrj5w0naR6tDPfB4cUmYCqouzyQiz6C5y/LtcDllJdrcc6WaWW6iXyIIOErTa/XRybj28aasdn4LkVk6Q==} + fast-deep-equal@3.1.3: + resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} + fast-equals@5.2.2: resolution: {integrity: sha512-V7/RktU11J3I36Nwq2JnZEM7tNm17eBJz+u25qdxBZeCKiX6BkVSZQjwWIr+IobgnZy+ag73tTZgZi7tr0LrBw==} engines: {node: '>=6.0.0'} @@ -1984,28 +3497,74 @@ packages: resolution: {integrity: sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==} engines: {node: '>=8.6.0'} + fast-json-stable-stringify@2.1.0: + resolution: {integrity: sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==} + fastq@1.19.1: resolution: {integrity: sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==} + fdir@6.4.3: + resolution: {integrity: sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw==} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + figures@3.2.0: resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==} engines: {node: '>=8'} + file-uri-to-path@1.0.0: + resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==} + fill-range@7.1.1: resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} engines: {node: '>=8'} + finalhandler@1.3.1: + resolution: {integrity: sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==} + engines: {node: '>= 0.8'} + + follow-redirects@1.15.9: + resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} + engines: {node: '>=4.0'} + peerDependencies: + debug: '*' + peerDependenciesMeta: + debug: + optional: true + foreground-child@3.3.1: resolution: {integrity: sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==} engines: {node: '>=14'} + form-data@4.0.2: + resolution: {integrity: sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==} + engines: {node: '>= 6'} + + forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + fraction.js@4.3.7: resolution: {integrity: sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==} + fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + + fs-constants@1.0.0: + resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==} + fs-extra@10.1.0: resolution: {integrity: sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==} engines: {node: '>=12'} + fs-extra@11.3.0: + resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} + engines: {node: '>=14.14'} + fs.realpath@1.0.0: resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} @@ -2017,10 +3576,22 @@ packages: function-bind@1.1.2: resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + + get-intrinsic@1.3.0: + resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==} + engines: {node: '>= 0.4'} + get-nonce@1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} engines: {node: '>=6'} + get-proto@1.0.1: + resolution: {integrity: sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==} + engines: {node: '>= 0.4'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -2029,6 +3600,9 @@ packages: resolution: {integrity: sha512-E1b1lFFLvLgak2whF2xDBcOy6NLVGZBqqjJjsIhvopKfWWEi64pLVTWWehV8KlLerZkfNTA95sTe2OdJKm1OzQ==} engines: {node: '>= 14'} + github-from-package@0.0.0: + resolution: {integrity: sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==} + glob-parent@5.1.2: resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} engines: {node: '>= 6'} @@ -2048,10 +3622,21 @@ packages: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} deprecated: Glob versions prior to v9 are no longer supported + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + globby@10.0.2: resolution: {integrity: sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==} engines: {node: '>=8'} + google-protobuf@3.21.4: + resolution: {integrity: sha512-MnG7N936zcKTco4Jd2PX2U96Kf9PxygAPKBug+74LHzmHXmceN16MmRcdgZv+DGef/S9YvQAfRsNCn4cjf9yyQ==} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + graceful-fs@4.2.11: resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} @@ -2059,6 +3644,19 @@ packages: resolution: {integrity: sha512-rEDCuqUQ4tbD78TpzsMtt5OIf0cBCSDWSJtUDaF6JsAh+k0v9r++NzxNEG87oDZx9ZwGhD8DaezR2L/yrw0Jdw==} engines: {node: '>=10'} + graphql-tag@2.12.6: + resolution: {integrity: sha512-FdSNcu2QQcWnM2VNvSCCDCVS5PpPqpzgFT8+GXzqJuoDd0CBncxCY278u4mhRO7tMgo2JjgJA5aZ+nWSQ/Z+xg==} + engines: {node: '>=10'} + peerDependencies: + graphql: ^0.9.0 || ^0.10.0 || ^0.11.0 || ^0.12.0 || ^0.13.0 || ^14.0.0 || ^15.0.0 || ^16.0.0 + + graphql.js@0.6.8: + resolution: {integrity: sha512-y1OxsvPCfBell00yb2T1E+JQjFXzbmqDT3hsf7Ckof80DlRuQ3SrmLL7KC04Up81vlBj+l9opYJjDLf9OgMH3w==} + + graphql@16.10.0: + resolution: {integrity: sha512-AjqGKbDGUFRKIRCP9tCKiIGHyriz2oHEbPIbEtcSLSs4YjReZOIPQQWek4+6hjw62H9QShXHyaGivGiYVLeYFQ==} + engines: {node: ^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0} + handlebars@4.7.8: resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} engines: {node: '>=0.4.7'} @@ -2072,6 +3670,24 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + has-symbols@1.1.0: + resolution: {integrity: sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==} + engines: {node: '>= 0.4'} + + has-tostringtag@1.0.2: + resolution: {integrity: sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==} + engines: {node: '>= 0.4'} + + hash-base@3.1.0: + resolution: {integrity: sha512-1nmYp/rhMDiE7AYkDw+lLwlAzz0AntGIe51F3RfFfEqyQ3feY2eI/NcwC6umIQVOASPMsWJLJScWKSSvzL9IVA==} + engines: {node: '>=4'} + + hash.js@1.1.7: + resolution: {integrity: sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==} + hasown@2.0.2: resolution: {integrity: sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==} engines: {node: '>= 0.4'} @@ -2079,6 +3695,16 @@ packages: header-case@1.0.1: resolution: {integrity: sha512-i0q9mkOeSuhXw6bGgiQCCBgY/jlZuV/7dZXyZ9c6LcBrqwvT8eT719E9uxE5LiZftdl+z81Ugbg/VvXV4OJOeQ==} + hmac-drbg@1.0.1: + resolution: {integrity: sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==} + + hoist-non-react-statics@3.3.2: + resolution: {integrity: sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==} + + http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + http-proxy-agent@7.0.2: resolution: {integrity: sha512-T1gkAiYYDWYx3V5Bmyu7HcfcvL7mUrTWiM6yOfa3PIphViJ/gFPbvidQ+veqSOHci/PxBcDabeUNCzpOODJZig==} engines: {node: '>= 14'} @@ -2134,10 +3760,18 @@ packages: resolution: {integrity: sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==} engines: {node: '>=12'} + interpret@1.4.0: + resolution: {integrity: sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==} + engines: {node: '>= 0.10'} + ip-address@9.0.5: resolution: {integrity: sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==} engines: {node: '>= 12'} + ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} @@ -2161,6 +3795,10 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} + is-hex-prefixed@1.0.0: + resolution: {integrity: sha512-WvtOiug1VFrE9v1Cydwm+FnXd3+w9GaeVUss5W4v/SLy3UW00vP+6iNF2SdnfiBoLy4bTqVdkftNGTUeOFVsbA==} + engines: {node: '>=6.5.0', npm: '>=3'} + is-interactive@1.0.0: resolution: {integrity: sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==} engines: {node: '>=8'} @@ -2191,6 +3829,12 @@ packages: is-upper-case@1.1.2: resolution: {integrity: sha512-GQYSJMgfeAmVwh9ixyk888l7OIhNAGKtY6QA+IrWlu9MDTCaXmeozOZ2S9Knj7bQwBO/H6J2kb+pbyTUiMNbsw==} + isarray@0.0.1: + resolution: {integrity: sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==} + + isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + isbinaryfile@4.0.10: resolution: {integrity: sha512-iHrqe5shvBUcFbmZq9zOQHBoeOhZJu6RQGrDpBgenUm/Am+F3JM2MgQj+rK3Z601fzrL5gLZWtAPH2OBaSVcyw==} engines: {node: '>= 8.0.0'} @@ -2198,6 +3842,11 @@ packages: isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + isomorphic-ws@4.0.1: + resolution: {integrity: sha512-BhBvN2MBpWTaSHdWRb/bwdZJ1WaehQ2L1KngkCkfLUGF0mAWAT1sQUQacEmQ0jXkFw/czDXPNQSL5u2/Krsz1w==} + peerDependencies: + ws: '*' + jackspeak@3.4.3: resolution: {integrity: sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==} @@ -2209,13 +3858,27 @@ packages: resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==} hasBin: true + joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + js-cookie@3.0.5: resolution: {integrity: sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==} engines: {node: '>=14'} + js-sha256@0.9.0: + resolution: {integrity: sha512-sga3MHh9sgQN2+pJ9VYZ+1LPwXOxuBJBA5nrR5/ofPfuiJBE2hnjsaN8se8JznOmGLN2p49Pe5U/ttafcs/apA==} + + js-sha3@0.8.0: + resolution: {integrity: sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==} + js-tokens@4.0.0: resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + js-yaml@3.14.1: + resolution: {integrity: sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==} + hasBin: true + js-yaml@4.1.0: resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} hasBin: true @@ -2226,60 +3889,94 @@ packages: jsonfile@6.1.0: resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} - lefthook-darwin-arm64@1.11.3: - resolution: {integrity: sha512-IYzAOf8Qwqk7q+LoRyy7kSk9vzpUZ5wb/vLzEAH/F86Vay9AUaWe1f2pzeLwFg18qEc1QNklT69h9p/uLQMojA==} + jsonwebtoken@9.0.2: + resolution: {integrity: sha512-PRp66vJ865SSqOlgqS8hujT5U4AOgMfhrwYIuIhfKaoSCZcirrmASQr8CX7cUg+RMih+hgznrjp99o+W4pJLHQ==} + engines: {node: '>=12', npm: '>=6'} + + junk@3.1.0: + resolution: {integrity: sha512-pBxcB3LFc8QVgdggvZWyeys+hnrNWg4OcZIU/1X59k5jQdLBlCsYGRQaz234SqoRLTCgMH00fY0xRJH+F9METQ==} + engines: {node: '>=8'} + + jwa@1.4.1: + resolution: {integrity: sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==} + + jws@3.2.2: + resolution: {integrity: sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==} + + keccak@3.0.4: + resolution: {integrity: sha512-3vKuW0jV8J3XNTzvfyicFR5qvxrSAGl7KIhvgOu5cmWwM7tZRj3fMbj/pfIf4be7aznbc+prBWGjywox/g2Y6Q==} + engines: {node: '>=10.0.0'} + + keygrip@1.1.0: + resolution: {integrity: sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==} + engines: {node: '>= 0.6'} + + lefthook-darwin-arm64@1.11.2: + resolution: {integrity: sha512-8DpvrybtWdt6UmfZk+hA8daYXr6zkpJVogZ8M49BQx6ISSKUaC03xzO1m4MrAsoKok77ka4JAidYhOa2gCu15A==} cpu: [arm64] os: [darwin] - lefthook-darwin-x64@1.11.3: - resolution: {integrity: sha512-z/Wp7UMjE1Vyl+x9sjN3NvN6qKdwgHl+cDf98MKKDg/WyPE5XnzqLm9rLLJgImjyClfH7ptTfZxEyhTG3M3XvQ==} + lefthook-darwin-x64@1.11.2: + resolution: {integrity: sha512-DrL1SOT8lJksjudRu6fTZTp3M0EbpCP2RQ22MDT71clS8BMrFL8x3h9Ziw+uNH76j9zA241tW5zMxWMSv+foAA==} cpu: [x64] os: [darwin] - lefthook-freebsd-arm64@1.11.3: - resolution: {integrity: sha512-QevwQ7lrv5wBCkk7LLTzT5KR3Bk/5nttSxT1UH2o0EsgirS/c2K5xSgQmV6m3CiZYuCe2Pja4BSIwN3zt17SMw==} + lefthook-freebsd-arm64@1.11.2: + resolution: {integrity: sha512-AliG4Wi8BNC27hCSnuFBeUXh/eA3fppnUbQQPISy/G94yfwRkzyml9MZzvb7HKmUpw1LT0sq9RQ6FQPxBZ2DYA==} cpu: [arm64] os: [freebsd] - lefthook-freebsd-x64@1.11.3: - resolution: {integrity: sha512-PYbcyNgdJJ4J2pEO9Ss4oYo5yq4vmQGTKm3RTYbRx4viSWR65hvKCP0C4LnIqspMvmR05SJi2bqe7UBP2t60EA==} + lefthook-freebsd-x64@1.11.2: + resolution: {integrity: sha512-V6cgRCoi5+jcq6XBIdRYraeEOK1UhBrtL/XZlNypAIkhPoBtfTP9u2wSprGMDzZvJCRriLXZxV/d0v94laKXzA==} cpu: [x64] os: [freebsd] - lefthook-linux-arm64@1.11.3: - resolution: {integrity: sha512-0pBMBAoafOAEg345eOPozsmRjWR0zCr6k+m5ZxwRBZbZx1bQFDqBakQ3TpFCphhcykmgFyaa1KeZJZUOrEsezA==} + lefthook-linux-arm64@1.11.2: + resolution: {integrity: sha512-VKcK7sjIK8UpXX/qK6Fxa0Lnwr4gzRtlXDS17jzxThcyFk8iGBpQ+9ZnPLv2yAaEIzmGhJUG9sDgOb9IQ5kpBQ==} cpu: [arm64] os: [linux] - lefthook-linux-x64@1.11.3: - resolution: {integrity: sha512-eiezheZ/bisBCMB2Ur0mctug/RDFyu39B5wzoE8y4z0W1yw6jHGrWMJ4Y8+5qKZ7fmdZg+7YPuMHZ2eFxOnhQA==} + lefthook-linux-x64@1.11.2: + resolution: {integrity: sha512-aGa2Krph14YwSW7KF0PrlCBK9P7V/Z4oFklonmz3r2Fjm8EdhA750y7OQvA9KerXRleIb5SaUH/cz1azG/izeQ==} cpu: [x64] os: [linux] - lefthook-openbsd-arm64@1.11.3: - resolution: {integrity: sha512-DRLTzXdtCj/TizpLcGSqXcnrqvgxeXgn/6nqzclIGqNdKCsNXDzpI0D3sP13Vwwmyoqv2etoTak2IHqZiXZDqg==} + lefthook-openbsd-arm64@1.11.2: + resolution: {integrity: sha512-f7owNQ9Ki6Y07KBgdXdH28EYO0eBdZuGTpIggMeHNhYFVDavxuINP2BjmbXtzpUu8K5BX6exGx0umtWhRhXbvQ==} cpu: [arm64] os: [openbsd] - lefthook-openbsd-x64@1.11.3: - resolution: {integrity: sha512-l7om+ZjWpYrVZyDuElwnucZhEqa7YfwlRaKBenkBxEh2zMje8O6Zodeuma1KmyDbSFvnvEjARo/Ejiot4gLXEw==} + lefthook-openbsd-x64@1.11.2: + resolution: {integrity: sha512-HKv6PV64vOjqPrlxAqo07N9+Z34jdPDBfeExqi0ldR7vACFaBJFIdhWCLLP+3uQUrNKc8GXlikqplZn8MgRSQw==} cpu: [x64] os: [openbsd] - lefthook-windows-arm64@1.11.3: - resolution: {integrity: sha512-X0iTrql2gfPAkU2dzRwuHWgW5RcqCPbzJtKQ41X6Y/F7iQacRknmuYUGyC81funSvzGAsvlusMVLUvaFjIKnbA==} + lefthook-windows-arm64@1.11.2: + resolution: {integrity: sha512-042jCKZ/H+lS6XYoMIf2FWMP2hxXqfAT52UW6lYObIOvQ5xu/epUXFjtmXRyYxCv57No3JYYMg1Yr06xdzTKkQ==} cpu: [arm64] os: [win32] - lefthook-windows-x64@1.11.3: - resolution: {integrity: sha512-F+ORMn6YJXoS0EXU5LtN1FgV4QX9rC9LucZEkRmK6sKmS7hcb9IHpyb7siRGytArYzJvXVjPbxPBNSBdN4egZQ==} + lefthook-windows-x64@1.11.2: + resolution: {integrity: sha512-1Map6Ck2AyfY6ptN9T19N41HFKFqRTzmILtGaRGJABEzHiE4+gSWcq5YT1R6cCtkVlewD3Lx+J/80D/Kb/cVtw==} cpu: [x64] os: [win32] - lefthook@1.11.3: - resolution: {integrity: sha512-HJp37y62j3j8qzAOODWuUJl4ysLwsDvCTBV6odr3jIRHR/a5e+tI14VQGIBcpK9ysqC3pGWyW5Rp9Jv1YDubyw==} + lefthook@1.11.2: + resolution: {integrity: sha512-/5royc/WbL2KTfFJ54wEdvxUZOBXwc54v/fW2Bz4LMOkAA3LWIxnoUiybSiauu+nhdTG98qERxH1YHwF2wZlAA==} hasBin: true + libsodium-sumo@0.7.15: + resolution: {integrity: sha512-5tPmqPmq8T8Nikpm1Nqj0hBHvsLFCXvdhBFV7SGOitQPZAA6jso8XoL0r4L7vmfKXr486fiQInvErHtEvizFMw==} + + libsodium-wrappers-sumo@0.7.15: + resolution: {integrity: sha512-aSWY8wKDZh5TC7rMvEdTHoyppVq/1dTSAeAR7H6pzd6QRT3vQWcT5pGwCotLcpPEOLXX6VvqihSPkpEhYAjANA==} + + libsodium-wrappers@0.7.15: + resolution: {integrity: sha512-E4anqJQwcfiC6+Yrl01C1m8p99wEhLmJSs0VQqST66SbQXXBoaJY0pF4BNjRYa/sOQAxx6lXAaAFIlx+15tXJQ==} + + libsodium@0.7.15: + resolution: {integrity: sha512-sZwRknt/tUpE2AwzHq3jEyUU5uvIZHtSssktXq7owd++3CSgn8RGrv6UZJJBpP7+iBghBqe7Z06/2M31rI2NKw==} + lightningcss-darwin-arm64@1.29.2: resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==} engines: {node: '>= 12.0.0'} @@ -2351,10 +4048,46 @@ packages: lines-and-columns@1.2.4: resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} + link-module-alias@1.2.0: + resolution: {integrity: sha512-ahPjXepbSVKbahTB6LxR//VHm8HPfI+QQygCH+E82spBY4HR5VPJTvlhKBc9F7muVxnS6C1rRfoPOXAbWO/fyw==} + engines: {node: '> 8.0.0'} + hasBin: true + + load-tsconfig@0.2.5: + resolution: {integrity: sha512-IXO6OCs9yg8tMKzfPZ1YmheJbZCiEsnBdcB03l0OcfK9prKnJb96siuHCr5Fl37/yo9DnKU+TLpxzTUspw9shg==} + engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + + lodash-clean@2.2.3: + resolution: {integrity: sha512-ioRhn/L0NNKq220nba58FPvjZ+bTdlUCb37+mhlDe4kzIzuPC/prUHLwDM9izeicr/rcnWrn0EanzNxhAbo8oA==} + lodash.get@4.4.2: resolution: {integrity: sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==} deprecated: This package is deprecated. Use the optional chaining (?.) operator instead. + lodash.includes@4.3.0: + resolution: {integrity: sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==} + + lodash.isboolean@3.0.3: + resolution: {integrity: sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==} + + lodash.isinteger@4.0.4: + resolution: {integrity: sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==} + + lodash.isnumber@3.0.3: + resolution: {integrity: sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==} + + lodash.isplainobject@4.0.6: + resolution: {integrity: sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==} + + lodash.isstring@4.0.1: + resolution: {integrity: sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==} + + lodash.once@4.1.1: + resolution: {integrity: sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==} + + lodash.sortby@4.7.0: + resolution: {integrity: sha512-HDWXG8isMntAyRF5vZ7xKuEvOhT4AhlRt/3czTSjvGUxjYCBVRQY48ViDHyfYz9VIoBkW4TMGQNapx+l3RUwdA==} + lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} @@ -2366,6 +4099,13 @@ packages: resolution: {integrity: sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==} engines: {node: '>=10'} + loglevel@1.9.2: + resolution: {integrity: sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg==} + engines: {node: '>= 0.6.0'} + + long@4.0.0: + resolution: {integrity: sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==} + loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -2382,6 +4122,14 @@ packages: lru-cache@10.4.3: resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==} + lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + + lru-cache@7.13.1: + resolution: {integrity: sha512-CHqbAq7NFlW3RSnoWXLJBxCWaZVBrfa9UEHId2M3AW8iEBurbqduNexEUCGc3SHc6iCYXNJCDi903LajSVAEPQ==} + engines: {node: '>=12'} + lru-cache@7.18.3: resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} engines: {node: '>=12'} @@ -2391,6 +4139,10 @@ packages: peerDependencies: react: ^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0 + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + make-error@1.3.6: resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} @@ -2398,6 +4150,20 @@ packages: resolution: {integrity: sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==} engines: {node: '>=8'} + math-intrinsics@1.1.0: + resolution: {integrity: sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==} + engines: {node: '>= 0.4'} + + md5.js@1.3.5: + resolution: {integrity: sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==} + + media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + + merge-descriptors@1.0.3: + resolution: {integrity: sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==} + merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} @@ -2405,14 +4171,41 @@ packages: resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==} engines: {node: '>= 8'} + methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + micromatch@4.0.8: resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==} engines: {node: '>=8.6'} + mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + + mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + + mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + mimic-fn@2.1.0: resolution: {integrity: sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==} engines: {node: '>=6'} + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + + minimalistic-crypto-utils@1.0.1: + resolution: {integrity: sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==} + minimatch@3.1.2: resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} @@ -2427,24 +4220,51 @@ packages: resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} engines: {node: '>=16 || 14 >=14.17'} + mkdirp-classic@0.5.3: + resolution: {integrity: sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==} + mkdirp@0.5.6: resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} hasBin: true + mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + multiformats@9.9.0: + resolution: {integrity: sha512-HoMUjhH9T8DDBNT+6xzkrd9ga/XiBI4xLr58LJACwK6G3HTOPeMz4nB4KJs33L2BelrIJa7P0VuNaVF3hMYfjg==} + mute-stream@0.0.8: resolution: {integrity: sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==} mz@2.7.0: resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} - nanoid@3.3.9: - resolution: {integrity: sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==} + nan@2.22.2: + resolution: {integrity: sha512-DANghxFkS1plDdRsX0X9pm0Z6SJNN6gBdtXfanwoZ8hooC5gosGFSBGRYHUVPz1asKA/kMRqDRdHrluZ61SpBQ==} + + nanoid-dictionary@5.0.0-beta.1: + resolution: {integrity: sha512-xBkL9zzkNjzJ/UnmWyiOUDVX/COoi05eS0oU28RYKFFQhdnzO5dTOPbVZ/fCFgIOGr1zNinDHJ68mm/KQfcgcw==} + + nanoid@3.3.8: + resolution: {integrity: sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + napi-build-utils@2.0.0: + resolution: {integrity: sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==} + + negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + neo-async@2.6.2: resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} @@ -2485,6 +4305,32 @@ packages: no-case@3.0.4: resolution: {integrity: sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==} + node-abi@3.74.0: + resolution: {integrity: sha512-c5XK0MjkGBrQPGYG24GBADZud0NCbznxNx0ZkS+ebUTrmV1qTDxPxSL8zEAPURXSbLRWVexxmP4986BziahL5w==} + engines: {node: '>=10'} + + node-abort-controller@3.1.1: + resolution: {integrity: sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==} + + node-addon-api@2.0.2: + resolution: {integrity: sha512-Ntyt4AIXyaLIuMHF6IOoTakB3K+RWxwtsHNRxllEoA6vPwP9o4866g6YWDLUdnucilZhmkxiHwHr11gAENw+QA==} + + node-addon-api@5.1.0: + resolution: {integrity: sha512-eh0GgfEkpnoWDq+VY8OyvYhFEzBk6jIYbRKdIlyTiAXIVJ8PyBaKb0rp7oDtoddbdoHWhq8wwr+XZ81F1rpNdA==} + + node-fetch@2.7.0: + resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==} + engines: {node: 4.x || >=6.0.0} + peerDependencies: + encoding: ^0.1.0 + peerDependenciesMeta: + encoding: + optional: true + + node-gyp-build@4.8.4: + resolution: {integrity: sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==} + hasBin: true + node-plop@0.26.3: resolution: {integrity: sha512-Cov028YhBZ5aB7MdMWJEmwyBig43aGL5WT4vdoB28Oitau1zZAcHUn8Sgfk9HM33TqhtLJ9PlM/O0Mv+QpV/4Q==} engines: {node: '>=8.9.4'} @@ -2492,6 +4338,14 @@ packages: node-releases@2.0.19: resolution: {integrity: sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==} + node-yaml@4.0.1: + resolution: {integrity: sha512-ZPKi3OexXdiklsRW9g4P7jAxHAhoBRZCFmIDMQ89clLhMz+MTJuCM9y5f1R7Ru75H84hWJouwpxVOq1SdRTe7A==} + peerDependencies: + js-yaml: ^3.13.x + + noms@0.0.0: + resolution: {integrity: sha512-lNDU9VJaOPxUmXcLb+HQFeUgQQPtMI24Gt6hgfuMHRJgMRHMF/qZ4HJD3GDru4sSw9IQl2jPjAYnQrdIeLbwow==} + normalize-path@3.0.0: resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} engines: {node: '>=0.10.0'} @@ -2512,6 +4366,26 @@ packages: resolution: {integrity: sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==} engines: {node: '>= 6'} + object-inspect@1.13.4: + resolution: {integrity: sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==} + engines: {node: '>= 0.4'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + octokit@3.2.1: + resolution: {integrity: sha512-u+XuSejhe3NdIvty3Jod00JvTdAE/0/+XbhIDhefHbu+2OcTRHd80aCiH6TX19ZybJmwPQBKFQmHGxp0i9mJrg==} + engines: {node: '>= 18'} + + on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + + on-headers@1.0.2: + resolution: {integrity: sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==} + engines: {node: '>= 0.8'} + once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} @@ -2519,6 +4393,13 @@ packages: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} engines: {node: '>=6'} + openpgp@6.1.0: + resolution: {integrity: sha512-fRTeitP+hoGJD3kbdUlAI++wE6MvfvXw1rBqHwmBMxIpLjowatJ2zb5ThkORpIkSz5F12wO+xCYRSTbT7M4qKA==} + engines: {node: '>= 18.0.0'} + + optimism@0.18.1: + resolution: {integrity: sha512-mLXNwWPa9dgFyDqkNi54sjDyNJ9/fTI6WGBLgnXku1vdKY/jovHfZT5r+aiVeFFLOz+foPNOm5YJ4mqgld2GBQ==} + ora@4.1.1: resolution: {integrity: sha512-sjYP8QyVWBpBZWD6Vr1M/KwknSw6kJOz41tvGMlwWeClHBtYKTbHMki1PsLZnxKpXMPbTKv9b3pjQu3REib96A==} engines: {node: '>=8'} @@ -2549,6 +4430,10 @@ packages: param-case@2.1.1: resolution: {integrity: sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==} + parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + pascal-case@2.0.1: resolution: {integrity: sha512-qjS4s8rBOJa2Xm0jmxXiyh1+OFf6ekCWOvUaRgAQSktzlTbMotS0nmG9gyYAybCWBcuP4fsBeRCKNwGBnMe2OQ==} @@ -2570,10 +4455,17 @@ packages: resolution: {integrity: sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==} engines: {node: '>=16 || 14 >=14.18'} + path-to-regexp@0.1.12: + resolution: {integrity: sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==} + path-type@4.0.0: resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} engines: {node: '>=8'} + pbkdf2@3.1.2: + resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} + engines: {node: '>=0.12'} + picocolors@1.0.1: resolution: {integrity: sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==} @@ -2584,6 +4476,10 @@ packages: resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} engines: {node: '>=8.6'} + picomatch@4.0.2: + resolution: {integrity: sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==} + engines: {node: '>=12'} + pify@2.3.0: resolution: {integrity: sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==} engines: {node: '>=0.10.0'} @@ -2616,6 +4512,24 @@ packages: ts-node: optional: true + postcss-load-config@6.0.1: + resolution: {integrity: sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==} + engines: {node: '>= 18'} + peerDependencies: + jiti: '>=1.21.0' + postcss: '>=8.0.9' + tsx: ^4.8.1 + yaml: ^2.4.2 + peerDependenciesMeta: + jiti: + optional: true + postcss: + optional: true + tsx: + optional: true + yaml: + optional: true + postcss-nested@6.2.0: resolution: {integrity: sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==} engines: {node: '>=12.0'} @@ -2637,9 +4551,34 @@ packages: resolution: {integrity: sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==} engines: {node: ^10 || ^12 || >=14} + prebuild-install@7.1.3: + resolution: {integrity: sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==} + engines: {node: '>=10'} + hasBin: true + + prettier@3.5.3: + resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==} + engines: {node: '>=14'} + hasBin: true + + process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + + promise-fs@2.1.1: + resolution: {integrity: sha512-43p7e4QzAQ3w6eyN0+gbBL7jXiZFWLWYITg9wIObqkBySu/a5K1EDcQ/S6UyB/bmiZWDA4NjTbcopKLTaKcGSw==} + engines: {node: '>=6'} + prop-types@15.8.1: resolution: {integrity: sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==} + protobufjs@6.11.4: + resolution: {integrity: sha512-5kQWPaJHi1WoCpjTGszzQ32PG2F4+wRY6BmAT4Vfw56Q2FZ4YZzK20xUYQH4YkfehY1e6QSICrJquM6xXZNcrw==} + hasBin: true + + proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + proxy-agent@6.5.0: resolution: {integrity: sha512-TmatMXdr2KlRiA2CyDu8GqR8EjahTG3aY3nXjdzFyoZbmB8hrBsTyMezhULIXKnC0jpfjlmiZ3+EaCzoInSu/A==} engines: {node: '>= 14'} @@ -2647,9 +4586,35 @@ packages: proxy-from-env@1.1.0: resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} + pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + + punycode@2.3.1: + resolution: {integrity: sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==} + engines: {node: '>=6'} + + qs@6.13.0: + resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} + engines: {node: '>=0.6'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + random-bytes@1.0.0: + resolution: {integrity: sha512-iv7LhNVO047HzYR3InF6pUcUsPQiHTM1Qal51DcGSuZFBil1aBBWG5eHPNek7bvILMaYJ/8RU1e8w1AMdHmLQQ==} + engines: {node: '>= 0.8'} + + randombytes@2.1.0: + resolution: {integrity: sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==} + + range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + + raw-body@2.5.2: + resolution: {integrity: sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==} + engines: {node: '>= 0.8'} + rc@1.2.8: resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==} hasBin: true @@ -2732,6 +4697,12 @@ packages: read-cache@1.0.0: resolution: {integrity: sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==} + readable-stream@1.0.34: + resolution: {integrity: sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==} + + readable-stream@2.3.8: + resolution: {integrity: sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==} + readable-stream@3.6.2: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} @@ -2740,6 +4711,13 @@ packages: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} + readdirp@4.1.2: + resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==} + engines: {node: '>= 14.18.0'} + + readonly-date@1.0.0: + resolution: {integrity: sha512-tMKIV7hlk0h4mO3JTmmVuIlJVXjKk3Sep9Bf5OH0O+758ruuVkUy2J9SttDLm91IEX/WHlXPSpxMGjPj4beMIQ==} + recharts-scale@0.4.5: resolution: {integrity: sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==} @@ -2750,6 +4728,13 @@ packages: react: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 react-dom: ^16.0.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + rechoir@0.6.2: + resolution: {integrity: sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==} + engines: {node: '>= 0.10'} + + reflect-metadata@0.2.2: + resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} + regenerator-runtime@0.14.1: resolution: {integrity: sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==} @@ -2760,6 +4745,25 @@ packages: resolution: {integrity: sha512-ZbgR5aZEdf4UKZVBPYIgaglBmSF2Hi94s2PcIHhRGFjKYu+chjJdYfHn4rt3hB6eCKLJ8giVIIfgMa1ehDfZKA==} engines: {node: '>=0.10.0'} + rehackt@0.1.0: + resolution: {integrity: sha512-7kRDOuLHB87D/JESKxQoRwv4DzbIdwkAGQ7p6QKGdVlY1IZheUnVhlk/4UZlNUVxdAXpyxikE3URsG067ybVzw==} + peerDependencies: + '@types/react': '*' + react: '*' + peerDependenciesMeta: + '@types/react': + optional: true + react: + optional: true + + require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + + resolve-from@5.0.0: + resolution: {integrity: sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==} + engines: {node: '>=8'} + resolve@1.22.10: resolution: {integrity: sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==} engines: {node: '>= 0.4'} @@ -2769,6 +4773,10 @@ packages: resolution: {integrity: sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==} engines: {node: '>=8'} + retry@0.13.1: + resolution: {integrity: sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==} + engines: {node: '>= 4'} + reusify@1.1.0: resolution: {integrity: sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==} engines: {iojs: '>=1.0.0', node: '>=0.10.0'} @@ -2778,6 +4786,22 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true + ripemd160-min@0.0.6: + resolution: {integrity: sha512-+GcJgQivhs6S9qvLogusiTcS9kQUfgR75whKuy5jIhuiOfQuJ8fjqxV6EGD5duH1Y/FawFUMtMhyeq3Fbnib8A==} + engines: {node: '>=8'} + + ripemd160@2.0.2: + resolution: {integrity: sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==} + + rlp@2.2.7: + resolution: {integrity: sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ==} + hasBin: true + + rollup@4.34.9: + resolution: {integrity: sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==} + engines: {node: '>=18.0.0', npm: '>=8.0.0'} + hasBin: true + run-async@2.4.1: resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} engines: {node: '>=0.12.0'} @@ -2792,6 +4816,9 @@ packages: rxjs@7.8.2: resolution: {integrity: sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==} + safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + safe-buffer@5.2.1: resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} @@ -2801,6 +4828,13 @@ packages: scheduler@0.25.0: resolution: {integrity: sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==} + scrypt-js@3.0.1: + resolution: {integrity: sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==} + + secp256k1@4.0.4: + resolution: {integrity: sha512-6JfvwvjUOn8F/jUoBY2Q1v5WY5XS+rj8qSe0v8Y4ezH4InLgTEeOOPQsRll9OV429Pvo6BCHGavIyJfr3TAhsw==} + engines: {node: '>=18.0.0'} + semver@7.6.2: resolution: {integrity: sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==} engines: {node: '>=10'} @@ -2811,12 +4845,36 @@ packages: engines: {node: '>=10'} hasBin: true + send@0.19.0: + resolution: {integrity: sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==} + engines: {node: '>= 0.8.0'} + sentence-case@2.1.1: resolution: {integrity: sha512-ENl7cYHaK/Ktwk5OTD+aDbQ3uC8IByu/6Bkg+HDv8Mm+XnBnppVNalcfJTNsp1ibstKh030/JKQQWglDvtKwEQ==} + serve-static@1.16.2: + resolution: {integrity: sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==} + engines: {node: '>= 0.8.0'} + server-only@0.0.1: resolution: {integrity: sha512-qepMx2JxAa5jjfzxG79yPPq+8BuFToHd1hm7kI+Z4zAq1ftQiP7HcxMhDDItrbtwVeLg/cY2JnKnrcFkmiswNA==} + setimmediate@1.0.5: + resolution: {integrity: sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==} + + setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + + sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + + sha256-uint8array@0.10.7: + resolution: {integrity: sha512-1Q6JQU4tX9NqsDGodej6pkrUVQVNapLZnvkwIhddH/JqzBZF1fSaxSWNY6sziXBE8aEa2twtGkXUrwzGeZCMpQ==} + + sha3@2.1.4: + resolution: {integrity: sha512-S8cNxbyb0UGUM2VhRD4Poe5N58gJnJsLJ5vC7FYWGUmGhcsj4++WaIOBFVDxlG0W3To6xBuiRh+i0Qp2oNCOtg==} + sharp@0.33.5: resolution: {integrity: sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==} engines: {node: ^18.17.0 || ^20.3.0 || >=21.0.0} @@ -2829,6 +4887,32 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + shelljs@0.8.5: + resolution: {integrity: sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==} + engines: {node: '>=4'} + hasBin: true + + shx@0.3.4: + resolution: {integrity: sha512-N6A9MLVqjxZYcVn8hLmtneQWIJtp8IKzMP4eMnx+nqkvXoqinUPCbUFLp2UcWTEIUONhlk0ewxr/jaVGlc+J+g==} + engines: {node: '>=6'} + hasBin: true + + side-channel-list@1.0.0: + resolution: {integrity: sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==} + engines: {node: '>= 0.4'} + + side-channel-map@1.0.1: + resolution: {integrity: sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==} + engines: {node: '>= 0.4'} + + side-channel-weakmap@1.0.2: + resolution: {integrity: sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==} + engines: {node: '>= 0.4'} + + side-channel@1.1.0: + resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==} + engines: {node: '>= 0.4'} + signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} @@ -2836,9 +4920,20 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} + simple-concat@1.0.1: + resolution: {integrity: sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==} + + simple-get@4.0.1: + resolution: {integrity: sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==} + simple-swizzle@0.2.2: resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + siwe@3.0.0: + resolution: {integrity: sha512-P2/ry7dHYJA6JJ5+veS//Gn2XDwNb3JMvuD6xiXX8L/PJ1SNVD4a3a8xqEbmANx+7kNQcD8YAh1B9bNKKvRy/g==} + peerDependencies: + ethers: ^5.6.8 || ^6.0.8 + slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -2879,9 +4974,24 @@ packages: resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} engines: {node: '>=0.10.0'} + source-map@0.8.0-beta.0: + resolution: {integrity: sha512-2ymg6oRBpebeZi9UUNsgQ89bhx01TcTkmNTGnNO88imTmbSgy4nfujrgVEFKWpMTEGA11EDkTt7mqObTPdigIA==} + engines: {node: '>= 8'} + + sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + sprintf-js@1.1.3: resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + sql-highlight@6.0.0: + resolution: {integrity: sha512-+fLpbAbWkQ+d0JEchJT/NrRRXbYRNbG15gFpANx73EwxQB1PRjj+k/OI0GTU0J63g8ikGkJECQp9z8XEJZvPRw==} + engines: {node: '>=14'} + + statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + std-env@3.8.1: resolution: {integrity: sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==} @@ -2897,6 +5007,12 @@ packages: resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} engines: {node: '>=12'} + string_decoder@0.10.31: + resolution: {integrity: sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==} + + string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + string_decoder@1.3.0: resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} @@ -2912,6 +5028,10 @@ packages: resolution: {integrity: sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==} engines: {node: '>=6'} + strip-hex-prefix@1.0.0: + resolution: {integrity: sha512-q8d4ue7JGEiVcypji1bALTos+0pWtyGlivAWyPuTkHzuTCJqrK9sWxYQZUq6Nq3cuyv3bm734IhHvHtGGURU6A==} + engines: {node: '>=6.5.0', npm: '>=3'} + strip-json-comments@2.0.1: resolution: {integrity: sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==} engines: {node: '>=0.10.0'} @@ -2954,6 +5074,14 @@ packages: peerDependencies: react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0 + symbol-observable@2.0.3: + resolution: {integrity: sha512-sQV7phh2WCYAn81oAkakC5qjq2Ml0g8ozqz03wOGnx9dDlG1de6yrF+0RAzSJD8fPUow3PTSMf2SAbOGxb93BA==} + engines: {node: '>=0.10'} + + symbol-observable@4.0.0: + resolution: {integrity: sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==} + engines: {node: '>=0.10'} + tailwind-merge@3.0.2: resolution: {integrity: sha512-l7z+OYZ7mu3DTqrL88RiKrKIqO3NcpEO8V/Od04bNpvk0kiIFndGEoqfuzvj4yuhRkHKjRkII2z+KS2HfPcSxw==} @@ -2967,13 +5095,20 @@ packages: engines: {node: '>=14.0.0'} hasBin: true - tailwindcss@4.0.12: - resolution: {integrity: sha512-bT0hJo91FtncsAMSsMzUkoo/iEU0Xs5xgFgVC9XmdM9bw5MhZuQFjPNl6wxAE0SiQF/YTZJa+PndGWYSDtuxAg==} + tailwindcss@4.0.11: + resolution: {integrity: sha512-GZ6+tNwieqvpFLZfx2tkZpfOMAK7iumbOJOLmd6v8AcYuHbjUb+cmDRu6l+rFkIqarh5FfLbCSRJhegcVdoPng==} tapable@2.2.1: resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==} engines: {node: '>=6'} + tar-fs@2.1.2: + resolution: {integrity: sha512-EsaAXwxmx8UB7FRKqeozqEPop69DXcmYwTQwXvyAPF352HJsPdkVhvTaDPYqfNgruveJIJy3TA2l+2zj8LJIJA==} + + tar-stream@2.2.0: + resolution: {integrity: sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==} + engines: {node: '>=6'} + thenify-all@1.6.0: resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} engines: {node: '>=0.8'} @@ -2981,15 +5116,29 @@ packages: thenify@3.3.1: resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + through2@2.0.5: + resolution: {integrity: sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==} + through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} tiny-invariant@1.3.3: resolution: {integrity: sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg==} + tiny-secp256k1@1.1.7: + resolution: {integrity: sha512-eb+F6NabSnjbLwNoC+2o5ItbmP1kg7HliWue71JgLegQt6A5mTN8YbvTLCazdlg6e5SV6A+r8OGvZYskdlmhqQ==} + engines: {node: '>=6.0.0'} + tinycolor2@1.6.0: resolution: {integrity: sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==} + tinyexec@0.3.2: + resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==} + + tinyglobby@0.2.12: + resolution: {integrity: sha512-qkf4trmKSIiMTs/E63cxH+ojC2unam7rJ0WrauAzpT3ECNTxGRMlaXxVbfxMUC/w0LaYk6jQ4y/nGR9uBO3tww==} + engines: {node: '>=12.0.0'} + tinygradient@1.1.5: resolution: {integrity: sha512-8nIfc2vgQ4TeLnk2lFj4tRLvvJwEfQuabdsmvDdQPT0xlk9TaNtpGd6nNRxXoK6vQhN6RSzj+Cnp5tTQmpxmbw==} @@ -3004,9 +5153,30 @@ packages: resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} engines: {node: '>=8.0'} + toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + + toml@3.0.0: + resolution: {integrity: sha512-y/mWCZinnvxjTKYhJ+pYxwD0mRLVvOtdS2Awbgxln6iEnt4rk0yBxeSBHkGJcPucRiG0e55mwWp+g/05rsrd6w==} + + tr46@0.0.3: + resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} + + tr46@1.0.1: + resolution: {integrity: sha512-dTpowEjclQ7Kgx5SdBkqRzVhERQXov8/l9Ft9dVM9fmg0W0KQSVaXX9T4i6twCPNtYiZM53lpSSUAwJbFPOHxA==} + + tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + ts-interface-checker@0.1.13: resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==} + ts-invariant@0.10.3: + resolution: {integrity: sha512-uivwYcQaxAucv1CzRp2n/QdYPo4ILf9VXgH19zEIjFx2EJufV16P0JtJVpYHy89DItG6Kwj2oIUjrcK5au+4tQ==} + engines: {node: '>=8'} + ts-node@10.9.2: resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} hasBin: true @@ -3030,6 +5200,32 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsscmp@1.0.6: + resolution: {integrity: sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==} + engines: {node: '>=0.6.x'} + + tsup@8.4.0: + resolution: {integrity: sha512-b+eZbPCjz10fRryaAA7C8xlIHnf8VnsaRqydheLIqwG/Mcpfk8Z5zp3HayX7GaTygkigHl5cBUs+IhcySiIexQ==} + engines: {node: '>=18'} + hasBin: true + peerDependencies: + '@microsoft/api-extractor': ^7.36.0 + '@swc/core': ^1 + postcss: ^8.4.12 + typescript: '>=4.5.0' + peerDependenciesMeta: + '@microsoft/api-extractor': + optional: true + '@swc/core': + optional: true + postcss: + optional: true + typescript: + optional: true + + tunnel-agent@0.6.0: + resolution: {integrity: sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==} + turbo-darwin-64@2.4.4: resolution: {integrity: sha512-5kPvRkLAfmWI0MH96D+/THnDMGXlFNmjeqNRj5grLKiry+M9pKj3pRuScddAXPdlxjO5Ptz06UNaOQrrYGTx1g==} cpu: [x64] @@ -3064,6 +5260,12 @@ packages: resolution: {integrity: sha512-N9FDOVaY3yz0YCOhYIgOGYad7+m2ptvinXygw27WPLQvcZDl3+0Sa77KGVlLSiuPDChOUEnTKE9VJwLSi9BPGQ==} hasBin: true + tweetnacl-util@0.15.1: + resolution: {integrity: sha512-RKJBIj8lySrShN4w6i/BonWp2Z/uxwC3h4y7xsRrpP59ZboCd0GpEVsOnMDYLMmKBpYhb5TgHzZXy7wTfYFBRw==} + + tweetnacl@1.0.3: + resolution: {integrity: sha512-6rt+RN7aOi1nGMyC4Xa5DdYiukl2UWCbcJft7YhxReBGQD7OAM8Pbxw6YMo4r2diNEA8FEmu32YOn9rhaiE5yw==} + type-fest@0.21.3: resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==} engines: {node: '>=10'} @@ -3072,6 +5274,72 @@ packages: resolution: {integrity: sha512-S/5/0kFftkq27FPNye0XM1e2NsnoD/3FS+pBmbjmmtLT6I+i344KoOf7pvXreaFsDamWeaJX55nczA1m5PsBDg==} engines: {node: '>=16'} + type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + + typeforce@1.18.0: + resolution: {integrity: sha512-7uc1O8h1M1g0rArakJdf0uLRSSgFcYexrVoKo+bzJd32gd4gDy2L/Z+8/FjPnU9ydY3pEnVPtr9FyscYY60K1g==} + + typeorm@0.3.21: + resolution: {integrity: sha512-lh4rUWl1liZGjyPTWpwcK8RNI5x4ekln+/JJOox1wCd7xbucYDOXWD+1cSzTN3L0wbTGxxOtloM5JlxbOxEufA==} + engines: {node: '>=16.13.0'} + hasBin: true + peerDependencies: + '@google-cloud/spanner': ^5.18.0 + '@sap/hana-client': ^2.12.25 + better-sqlite3: ^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 + hdb-pool: ^0.1.6 + ioredis: ^5.0.4 + mongodb: ^5.8.0 + mssql: ^9.1.1 || ^10.0.1 || ^11.0.1 + mysql2: ^2.2.5 || ^3.0.1 + oracledb: ^6.3.0 + pg: ^8.5.1 + pg-native: ^3.0.0 + pg-query-stream: ^4.0.0 + redis: ^3.1.1 || ^4.0.0 + reflect-metadata: ^0.1.14 || ^0.2.0 + sql.js: ^1.4.0 + sqlite3: ^5.0.3 + ts-node: ^10.7.0 + typeorm-aurora-data-api-driver: ^2.0.0 + peerDependenciesMeta: + '@google-cloud/spanner': + optional: true + '@sap/hana-client': + optional: true + better-sqlite3: + optional: true + hdb-pool: + optional: true + ioredis: + optional: true + mongodb: + optional: true + mssql: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-native: + optional: true + pg-query-stream: + optional: true + redis: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + ts-node: + optional: true + typeorm-aurora-data-api-driver: + optional: true + typescript@5.8.2: resolution: {integrity: sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==} engines: {node: '>=14.17'} @@ -3082,12 +5350,22 @@ packages: engines: {node: '>=0.8.0'} hasBin: true + uid-safe@2.1.5: + resolution: {integrity: sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==} + engines: {node: '>= 0.8'} + undici-types@6.19.8: resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} undici-types@6.20.0: resolution: {integrity: sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==} + universal-github-app-jwt@1.2.0: + resolution: {integrity: sha512-dncpMpnsKBk0eetwfN8D8OUHGfiDhhJ+mtsbMl+7PfW7mYjiH8LIcqRmYMtzYLgSh47HjfdBtrBwIQ/gizKR3g==} + + universal-user-agent@6.0.1: + resolution: {integrity: sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==} + universal-user-agent@7.0.2: resolution: {integrity: sha512-0JCqzSKnStlRRQfCdowvqy3cy0Dvtlb8xecj/H8JFZuCze4rwjPZQOgvFvn0Ws/usCHQFGpyr+pB9adaGwXn4Q==} @@ -3095,6 +5373,14 @@ packages: resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} engines: {node: '>= 10.0.0'} + unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + + untildify@4.0.0: + resolution: {integrity: sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==} + engines: {node: '>=8'} + update-browserslist-db@1.1.3: resolution: {integrity: sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==} hasBin: true @@ -3138,6 +5424,18 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + + uuid@11.1.0: + resolution: {integrity: sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==} + hasBin: true + + uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + v8-compile-cache-lib@3.0.1: resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} @@ -3145,6 +5443,18 @@ packages: resolution: {integrity: sha512-OljLrQ9SQdOUqTaQxqL5dEfZWrXExyyWsozYlAWFawPVNuD83igl7uJD2RTkNMbniIYgt8l81eCJGIdQF7avLQ==} engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + value-or-promise@1.0.11: + resolution: {integrity: sha512-41BrgH+dIbCFXClcSapVs5M6GkENd3gQOJpEfPDNa71LsUGMXDL0jMWpI/Rh7WhX+Aalfz2TTS3Zt5pUsbnhLg==} + engines: {node: '>=12'} + + value-or-promise@1.0.12: + resolution: {integrity: sha512-Z6Uz+TYwEqE7ZN50gwn+1LCVo9ZVrpxRPOhOLnncYkY1ZzOYtrX8Fwf/rFktZ8R5mJms6EZf5TqNOMeZmnPq9Q==} + engines: {node: '>=12'} + + vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + vaul@1.1.2: resolution: {integrity: sha512-ZFkClGpWyI2WUQjdLJ/BaGuV6AVQiJ3uELGk3OYtP+B6yCO7Cmn9vPFXVJkRaGkOJu3m8bQMgtyzNHixULceQA==} peerDependencies: @@ -3157,14 +5467,36 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + webidl-conversions@3.0.1: + resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} + + webidl-conversions@4.0.2: + resolution: {integrity: sha512-YQ+BmxuTgd6UXZW3+ICGfyqRyHXVlD5GtQr5+qjiNW7bF0cqrzX500HVXPBOvgXb5YnzDd+h0zqyv61KUD7+Sg==} + + whatwg-mimetype@3.0.0: + resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} + engines: {node: '>=12'} + + whatwg-url@5.0.0: + resolution: {integrity: sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==} + + whatwg-url@7.1.0: + resolution: {integrity: sha512-WUu7Rg1DroM7oQvGWfOiAK21n74Gg+T4elXEQYkOhtyLeWiJFoOGLXPKI/9gzIie9CtwVLm8wtw6YJdKyxSjeg==} + which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} hasBin: true + wif@2.0.6: + resolution: {integrity: sha512-HIanZn1zmduSF+BQhkE+YXIbEiH0xPr1012QbFEGB0xsKqJii0/SqJjyn8dFv6y36kOznMgMB+LGcbZTJ1xACQ==} + wordwrap@1.0.0: resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + workspace@0.0.1-preview.2: + resolution: {integrity: sha512-UwDfYOgc0XET22pr/nlU0l02/8bG7xDW55EKKj+gp6fM2+23GdVVsGV0mMtMCAzJ/H9G3POdiJ5Ny2tyGZVefQ==} + wrap-ansi@6.2.0: resolution: {integrity: sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==} engines: {node: '>=8'} @@ -3180,15 +5512,80 @@ packages: wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + ws@7.5.10: + resolution: {integrity: sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==} + engines: {node: '>=8.3.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: ^5.0.2 + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + + ws@8.18.0: + resolution: {integrity: sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==} + 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 + + xss@1.0.15: + resolution: {integrity: sha512-FVdlVVC67WOIPvfOwhoMETV72f6GbW7aOabBC3WxN/oUdoEMDyLz4OgRv5/gck2ZeNqEQu+Tb0kloovXOfpYVg==} + engines: {node: '>= 0.10.0'} + hasBin: true + + xstream@11.14.0: + resolution: {integrity: sha512-1bLb+kKKtKPbgTK6i/BaoAn03g47PpFstlbe1BA+y3pNS/LfvcaghS5BFf9+EE1J+KwSQsEpfJvFN5GqFtiNmw==} + + xtend@4.0.2: + resolution: {integrity: sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==} + engines: {node: '>=0.4'} + + y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + + yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + yaml@2.7.0: resolution: {integrity: sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==} engines: {node: '>= 14'} hasBin: true + yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + + yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + + yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + + yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + yn@3.1.1: resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} engines: {node: '>=6'} + zen-observable-ts@1.2.5: + resolution: {integrity: sha512-QZWQekv6iB72Naeake9hS1KxHlotfRpe+WGNbNx5/ta+R3DNjVO2bswf63gXlWDcs+EMd7XY8HfVQyP1X6T4Zg==} + + zen-observable@0.8.15: + resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} + zod@3.24.2: resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==} @@ -3214,6 +5611,109 @@ snapshots: '@alloc/quick-lru@5.2.0': {} + '@apollo/client@3.13.3(@types/react@18.3.0)(graphql@16.10.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + '@wry/caches': 1.0.1 + '@wry/equality': 0.5.7 + '@wry/trie': 0.5.0 + graphql: 16.10.0 + graphql-tag: 2.12.6(graphql@16.10.0) + hoist-non-react-statics: 3.3.2 + optimism: 0.18.1 + prop-types: 15.8.1 + rehackt: 0.1.0(@types/react@18.3.0)(react@19.0.0) + symbol-observable: 4.0.0 + ts-invariant: 0.10.3 + tslib: 2.8.1 + zen-observable-ts: 1.2.5 + optionalDependencies: + react: 19.0.0 + react-dom: 19.0.0(react@19.0.0) + transitivePeerDependencies: + - '@types/react' + + '@apollo/protobufjs@1.2.6': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/long': 4.0.2 + '@types/node': 10.17.60 + long: 4.0.0 + + '@apollo/protobufjs@1.2.7': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/long': 4.0.2 + long: 4.0.0 + + '@apollo/usage-reporting-protobuf@4.1.1': + dependencies: + '@apollo/protobufjs': 1.2.7 + + '@apollo/utils.dropunuseddefinitions@1.1.0(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + + '@apollo/utils.keyvaluecache@1.0.2': + dependencies: + '@apollo/utils.logger': 1.0.1 + lru-cache: 7.13.1 + + '@apollo/utils.logger@1.0.1': {} + + '@apollo/utils.printwithreducedwhitespace@1.1.0(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + + '@apollo/utils.removealiases@1.0.0(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + + '@apollo/utils.sortast@1.1.0(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + lodash.sortby: 4.7.0 + + '@apollo/utils.stripsensitiveliterals@1.2.0(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + + '@apollo/utils.usagereporting@1.0.1(graphql@16.10.0)': + dependencies: + '@apollo/usage-reporting-protobuf': 4.1.1 + '@apollo/utils.dropunuseddefinitions': 1.1.0(graphql@16.10.0) + '@apollo/utils.printwithreducedwhitespace': 1.1.0(graphql@16.10.0) + '@apollo/utils.removealiases': 1.0.0(graphql@16.10.0) + '@apollo/utils.sortast': 1.1.0(graphql@16.10.0) + '@apollo/utils.stripsensitiveliterals': 1.2.0(graphql@16.10.0) + graphql: 16.10.0 + + '@apollographql/apollo-tools@0.5.4(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + + '@apollographql/graphql-playground-html@1.6.29': + dependencies: + xss: 1.0.15 + '@babel/runtime-corejs3@7.26.9': dependencies: core-js-pure: 3.41.0 @@ -3260,6 +5760,56 @@ snapshots: '@biomejs/monorepo@https://codeload.github.com/biomejs/biome/tar.gz/0ce750c5052cc0620af1fb95acb863c1f16b2bce': {} + '@cerc-io/laconic-registry-cli@0.2.10': + dependencies: + '@cerc-io/registry-sdk': 0.2.11(debug@4.4.0) + '@cosmjs/stargate': 0.32.4(debug@4.4.0) + fs-extra: 10.1.0 + js-yaml: 3.14.1 + lodash: 4.17.21 + lodash-clean: 2.2.3 + yargs: 17.7.2 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + '@cerc-io/registry-sdk@0.2.11(debug@4.4.0)': + dependencies: + '@cosmjs/amino': 0.28.13 + '@cosmjs/crypto': 0.28.13 + '@cosmjs/encoding': 0.28.13 + '@cosmjs/launchpad': 0.27.1(debug@4.4.0) + '@cosmjs/proto-signing': 0.32.4 + '@cosmjs/stargate': 0.32.4(debug@4.4.0) + '@cosmjs/tendermint-rpc': 0.32.4(debug@4.4.0) + '@ipld/dag-cbor': 7.0.3 + '@ipld/dag-json': 8.0.11 + '@metamask/eth-sig-util': 4.0.1 + '@tharsis/address-converter': 0.1.8 + '@tharsis/eip712': 0.2.4 + '@tharsis/proto': 0.1.20 + '@tharsis/provider': 0.2.4 + '@tharsis/transactions': 0.2.6 + axios: 0.26.1(debug@4.4.0) + bip32: 3.0.1 + bip39: 3.1.0 + canonical-json: 0.0.4 + ethers: 5.8.0 + graphql.js: 0.6.8 + js-sha256: 0.9.0 + js-yaml: 3.14.1 + lodash: 4.17.21 + multiformats: 9.9.0 + node-yaml: 4.0.1(js-yaml@3.14.1) + secp256k1: 4.0.4 + semver: 7.7.1 + tiny-secp256k1: 1.1.7 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + '@clerk/backend@1.25.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)': dependencies: '@clerk/shared': 3.0.0(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -3313,6 +5863,264 @@ snapshots: dependencies: csstype: 3.1.3 + '@confio/ics23@0.6.8': + dependencies: + '@noble/hashes': 1.7.1 + protobufjs: 6.11.4 + + '@cosmjs/amino@0.27.1': + dependencies: + '@cosmjs/crypto': 0.27.1 + '@cosmjs/encoding': 0.27.1 + '@cosmjs/math': 0.27.1 + '@cosmjs/utils': 0.27.1 + + '@cosmjs/amino@0.28.13': + dependencies: + '@cosmjs/crypto': 0.28.13 + '@cosmjs/encoding': 0.28.13 + '@cosmjs/math': 0.28.13 + '@cosmjs/utils': 0.28.13 + + '@cosmjs/amino@0.32.4': + dependencies: + '@cosmjs/crypto': 0.32.4 + '@cosmjs/encoding': 0.32.4 + '@cosmjs/math': 0.32.4 + '@cosmjs/utils': 0.32.4 + + '@cosmjs/amino@0.33.0': + dependencies: + '@cosmjs/crypto': 0.33.0 + '@cosmjs/encoding': 0.33.0 + '@cosmjs/math': 0.33.0 + '@cosmjs/utils': 0.33.0 + + '@cosmjs/crypto@0.27.1': + dependencies: + '@cosmjs/encoding': 0.27.1 + '@cosmjs/math': 0.27.1 + '@cosmjs/utils': 0.27.1 + bip39: 3.1.0 + bn.js: 5.2.1 + elliptic: 6.6.1 + js-sha3: 0.8.0 + libsodium-wrappers: 0.7.15 + ripemd160: 2.0.2 + sha.js: 2.4.11 + + '@cosmjs/crypto@0.28.13': + dependencies: + '@cosmjs/encoding': 0.28.13 + '@cosmjs/math': 0.28.13 + '@cosmjs/utils': 0.28.13 + '@noble/hashes': 1.7.1 + bn.js: 5.2.1 + elliptic: 6.6.1 + libsodium-wrappers: 0.7.15 + + '@cosmjs/crypto@0.32.4': + dependencies: + '@cosmjs/encoding': 0.32.4 + '@cosmjs/math': 0.32.4 + '@cosmjs/utils': 0.32.4 + '@noble/hashes': 1.7.1 + bn.js: 5.2.1 + elliptic: 6.6.1 + libsodium-wrappers-sumo: 0.7.15 + + '@cosmjs/crypto@0.33.0': + dependencies: + '@cosmjs/encoding': 0.33.0 + '@cosmjs/math': 0.33.0 + '@cosmjs/utils': 0.33.0 + '@noble/hashes': 1.7.1 + bn.js: 5.2.1 + elliptic: 6.6.1 + libsodium-wrappers-sumo: 0.7.15 + + '@cosmjs/encoding@0.27.1': + dependencies: + base64-js: 1.5.1 + bech32: 1.1.4 + readonly-date: 1.0.0 + + '@cosmjs/encoding@0.28.13': + dependencies: + base64-js: 1.5.1 + bech32: 1.1.4 + readonly-date: 1.0.0 + + '@cosmjs/encoding@0.32.4': + dependencies: + base64-js: 1.5.1 + bech32: 1.1.4 + readonly-date: 1.0.0 + + '@cosmjs/encoding@0.33.0': + dependencies: + base64-js: 1.5.1 + bech32: 1.1.4 + readonly-date: 1.0.0 + + '@cosmjs/json-rpc@0.32.4': + dependencies: + '@cosmjs/stream': 0.32.4 + xstream: 11.14.0 + + '@cosmjs/json-rpc@0.33.0': + dependencies: + '@cosmjs/stream': 0.33.0 + xstream: 11.14.0 + + '@cosmjs/launchpad@0.27.1(debug@4.4.0)': + dependencies: + '@cosmjs/amino': 0.27.1 + '@cosmjs/crypto': 0.27.1 + '@cosmjs/encoding': 0.27.1 + '@cosmjs/math': 0.27.1 + '@cosmjs/utils': 0.27.1 + axios: 0.21.4(debug@4.4.0) + fast-deep-equal: 3.1.3 + transitivePeerDependencies: + - debug + + '@cosmjs/math@0.27.1': + dependencies: + bn.js: 5.2.1 + + '@cosmjs/math@0.28.13': + dependencies: + bn.js: 5.2.1 + + '@cosmjs/math@0.32.4': + dependencies: + bn.js: 5.2.1 + + '@cosmjs/math@0.33.0': + dependencies: + bn.js: 5.2.1 + + '@cosmjs/proto-signing@0.32.4': + dependencies: + '@cosmjs/amino': 0.32.4 + '@cosmjs/crypto': 0.32.4 + '@cosmjs/encoding': 0.32.4 + '@cosmjs/math': 0.32.4 + '@cosmjs/utils': 0.32.4 + cosmjs-types: 0.9.0 + + '@cosmjs/proto-signing@0.33.0': + dependencies: + '@cosmjs/amino': 0.33.0 + '@cosmjs/crypto': 0.33.0 + '@cosmjs/encoding': 0.33.0 + '@cosmjs/math': 0.33.0 + '@cosmjs/utils': 0.33.0 + cosmjs-types: 0.9.0 + + '@cosmjs/socket@0.32.4': + dependencies: + '@cosmjs/stream': 0.32.4 + isomorphic-ws: 4.0.1(ws@7.5.10) + ws: 7.5.10 + xstream: 11.14.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@cosmjs/socket@0.33.0': + dependencies: + '@cosmjs/stream': 0.33.0 + isomorphic-ws: 4.0.1(ws@7.5.10) + ws: 7.5.10 + xstream: 11.14.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@cosmjs/stargate@0.32.4(debug@4.4.0)': + dependencies: + '@confio/ics23': 0.6.8 + '@cosmjs/amino': 0.32.4 + '@cosmjs/encoding': 0.32.4 + '@cosmjs/math': 0.32.4 + '@cosmjs/proto-signing': 0.32.4 + '@cosmjs/stream': 0.32.4 + '@cosmjs/tendermint-rpc': 0.32.4(debug@4.4.0) + '@cosmjs/utils': 0.32.4 + cosmjs-types: 0.9.0 + xstream: 11.14.0 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + '@cosmjs/stargate@0.33.0(debug@4.4.0)': + dependencies: + '@cosmjs/amino': 0.33.0 + '@cosmjs/encoding': 0.33.0 + '@cosmjs/math': 0.33.0 + '@cosmjs/proto-signing': 0.33.0 + '@cosmjs/stream': 0.33.0 + '@cosmjs/tendermint-rpc': 0.33.0(debug@4.4.0) + '@cosmjs/utils': 0.33.0 + cosmjs-types: 0.9.0 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + '@cosmjs/stream@0.32.4': + dependencies: + xstream: 11.14.0 + + '@cosmjs/stream@0.33.0': + dependencies: + xstream: 11.14.0 + + '@cosmjs/tendermint-rpc@0.32.4(debug@4.4.0)': + dependencies: + '@cosmjs/crypto': 0.32.4 + '@cosmjs/encoding': 0.32.4 + '@cosmjs/json-rpc': 0.32.4 + '@cosmjs/math': 0.32.4 + '@cosmjs/socket': 0.32.4 + '@cosmjs/stream': 0.32.4 + '@cosmjs/utils': 0.32.4 + axios: 1.8.2(debug@4.4.0) + readonly-date: 1.0.0 + xstream: 11.14.0 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + '@cosmjs/tendermint-rpc@0.33.0(debug@4.4.0)': + dependencies: + '@cosmjs/crypto': 0.33.0 + '@cosmjs/encoding': 0.33.0 + '@cosmjs/json-rpc': 0.33.0 + '@cosmjs/math': 0.33.0 + '@cosmjs/socket': 0.33.0 + '@cosmjs/stream': 0.33.0 + '@cosmjs/utils': 0.33.0 + axios: 1.8.2(debug@4.4.0) + readonly-date: 1.0.0 + xstream: 11.14.0 + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + + '@cosmjs/utils@0.27.1': {} + + '@cosmjs/utils@0.28.13': {} + + '@cosmjs/utils@0.32.4': {} + + '@cosmjs/utils@0.33.0': {} + '@cspotcode/source-map-support@0.8.1': dependencies: '@jridgewell/trace-mapping': 0.3.9 @@ -3322,6 +6130,336 @@ snapshots: tslib: 2.8.1 optional: true + '@esbuild/aix-ppc64@0.25.0': + optional: true + + '@esbuild/android-arm64@0.25.0': + optional: true + + '@esbuild/android-arm@0.25.0': + optional: true + + '@esbuild/android-x64@0.25.0': + optional: true + + '@esbuild/darwin-arm64@0.25.0': + optional: true + + '@esbuild/darwin-x64@0.25.0': + optional: true + + '@esbuild/freebsd-arm64@0.25.0': + optional: true + + '@esbuild/freebsd-x64@0.25.0': + optional: true + + '@esbuild/linux-arm64@0.25.0': + optional: true + + '@esbuild/linux-arm@0.25.0': + optional: true + + '@esbuild/linux-ia32@0.25.0': + optional: true + + '@esbuild/linux-loong64@0.25.0': + optional: true + + '@esbuild/linux-mips64el@0.25.0': + optional: true + + '@esbuild/linux-ppc64@0.25.0': + optional: true + + '@esbuild/linux-riscv64@0.25.0': + optional: true + + '@esbuild/linux-s390x@0.25.0': + optional: true + + '@esbuild/linux-x64@0.25.0': + optional: true + + '@esbuild/netbsd-arm64@0.25.0': + optional: true + + '@esbuild/netbsd-x64@0.25.0': + optional: true + + '@esbuild/openbsd-arm64@0.25.0': + optional: true + + '@esbuild/openbsd-x64@0.25.0': + optional: true + + '@esbuild/sunos-x64@0.25.0': + optional: true + + '@esbuild/win32-arm64@0.25.0': + optional: true + + '@esbuild/win32-ia32@0.25.0': + optional: true + + '@esbuild/win32-x64@0.25.0': + optional: true + + '@ethersproject/abi@5.8.0': + dependencies: + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/abstract-provider@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/web': 5.8.0 + + '@ethersproject/abstract-signer@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + + '@ethersproject/address@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/rlp': 5.8.0 + + '@ethersproject/base64@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + + '@ethersproject/basex@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/properties': 5.8.0 + + '@ethersproject/bignumber@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + bn.js: 5.2.1 + + '@ethersproject/bytes@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/constants@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + + '@ethersproject/contracts@5.8.0': + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/transactions': 5.8.0 + + '@ethersproject/hash@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/hdnode@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + + '@ethersproject/json-wallets@5.8.0': + dependencies: + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + aes-js: 3.0.0 + scrypt-js: 3.0.1 + + '@ethersproject/keccak256@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + js-sha3: 0.8.0 + + '@ethersproject/logger@5.8.0': {} + + '@ethersproject/networks@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/pbkdf2@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/sha2': 5.8.0 + + '@ethersproject/properties@5.8.0': + dependencies: + '@ethersproject/logger': 5.8.0 + + '@ethersproject/providers@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/web': 5.8.0 + bech32: 1.1.4 + ws: 8.18.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + '@ethersproject/random@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/rlp@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/sha2@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + hash.js: 1.1.7 + + '@ethersproject/signing-key@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + bn.js: 5.2.1 + elliptic: 6.6.1 + hash.js: 1.1.7 + + '@ethersproject/solidity@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/strings@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/transactions@5.8.0': + dependencies: + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + + '@ethersproject/units@5.8.0': + dependencies: + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/logger': 5.8.0 + + '@ethersproject/wallet@5.8.0': + dependencies: + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/json-wallets': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + + '@ethersproject/web@5.8.0': + dependencies: + '@ethersproject/base64': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + + '@ethersproject/wordlists@5.8.0': + dependencies: + '@ethersproject/bytes': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@floating-ui/core@1.6.9': dependencies: '@floating-ui/utils': 0.2.9 @@ -3339,6 +6477,79 @@ snapshots: '@floating-ui/utils@0.2.9': {} + '@graphql-tools/merge@8.3.1(graphql@16.10.0)': + dependencies: + '@graphql-tools/utils': 8.9.0(graphql@16.10.0) + graphql: 16.10.0 + tslib: 2.8.1 + + '@graphql-tools/merge@8.4.2(graphql@16.10.0)': + dependencies: + '@graphql-tools/utils': 9.2.1(graphql@16.10.0) + graphql: 16.10.0 + tslib: 2.8.1 + + '@graphql-tools/merge@9.0.22(graphql@16.10.0)': + dependencies: + '@graphql-tools/utils': 10.8.4(graphql@16.10.0) + graphql: 16.10.0 + tslib: 2.8.1 + + '@graphql-tools/mock@8.7.20(graphql@16.10.0)': + dependencies: + '@graphql-tools/schema': 9.0.19(graphql@16.10.0) + '@graphql-tools/utils': 9.2.1(graphql@16.10.0) + fast-json-stable-stringify: 2.1.0 + graphql: 16.10.0 + tslib: 2.8.1 + + '@graphql-tools/schema@10.0.21(graphql@16.10.0)': + dependencies: + '@graphql-tools/merge': 9.0.22(graphql@16.10.0) + '@graphql-tools/utils': 10.8.4(graphql@16.10.0) + graphql: 16.10.0 + tslib: 2.8.1 + + '@graphql-tools/schema@8.5.1(graphql@16.10.0)': + dependencies: + '@graphql-tools/merge': 8.3.1(graphql@16.10.0) + '@graphql-tools/utils': 8.9.0(graphql@16.10.0) + graphql: 16.10.0 + tslib: 2.8.1 + value-or-promise: 1.0.11 + + '@graphql-tools/schema@9.0.19(graphql@16.10.0)': + dependencies: + '@graphql-tools/merge': 8.4.2(graphql@16.10.0) + '@graphql-tools/utils': 9.2.1(graphql@16.10.0) + graphql: 16.10.0 + tslib: 2.8.1 + value-or-promise: 1.0.12 + + '@graphql-tools/utils@10.8.4(graphql@16.10.0)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + '@whatwg-node/promise-helpers': 1.2.4 + cross-inspect: 1.0.1 + dset: 3.1.4 + graphql: 16.10.0 + tslib: 2.8.1 + + '@graphql-tools/utils@8.9.0(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + tslib: 2.8.1 + + '@graphql-tools/utils@9.2.1(graphql@16.10.0)': + dependencies: + '@graphql-typed-document-node/core': 3.2.0(graphql@16.10.0) + graphql: 16.10.0 + tslib: 2.8.1 + + '@graphql-typed-document-node/core@3.2.0(graphql@16.10.0)': + dependencies: + graphql: 16.10.0 + '@hookform/resolvers@4.1.3(react-hook-form@7.54.2(react@19.0.0))': dependencies: '@standard-schema/utils': 0.3.0 @@ -3419,6 +6630,16 @@ snapshots: '@img/sharp-win32-x64@0.33.5': optional: true + '@ipld/dag-cbor@7.0.3': + dependencies: + cborg: 1.10.2 + multiformats: 9.9.0 + + '@ipld/dag-json@8.0.11': + dependencies: + cborg: 1.10.2 + multiformats: 9.9.0 + '@isaacs/cliui@8.0.2': dependencies: string-width: 5.1.2 @@ -3428,6 +6649,8 @@ snapshots: wrap-ansi: 8.1.0 wrap-ansi-cjs: wrap-ansi@7.0.0 + '@josephg/resolvable@1.0.1': {} + '@jridgewell/gen-mapping@0.3.8': dependencies: '@jridgewell/set-array': 1.2.1 @@ -3450,6 +6673,14 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.0 + '@metamask/eth-sig-util@4.0.1': + dependencies: + ethereumjs-abi: 0.6.8 + ethereumjs-util: 6.2.1 + ethjs-util: 0.1.6 + tweetnacl: 1.0.3 + tweetnacl-util: 0.15.1 + '@next/env@15.2.1': {} '@next/swc-darwin-arm64@15.2.1': @@ -3476,6 +6707,12 @@ snapshots: '@next/swc-win32-x64-msvc@15.2.1': optional: true + '@noble/curves@1.8.1': + dependencies: + '@noble/hashes': 1.7.1 + + '@noble/hashes@1.7.1': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -3488,8 +6725,75 @@ snapshots: '@nodelib/fs.scandir': 2.1.5 fastq: 1.19.1 + '@octetstream/promisify@2.0.2': {} + + '@octokit/app@14.1.0': + dependencies: + '@octokit/auth-app': 6.1.3 + '@octokit/auth-unauthenticated': 5.0.1 + '@octokit/core': 5.2.0 + '@octokit/oauth-app': 6.1.0 + '@octokit/plugin-paginate-rest': 9.2.2(@octokit/core@5.2.0) + '@octokit/types': 12.6.0 + '@octokit/webhooks': 12.3.1 + + '@octokit/auth-app@6.1.3': + dependencies: + '@octokit/auth-oauth-app': 7.1.0 + '@octokit/auth-oauth-user': 4.1.0 + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.8.0 + deprecation: 2.3.1 + lru-cache: '@wolfy1339/lru-cache@11.0.2-patch.1' + universal-github-app-jwt: 1.2.0 + universal-user-agent: 6.0.1 + + '@octokit/auth-oauth-app@7.1.0': + dependencies: + '@octokit/auth-oauth-device': 6.1.0 + '@octokit/auth-oauth-user': 4.1.0 + '@octokit/request': 8.4.1 + '@octokit/types': 13.8.0 + '@types/btoa-lite': 1.0.2 + btoa-lite: 1.0.0 + universal-user-agent: 6.0.1 + + '@octokit/auth-oauth-device@6.1.0': + dependencies: + '@octokit/oauth-methods': 4.1.0 + '@octokit/request': 8.4.1 + '@octokit/types': 13.8.0 + universal-user-agent: 6.0.1 + + '@octokit/auth-oauth-user@4.1.0': + dependencies: + '@octokit/auth-oauth-device': 6.1.0 + '@octokit/oauth-methods': 4.1.0 + '@octokit/request': 8.4.1 + '@octokit/types': 13.8.0 + btoa-lite: 1.0.0 + universal-user-agent: 6.0.1 + + '@octokit/auth-token@4.0.0': {} + '@octokit/auth-token@5.1.2': {} + '@octokit/auth-unauthenticated@5.0.1': + dependencies: + '@octokit/request-error': 5.1.1 + '@octokit/types': 12.6.0 + + '@octokit/core@5.2.0': + dependencies: + '@octokit/auth-token': 4.0.0 + '@octokit/graphql': 7.1.1 + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.8.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.1 + '@octokit/core@6.1.4': dependencies: '@octokit/auth-token': 5.1.2 @@ -3505,32 +6809,111 @@ snapshots: '@octokit/types': 13.8.0 universal-user-agent: 7.0.2 + '@octokit/endpoint@9.0.6': + dependencies: + '@octokit/types': 13.8.0 + universal-user-agent: 6.0.1 + + '@octokit/graphql@7.1.1': + dependencies: + '@octokit/request': 8.4.1 + '@octokit/types': 13.8.0 + universal-user-agent: 6.0.1 + '@octokit/graphql@8.2.1': dependencies: '@octokit/request': 9.2.2 '@octokit/types': 13.8.0 universal-user-agent: 7.0.2 + '@octokit/oauth-app@6.1.0': + dependencies: + '@octokit/auth-oauth-app': 7.1.0 + '@octokit/auth-oauth-user': 4.1.0 + '@octokit/auth-unauthenticated': 5.0.1 + '@octokit/core': 5.2.0 + '@octokit/oauth-authorization-url': 6.0.2 + '@octokit/oauth-methods': 4.1.0 + '@types/aws-lambda': 8.10.147 + universal-user-agent: 6.0.1 + + '@octokit/oauth-authorization-url@6.0.2': {} + + '@octokit/oauth-methods@4.1.0': + dependencies: + '@octokit/oauth-authorization-url': 6.0.2 + '@octokit/request': 8.4.1 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.8.0 + btoa-lite: 1.0.0 + + '@octokit/openapi-types@20.0.0': {} + '@octokit/openapi-types@23.0.1': {} + '@octokit/plugin-paginate-graphql@4.0.1(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + + '@octokit/plugin-paginate-rest@11.3.1(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 13.8.0 + '@octokit/plugin-paginate-rest@11.4.3(@octokit/core@6.1.4)': dependencies: '@octokit/core': 6.1.4 '@octokit/types': 13.8.0 + '@octokit/plugin-paginate-rest@9.2.2(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 12.6.0 + '@octokit/plugin-request-log@5.3.1(@octokit/core@6.1.4)': dependencies: '@octokit/core': 6.1.4 + '@octokit/plugin-rest-endpoint-methods@13.2.2(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 13.8.0 + '@octokit/plugin-rest-endpoint-methods@13.3.1(@octokit/core@6.1.4)': dependencies: '@octokit/core': 6.1.4 '@octokit/types': 13.8.0 + '@octokit/plugin-retry@6.1.0(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.8.0 + bottleneck: 2.19.5 + + '@octokit/plugin-throttling@8.2.0(@octokit/core@5.2.0)': + dependencies: + '@octokit/core': 5.2.0 + '@octokit/types': 12.6.0 + bottleneck: 2.19.5 + + '@octokit/request-error@5.1.1': + dependencies: + '@octokit/types': 13.8.0 + deprecation: 2.3.1 + once: 1.4.0 + '@octokit/request-error@6.1.7': dependencies: '@octokit/types': 13.8.0 + '@octokit/request@8.4.1': + dependencies: + '@octokit/endpoint': 9.0.6 + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.8.0 + universal-user-agent: 6.0.1 + '@octokit/request@9.2.2': dependencies: '@octokit/endpoint': 10.1.3 @@ -3546,15 +6929,51 @@ snapshots: '@octokit/plugin-request-log': 5.3.1(@octokit/core@6.1.4) '@octokit/plugin-rest-endpoint-methods': 13.3.1(@octokit/core@6.1.4) + '@octokit/types@12.6.0': + dependencies: + '@octokit/openapi-types': 20.0.0 + '@octokit/types@13.8.0': dependencies: '@octokit/openapi-types': 23.0.1 + '@octokit/webhooks-methods@4.1.0': {} + '@octokit/webhooks-types@7.6.1': {} + '@octokit/webhooks@12.3.1': + dependencies: + '@octokit/request-error': 5.1.1 + '@octokit/webhooks-methods': 4.1.0 + '@octokit/webhooks-types': 7.6.1 + aggregate-error: 3.1.0 + '@pkgjs/parseargs@0.11.0': optional: true + '@protobufjs/aspromise@1.1.2': {} + + '@protobufjs/base64@1.1.2': {} + + '@protobufjs/codegen@2.0.4': {} + + '@protobufjs/eventemitter@1.1.0': {} + + '@protobufjs/fetch@1.1.0': + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/inquire': 1.1.0 + + '@protobufjs/float@1.0.2': {} + + '@protobufjs/inquire@1.1.0': {} + + '@protobufjs/path@1.1.2': {} + + '@protobufjs/pool@1.1.0': {} + + '@protobufjs/utf8@1.1.0': {} + '@radix-ui/number@1.1.0': {} '@radix-ui/primitive@1.1.1': {} @@ -4192,6 +7611,83 @@ snapshots: '@radix-ui/rect@1.1.0': {} + '@rollup/rollup-android-arm-eabi@4.34.9': + optional: true + + '@rollup/rollup-android-arm64@4.34.9': + optional: true + + '@rollup/rollup-darwin-arm64@4.34.9': + optional: true + + '@rollup/rollup-darwin-x64@4.34.9': + optional: true + + '@rollup/rollup-freebsd-arm64@4.34.9': + optional: true + + '@rollup/rollup-freebsd-x64@4.34.9': + optional: true + + '@rollup/rollup-linux-arm-gnueabihf@4.34.9': + optional: true + + '@rollup/rollup-linux-arm-musleabihf@4.34.9': + optional: true + + '@rollup/rollup-linux-arm64-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-arm64-musl@4.34.9': + optional: true + + '@rollup/rollup-linux-loongarch64-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-powerpc64le-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-riscv64-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-s390x-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-x64-gnu@4.34.9': + optional: true + + '@rollup/rollup-linux-x64-musl@4.34.9': + optional: true + + '@rollup/rollup-win32-arm64-msvc@4.34.9': + optional: true + + '@rollup/rollup-win32-ia32-msvc@4.34.9': + optional: true + + '@rollup/rollup-win32-x64-msvc@4.34.9': + optional: true + + '@spruceid/siwe-parser@3.0.0': + dependencies: + '@noble/hashes': 1.7.1 + apg-js: 4.4.0 + + '@sqltools/formatter@1.2.5': {} + + '@stablelib/binary@1.0.1': + dependencies: + '@stablelib/int': 1.0.1 + + '@stablelib/int@1.0.1': {} + + '@stablelib/random@1.0.2': + dependencies: + '@stablelib/binary': 1.0.1 + '@stablelib/wipe': 1.0.1 + + '@stablelib/wipe@1.0.1': {} + '@standard-schema/utils@0.3.0': {} '@swc/counter@0.1.3': {} @@ -4200,67 +7696,102 @@ snapshots: dependencies: tslib: 2.8.1 - '@tailwindcss/node@4.0.12': + '@tailwindcss/node@4.0.11': dependencies: enhanced-resolve: 5.18.1 jiti: 2.4.2 - tailwindcss: 4.0.12 + tailwindcss: 4.0.11 - '@tailwindcss/oxide-android-arm64@4.0.12': + '@tailwindcss/oxide-android-arm64@4.0.11': optional: true - '@tailwindcss/oxide-darwin-arm64@4.0.12': + '@tailwindcss/oxide-darwin-arm64@4.0.11': optional: true - '@tailwindcss/oxide-darwin-x64@4.0.12': + '@tailwindcss/oxide-darwin-x64@4.0.11': optional: true - '@tailwindcss/oxide-freebsd-x64@4.0.12': + '@tailwindcss/oxide-freebsd-x64@4.0.11': optional: true - '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.12': + '@tailwindcss/oxide-linux-arm-gnueabihf@4.0.11': optional: true - '@tailwindcss/oxide-linux-arm64-gnu@4.0.12': + '@tailwindcss/oxide-linux-arm64-gnu@4.0.11': optional: true - '@tailwindcss/oxide-linux-arm64-musl@4.0.12': + '@tailwindcss/oxide-linux-arm64-musl@4.0.11': optional: true - '@tailwindcss/oxide-linux-x64-gnu@4.0.12': + '@tailwindcss/oxide-linux-x64-gnu@4.0.11': optional: true - '@tailwindcss/oxide-linux-x64-musl@4.0.12': + '@tailwindcss/oxide-linux-x64-musl@4.0.11': optional: true - '@tailwindcss/oxide-win32-arm64-msvc@4.0.12': + '@tailwindcss/oxide-win32-arm64-msvc@4.0.11': optional: true - '@tailwindcss/oxide-win32-x64-msvc@4.0.12': + '@tailwindcss/oxide-win32-x64-msvc@4.0.11': optional: true - '@tailwindcss/oxide@4.0.12': + '@tailwindcss/oxide@4.0.11': optionalDependencies: - '@tailwindcss/oxide-android-arm64': 4.0.12 - '@tailwindcss/oxide-darwin-arm64': 4.0.12 - '@tailwindcss/oxide-darwin-x64': 4.0.12 - '@tailwindcss/oxide-freebsd-x64': 4.0.12 - '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.12 - '@tailwindcss/oxide-linux-arm64-gnu': 4.0.12 - '@tailwindcss/oxide-linux-arm64-musl': 4.0.12 - '@tailwindcss/oxide-linux-x64-gnu': 4.0.12 - '@tailwindcss/oxide-linux-x64-musl': 4.0.12 - '@tailwindcss/oxide-win32-arm64-msvc': 4.0.12 - '@tailwindcss/oxide-win32-x64-msvc': 4.0.12 + '@tailwindcss/oxide-android-arm64': 4.0.11 + '@tailwindcss/oxide-darwin-arm64': 4.0.11 + '@tailwindcss/oxide-darwin-x64': 4.0.11 + '@tailwindcss/oxide-freebsd-x64': 4.0.11 + '@tailwindcss/oxide-linux-arm-gnueabihf': 4.0.11 + '@tailwindcss/oxide-linux-arm64-gnu': 4.0.11 + '@tailwindcss/oxide-linux-arm64-musl': 4.0.11 + '@tailwindcss/oxide-linux-x64-gnu': 4.0.11 + '@tailwindcss/oxide-linux-x64-musl': 4.0.11 + '@tailwindcss/oxide-win32-arm64-msvc': 4.0.11 + '@tailwindcss/oxide-win32-x64-msvc': 4.0.11 - '@tailwindcss/postcss@4.0.12': + '@tailwindcss/postcss@4.0.11': dependencies: '@alloc/quick-lru': 5.2.0 - '@tailwindcss/node': 4.0.12 - '@tailwindcss/oxide': 4.0.12 + '@tailwindcss/node': 4.0.11 + '@tailwindcss/oxide': 4.0.11 lightningcss: 1.29.2 postcss: 8.5.3 - tailwindcss: 4.0.12 + tailwindcss: 4.0.11 + + '@tharsis/address-converter@0.1.8': + dependencies: + bech32: 2.0.0 + crypto-addr-codec: 0.1.8 + link-module-alias: 1.2.0 + shx: 0.3.4 + + '@tharsis/eip712@0.2.4': + dependencies: + link-module-alias: 1.2.0 + shx: 0.3.4 + + '@tharsis/proto@0.1.20': + dependencies: + '@types/google-protobuf': 3.15.12 + '@types/node': 17.0.45 + google-protobuf: 3.21.4 + link-module-alias: 1.2.0 + sha3: 2.1.4 + shx: 0.3.4 + + '@tharsis/provider@0.2.4': + dependencies: + '@types/node': 17.0.45 + link-module-alias: 1.2.0 + shx: 0.3.4 + + '@tharsis/transactions@0.2.6': + dependencies: + '@tharsis/eip712': 0.2.4 + '@tharsis/proto': 0.1.20 + '@types/node': 17.0.45 + link-module-alias: 1.2.0 + shx: 0.3.4 '@tootallnate/quickjs-emscripten@0.23.0': {} @@ -4306,6 +7837,74 @@ snapshots: semver: 7.6.2 update-check: 1.5.4 + '@turnkey/api-key-stamper@0.4.0': + dependencies: + '@noble/curves': 1.8.1 + '@turnkey/encoding': 0.1.0 + sha256-uint8array: 0.10.7 + + '@turnkey/encoding@0.1.0': {} + + '@turnkey/http@2.10.0': + dependencies: + '@turnkey/api-key-stamper': 0.4.0 + '@turnkey/encoding': 0.1.0 + '@turnkey/webauthn-stamper': 0.5.0 + cross-fetch: 3.2.0 + transitivePeerDependencies: + - encoding + + '@turnkey/sdk-server@0.1.0': + dependencies: + '@turnkey/api-key-stamper': 0.4.0 + '@turnkey/http': 2.10.0 + buffer: 6.0.3 + cross-fetch: 3.2.0 + elliptic: 6.6.1 + transitivePeerDependencies: + - encoding + + '@turnkey/webauthn-stamper@0.5.0': + dependencies: + sha256-uint8array: 0.10.7 + + '@types/accepts@1.3.7': + dependencies: + '@types/node': 20.17.23 + + '@types/aws-lambda@8.10.147': {} + + '@types/bn.js@4.11.6': + dependencies: + '@types/node': 20.17.23 + + '@types/body-parser@1.19.2': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 20.17.23 + + '@types/body-parser@1.19.5': + dependencies: + '@types/connect': 3.4.38 + '@types/node': 20.17.23 + + '@types/btoa-lite@1.0.2': {} + + '@types/connect@3.4.38': + dependencies: + '@types/node': 20.17.23 + + '@types/cookie-session@2.0.49': + dependencies: + '@types/express': 4.17.21 + '@types/keygrip': 1.0.6 + + '@types/cors@2.8.12': {} + + '@types/cors@2.8.17': + dependencies: + '@types/node': 20.17.23 + '@types/d3-array@3.2.1': {} '@types/d3-color@3.1.3': {} @@ -4330,18 +7929,89 @@ snapshots: '@types/d3-timer@3.0.2': {} + '@types/debug@4.1.12': + dependencies: + '@types/ms': 2.1.0 + + '@types/estree@1.0.6': {} + + '@types/express-serve-static-core@4.17.31': + dependencies: + '@types/node': 20.17.23 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + + '@types/express-serve-static-core@4.19.6': + dependencies: + '@types/node': 20.17.23 + '@types/qs': 6.9.18 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + '@types/express-session@1.18.1': + dependencies: + '@types/express': 4.17.21 + + '@types/express@4.17.14': + dependencies: + '@types/body-parser': 1.19.2 + '@types/express-serve-static-core': 4.17.31 + '@types/qs': 6.9.18 + '@types/serve-static': 1.15.7 + + '@types/express@4.17.21': + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.19.6 + '@types/qs': 6.9.18 + '@types/serve-static': 1.15.7 + + '@types/fs-extra@11.0.4': + dependencies: + '@types/jsonfile': 6.1.4 + '@types/node': 20.17.23 + '@types/glob@7.2.0': dependencies: '@types/minimatch': 5.1.2 - '@types/node': 22.13.9 + '@types/node': 20.17.23 + + '@types/google-protobuf@3.15.12': {} + + '@types/http-errors@2.0.4': {} '@types/inquirer@6.5.0': dependencies: '@types/through': 0.0.33 rxjs: 6.6.7 + '@types/jsonfile@6.1.4': + dependencies: + '@types/node': 20.17.23 + + '@types/jsonwebtoken@9.0.9': + dependencies: + '@types/ms': 2.1.0 + '@types/node': 20.17.23 + + '@types/keygrip@1.0.6': {} + + '@types/long@4.0.2': {} + + '@types/luxon@3.4.2': {} + + '@types/mime@1.3.5': {} + '@types/minimatch@5.1.2': {} + '@types/ms@2.1.0': {} + + '@types/node@10.12.18': {} + + '@types/node@10.17.60': {} + + '@types/node@17.0.45': {} + '@types/node@20.17.23': dependencies: undici-types: 6.19.8 @@ -4350,8 +8020,16 @@ snapshots: dependencies: undici-types: 6.20.0 + '@types/pbkdf2@3.1.2': + dependencies: + '@types/node': 20.17.23 + '@types/prop-types@15.7.14': {} + '@types/qs@6.9.18': {} + + '@types/range-parser@1.2.7': {} + '@types/react-dom@18.3.1': dependencies: '@types/react': 18.3.0 @@ -4361,18 +8039,64 @@ snapshots: '@types/prop-types': 15.7.14 csstype: 3.1.3 + '@types/secp256k1@4.0.6': + dependencies: + '@types/node': 20.17.23 + + '@types/semver@7.5.8': {} + + '@types/send@0.17.4': + dependencies: + '@types/mime': 1.3.5 + '@types/node': 20.17.23 + + '@types/serve-static@1.15.7': + dependencies: + '@types/http-errors': 2.0.4 + '@types/node': 20.17.23 + '@types/send': 0.17.4 + '@types/through@0.0.33': dependencies: - '@types/node': 22.13.9 + '@types/node': 20.17.23 '@types/tinycolor2@1.4.6': {} + '@whatwg-node/promise-helpers@1.2.4': + dependencies: + tslib: 2.8.1 + + '@wolfy1339/lru-cache@11.0.2-patch.1': {} + + '@wry/caches@1.0.1': + dependencies: + tslib: 2.8.1 + + '@wry/context@0.7.4': + dependencies: + tslib: 2.8.1 + + '@wry/equality@0.5.7': + dependencies: + tslib: 2.8.1 + + '@wry/trie@0.5.0': + dependencies: + tslib: 2.8.1 + + accepts@1.3.8: + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + acorn-walk@8.3.4: dependencies: acorn: 8.14.1 acorn@8.14.1: {} + aes-js@3.0.0: {} + agent-base@7.1.3: {} aggregate-error@3.1.0: @@ -4398,6 +8122,8 @@ snapshots: ansi-styles@6.2.1: {} + ansis@3.17.0: {} + any-promise@1.3.0: {} anymatch@3.1.3: @@ -4405,22 +8131,124 @@ snapshots: normalize-path: 3.0.0 picomatch: 2.3.1 + apg-js@4.4.0: {} + + apollo-datasource@3.3.2: + dependencies: + '@apollo/utils.keyvaluecache': 1.0.2 + apollo-server-env: 4.2.1 + transitivePeerDependencies: + - encoding + + apollo-reporting-protobuf@3.4.0: + dependencies: + '@apollo/protobufjs': 1.2.6 + + apollo-server-core@3.13.0(graphql@16.10.0): + dependencies: + '@apollo/utils.keyvaluecache': 1.0.2 + '@apollo/utils.logger': 1.0.1 + '@apollo/utils.usagereporting': 1.0.1(graphql@16.10.0) + '@apollographql/apollo-tools': 0.5.4(graphql@16.10.0) + '@apollographql/graphql-playground-html': 1.6.29 + '@graphql-tools/mock': 8.7.20(graphql@16.10.0) + '@graphql-tools/schema': 8.5.1(graphql@16.10.0) + '@josephg/resolvable': 1.0.1 + apollo-datasource: 3.3.2 + apollo-reporting-protobuf: 3.4.0 + apollo-server-env: 4.2.1 + apollo-server-errors: 3.3.1(graphql@16.10.0) + apollo-server-plugin-base: 3.7.2(graphql@16.10.0) + apollo-server-types: 3.8.0(graphql@16.10.0) + async-retry: 1.3.3 + fast-json-stable-stringify: 2.1.0 + graphql: 16.10.0 + graphql-tag: 2.12.6(graphql@16.10.0) + loglevel: 1.9.2 + lru-cache: 6.0.0 + node-abort-controller: 3.1.1 + sha.js: 2.4.11 + uuid: 9.0.1 + whatwg-mimetype: 3.0.0 + transitivePeerDependencies: + - encoding + + apollo-server-env@4.2.1: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + apollo-server-errors@3.3.1(graphql@16.10.0): + dependencies: + graphql: 16.10.0 + + apollo-server-express@3.13.0(express@4.21.2)(graphql@16.10.0): + dependencies: + '@types/accepts': 1.3.7 + '@types/body-parser': 1.19.2 + '@types/cors': 2.8.12 + '@types/express': 4.17.14 + '@types/express-serve-static-core': 4.17.31 + accepts: 1.3.8 + apollo-server-core: 3.13.0(graphql@16.10.0) + apollo-server-types: 3.8.0(graphql@16.10.0) + body-parser: 1.20.3 + cors: 2.8.5 + express: 4.21.2 + graphql: 16.10.0 + parseurl: 1.3.3 + transitivePeerDependencies: + - encoding + - supports-color + + apollo-server-plugin-base@3.7.2(graphql@16.10.0): + dependencies: + apollo-server-types: 3.8.0(graphql@16.10.0) + graphql: 16.10.0 + transitivePeerDependencies: + - encoding + + apollo-server-types@3.8.0(graphql@16.10.0): + dependencies: + '@apollo/utils.keyvaluecache': 1.0.2 + '@apollo/utils.logger': 1.0.1 + apollo-reporting-protobuf: 3.4.0 + apollo-server-env: 4.2.1 + graphql: 16.10.0 + transitivePeerDependencies: + - encoding + + app-root-path@3.1.0: {} + arg@4.1.3: {} arg@5.0.2: {} + argparse@1.0.10: + dependencies: + sprintf-js: 1.0.3 + argparse@2.0.1: {} aria-hidden@1.2.4: dependencies: tslib: 2.8.1 + array-flatten@1.1.1: {} + array-union@2.1.0: {} ast-types@0.13.4: dependencies: tslib: 2.8.1 + async-retry@1.3.3: + dependencies: + retry: 0.13.1 + + asynckit@0.4.0: {} + autoprefixer@10.4.20(postcss@8.5.3): dependencies: browserslist: 4.24.4 @@ -4431,22 +8259,101 @@ snapshots: postcss: 8.5.3 postcss-value-parser: 4.2.0 + axios@0.21.4(debug@4.4.0): + dependencies: + follow-redirects: 1.15.9(debug@4.4.0) + transitivePeerDependencies: + - debug + + axios@0.26.1(debug@4.4.0): + dependencies: + follow-redirects: 1.15.9(debug@4.4.0) + transitivePeerDependencies: + - debug + + axios@1.8.2(debug@4.4.0): + dependencies: + follow-redirects: 1.15.9(debug@4.4.0) + form-data: 4.0.2 + proxy-from-env: 1.1.0 + transitivePeerDependencies: + - debug + balanced-match@1.0.2: {} + base-x@3.0.10: + dependencies: + safe-buffer: 5.2.1 + base64-js@1.5.1: {} basic-ftp@5.0.5: {} + bech32@1.1.4: {} + + bech32@2.0.0: {} + + before-after-hook@2.2.3: {} + before-after-hook@3.0.2: {} + better-sqlite3@9.6.0: + dependencies: + bindings: 1.5.0 + prebuild-install: 7.1.3 + + big-integer@1.6.36: {} + binary-extensions@2.3.0: {} + bindings@1.5.0: + dependencies: + file-uri-to-path: 1.0.0 + + bip32@3.0.1: + dependencies: + '@types/node': 10.12.18 + bs58check: 2.1.2 + create-hash: 1.2.0 + create-hmac: 1.1.7 + typeforce: 1.18.0 + wif: 2.0.6 + + bip39@3.1.0: + dependencies: + '@noble/hashes': 1.7.1 + bl@4.1.0: dependencies: buffer: 5.7.1 inherits: 2.0.4 readable-stream: 3.6.2 + blakejs@1.2.1: {} + + bn.js@4.12.1: {} + + bn.js@5.2.1: {} + + body-parser@1.20.3: + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + 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.13.0 + raw-body: 2.5.2 + type-is: 1.6.18 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + bottleneck@2.19.5: {} + brace-expansion@1.1.11: dependencies: balanced-match: 1.0.2 @@ -4460,22 +8367,73 @@ snapshots: dependencies: fill-range: 7.1.1 + brorand@1.1.0: {} + + browserify-aes@1.2.0: + dependencies: + buffer-xor: 1.0.3 + cipher-base: 1.0.6 + create-hash: 1.2.0 + evp_bytestokey: 1.0.3 + inherits: 2.0.4 + safe-buffer: 5.2.1 + browserslist@4.24.4: dependencies: caniuse-lite: 1.0.30001702 - electron-to-chromium: 1.5.113 + electron-to-chromium: 1.5.112 node-releases: 2.0.19 update-browserslist-db: 1.1.3(browserslist@4.24.4) + bs58@4.0.1: + dependencies: + base-x: 3.0.10 + + bs58check@2.1.2: + dependencies: + bs58: 4.0.1 + create-hash: 1.2.0 + safe-buffer: 5.2.1 + + btoa-lite@1.0.0: {} + + buffer-equal-constant-time@1.0.1: {} + + buffer-xor@1.0.3: {} + buffer@5.7.1: dependencies: base64-js: 1.5.1 ieee754: 1.2.1 + buffer@6.0.3: + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + + bundle-require@5.1.0(esbuild@0.25.0): + dependencies: + esbuild: 0.25.0 + load-tsconfig: 0.2.5 + busboy@1.6.0: dependencies: streamsearch: 1.1.0 + bytes@3.1.2: {} + + cac@6.7.14: {} + + call-bind-apply-helpers@1.0.2: + dependencies: + es-errors: 1.3.0 + function-bind: 1.1.2 + + call-bound@1.0.4: + dependencies: + call-bind-apply-helpers: 1.0.2 + get-intrinsic: 1.3.0 + camel-case@3.0.0: dependencies: no-case: 2.3.2 @@ -4485,6 +8443,10 @@ snapshots: caniuse-lite@1.0.30001702: {} + canonical-json@0.0.4: {} + + cborg@1.10.2: {} + chalk@2.4.2: dependencies: ansi-styles: 3.2.1 @@ -4538,6 +8500,17 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + chokidar@4.0.3: + dependencies: + readdirp: 4.1.2 + + chownr@1.1.4: {} + + cipher-base@1.0.6: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + class-variance-authority@0.7.1: dependencies: clsx: 2.1.1 @@ -4554,6 +8527,18 @@ snapshots: client-only@0.0.1: {} + cliui@7.0.4: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + + cliui@8.0.1: + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + clone@1.0.4: {} clsx@2.1.1: {} @@ -4570,6 +8555,8 @@ snapshots: - '@types/react' - '@types/react-dom' + co@4.6.0: {} + color-convert@1.9.3: dependencies: color-name: 1.1.3 @@ -4594,33 +8581,127 @@ snapshots: color-string: 1.9.1 optional: true + combined-stream@1.0.8: + dependencies: + delayed-stream: 1.0.0 + commander@10.0.1: {} + commander@2.20.3: {} + commander@4.1.1: {} concat-map@0.0.1: {} + consola@3.4.0: {} + constant-case@2.0.0: dependencies: snake-case: 2.1.0 upper-case: 1.1.3 + content-disposition@0.5.4: + dependencies: + safe-buffer: 5.2.1 + + content-type@1.0.5: {} + + cookie-session@2.1.0: + dependencies: + cookies: 0.9.1 + debug: 3.2.7 + on-headers: 1.0.2 + safe-buffer: 5.2.1 + transitivePeerDependencies: + - supports-color + + cookie-signature@1.0.6: {} + + cookie-signature@1.0.7: {} + + cookie@0.7.1: {} + + cookie@0.7.2: {} + cookie@1.0.2: {} + cookies@0.9.1: + dependencies: + depd: 2.0.0 + keygrip: 1.1.0 + + copyfiles@2.4.1: + dependencies: + glob: 7.2.3 + minimatch: 3.1.2 + mkdirp: 1.0.4 + noms: 0.0.0 + through2: 2.0.5 + untildify: 4.0.0 + yargs: 16.2.0 + core-js-pure@3.41.0: {} + core-util-is@1.0.3: {} + + cors@2.8.5: + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + + cosmjs-types@0.9.0: {} + + create-hash@1.2.0: + dependencies: + cipher-base: 1.0.6 + inherits: 2.0.4 + md5.js: 1.3.5 + ripemd160: 2.0.2 + sha.js: 2.4.11 + + create-hmac@1.1.7: + dependencies: + cipher-base: 1.0.6 + create-hash: 1.2.0 + inherits: 2.0.4 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + create-require@1.1.1: {} + cross-fetch@3.2.0: + dependencies: + node-fetch: 2.7.0 + transitivePeerDependencies: + - encoding + + cross-inspect@1.0.1: + dependencies: + tslib: 2.8.1 + cross-spawn@7.0.6: dependencies: path-key: 3.1.1 shebang-command: 2.0.0 which: 2.0.2 + crypto-addr-codec@0.1.8: + dependencies: + base-x: 3.0.10 + big-integer: 1.6.36 + blakejs: 1.2.1 + bs58: 4.0.1 + ripemd160-min: 0.0.6 + safe-buffer: 5.2.1 + sha3: 2.1.4 + crypto-js@4.2.0: {} cssesc@3.0.0: {} + cssfilter@0.0.10: {} + csstype@3.1.3: {} d3-array@3.2.4: @@ -4665,18 +8746,44 @@ snapshots: date-fns@4.1.0: {} + dayjs@1.11.13: {} + + debug@2.6.9: + dependencies: + ms: 2.0.0 + + debug@3.2.7: + dependencies: + ms: 2.1.3 + debug@4.4.0: dependencies: ms: 2.1.3 decimal.js-light@2.5.1: {} + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + deep-extend@0.6.0: {} defaults@1.0.4: dependencies: clone: 1.0.4 + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + degenerator@5.0.1: dependencies: ast-types: 0.13.4 @@ -4694,8 +8801,16 @@ snapshots: rimraf: 3.0.2 slash: 3.0.0 + delayed-stream@1.0.0: {} + + depd@2.0.0: {} + + deprecation@2.3.1: {} + dequal@2.0.3: {} + destroy@1.2.0: {} + detect-libc@2.0.3: {} detect-node-es@1.1.0: {} @@ -4722,13 +8837,37 @@ snapshots: dot-case@3.0.4: dependencies: no-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 dotenv@16.4.7: {} + dset@3.1.4: {} + + dunder-proto@1.0.1: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-errors: 1.3.0 + gopd: 1.2.0 + eastasianwidth@0.2.0: {} - electron-to-chromium@1.5.113: {} + ecdsa-sig-formatter@1.0.11: + dependencies: + safe-buffer: 5.2.1 + + ee-first@1.1.1: {} + + electron-to-chromium@1.5.112: {} + + elliptic@6.6.1: + dependencies: + bn.js: 4.12.1 + brorand: 1.1.0 + hash.js: 1.1.7 + hmac-drbg: 1.0.1 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 embla-carousel-react@8.5.2(react@19.0.0): dependencies: @@ -4746,13 +8885,66 @@ snapshots: emoji-regex@9.2.2: {} + encodeurl@1.0.2: {} + + encodeurl@2.0.0: {} + + end-of-stream@1.4.4: + dependencies: + once: 1.4.0 + enhanced-resolve@5.18.1: dependencies: graceful-fs: 4.2.11 tapable: 2.2.1 + es-define-property@1.0.1: {} + + es-errors@1.3.0: {} + + es-object-atoms@1.1.1: + dependencies: + es-errors: 1.3.0 + + es-set-tostringtag@2.1.0: + dependencies: + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + has-tostringtag: 1.0.2 + hasown: 2.0.2 + + esbuild@0.25.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.25.0 + '@esbuild/android-arm': 0.25.0 + '@esbuild/android-arm64': 0.25.0 + '@esbuild/android-x64': 0.25.0 + '@esbuild/darwin-arm64': 0.25.0 + '@esbuild/darwin-x64': 0.25.0 + '@esbuild/freebsd-arm64': 0.25.0 + '@esbuild/freebsd-x64': 0.25.0 + '@esbuild/linux-arm': 0.25.0 + '@esbuild/linux-arm64': 0.25.0 + '@esbuild/linux-ia32': 0.25.0 + '@esbuild/linux-loong64': 0.25.0 + '@esbuild/linux-mips64el': 0.25.0 + '@esbuild/linux-ppc64': 0.25.0 + '@esbuild/linux-riscv64': 0.25.0 + '@esbuild/linux-s390x': 0.25.0 + '@esbuild/linux-x64': 0.25.0 + '@esbuild/netbsd-arm64': 0.25.0 + '@esbuild/netbsd-x64': 0.25.0 + '@esbuild/openbsd-arm64': 0.25.0 + '@esbuild/openbsd-x64': 0.25.0 + '@esbuild/sunos-x64': 0.25.0 + '@esbuild/win32-arm64': 0.25.0 + '@esbuild/win32-ia32': 0.25.0 + '@esbuild/win32-x64': 0.25.0 + escalade@3.2.0: {} + escape-html@1.0.3: {} + escape-string-regexp@1.0.5: {} escodegen@2.1.0: @@ -4769,8 +8961,89 @@ snapshots: esutils@2.0.3: {} + etag@1.8.1: {} + + ethereum-cryptography@0.1.3: + dependencies: + '@types/pbkdf2': 3.1.2 + '@types/secp256k1': 4.0.6 + blakejs: 1.2.1 + browserify-aes: 1.2.0 + bs58check: 2.1.2 + create-hash: 1.2.0 + create-hmac: 1.1.7 + hash.js: 1.1.7 + keccak: 3.0.4 + pbkdf2: 3.1.2 + randombytes: 2.1.0 + safe-buffer: 5.2.1 + scrypt-js: 3.0.1 + secp256k1: 4.0.4 + setimmediate: 1.0.5 + + ethereumjs-abi@0.6.8: + dependencies: + bn.js: 4.12.1 + ethereumjs-util: 6.2.1 + + ethereumjs-util@6.2.1: + dependencies: + '@types/bn.js': 4.11.6 + bn.js: 4.12.1 + create-hash: 1.2.0 + elliptic: 6.6.1 + ethereum-cryptography: 0.1.3 + ethjs-util: 0.1.6 + rlp: 2.2.7 + + ethers@5.8.0: + dependencies: + '@ethersproject/abi': 5.8.0 + '@ethersproject/abstract-provider': 5.8.0 + '@ethersproject/abstract-signer': 5.8.0 + '@ethersproject/address': 5.8.0 + '@ethersproject/base64': 5.8.0 + '@ethersproject/basex': 5.8.0 + '@ethersproject/bignumber': 5.8.0 + '@ethersproject/bytes': 5.8.0 + '@ethersproject/constants': 5.8.0 + '@ethersproject/contracts': 5.8.0 + '@ethersproject/hash': 5.8.0 + '@ethersproject/hdnode': 5.8.0 + '@ethersproject/json-wallets': 5.8.0 + '@ethersproject/keccak256': 5.8.0 + '@ethersproject/logger': 5.8.0 + '@ethersproject/networks': 5.8.0 + '@ethersproject/pbkdf2': 5.8.0 + '@ethersproject/properties': 5.8.0 + '@ethersproject/providers': 5.8.0 + '@ethersproject/random': 5.8.0 + '@ethersproject/rlp': 5.8.0 + '@ethersproject/sha2': 5.8.0 + '@ethersproject/signing-key': 5.8.0 + '@ethersproject/solidity': 5.8.0 + '@ethersproject/strings': 5.8.0 + '@ethersproject/transactions': 5.8.0 + '@ethersproject/units': 5.8.0 + '@ethersproject/wallet': 5.8.0 + '@ethersproject/web': 5.8.0 + '@ethersproject/wordlists': 5.8.0 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + + ethjs-util@0.1.6: + dependencies: + is-hex-prefixed: 1.0.0 + strip-hex-prefix: 1.0.0 + eventemitter3@4.0.7: {} + evp_bytestokey@1.0.3: + dependencies: + md5.js: 1.3.5 + safe-buffer: 5.2.1 + execa@5.1.1: dependencies: cross-spawn: 7.0.6 @@ -4783,6 +9056,61 @@ snapshots: signal-exit: 3.0.7 strip-final-newline: 2.0.0 + expand-template@2.0.3: {} + + express-async-errors@3.1.1(express@4.21.2): + dependencies: + express: 4.21.2 + + express-session@1.18.1: + dependencies: + cookie: 0.7.2 + cookie-signature: 1.0.7 + debug: 2.6.9 + depd: 2.0.0 + on-headers: 1.0.2 + parseurl: 1.3.3 + safe-buffer: 5.2.1 + uid-safe: 2.1.5 + transitivePeerDependencies: + - supports-color + + express@4.21.2: + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.3 + content-disposition: 0.5.4 + content-type: 1.0.5 + cookie: 0.7.1 + cookie-signature: 1.0.6 + debug: 2.6.9 + depd: 2.0.0 + encodeurl: 2.0.0 + escape-html: 1.0.3 + etag: 1.8.1 + finalhandler: 1.3.1 + fresh: 0.5.2 + http-errors: 2.0.0 + merge-descriptors: 1.0.3 + methods: 1.1.2 + on-finished: 2.4.1 + parseurl: 1.3.3 + path-to-regexp: 0.1.12 + proxy-addr: 2.0.7 + qs: 6.13.0 + range-parser: 1.2.1 + safe-buffer: 5.2.1 + send: 0.19.0 + serve-static: 1.16.2 + setprototypeof: 1.2.0 + statuses: 2.0.1 + type-is: 1.6.18 + utils-merge: 1.0.1 + vary: 1.1.2 + transitivePeerDependencies: + - supports-color + external-editor@3.1.0: dependencies: chardet: 0.7.0 @@ -4791,6 +9119,8 @@ snapshots: fast-content-type-parse@2.0.1: {} + fast-deep-equal@3.1.3: {} + fast-equals@5.2.2: {} fast-glob@3.3.3: @@ -4801,31 +9131,74 @@ snapshots: merge2: 1.4.1 micromatch: 4.0.8 + fast-json-stable-stringify@2.1.0: {} + fastq@1.19.1: dependencies: reusify: 1.1.0 + fdir@6.4.3(picomatch@4.0.2): + optionalDependencies: + picomatch: 4.0.2 + figures@3.2.0: dependencies: escape-string-regexp: 1.0.5 + file-uri-to-path@1.0.0: {} + fill-range@7.1.1: dependencies: to-regex-range: 5.0.1 + finalhandler@1.3.1: + dependencies: + debug: 2.6.9 + encodeurl: 2.0.0 + escape-html: 1.0.3 + on-finished: 2.4.1 + parseurl: 1.3.3 + statuses: 2.0.1 + unpipe: 1.0.0 + transitivePeerDependencies: + - supports-color + + follow-redirects@1.15.9(debug@4.4.0): + optionalDependencies: + debug: 4.4.0 + foreground-child@3.3.1: dependencies: cross-spawn: 7.0.6 signal-exit: 4.1.0 + form-data@4.0.2: + dependencies: + asynckit: 0.4.0 + combined-stream: 1.0.8 + es-set-tostringtag: 2.1.0 + mime-types: 2.1.35 + + forwarded@0.2.0: {} + fraction.js@4.3.7: {} + fresh@0.5.2: {} + + fs-constants@1.0.0: {} + fs-extra@10.1.0: dependencies: graceful-fs: 4.2.11 jsonfile: 6.1.0 universalify: 2.0.1 + fs-extra@11.3.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fs.realpath@1.0.0: {} fsevents@2.3.3: @@ -4833,8 +9206,28 @@ snapshots: function-bind@1.1.2: {} + get-caller-file@2.0.5: {} + + get-intrinsic@1.3.0: + dependencies: + call-bind-apply-helpers: 1.0.2 + es-define-property: 1.0.1 + es-errors: 1.3.0 + es-object-atoms: 1.1.1 + function-bind: 1.1.2 + get-proto: 1.0.1 + gopd: 1.2.0 + has-symbols: 1.1.0 + hasown: 2.0.2 + math-intrinsics: 1.1.0 + get-nonce@1.0.1: {} + get-proto@1.0.1: + dependencies: + dunder-proto: 1.0.1 + es-object-atoms: 1.1.1 + get-stream@6.0.1: {} get-uri@6.0.4: @@ -4845,6 +9238,8 @@ snapshots: transitivePeerDependencies: - supports-color + github-from-package@0.0.0: {} + glob-parent@5.1.2: dependencies: is-glob: 4.0.3 @@ -4873,6 +9268,11 @@ snapshots: once: 1.4.0 path-is-absolute: 1.0.1 + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + globby@10.0.2: dependencies: '@types/glob': 7.2.0 @@ -4884,6 +9284,10 @@ snapshots: merge2: 1.4.1 slash: 3.0.0 + google-protobuf@3.21.4: {} + + gopd@1.2.0: {} + graceful-fs@4.2.11: {} gradient-string@2.0.2: @@ -4891,6 +9295,15 @@ snapshots: chalk: 4.1.2 tinygradient: 1.1.5 + graphql-tag@2.12.6(graphql@16.10.0): + dependencies: + graphql: 16.10.0 + tslib: 2.8.1 + + graphql.js@0.6.8: {} + + graphql@16.10.0: {} + handlebars@4.7.8: dependencies: minimist: 1.2.8 @@ -4904,6 +9317,27 @@ snapshots: has-flag@4.0.0: {} + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + + has-symbols@1.1.0: {} + + has-tostringtag@1.0.2: + dependencies: + has-symbols: 1.1.0 + + hash-base@3.1.0: + dependencies: + inherits: 2.0.4 + readable-stream: 3.6.2 + safe-buffer: 5.2.1 + + hash.js@1.1.7: + dependencies: + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + hasown@2.0.2: dependencies: function-bind: 1.1.2 @@ -4913,6 +9347,24 @@ snapshots: no-case: 2.3.2 upper-case: 1.1.3 + hmac-drbg@1.0.1: + dependencies: + hash.js: 1.1.7 + minimalistic-assert: 1.0.1 + minimalistic-crypto-utils: 1.0.1 + + hoist-non-react-statics@3.3.2: + dependencies: + react-is: 16.13.1 + + http-errors@2.0.0: + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + http-proxy-agent@7.0.2: dependencies: agent-base: 7.1.3 @@ -4989,11 +9441,15 @@ snapshots: internmap@2.0.3: {} + interpret@1.4.0: {} + ip-address@9.0.5: dependencies: jsbn: 1.1.0 sprintf-js: 1.1.3 + ipaddr.js@1.9.1: {} + is-arrayish@0.3.2: optional: true @@ -5013,6 +9469,8 @@ snapshots: dependencies: is-extglob: 2.1.1 + is-hex-prefixed@1.0.0: {} + is-interactive@1.0.0: {} is-lower-case@1.1.3: @@ -5033,10 +9491,18 @@ snapshots: dependencies: upper-case: 1.1.3 + isarray@0.0.1: {} + + isarray@1.0.0: {} + isbinaryfile@4.0.10: {} isexe@2.0.0: {} + isomorphic-ws@4.0.1(ws@7.5.10): + dependencies: + ws: 7.5.10 + jackspeak@3.4.3: dependencies: '@isaacs/cliui': 8.0.2 @@ -5047,10 +9513,21 @@ snapshots: jiti@2.4.2: {} + joycon@3.1.1: {} + js-cookie@3.0.5: {} + js-sha256@0.9.0: {} + + js-sha3@0.8.0: {} + js-tokens@4.0.0: {} + js-yaml@3.14.1: + dependencies: + argparse: 1.0.10 + esprima: 4.0.1 + js-yaml@4.1.0: dependencies: argparse: 2.0.1 @@ -5063,48 +9540,96 @@ snapshots: optionalDependencies: graceful-fs: 4.2.11 - lefthook-darwin-arm64@1.11.3: + jsonwebtoken@9.0.2: + dependencies: + jws: 3.2.2 + lodash.includes: 4.3.0 + lodash.isboolean: 3.0.3 + lodash.isinteger: 4.0.4 + lodash.isnumber: 3.0.3 + lodash.isplainobject: 4.0.6 + lodash.isstring: 4.0.1 + lodash.once: 4.1.1 + ms: 2.1.3 + semver: 7.7.1 + + junk@3.1.0: {} + + jwa@1.4.1: + dependencies: + buffer-equal-constant-time: 1.0.1 + ecdsa-sig-formatter: 1.0.11 + safe-buffer: 5.2.1 + + jws@3.2.2: + dependencies: + jwa: 1.4.1 + safe-buffer: 5.2.1 + + keccak@3.0.4: + dependencies: + node-addon-api: 2.0.2 + node-gyp-build: 4.8.4 + readable-stream: 3.6.2 + + keygrip@1.1.0: + dependencies: + tsscmp: 1.0.6 + + lefthook-darwin-arm64@1.11.2: optional: true - lefthook-darwin-x64@1.11.3: + lefthook-darwin-x64@1.11.2: optional: true - lefthook-freebsd-arm64@1.11.3: + lefthook-freebsd-arm64@1.11.2: optional: true - lefthook-freebsd-x64@1.11.3: + lefthook-freebsd-x64@1.11.2: optional: true - lefthook-linux-arm64@1.11.3: + lefthook-linux-arm64@1.11.2: optional: true - lefthook-linux-x64@1.11.3: + lefthook-linux-x64@1.11.2: optional: true - lefthook-openbsd-arm64@1.11.3: + lefthook-openbsd-arm64@1.11.2: optional: true - lefthook-openbsd-x64@1.11.3: + lefthook-openbsd-x64@1.11.2: optional: true - lefthook-windows-arm64@1.11.3: + lefthook-windows-arm64@1.11.2: optional: true - lefthook-windows-x64@1.11.3: + lefthook-windows-x64@1.11.2: optional: true - lefthook@1.11.3: + lefthook@1.11.2: optionalDependencies: - lefthook-darwin-arm64: 1.11.3 - lefthook-darwin-x64: 1.11.3 - lefthook-freebsd-arm64: 1.11.3 - lefthook-freebsd-x64: 1.11.3 - lefthook-linux-arm64: 1.11.3 - lefthook-linux-x64: 1.11.3 - lefthook-openbsd-arm64: 1.11.3 - lefthook-openbsd-x64: 1.11.3 - lefthook-windows-arm64: 1.11.3 - lefthook-windows-x64: 1.11.3 + lefthook-darwin-arm64: 1.11.2 + lefthook-darwin-x64: 1.11.2 + lefthook-freebsd-arm64: 1.11.2 + lefthook-freebsd-x64: 1.11.2 + lefthook-linux-arm64: 1.11.2 + lefthook-linux-x64: 1.11.2 + lefthook-openbsd-arm64: 1.11.2 + lefthook-openbsd-x64: 1.11.2 + lefthook-windows-arm64: 1.11.2 + lefthook-windows-x64: 1.11.2 + + libsodium-sumo@0.7.15: {} + + libsodium-wrappers-sumo@0.7.15: + dependencies: + libsodium-sumo: 0.7.15 + + libsodium-wrappers@0.7.15: + dependencies: + libsodium: 0.7.15 + + libsodium@0.7.15: {} lightningcss-darwin-arm64@1.29.2: optional: true @@ -5155,8 +9680,34 @@ snapshots: lines-and-columns@1.2.4: {} + link-module-alias@1.2.0: + dependencies: + chalk: 2.4.2 + + load-tsconfig@0.2.5: {} + + lodash-clean@2.2.3: + dependencies: + lodash: 4.17.21 + lodash.get@4.4.2: {} + lodash.includes@4.3.0: {} + + lodash.isboolean@3.0.3: {} + + lodash.isinteger@4.0.4: {} + + lodash.isnumber@3.0.3: {} + + lodash.isplainobject@4.0.6: {} + + lodash.isstring@4.0.1: {} + + lodash.once@4.1.1: {} + + lodash.sortby@4.7.0: {} + lodash@4.17.21: {} log-symbols@3.0.0: @@ -5168,6 +9719,10 @@ snapshots: chalk: 4.1.2 is-unicode-supported: 0.1.0 + loglevel@1.9.2: {} + + long@4.0.0: {} + loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -5180,31 +9735,67 @@ snapshots: lower-case@2.0.2: dependencies: - tslib: 2.4.1 + tslib: 2.8.1 lru-cache@10.4.3: {} + lru-cache@6.0.0: + dependencies: + yallist: 4.0.0 + + lru-cache@7.13.1: {} + lru-cache@7.18.3: {} lucide-react@0.477.0(react@19.0.0): dependencies: react: 19.0.0 + luxon@3.5.0: {} + make-error@1.3.6: {} map-obj@4.3.0: {} + math-intrinsics@1.1.0: {} + + md5.js@1.3.5: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + safe-buffer: 5.2.1 + + media-typer@0.3.0: {} + + merge-descriptors@1.0.3: {} + merge-stream@2.0.0: {} merge2@1.4.1: {} + methods@1.1.2: {} + micromatch@4.0.8: dependencies: braces: 3.0.3 picomatch: 2.3.1 + mime-db@1.52.0: {} + + mime-types@2.1.35: + dependencies: + mime-db: 1.52.0 + + mime@1.6.0: {} + mimic-fn@2.1.0: {} + mimic-response@3.1.0: {} + + minimalistic-assert@1.0.1: {} + + minimalistic-crypto-utils@1.0.1: {} + minimatch@3.1.2: dependencies: brace-expansion: 1.1.11 @@ -5217,12 +9808,20 @@ snapshots: minipass@7.1.2: {} + mkdirp-classic@0.5.3: {} + mkdirp@0.5.6: dependencies: minimist: 1.2.8 + mkdirp@1.0.4: {} + + ms@2.0.0: {} + ms@2.1.3: {} + multiformats@9.9.0: {} + mute-stream@0.0.8: {} mz@2.7.0: @@ -5231,7 +9830,15 @@ snapshots: object-assign: 4.1.1 thenify-all: 1.6.0 - nanoid@3.3.9: {} + nan@2.22.2: {} + + nanoid-dictionary@5.0.0-beta.1: {} + + nanoid@3.3.8: {} + + napi-build-utils@2.0.0: {} + + negotiator@0.6.3: {} neo-async@2.6.2: {} @@ -5274,7 +9881,23 @@ snapshots: no-case@3.0.4: dependencies: lower-case: 2.0.2 - tslib: 2.4.1 + tslib: 2.8.1 + + node-abi@3.74.0: + dependencies: + semver: 7.7.1 + + node-abort-controller@3.1.1: {} + + node-addon-api@2.0.2: {} + + node-addon-api@5.1.0: {} + + node-fetch@2.7.0: + dependencies: + whatwg-url: 5.0.0 + + node-gyp-build@4.8.4: {} node-plop@0.26.3: dependencies: @@ -5292,6 +9915,18 @@ snapshots: node-releases@2.0.19: {} + node-yaml@4.0.1(js-yaml@3.14.1): + dependencies: + co: 4.6.0 + js-yaml: 3.14.1 + junk: 3.1.0 + promise-fs: 2.1.1 + + noms@0.0.0: + dependencies: + inherits: 2.0.4 + readable-stream: 1.0.34 + normalize-path@3.0.0: {} normalize-range@0.1.2: {} @@ -5304,6 +9939,29 @@ snapshots: object-hash@3.0.0: {} + object-inspect@1.13.4: {} + + object-keys@1.1.1: {} + + octokit@3.2.1: + dependencies: + '@octokit/app': 14.1.0 + '@octokit/core': 5.2.0 + '@octokit/oauth-app': 6.1.0 + '@octokit/plugin-paginate-graphql': 4.0.1(@octokit/core@5.2.0) + '@octokit/plugin-paginate-rest': 11.3.1(@octokit/core@5.2.0) + '@octokit/plugin-rest-endpoint-methods': 13.2.2(@octokit/core@5.2.0) + '@octokit/plugin-retry': 6.1.0(@octokit/core@5.2.0) + '@octokit/plugin-throttling': 8.2.0(@octokit/core@5.2.0) + '@octokit/request-error': 5.1.1 + '@octokit/types': 13.8.0 + + on-finished@2.4.1: + dependencies: + ee-first: 1.1.1 + + on-headers@1.0.2: {} + once@1.4.0: dependencies: wrappy: 1.0.2 @@ -5312,6 +9970,15 @@ snapshots: dependencies: mimic-fn: 2.1.0 + openpgp@6.1.0: {} + + optimism@0.18.1: + dependencies: + '@wry/caches': 1.0.1 + '@wry/context': 0.7.4 + '@wry/trie': 0.5.0 + tslib: 2.8.1 + ora@4.1.1: dependencies: chalk: 3.0.0 @@ -5365,6 +10032,8 @@ snapshots: dependencies: no-case: 2.3.2 + parseurl@1.3.3: {} + pascal-case@2.0.1: dependencies: camel-case: 3.0.0 @@ -5385,14 +10054,26 @@ snapshots: lru-cache: 10.4.3 minipass: 7.1.2 + path-to-regexp@0.1.12: {} + path-type@4.0.0: {} + pbkdf2@3.1.2: + dependencies: + create-hash: 1.2.0 + create-hmac: 1.1.7 + ripemd160: 2.0.2 + safe-buffer: 5.2.1 + sha.js: 2.4.11 + picocolors@1.0.1: {} picocolors@1.1.1: {} picomatch@2.3.1: {} + picomatch@4.0.2: {} + pify@2.3.0: {} pirates@4.0.6: {} @@ -5425,6 +10106,14 @@ snapshots: postcss: 8.5.3 ts-node: 10.9.2(@types/node@22.13.9)(typescript@5.8.2) + postcss-load-config@6.0.1(jiti@2.4.2)(postcss@8.5.3)(yaml@2.7.0): + dependencies: + lilconfig: 3.1.3 + optionalDependencies: + jiti: 2.4.2 + postcss: 8.5.3 + yaml: 2.7.0 + postcss-nested@6.2.0(postcss@8.5.3): dependencies: postcss: 8.5.3 @@ -5439,22 +10128,66 @@ snapshots: postcss@8.4.31: dependencies: - nanoid: 3.3.9 + nanoid: 3.3.8 picocolors: 1.1.1 source-map-js: 1.2.1 postcss@8.5.3: dependencies: - nanoid: 3.3.9 + nanoid: 3.3.8 picocolors: 1.1.1 source-map-js: 1.2.1 + prebuild-install@7.1.3: + dependencies: + detect-libc: 2.0.3 + expand-template: 2.0.3 + github-from-package: 0.0.0 + minimist: 1.2.8 + mkdirp-classic: 0.5.3 + napi-build-utils: 2.0.0 + node-abi: 3.74.0 + pump: 3.0.2 + rc: 1.2.8 + simple-get: 4.0.1 + tar-fs: 2.1.2 + tunnel-agent: 0.6.0 + + prettier@3.5.3: {} + + process-nextick-args@2.0.1: {} + + promise-fs@2.1.1: + dependencies: + '@octetstream/promisify': 2.0.2 + prop-types@15.8.1: dependencies: loose-envify: 1.4.0 object-assign: 4.1.1 react-is: 16.13.1 + protobufjs@6.11.4: + dependencies: + '@protobufjs/aspromise': 1.1.2 + '@protobufjs/base64': 1.1.2 + '@protobufjs/codegen': 2.0.4 + '@protobufjs/eventemitter': 1.1.0 + '@protobufjs/fetch': 1.1.0 + '@protobufjs/float': 1.0.2 + '@protobufjs/inquire': 1.1.0 + '@protobufjs/path': 1.1.2 + '@protobufjs/pool': 1.1.0 + '@protobufjs/utf8': 1.1.0 + '@types/long': 4.0.2 + '@types/node': 20.17.23 + long: 4.0.0 + + proxy-addr@2.0.7: + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + proxy-agent@6.5.0: dependencies: agent-base: 7.1.3 @@ -5470,8 +10203,34 @@ snapshots: proxy-from-env@1.1.0: {} + pump@3.0.2: + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + + punycode@2.3.1: {} + + qs@6.13.0: + dependencies: + side-channel: 1.1.0 + queue-microtask@1.2.3: {} + random-bytes@1.0.0: {} + + randombytes@2.1.0: + dependencies: + safe-buffer: 5.2.1 + + range-parser@1.2.1: {} + + raw-body@2.5.2: + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + rc@1.2.8: dependencies: deep-extend: 0.6.0 @@ -5552,6 +10311,23 @@ snapshots: dependencies: pify: 2.3.0 + readable-stream@1.0.34: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 0.0.1 + string_decoder: 0.10.31 + + readable-stream@2.3.8: + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + readable-stream@3.6.2: dependencies: inherits: 2.0.4 @@ -5562,6 +10338,10 @@ snapshots: dependencies: picomatch: 2.3.1 + readdirp@4.1.2: {} + + readonly-date@1.0.0: {} + recharts-scale@0.4.5: dependencies: decimal.js-light: 2.5.1 @@ -5579,6 +10359,12 @@ snapshots: tiny-invariant: 1.3.3 victory-vendor: 36.9.2 + rechoir@0.6.2: + dependencies: + resolve: 1.22.10 + + reflect-metadata@0.2.2: {} + regenerator-runtime@0.14.1: {} registry-auth-token@3.3.2: @@ -5590,6 +10376,15 @@ snapshots: dependencies: rc: 1.2.8 + rehackt@0.1.0(@types/react@18.3.0)(react@19.0.0): + optionalDependencies: + '@types/react': 18.3.0 + react: 19.0.0 + + require-directory@2.1.1: {} + + resolve-from@5.0.0: {} + resolve@1.22.10: dependencies: is-core-module: 2.16.1 @@ -5601,12 +10396,50 @@ snapshots: onetime: 5.1.2 signal-exit: 3.0.7 + retry@0.13.1: {} + reusify@1.1.0: {} rimraf@3.0.2: dependencies: glob: 7.2.3 + ripemd160-min@0.0.6: {} + + ripemd160@2.0.2: + dependencies: + hash-base: 3.1.0 + inherits: 2.0.4 + + rlp@2.2.7: + dependencies: + bn.js: 5.2.1 + + rollup@4.34.9: + dependencies: + '@types/estree': 1.0.6 + optionalDependencies: + '@rollup/rollup-android-arm-eabi': 4.34.9 + '@rollup/rollup-android-arm64': 4.34.9 + '@rollup/rollup-darwin-arm64': 4.34.9 + '@rollup/rollup-darwin-x64': 4.34.9 + '@rollup/rollup-freebsd-arm64': 4.34.9 + '@rollup/rollup-freebsd-x64': 4.34.9 + '@rollup/rollup-linux-arm-gnueabihf': 4.34.9 + '@rollup/rollup-linux-arm-musleabihf': 4.34.9 + '@rollup/rollup-linux-arm64-gnu': 4.34.9 + '@rollup/rollup-linux-arm64-musl': 4.34.9 + '@rollup/rollup-linux-loongarch64-gnu': 4.34.9 + '@rollup/rollup-linux-powerpc64le-gnu': 4.34.9 + '@rollup/rollup-linux-riscv64-gnu': 4.34.9 + '@rollup/rollup-linux-s390x-gnu': 4.34.9 + '@rollup/rollup-linux-x64-gnu': 4.34.9 + '@rollup/rollup-linux-x64-musl': 4.34.9 + '@rollup/rollup-win32-arm64-msvc': 4.34.9 + '@rollup/rollup-win32-ia32-msvc': 4.34.9 + '@rollup/rollup-win32-x64-msvc': 4.34.9 + fsevents: 2.3.3 + run-async@2.4.1: {} run-parallel@1.2.0: @@ -5621,24 +10454,75 @@ snapshots: dependencies: tslib: 2.8.1 + safe-buffer@5.1.2: {} + safe-buffer@5.2.1: {} safer-buffer@2.1.2: {} scheduler@0.25.0: {} + scrypt-js@3.0.1: {} + + secp256k1@4.0.4: + dependencies: + elliptic: 6.6.1 + node-addon-api: 5.1.0 + node-gyp-build: 4.8.4 + semver@7.6.2: {} - semver@7.7.1: - optional: true + semver@7.7.1: {} + + send@0.19.0: + dependencies: + debug: 2.6.9 + depd: 2.0.0 + destroy: 1.2.0 + encodeurl: 1.0.2 + escape-html: 1.0.3 + etag: 1.8.1 + fresh: 0.5.2 + http-errors: 2.0.0 + mime: 1.6.0 + ms: 2.1.3 + on-finished: 2.4.1 + range-parser: 1.2.1 + statuses: 2.0.1 + transitivePeerDependencies: + - supports-color sentence-case@2.1.1: dependencies: no-case: 2.3.2 upper-case-first: 1.1.2 + serve-static@1.16.2: + dependencies: + encodeurl: 2.0.0 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.19.0 + transitivePeerDependencies: + - supports-color + server-only@0.0.1: {} + setimmediate@1.0.5: {} + + setprototypeof@1.2.0: {} + + sha.js@2.4.11: + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + + sha256-uint8array@0.10.7: {} + + sha3@2.1.4: + dependencies: + buffer: 6.0.3 + sharp@0.33.5: dependencies: color: 4.2.3 @@ -5672,15 +10556,68 @@ snapshots: shebang-regex@3.0.0: {} + shelljs@0.8.5: + dependencies: + glob: 7.2.3 + interpret: 1.4.0 + rechoir: 0.6.2 + + shx@0.3.4: + dependencies: + minimist: 1.2.8 + shelljs: 0.8.5 + + side-channel-list@1.0.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + + side-channel-map@1.0.1: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + + side-channel-weakmap@1.0.2: + dependencies: + call-bound: 1.0.4 + es-errors: 1.3.0 + get-intrinsic: 1.3.0 + object-inspect: 1.13.4 + side-channel-map: 1.0.1 + + side-channel@1.1.0: + dependencies: + es-errors: 1.3.0 + object-inspect: 1.13.4 + side-channel-list: 1.0.0 + side-channel-map: 1.0.1 + side-channel-weakmap: 1.0.2 + signal-exit@3.0.7: {} signal-exit@4.1.0: {} + simple-concat@1.0.1: {} + + simple-get@4.0.1: + dependencies: + decompress-response: 6.0.0 + once: 1.4.0 + simple-concat: 1.0.1 + simple-swizzle@0.2.2: dependencies: is-arrayish: 0.3.2 optional: true + siwe@3.0.0(ethers@5.8.0): + dependencies: + '@spruceid/siwe-parser': 3.0.0 + '@stablelib/random': 1.0.2 + ethers: 5.8.0 + slash@3.0.0: {} smart-buffer@4.2.0: {} @@ -5692,7 +10629,7 @@ snapshots: snake-case@3.0.4: dependencies: dot-case: 3.0.4 - tslib: 2.4.1 + tslib: 2.8.1 snakecase-keys@8.0.1: dependencies: @@ -5722,8 +10659,18 @@ snapshots: source-map@0.6.1: {} + source-map@0.8.0-beta.0: + dependencies: + whatwg-url: 7.1.0 + + sprintf-js@1.0.3: {} + sprintf-js@1.1.3: {} + sql-highlight@6.0.0: {} + + statuses@2.0.1: {} + std-env@3.8.1: {} streamsearch@1.1.0: {} @@ -5740,6 +10687,12 @@ snapshots: emoji-regex: 9.2.2 strip-ansi: 7.1.0 + string_decoder@0.10.31: {} + + string_decoder@1.1.1: + dependencies: + safe-buffer: 5.1.2 + string_decoder@1.3.0: dependencies: safe-buffer: 5.2.1 @@ -5754,6 +10707,10 @@ snapshots: strip-final-newline@2.0.0: {} + strip-hex-prefix@1.0.0: + dependencies: + is-hex-prefixed: 1.0.0 + strip-json-comments@2.0.1: {} styled-jsx@5.1.6(react@19.0.0): @@ -5792,6 +10749,10 @@ snapshots: react: 19.0.0 use-sync-external-store: 1.4.0(react@19.0.0) + symbol-observable@2.0.3: {} + + symbol-observable@4.0.0: {} + tailwind-merge@3.0.2: {} tailwindcss-animate@1.0.7(tailwindcss@3.4.17(ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2))): @@ -5852,10 +10813,25 @@ snapshots: transitivePeerDependencies: - ts-node - tailwindcss@4.0.12: {} + tailwindcss@4.0.11: {} tapable@2.2.1: {} + tar-fs@2.1.2: + dependencies: + chownr: 1.1.4 + mkdirp-classic: 0.5.3 + pump: 3.0.2 + tar-stream: 2.2.0 + + tar-stream@2.2.0: + dependencies: + bl: 4.1.0 + end-of-stream: 1.4.4 + fs-constants: 1.0.0 + inherits: 2.0.4 + readable-stream: 3.6.2 + thenify-all@1.6.0: dependencies: thenify: 3.3.1 @@ -5864,12 +10840,32 @@ snapshots: dependencies: any-promise: 1.3.0 + through2@2.0.5: + dependencies: + readable-stream: 2.3.8 + xtend: 4.0.2 + through@2.3.8: {} tiny-invariant@1.3.3: {} + tiny-secp256k1@1.1.7: + dependencies: + bindings: 1.5.0 + bn.js: 4.12.1 + create-hmac: 1.1.7 + elliptic: 6.6.1 + nan: 2.22.2 + tinycolor2@1.6.0: {} + tinyexec@0.3.2: {} + + tinyglobby@0.2.12: + dependencies: + fdir: 6.4.3(picomatch@4.0.2) + picomatch: 4.0.2 + tinygradient@1.1.5: dependencies: '@types/tinycolor2': 1.4.6 @@ -5888,8 +10884,24 @@ snapshots: dependencies: is-number: 7.0.0 + toidentifier@1.0.1: {} + + toml@3.0.0: {} + + tr46@0.0.3: {} + + tr46@1.0.1: + dependencies: + punycode: 2.3.1 + + tree-kill@1.2.2: {} + ts-interface-checker@0.1.13: {} + ts-invariant@0.10.3: + dependencies: + tslib: 2.8.1 + ts-node@10.9.2(@types/node@20.17.23)(typescript@5.8.2): dependencies: '@cspotcode/source-map-support': 0.8.1 @@ -5907,7 +10919,6 @@ snapshots: typescript: 5.8.2 v8-compile-cache-lib: 3.0.1 yn: 3.1.1 - optional: true ts-node@10.9.2(@types/node@22.13.9)(typescript@5.8.2): dependencies: @@ -5933,6 +10944,39 @@ snapshots: tslib@2.8.1: {} + tsscmp@1.0.6: {} + + tsup@8.4.0(jiti@2.4.2)(postcss@8.5.3)(typescript@5.8.2)(yaml@2.7.0): + dependencies: + bundle-require: 5.1.0(esbuild@0.25.0) + cac: 6.7.14 + chokidar: 4.0.3 + consola: 3.4.0 + debug: 4.4.0 + esbuild: 0.25.0 + joycon: 3.1.1 + picocolors: 1.1.1 + postcss-load-config: 6.0.1(jiti@2.4.2)(postcss@8.5.3)(yaml@2.7.0) + resolve-from: 5.0.0 + rollup: 4.34.9 + source-map: 0.8.0-beta.0 + sucrase: 3.35.0 + tinyexec: 0.3.2 + tinyglobby: 0.2.12 + tree-kill: 1.2.2 + optionalDependencies: + postcss: 8.5.3 + typescript: 5.8.2 + transitivePeerDependencies: + - jiti + - supports-color + - tsx + - yaml + + tunnel-agent@0.6.0: + dependencies: + safe-buffer: 5.2.1 + turbo-darwin-64@2.4.4: optional: true @@ -5960,23 +11004,71 @@ snapshots: turbo-windows-64: 2.4.4 turbo-windows-arm64: 2.4.4 + tweetnacl-util@0.15.1: {} + + tweetnacl@1.0.3: {} + type-fest@0.21.3: {} type-fest@4.37.0: {} + type-is@1.6.18: + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + + typeforce@1.18.0: {} + + typeorm@0.3.21(better-sqlite3@9.6.0)(reflect-metadata@0.2.2)(ts-node@10.9.2(@types/node@20.17.23)(typescript@5.8.2)): + dependencies: + '@sqltools/formatter': 1.2.5 + ansis: 3.17.0 + app-root-path: 3.1.0 + buffer: 6.0.3 + dayjs: 1.11.13 + debug: 4.4.0 + dotenv: 16.4.7 + glob: 10.4.5 + reflect-metadata: 0.2.2 + sha.js: 2.4.11 + sql-highlight: 6.0.0 + tslib: 2.8.1 + uuid: 11.1.0 + yargs: 17.7.2 + optionalDependencies: + better-sqlite3: 9.6.0 + ts-node: 10.9.2(@types/node@20.17.23)(typescript@5.8.2) + transitivePeerDependencies: + - supports-color + typescript@5.8.2: {} uglify-js@3.19.3: optional: true + uid-safe@2.1.5: + dependencies: + random-bytes: 1.0.0 + undici-types@6.19.8: {} undici-types@6.20.0: {} + universal-github-app-jwt@1.2.0: + dependencies: + '@types/jsonwebtoken': 9.0.9 + jsonwebtoken: 9.0.2 + + universal-user-agent@6.0.1: {} + universal-user-agent@7.0.2: {} universalify@2.0.1: {} + unpipe@1.0.0: {} + + untildify@4.0.0: {} + update-browserslist-db@1.1.3(browserslist@4.24.4): dependencies: browserslist: 4.24.4 @@ -6015,10 +11107,22 @@ snapshots: util-deprecate@1.0.2: {} + utils-merge@1.0.1: {} + + uuid@11.1.0: {} + + uuid@9.0.1: {} + v8-compile-cache-lib@3.0.1: {} validate-npm-package-name@5.0.1: {} + value-or-promise@1.0.11: {} + + value-or-promise@1.0.12: {} + + vary@1.1.2: {} + vaul@1.1.2(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0): dependencies: '@radix-ui/react-dialog': 1.1.6(@types/react-dom@18.3.1)(@types/react@18.3.0)(react-dom@19.0.0(react@19.0.0))(react@19.0.0) @@ -6049,12 +11153,35 @@ snapshots: dependencies: defaults: 1.0.4 + webidl-conversions@3.0.1: {} + + webidl-conversions@4.0.2: {} + + whatwg-mimetype@3.0.0: {} + + whatwg-url@5.0.0: + dependencies: + tr46: 0.0.3 + webidl-conversions: 3.0.1 + + whatwg-url@7.1.0: + dependencies: + lodash.sortby: 4.7.0 + tr46: 1.0.1 + webidl-conversions: 4.0.2 + which@2.0.2: dependencies: isexe: 2.0.0 + wif@2.0.6: + dependencies: + bs58check: 2.1.2 + wordwrap@1.0.0: {} + workspace@0.0.1-preview.2: {} + wrap-ansi@6.2.0: dependencies: ansi-styles: 4.3.0 @@ -6075,10 +11202,60 @@ snapshots: wrappy@1.0.2: {} + ws@7.5.10: {} + + ws@8.18.0: {} + + xss@1.0.15: + dependencies: + commander: 2.20.3 + cssfilter: 0.0.10 + + xstream@11.14.0: + dependencies: + globalthis: 1.0.4 + symbol-observable: 2.0.3 + + xtend@4.0.2: {} + + y18n@5.0.8: {} + + yallist@4.0.0: {} + yaml@2.7.0: {} + yargs-parser@20.2.9: {} + + yargs-parser@21.1.1: {} + + yargs@16.2.0: + dependencies: + cliui: 7.0.4 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + + yargs@17.7.2: + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + yn@3.1.1: {} + zen-observable-ts@1.2.5: + dependencies: + zen-observable: 0.8.15 + + zen-observable@0.8.15: {} + zod@3.24.2: {} zustand@5.0.3(@types/react@18.3.0)(react@19.0.0)(use-sync-external-store@1.4.0(react@19.0.0)): diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index b697e5b..d6e82b1 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -2,13 +2,25 @@ packages: - apps/* - services/* onlyBuiltDependencies: + - '@apollo/protobufjs' - '@biomejs/biome' - '@biomejs/cli-darwin-arm64' + - '@tharsis/address-converter' + - '@tharsis/eip712' + - '@tharsis/proto' + - '@tharsis/provider' + - '@tharsis/transactions' + - better-sqlite3 - chalk - core-js-pure + - esbuild + - keccak - lefthook - lefthook-darwin-arm64 + - protobufjs + - secp256k1 - sharp + - tiny-secp256k1 - tree-sitter - tree-sitter-javascript - tree-sitter-typescript diff --git a/services/gql-client/biome.json b/services/gql-client/biome.json new file mode 100644 index 0000000..0b8bb44 --- /dev/null +++ b/services/gql-client/biome.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", + "extends": ["../../biome.json"], + "files": { + "ignore": ["node_modules", "dist", ".turbo"] + } +} diff --git a/services/gql-client/package.json b/services/gql-client/package.json new file mode 100644 index 0000000..a6a68e9 --- /dev/null +++ b/services/gql-client/package.json @@ -0,0 +1,23 @@ +{ + "name": "@workspace/gql-client", + "license": "UNLICENSED", + "version": "0.0.1", + "private": true, + "main": "./dist/index.js", + "module": "./dist/index.mjs", + "types": "./dist/index.d.ts", + "scripts": { + "build": "tsup", + "dev": "tsup --watch", + "lint": "biome check .", + "format": "biome format . --write" + }, + "devDependencies": { + "@types/node": "^20.11.4", + "tsup": "^8.0.2", + "typescript": "^5.3.3" + }, + "dependencies": { + "@apollo/client": "^3.8.9" + } +} diff --git a/services/gql-client/src/client.ts b/services/gql-client/src/client.ts new file mode 100644 index 0000000..bea2f99 --- /dev/null +++ b/services/gql-client/src/client.ts @@ -0,0 +1,473 @@ +import { + ApolloClient, + type DefaultOptions, + InMemoryCache, + type NormalizedCacheObject +} from '@apollo/client' + +import * as mutations from './mutations' +import * as queries from './queries' +import type * as types from './types' + +export interface GraphQLConfig { + gqlEndpoint: string +} + +// TODO: check options +const defaultOptions: DefaultOptions = { + watchQuery: { + fetchPolicy: 'no-cache', + errorPolicy: 'ignore' + }, + query: { + fetchPolicy: 'no-cache', + errorPolicy: 'all' + } +} + +export class GQLClient { + private client: ApolloClient + + constructor(config: GraphQLConfig) { + this.client = new ApolloClient({ + uri: config.gqlEndpoint, + cache: new InMemoryCache(), + defaultOptions, + credentials: 'include' + }) + } + + async getUser(): Promise { + const { data } = await this.client.query({ + query: queries.getUser + }) + + return data + } + + async getProject(projectId: string): Promise { + const { data } = await this.client.query({ + query: queries.getProject, + variables: { + projectId + } + }) + + return data + } + + async getProjectsInOrganization( + organizationSlug: string + ): Promise { + const { data } = await this.client.query({ + query: queries.getProjectsInOrganization, + variables: { + organizationSlug + } + }) + + return data + } + + async getOrganizations(): Promise { + const { data } = await this.client.query({ + query: queries.getOrganizations + }) + + return data + } + + async getDeployments( + projectId: string + ): Promise { + const { data } = await this.client.query({ + query: queries.getDeployments, + variables: { + projectId + } + }) + + return data + } + + async getEnvironmentVariables( + projectId: string + ): Promise { + const { data } = await this.client.query({ + query: queries.getEnvironmentVariables, + variables: { + projectId + } + }) + + return data + } + + async getProjectMembers( + projectId: string + ): Promise { + const result = await this.client.query({ + query: queries.getProjectMembers, + variables: { + projectId + } + }) + + return result.data + } + + async addProjectMember( + projectId: string, + data: types.AddProjectMemberInput + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.addProjectMember, + variables: { + projectId, + data + } + }) + + return result.data + } + + async updateProjectMember( + projectMemberId: string, + data: types.UpdateProjectMemberInput + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.updateProjectMember, + variables: { + projectMemberId, + data + } + }) + + return result.data + } + + async removeProjectMember( + projectMemberId: string + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.removeProjectMember, + variables: { + projectMemberId + } + }) + + return result.data + } + + async searchProjects( + searchText: string + ): Promise { + const { data } = await this.client.query({ + query: queries.searchProjects, + variables: { + searchText + } + }) + + return data + } + + async addEnvironmentVariables( + projectId: string, + data: types.AddEnvironmentVariableInput[] + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.addEnvironmentVariables, + variables: { + projectId, + data + } + }) + + return result.data + } + + async updateEnvironmentVariable( + environmentVariableId: string, + data: types.UpdateEnvironmentVariableInput + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.updateEnvironmentVariable, + variables: { + environmentVariableId, + data + } + }) + + return result.data + } + + async removeEnvironmentVariable( + environmentVariableId: string + ): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.removeEnvironmentVariable, + variables: { + environmentVariableId + } + }) + + return data + } + + async updateDeploymentToProd( + deploymentId: string + ): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.updateDeploymentToProd, + variables: { + deploymentId + } + }) + + return data + } + + async addProjectFromTemplate( + organizationSlug: string, + data: types.AddProjectFromTemplateInput, + lrn?: string, + auctionParams?: types.AuctionParams, + environmentVariables?: types.AddEnvironmentVariableInput[] + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.addProjectFromTemplate, + variables: { + organizationSlug, + data, + lrn, + auctionParams, + environmentVariables + } + }) + + return result.data + } + + async addProject( + organizationSlug: string, + data: types.AddProjectInput, + lrn?: string, + auctionParams?: types.AuctionParams, + environmentVariables?: types.AddEnvironmentVariableInput[] + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.addProject, + variables: { + organizationSlug, + data, + lrn, + auctionParams, + environmentVariables + } + }) + + return result.data + } + + async updateProject( + projectId: string, + data: types.UpdateProjectInput + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.updateProjectMutation, + variables: { + projectId, + data + } + }) + + return result.data + } + + async updateDomain( + domainId: string, + data: types.UpdateDomainInput + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.updateDomainMutation, + variables: { + domainId, + data + } + }) + + return result.data + } + + async redeployToProd( + deploymentId: string + ): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.redeployToProd, + variables: { + deploymentId + } + }) + + return data + } + + async deleteProject(projectId: string): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.deleteProject, + variables: { + projectId + } + }) + + return data + } + + async deleteDomain(domainId: string): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.deleteDomain, + variables: { + domainId + } + }) + + return data + } + + async rollbackDeployment( + projectId: string, + deploymentId: string + ): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.rollbackDeployment, + variables: { + projectId, + deploymentId + } + }) + + return data + } + + async deleteDeployment( + deploymentId: string + ): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.deleteDeployment, + variables: { + deploymentId + } + }) + + return data + } + + async addDomain( + projectId: string, + data: types.AddDomainInput + ): Promise { + const result = await this.client.mutate({ + mutation: mutations.addDomain, + variables: { + projectId, + data + } + }) + + return result.data + } + + async getDomains( + projectId: string, + filter?: types.FilterDomainInput + ): Promise { + const { data } = await this.client.query({ + query: queries.getDomains, + variables: { + projectId, + filter + } + }) + + return data + } + + async authenticateGitHub( + code: string + ): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.authenticateGitHub, + variables: { + code + } + }) + + return data + } + + async unauthenticateGithub(): Promise { + const { data } = await this.client.mutate({ + mutation: mutations.unauthenticateGitHub + }) + + return data + } + + async getAuctionData(auctionId: string): Promise { + const { data } = await this.client.query({ + query: queries.getAuctionData, + variables: { + auctionId + } + }) + + return data.getAuctionData + } + + async getDeployers(): Promise { + const { data } = await this.client.query({ + query: queries.getDeployers + }) + + return data + } + + async getAddress(): Promise { + const { data } = await this.client.query({ + query: queries.getAddress + }) + + return data.address + } + + async verifyTx( + txHash: string, + amount: string, + senderAddress: string + ): Promise { + const { data } = await this.client.query({ + query: queries.verifyTx, + variables: { + txHash, + amount, + senderAddress + } + }) + + return data.verifyTx + } + + async getLatestDNSRecordByProjectId( + projectId: string + ): Promise { + const { data } = await this.client.query({ + query: queries.getLatestDNSRecordByProjectId, + variables: { + projectId + } + }) + + return data + } +} diff --git a/services/gql-client/src/index.ts b/services/gql-client/src/index.ts new file mode 100644 index 0000000..edfed4a --- /dev/null +++ b/services/gql-client/src/index.ts @@ -0,0 +1,2 @@ +export * from './client' +export * from './types' diff --git a/services/gql-client/src/mutations.ts b/services/gql-client/src/mutations.ts new file mode 100644 index 0000000..d2ff0ee --- /dev/null +++ b/services/gql-client/src/mutations.ts @@ -0,0 +1,127 @@ +import { gql } from '@apollo/client' + +export const removeProjectMember = gql` + mutation ($projectMemberId: String!) { + removeProjectMember(projectMemberId: $projectMemberId) + } +` + +export const updateProjectMember = gql` + mutation ($projectMemberId: String!, $data: UpdateProjectMemberInput) { + updateProjectMember(projectMemberId: $projectMemberId, data: $data) + } +` + +export const addProjectMember = gql` + mutation ($projectId: String!, $data: AddProjectMemberInput) { + addProjectMember(projectId: $projectId, data: $data) + } +` + +export const addEnvironmentVariables = gql` + mutation ($projectId: String!, $data: [AddEnvironmentVariableInput!]) { + addEnvironmentVariables(projectId: $projectId, data: $data) + } +` + +export const updateEnvironmentVariable = gql` + mutation ( + $environmentVariableId: String! + $data: UpdateEnvironmentVariableInput! + ) { + updateEnvironmentVariable( + environmentVariableId: $environmentVariableId + data: $data + ) + } +` + +export const removeEnvironmentVariable = gql` + mutation ($environmentVariableId: String!) { + removeEnvironmentVariable(environmentVariableId: $environmentVariableId) + } +` + +export const updateDeploymentToProd = gql` + mutation ($deploymentId: String!) { + updateDeploymentToProd(deploymentId: $deploymentId) + } +` + +export const addProjectFromTemplate = gql` + mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput, $lrn: String, $auctionParams: AuctionParams, $environmentVariables: [AddEnvironmentVariableInput!]) { + addProjectFromTemplate(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionParams: $auctionParams, environmentVariables: $environmentVariables) { + id + } + } +` + +export const addProject = gql` + mutation ($organizationSlug: String!, $data: AddProjectInput!, $lrn: String, $auctionParams: AuctionParams, $environmentVariables: [AddEnvironmentVariableInput!]) { + addProject(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionParams: $auctionParams, environmentVariables: $environmentVariables) { + id + } + } +` + +export const updateProjectMutation = gql` + mutation ($projectId: String!, $data: UpdateProjectInput) { + updateProject(projectId: $projectId, data: $data) + } +` + +export const updateDomainMutation = gql` + mutation ($domainId: String!, $data: UpdateDomainInput!) { + updateDomain(domainId: $domainId, data: $data) + } +` + +export const redeployToProd = gql` + mutation ($deploymentId: String!) { + redeployToProd(deploymentId: $deploymentId) + } +` + +export const deleteProject = gql` + mutation ($projectId: String!) { + deleteProject(projectId: $projectId) + } +` + +export const deleteDomain = gql` + mutation ($domainId: String!) { + deleteDomain(domainId: $domainId) + } +` + +export const rollbackDeployment = gql` + mutation ($projectId: String!, $deploymentId: String!) { + rollbackDeployment(projectId: $projectId, deploymentId: $deploymentId) + } +` + +export const deleteDeployment = gql` + mutation ($deploymentId: String!) { + deleteDeployment(deploymentId: $deploymentId) + } +` + +export const addDomain = gql` + mutation ($projectId: String!, $data: AddDomainInput!) { + addDomain(projectId: $projectId, data: $data) + } +` + +export const authenticateGitHub = gql` + mutation ($code: String!) { + authenticateGitHub(code: $code) { + token + } + } +` + +export const unauthenticateGitHub = gql` + mutation { + unauthenticateGitHub + } +` diff --git a/services/gql-client/src/queries.ts b/services/gql-client/src/queries.ts new file mode 100644 index 0000000..d54f198 --- /dev/null +++ b/services/gql-client/src/queries.ts @@ -0,0 +1,339 @@ +import { gql } from '@apollo/client' + +export const getUser = gql` +query { + user { + id + name + email + createdAt + updatedAt + gitHubToken + } +} +` + +export const getProject = gql` +query ($projectId: String!) { + project(projectId: $projectId) { + createdAt + description + id + name + template + updatedAt + prodBranch + auctionId + deployers { + deployerLrn + deployerId + deployerApiUrl + minimumPayment + } + paymentAddress + txHash + fundsReleased + framework + repository + webhooks + icon + baseDomains + organization { + id + name + } + owner { + id + name + email + } + deployments { + id + branch + isCurrent + baseDomain + status + updatedAt + commitHash + createdAt + environment + applicationDeploymentRecordData { + url + } + deployer { + baseDomain + } + createdBy { + id + name + } + } + } +} +` + +export const getProjectsInOrganization = gql` +query ($organizationSlug: String!) { + projectsInOrganization(organizationSlug: $organizationSlug) { + id + name + createdAt + description + framework + auctionId + deployers { + deployerLrn + deployerId + deployerApiUrl + minimumPayment + } + paymentAddress + txHash + fundsReleased + prodBranch + webhooks + repository + updatedAt + icon + baseDomains + deployments { + id + branch + isCurrent + baseDomain + status + updatedAt + commitHash + commitMessage + createdAt + environment + applicationDeploymentRecordData { + url + } + } + } +} +` + +export const getOrganizations = gql` +query { + organizations { + id + name + slug + createdAt + updatedAt + } +} +` + +export const getDeployments = gql` +query ($projectId: String!) { + deployments(projectId: $projectId) { + id + branch + commitHash + commitMessage + url + deployer { + deployerLrn + deployerId + deployerApiUrl + minimumPayment + } + environment + isCurrent + baseDomain + status + createdAt + updatedAt + createdBy { + id + name + email + } + applicationDeploymentRequestId + } +} +` + +export const getEnvironmentVariables = gql` +query ($projectId: String!) { + environmentVariables(projectId: $projectId) { + createdAt + environment + id + key + updatedAt + value + } +} +` + +export const getProjectMembers = gql` +query ($projectId: String!) { + projectMembers(projectId: $projectId) { + id + member { + id + name + email + isVerified + } + isPending + createdAt + updatedAt + permissions + } +} +` + +export const searchProjects = gql` +query ($searchText: String!) { + searchProjects(searchText: $searchText) { + id + name + prodBranch + repository + createdAt + description + framework + auctionId + deployers { + deployerLrn + deployerId + deployerApiUrl + minimumPayment + } + paymentAddress + txHash + fundsReleased + prodBranch + webhooks + updatedAt + template + repository + organization { + id + name + slug + createdAt + updatedAt + } + } +} +` + +export const getDomains = gql` +query ($projectId: String!, $filter: FilterDomainsInput) { + domains(projectId: $projectId, filter: $filter) { + branch + createdAt + redirectTo { + id + name + branch + status + } + id + name + status + updatedAt + } +} +` + +export const getAuctionData = gql` +query ($auctionId: String!) { + getAuctionData(auctionId: $auctionId){ + id + kind + status + ownerAddress + createTime + commitsEndTime + revealsEndTime + commitFee { + type + quantity + } + revealFee { + type + quantity + } + minimumBid { + type + quantity + } + winnerAddresses + winnerBids { + type + quantity + } + winnerPrice { + type + quantity + } + maxPrice { + type + quantity + } + numProviders + fundsReleased + bids { + bidderAddress + status + commitHash + commitTime + revealTime + commitFee { + type + quantity + } + revealFee { + type + quantity + } + bidAmount { + type + quantity + } + } + } +} +` + +export const getDeployers = gql` +query { + deployers { + deployerLrn + deployerId + deployerApiUrl + minimumPayment + } +} +` + +export const getAddress = gql` +query { + address +} +` + +export const verifyTx = gql` +query ($txHash: String!, $amount: String!, $senderAddress: String!) { + verifyTx(txHash: $txHash, amount: $amount, senderAddress: $senderAddress) +} +` + +export const getLatestDNSRecordByProjectId = gql` +query($projectId: String!) { + latestDNSRecord(projectId: $projectId) { + name + value + request + resourceType + version + } +} +` diff --git a/services/gql-client/src/types.ts b/services/gql-client/src/types.ts new file mode 100644 index 0000000..54812e0 --- /dev/null +++ b/services/gql-client/src/types.ts @@ -0,0 +1,403 @@ +// Note: equivalent to types present in GQL schema + +export enum Role { + Owner = 'Owner', + Maintainer = 'Maintainer', + Reader = 'Reader' +} + +export enum Permission { + View = 'View', + Edit = 'Edit' +} + +export enum Environment { + Production = 'Production', + Preview = 'Preview', + Development = 'Development' +} + +export enum DeploymentStatus { + Building = 'Building', + Ready = 'Ready', + Error = 'Error', + Deleting = 'Deleting' +} + +export enum AuctionStatus { + AuctionStatusCommitPhase = 'commit', + AuctionStatusRevealPhase = 'reveal', + AuctionStatusExpired = 'expired', + AuctionStatusCompleted = 'completed' +} + +export type Bid = { + auctionId: string + bidderAddress: string + status: string + commitHash: string + commitTime?: Date + commitFee?: string + revealTime?: Date + revealFee?: string + bidAmount?: string +} + +export type Auction = { + id: string + kind: string + status: string + ownerAddress: string + createTime?: Date + commitsEndTime?: Date + revealsEndTime?: Date + commitFee?: string + revealFee?: string + minimumBid?: string + winnerAddresses: string[] + winnerBids?: string[] + winnerPrice?: string + maxPrice?: string + numProviders: number + fundsReleased: boolean + bids: Bid[] +} + +export enum DomainStatus { + Live = 'Live', + Pending = 'Pending' +} + +export type EnvironmentVariable = { + id: string + environment: Environment + key: string + value: string + createdAt: string + updatedAt: string +} + +export type Domain = { + id: string + branch: string + name: string + status: DomainStatus + redirectTo: Domain | null + createdAt: string + updatedAt: string +} + +export type User = { + id: string + name: string | null + email: string + isVerified: boolean + createdAt: string + updatedAt: string + gitHubToken: string | null +} + +export type Deployment = { + id: string + branch: string + commitHash: string + commitMessage: string + url?: string + deployer: Deployer + environment: Environment + isCurrent: boolean + baseDomain?: string + applicationDeploymentRecordData: AppDeploymentRecordAttributes + status: DeploymentStatus + createdBy: User + createdAt: string + updatedAt: string + applicationDeploymentRequestId: string +} + +export type Deployer = { + deployerLrn: string + deployerId: string + deployerApiUrl: string + baseDomain: string + minimumPayment: string | null +} + +export type OrganizationMember = { + id: string + member: User + role: Role + createdAt: string + updatedAt: string +} + +export type ProjectMember = { + id: string + member: User + permissions: Permission[] + isPending: boolean + createdAt: string + updatedAt: string +} + +export type OrganizationProject = { + id: string + owner: User + deployments: Deployment[] + name: string + repository: string + prodBranch: string + description: string + template: string + framework: string + webhooks: string[] + members: ProjectMember[] + environmentVariables: EnvironmentVariable[] + createdAt: string + updatedAt: string +} + +export type Organization = { + id: string + name: string + slug: string + projects: OrganizationProject[] + createdAt: string + updatedAt: string + members: OrganizationMember[] +} + +export type Project = { + id: string + owner: User + deployments: Deployment[] + name: string + repository: string + prodBranch: string + description: string + template: string + framework: string + deployers: [Deployer] + auctionId: string + paymentAddress: string + txHash: string + fundsReleased: boolean + webhooks: string[] + members: ProjectMember[] + environmentVariables: EnvironmentVariable[] + createdAt: string + updatedAt: string + organization: Organization + icon: string + baseDomains?: string[] | null +} + +export type GetProjectMembersResponse = { + projectMembers: ProjectMember[] +} + +export type AddProjectMemberResponse = { + addProjectMember: boolean +} + +export type RemoveProjectMemberResponse = { + removeProjectMember: boolean +} + +export type UpdateProjectMemberResponse = { + updateProjectMember: boolean +} + +export type GetDeploymentsResponse = { + deployments: Deployment[] +} + +export type GetEnvironmentVariablesResponse = { + environmentVariables: EnvironmentVariable[] +} + +export type GetOrganizationsResponse = { + organizations: Organization[] +} + +export type GetUserResponse = { + user: User +} + +export type GetProjectResponse = { + project: Project | null +} + +export type GetProjectsInOrganizationResponse = { + projectsInOrganization: Project[] +} + +export type GetDomainsResponse = { + domains: Domain[] +} + +export type GetDeployersResponse = { + deployers: Deployer[] +} + +export type SearchProjectsResponse = { + searchProjects: Project[] +} + +export type AddEnvironmentVariablesResponse = { + addEnvironmentVariables: boolean +} + +export type AddEnvironmentVariableInput = { + environments: string[] + key: string + value: string +} + +export type UpdateEnvironmentVariableInput = { + key: string + value: string +} + +export type UpdateProjectMemberInput = { + permissions: Permission[] +} + +export type AddProjectMemberInput = { + email: string + permissions: Permission[] +} + +export type UpdateEnvironmentVariableResponse = { + updateEnvironmentVariable: boolean +} + +export type RemoveEnvironmentVariableResponse = { + removeEnvironmentVariable: boolean +} + +export type UpdateDeploymentToProdResponse = { + updateDeploymentToProd: boolean +} + +export type AddProjectFromTemplateResponse = { + addProjectFromTemplate: Project +} + +export type AddProjectResponse = { + addProject: Project +} + +export type UpdateProjectResponse = { + updateProject: boolean +} + +export type UpdateDomainResponse = { + updateDomain: boolean +} + +export type DeleteProjectResponse = { + deleteProject: boolean +} + +export type DeleteDomainResponse = { + deleteDomain: boolean +} + +export type AddProjectFromTemplateInput = { + templateOwner: string + templateRepo: string + owner: string + name: string + isPrivate: boolean + paymentAddress: string + txHash: string +} + +export type AddProjectInput = { + name: string + repository: string + prodBranch: string + template?: string + paymentAddress: string + txHash: string +} + +export type UpdateProjectInput = { + name?: string + description?: string + prodBranch?: string + webhooks?: string[] + organizationId?: string +} + +export type UpdateDomainInput = { + name?: string + branch?: string + redirectToId?: string | null +} + +export type RedeployToProdResponse = { + redeployToProd: boolean +} + +export type RollbackDeploymentResponse = { + rollbackDeployment: boolean +} + +export type DeleteDeploymentResponse = { + deleteDeployment: boolean +} + +export type AddDomainInput = { + name: string +} + +export type FilterDomainInput = { + branch?: string + status?: DomainStatus +} + +export type AddDomainResponse = { + addDomain: true +} + +export type AuthenticateGitHubResponse = { + authenticateGitHub: { + token: string + } +} + +export type UnauthenticateGitHubResponse = { + unauthenticateGitHub: boolean +} + +export type AuctionParams = { + maxPrice: string + numProviders: number +} + +export type DNSRecordAttributes = { + name: string + value: string + request: string + resourceType: string + version: string +} + +export type GetLatestDNSDataResponse = { + latestDNSRecord: DNSRecordAttributes | null +} + +export interface AppDeploymentRecordAttributes { + application: string + auction: string + deployer: string + dns: string + meta: string + name: string + request: string + type: string + url: string + version: string +} diff --git a/services/gql-client/tsconfig.json b/services/gql-client/tsconfig.json new file mode 100644 index 0000000..93da6d0 --- /dev/null +++ b/services/gql-client/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.json", + "include": ["src"], + "exclude": ["node_modules", "dist"], + "compilerOptions": { + "outDir": "./dist", + "rootDir": "./src" + } +} diff --git a/services/gql-client/tsup.config.ts b/services/gql-client/tsup.config.ts new file mode 100644 index 0000000..3274278 --- /dev/null +++ b/services/gql-client/tsup.config.ts @@ -0,0 +1,9 @@ +import { defineConfig } from 'tsup' + +export default defineConfig({ + entry: ['src/index.ts'], + format: ['esm', 'cjs'], + dts: true, + sourcemap: true, + clean: true +}) diff --git a/services/ui/src/components/accordion.tsx b/services/ui/src/components/accordion.tsx index c14d779..0c7178b 100644 --- a/services/ui/src/components/accordion.tsx +++ b/services/ui/src/components/accordion.tsx @@ -1,15 +1,15 @@ -"use client"; +'use client' -import * as AccordionPrimitive from "@radix-ui/react-accordion"; -import { ChevronDownIcon } from "lucide-react"; -import type * as React from "react"; +import * as AccordionPrimitive from '@radix-ui/react-accordion' +import { ChevronDownIcon } from 'lucide-react' +import type * as React from 'react' -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from '@workspace/ui/lib/utils' function Accordion({ ...props }: React.ComponentProps) { - return ; + return } function AccordionItem({ @@ -19,10 +19,10 @@ function AccordionItem({ return ( - ); + ) } function AccordionTrigger({ @@ -35,8 +35,8 @@ function AccordionTrigger({ svg]:rotate-180", - className, + 'focus-visible:border-ring focus-visible:ring-ring/50 flex flex-1 items-start justify-between gap-4 rounded-md py-4 text-left text-sm font-medium transition-all outline-none hover:underline focus-visible:ring-[3px] disabled:pointer-events-none disabled:opacity-50 [&[data-state=open]>svg]:rotate-180', + className )} {...props} > @@ -44,7 +44,7 @@ function AccordionTrigger({ - ); + ) } function AccordionContent({ @@ -58,9 +58,9 @@ function AccordionContent({ className="data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden text-sm" {...props} > -
{children}
+
{children}
- ); + ) } -export { Accordion, AccordionItem, AccordionTrigger, AccordionContent }; +export { Accordion, AccordionItem, AccordionTrigger, AccordionContent } diff --git a/services/ui/src/components/alert-dialog.tsx b/services/ui/src/components/alert-dialog.tsx index 1eee18f..d0a7b3d 100644 --- a/services/ui/src/components/alert-dialog.tsx +++ b/services/ui/src/components/alert-dialog.tsx @@ -1,15 +1,15 @@ -"use client"; +'use client' -import * as React from "react"; -import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; +import * as AlertDialogPrimitive from '@radix-ui/react-alert-dialog' +import type * as React from 'react' -import { cn } from "@workspace/ui/lib/utils"; -import { buttonVariants } from "@workspace/ui/components/button"; +import { buttonVariants } from '@workspace/ui/components/button' +import { cn } from '@workspace/ui/lib/utils' function AlertDialog({ ...props }: React.ComponentProps) { - return ; + return } function AlertDialogTrigger({ @@ -17,7 +17,7 @@ function AlertDialogTrigger({ }: React.ComponentProps) { return ( - ); + ) } function AlertDialogPortal({ @@ -25,7 +25,7 @@ function AlertDialogPortal({ }: React.ComponentProps) { return ( - ); + ) } function AlertDialogOverlay({ @@ -36,12 +36,12 @@ function AlertDialogOverlay({ - ); + ) } function AlertDialogContent({ @@ -54,42 +54,42 @@ function AlertDialogContent({ - ); + ) } function AlertDialogHeader({ className, ...props -}: React.ComponentProps<"div">) { +}: React.ComponentProps<'div'>) { return (
- ); + ) } function AlertDialogFooter({ className, ...props -}: React.ComponentProps<"div">) { +}: React.ComponentProps<'div'>) { return (
- ); + ) } function AlertDialogTitle({ @@ -99,10 +99,10 @@ function AlertDialogTitle({ return ( - ); + ) } function AlertDialogDescription({ @@ -112,10 +112,10 @@ function AlertDialogDescription({ return ( - ); + ) } function AlertDialogAction({ @@ -127,7 +127,7 @@ function AlertDialogAction({ className={cn(buttonVariants(), className)} {...props} /> - ); + ) } function AlertDialogCancel({ @@ -136,10 +136,10 @@ function AlertDialogCancel({ }: React.ComponentProps) { return ( - ); + ) } export { @@ -153,5 +153,5 @@ export { AlertDialogTitle, AlertDialogDescription, AlertDialogAction, - AlertDialogCancel, -}; + AlertDialogCancel +} diff --git a/services/ui/src/components/alert.tsx b/services/ui/src/components/alert.tsx index e988f0b..5e19f3c 100644 --- a/services/ui/src/components/alert.tsx +++ b/services/ui/src/components/alert.tsx @@ -1,29 +1,29 @@ -import * as React from "react"; -import { cva, type VariantProps } from "class-variance-authority"; +import { type VariantProps, cva } from 'class-variance-authority' +import type * as React from 'react' -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from '@workspace/ui/lib/utils' const alertVariants = cva( - "relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", + 'relative w-full rounded-lg border px-4 py-3 text-sm grid has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] grid-cols-[0_1fr] has-[>svg]:gap-x-3 gap-y-0.5 items-start [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current', { variants: { variant: { - default: "bg-background text-foreground", + default: 'bg-background text-foreground', destructive: - "text-destructive-foreground [&>svg]:text-current *:data-[slot=alert-description]:text-destructive-foreground/80", - }, + 'text-destructive-foreground [&>svg]:text-current *:data-[slot=alert-description]:text-destructive-foreground/80' + } }, defaultVariants: { - variant: "default", - }, - }, -); + variant: 'default' + } + } +) function Alert({ className, variant, ...props -}: React.ComponentProps<"div"> & VariantProps) { +}: React.ComponentProps<'div'> & VariantProps) { return (
- ); + ) } -function AlertTitle({ className, ...props }: React.ComponentProps<"div">) { +function AlertTitle({ className, ...props }: React.ComponentProps<'div'>) { return (
- ); + ) } function AlertDescription({ className, ...props -}: React.ComponentProps<"div">) { +}: React.ComponentProps<'div'>) { return (
- ); + ) } -export { Alert, AlertTitle, AlertDescription }; +export { Alert, AlertTitle, AlertDescription } diff --git a/services/ui/src/components/aspect-ratio.tsx b/services/ui/src/components/aspect-ratio.tsx index c16d6bc..40bb120 100644 --- a/services/ui/src/components/aspect-ratio.tsx +++ b/services/ui/src/components/aspect-ratio.tsx @@ -1,11 +1,11 @@ -"use client"; +'use client' -import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"; +import * as AspectRatioPrimitive from '@radix-ui/react-aspect-ratio' function AspectRatio({ ...props }: React.ComponentProps) { - return ; + return } -export { AspectRatio }; +export { AspectRatio } diff --git a/services/ui/src/components/avatar.tsx b/services/ui/src/components/avatar.tsx index 2cf6dd8..6dd9a7e 100644 --- a/services/ui/src/components/avatar.tsx +++ b/services/ui/src/components/avatar.tsx @@ -1,9 +1,9 @@ -"use client"; +'use client' -import * as React from "react"; -import * as AvatarPrimitive from "@radix-ui/react-avatar"; +import * as AvatarPrimitive from '@radix-ui/react-avatar' +import type * as React from 'react' -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from '@workspace/ui/lib/utils' function Avatar({ className, @@ -13,12 +13,12 @@ function Avatar({ - ); + ) } function AvatarImage({ @@ -28,10 +28,10 @@ function AvatarImage({ return ( - ); + ) } function AvatarFallback({ @@ -42,12 +42,12 @@ function AvatarFallback({ - ); + ) } -export { Avatar, AvatarImage, AvatarFallback }; +export { Avatar, AvatarImage, AvatarFallback } diff --git a/services/ui/src/components/badge.tsx b/services/ui/src/components/badge.tsx index bbdb194..5efa685 100644 --- a/services/ui/src/components/badge.tsx +++ b/services/ui/src/components/badge.tsx @@ -1,38 +1,38 @@ -import * as React from "react"; -import { Slot } from "@radix-ui/react-slot"; -import { cva, type VariantProps } from "class-variance-authority"; +import { Slot } from '@radix-ui/react-slot' +import { type VariantProps, cva } from 'class-variance-authority' +import type * as React from 'react' -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from '@workspace/ui/lib/utils' const badgeVariants = cva( - "inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden", + 'inline-flex items-center justify-center rounded-md border px-2 py-0.5 text-xs font-medium w-fit whitespace-nowrap shrink-0 [&>svg]:size-3 gap-1 [&>svg]:pointer-events-none focus-visible:border-ring focus-visible:ring-ring/50 focus-visible:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive transition-[color,box-shadow] overflow-hidden', { variants: { variant: { default: - "border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90", + 'border-transparent bg-primary text-primary-foreground [a&]:hover:bg-primary/90', secondary: - "border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90", + 'border-transparent bg-secondary text-secondary-foreground [a&]:hover:bg-secondary/90', destructive: - "border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40", + 'border-transparent bg-destructive text-white [a&]:hover:bg-destructive/90 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40', outline: - "text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground", - }, + 'text-foreground [a&]:hover:bg-accent [a&]:hover:text-accent-foreground' + } }, defaultVariants: { - variant: "default", - }, - }, -); + variant: 'default' + } + } +) function Badge({ className, variant, asChild = false, ...props -}: React.ComponentProps<"span"> & +}: React.ComponentProps<'span'> & VariantProps & { asChild?: boolean }) { - const Comp = asChild ? Slot : "span"; + const Comp = asChild ? Slot : 'span' return ( - ); + ) } -export { Badge, badgeVariants }; +export { Badge, badgeVariants } diff --git a/services/ui/src/components/breadcrumb.tsx b/services/ui/src/components/breadcrumb.tsx index d9471c1..b24ffa4 100644 --- a/services/ui/src/components/breadcrumb.tsx +++ b/services/ui/src/components/breadcrumb.tsx @@ -1,98 +1,98 @@ -import { Slot } from "@radix-ui/react-slot"; -import { ChevronRight, MoreHorizontal } from "lucide-react"; +import { Slot } from '@radix-ui/react-slot' +import { ChevronRight, MoreHorizontal } from 'lucide-react' -import { cn } from "@workspace/ui/lib/utils"; +import { cn } from '@workspace/ui/lib/utils' -function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { - return