Integrate SP auctions for app deployment (#2)
All checks were successful
Lint / lint (20.x) (push) Successful in 4m5s

Part of [Service provider auctions for web deployments](https://www.notion.so/Service-provider-auctions-for-web-deployments-104a6b22d47280dbad51d28aa3a91d75)
- Add support for configuring web-app deployers by -
  - Configuring deployer LRN (for targeted deployments)
  - Configuring SP auction params for deployment auction (max price and number of providers)

Co-authored-by: IshaVenikar <ishavenikar7@gmail.com>
Reviewed-on: #2
This commit is contained in:
nabarun 2024-10-18 12:37:01 +00:00
parent 42bdd21089
commit 5aefda1248
41 changed files with 1609 additions and 2347 deletions

View File

@ -29,6 +29,7 @@
[registryConfig]
fetchDeploymentRecordDelay = 5000
checkAuctionStatusDelay = 5000
restEndpoint = "http://localhost:1317"
gqlEndpoint = "http://localhost:9473/api"
chainId = "laconic_9000-1"
@ -36,9 +37,17 @@
bondId = ""
authority = ""
[registryConfig.fee]
gas = "200000"
fees = "200000alnt"
gasPrice = ""
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"
[misc]
projectDomain = "apps.snowballtools.com"

View File

@ -34,6 +34,7 @@ export interface RegistryConfig {
privateKey: string;
bondId: string;
fetchDeploymentRecordDelay: number;
checkAuctionStatusDelay: number;
authority: string;
fee: {
gas: string;
@ -42,6 +43,14 @@ export interface RegistryConfig {
};
}
export interface AuctionConfig {
commitFee: string;
commitsDuration: string;
revealFee: string;
revealsDuration: string;
denom: string;
}
export interface MiscConfig {
projectDomain: string;
}
@ -51,6 +60,7 @@ export interface Config {
database: DatabaseConfig;
gitHub: GitHubConfig;
registryConfig: RegistryConfig;
auction: AuctionConfig;
misc: MiscConfig;
turnkey: {
apiBaseUrl: string;

View File

@ -465,8 +465,6 @@ export class Database {
id: organizationId
});
newProject.subDomain = `${newProject.name}.${this.projectDomain}`;
return projectRepository.save(newProject);
}

View File

@ -33,6 +33,8 @@ export interface ApplicationDeploymentRequest {
version: string;
name: string;
application: string;
lrn?: string;
auction?: string;
config: string;
meta: string;
}
@ -112,19 +114,22 @@ export class Deployment {
@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('varchar')
deployerLrn!: string;
@Column({
enum: Environment
})
@ -133,6 +138,9 @@ export class Deployment {
@Column('boolean', { default: false })
isCurrent!: boolean;
@Column('varchar', { nullable: true })
baseDomain!: string | null;
@Column({
enum: DeploymentStatus
})
@ -147,7 +155,7 @@ export class Deployment {
@UpdateDateColumn()
updatedAt!: Date;
@DeleteDateColumn()
deletedAt!: Date | null;
}

View File

@ -46,6 +46,12 @@ export class Project {
@Column('text', { default: '' })
description!: string;
@Column('varchar', { nullable: true })
auctionId!: string | null;
@Column({ type: 'simple-array', nullable: true })
deployerLrns!: string[] | null;
// TODO: Compute template & framework in import repository
@Column('varchar', { nullable: true })
template!: string | null;
@ -61,8 +67,8 @@ export class Project {
@Column('varchar')
icon!: string;
@Column('varchar')
subDomain!: string;
@Column({ type: 'simple-array', nullable: true })
baseDomains!: string[] | null;
@CreateDateColumn()
createdAt!: Date;

View File

@ -1,9 +1,11 @@
import debug from 'debug';
import assert from 'assert';
import { inc as semverInc } from 'semver';
import debug from 'debug';
import { DateTime } from 'luxon';
import { Octokit } from 'octokit';
import { inc as semverInc } from 'semver';
import { DeepPartial } from 'typeorm';
import { Registry as LaconicRegistry, parseGasAndFees } from '@cerc-io/registry-sdk';
import { Registry as LaconicRegistry, getGasPrice, parseGasAndFees } from '@cerc-io/registry-sdk';
import { RegistryConfig } from './config';
import {
@ -12,12 +14,13 @@ import {
ApplicationDeploymentRequest,
ApplicationDeploymentRemovalRequest
} from './entity/Deployment';
import { AppDeploymentRecord, AppDeploymentRemovalRecord, PackageJSON } from './types';
import { sleep } from './utils';
import { AppDeploymentRecord, AppDeploymentRemovalRecord, AuctionParams } from './types';
import { getConfig, getRepoDetails, 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';
@ -29,31 +32,33 @@ export class Registry {
private registry: LaconicRegistry;
private registryConfig: RegistryConfig;
constructor (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 }
{ chainId: registryConfig.chainId, gasPrice }
);
}
async createApplicationRecord ({
appName,
packageJSON,
async createApplicationRecord({
octokit,
repository,
commitHash,
appType,
repoUrl
}: {
appName: string;
packageJSON: PackageJSON;
octokit: Octokit
repository: string;
commitHash: string;
appType: string;
repoUrl: 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
@ -87,7 +92,7 @@ export class Registry {
repository_ref: commitHash,
repository: [repoUrl],
app_type: appType,
name: appName,
name: repo,
...(packageJSON.description && { description: packageJSON.description }),
...(packageJSON.homepage && { homepage: packageJSON.homepage }),
...(packageJSON.license && { license: packageJSON.license }),
@ -112,22 +117,29 @@ export class Registry {
fee
);
log(`Published application record ${result.id}`);
log('Application record data:', applicationRecord);
// TODO: Discuss computation of LRN
const lrn = this.getLrn(appName);
const lrn = this.getLrn(repo);
log(`Setting name: ${lrn} for record ID: ${result.id}`);
await sleep(SLEEP_DURATION);
await this.registry.setName(
{ cid: result.id, lrn },
{
cid: result.id,
lrn
},
this.registryConfig.privateKey,
fee
);
await sleep(SLEEP_DURATION);
await this.registry.setName(
{ cid: result.id, lrn: `${lrn}@${applicationRecord.app_version}` },
{
cid: result.id,
lrn: `${lrn}@${applicationRecord.app_version}`
},
this.registryConfig.privateKey,
fee
);
@ -148,10 +160,78 @@ export class Registry {
};
}
async createApplicationDeploymentRequest (data: {
async createApplicationDeploymentAuction(
appName: string,
octokit: Octokit,
auctionParams: AuctionParams,
data: DeepPartial<Deployment>,
): 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 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.registry.setRecord(
{
privateKey: this.registryConfig.privateKey,
record: applicationDeploymentAuction,
bondId: this.registryConfig.bondId
},
this.registryConfig.privateKey,
fee
);
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,
lrn: string,
environmentVariables: { [key: string]: string },
dns: string,
}): Promise<{
@ -174,9 +254,6 @@ export class Registry {
application: `${lrn}@${applicationRecord.attributes.app_version}`,
dns: data.dns,
// TODO: Not set in test-progressive-web-app CI
// deployment: '$CERC_REGISTRY_DEPLOYMENT_LRN',
// https://git.vdb.to/cerc-io/laconic-registry-cli/commit/129019105dfb93bebcea02fde0ed64d0f8e5983b
config: JSON.stringify({
env: data.environmentVariables
@ -187,7 +264,9 @@ export class Registry {
)}`,
repository: data.repository,
repository_ref: data.deployment.commitHash
})
}),
deployer: data.lrn,
...(data.auctionId && { auction: data.auctionId }),
};
await sleep(SLEEP_DURATION);
@ -212,10 +291,38 @@ export class Registry {
};
}
async getAuctionWinningDeployers(
auctionId: string
): Promise<string[]> {
const records = await this.registry.getAuctionsByIds([auctionId]);
const auctionResult = records[0];
let deployerLrns = [];
const { winnerAddresses } = auctionResult;
for (const auctionWinner of winnerAddresses) {
const deployerRecords = await this.registry.queryRecords(
{
paymentAddress: auctionWinner,
},
true
);
for (const record of deployerRecords) {
if (record.names && record.names.length > 0) {
deployerLrns.push(record.names[0]);
break;
}
}
}
return deployerLrns;
}
/**
* Fetch ApplicationDeploymentRecords for deployments
*/
async getDeploymentRecords (
async getDeploymentRecords(
deployments: Deployment[]
): Promise<AppDeploymentRecord[]> {
// Fetch ApplicationDeploymentRecords for corresponding ApplicationRecord set in deployments
@ -227,11 +334,11 @@ export class Registry {
true
);
// Filter records with ApplicationRecord ID and Deployment specific URL
// Filter records with ApplicationDeploymentRequestId ID and Deployment specific URL
return records.filter((record: AppDeploymentRecord) =>
deployments.some(
(deployment) =>
deployment.applicationRecordId === record.attributes.application &&
deployment.applicationDeploymentRequestId === record.attributes.request &&
record.attributes.url.includes(deployment.id)
)
);
@ -240,7 +347,7 @@ export class Registry {
/**
* Fetch ApplicationDeploymentRecords by filter
*/
async getDeploymentRecordsByFilter (filter: { [key: string]: any }): Promise<AppDeploymentRecord[]> {
async getDeploymentRecordsByFilter(filter: { [key: string]: any }): Promise<AppDeploymentRecord[]> {
return this.registry.queryRecords(
{
type: APP_DEPLOYMENT_RECORD_TYPE,
@ -253,7 +360,7 @@ export class Registry {
/**
* Fetch ApplicationDeploymentRemovalRecords for deployments
*/
async getDeploymentRemovalRecords (
async getDeploymentRemovalRecords(
deployments: Deployment[]
): Promise<AppDeploymentRemovalRecord[]> {
// Fetch ApplicationDeploymentRemovalRecords for corresponding ApplicationDeploymentRecord set in deployments
@ -274,8 +381,9 @@ export class Registry {
);
}
async createApplicationDeploymentRemovalRequest (data: {
async createApplicationDeploymentRemovalRequest(data: {
deploymentId: string;
deployerLrn: string;
}): Promise<{
applicationDeploymentRemovalRequestId: string;
applicationDeploymentRemovalRequestData: ApplicationDeploymentRemovalRequest;
@ -283,7 +391,8 @@ export class Registry {
const applicationDeploymentRemovalRequest = {
type: APP_DEPLOYMENT_REMOVAL_REQUEST_TYPE,
version: '1.0.0',
deployment: data.deploymentId
deployment: data.deploymentId,
deployer: data.deployerLrn
};
const fee = parseGasAndFees(this.registryConfig.fee.gas, this.registryConfig.fee.fees);
@ -307,6 +416,30 @@ export class Registry {
};
}
async getCompletedAuctionIds(auctionIds: (string | null | undefined)[]): Promise<string[] | null> {
const validAuctionIds = auctionIds.filter((id): id is string => id !== null && id !== undefined);
if (!validAuctionIds.length) {
return null;
}
const auctions = await this.registry.getAuctionsByIds(validAuctionIds);
const completedAuctions = auctions
.filter((auction: { id: string, status: string }) => auction.status === 'completed')
.map((auction: { id: string, status: string }) => auction.id);
return completedAuctions;
}
async getRecordsByName(name: string): Promise<any> {
return this.registry.resolveNames([name]);
}
async getAuctionData(auctionId: string): Promise<any> {
return this.registry.getAuctionsByIds([auctionId]);
}
getLrn(appName: string): string {
assert(this.registryConfig.authority, "Authority doesn't exist");
return `lrn://${this.registryConfig.authority}/applications/${appName}`;

View File

@ -6,7 +6,7 @@ import { Permission } from './entity/ProjectMember';
import { Domain } from './entity/Domain';
import { Project } from './entity/Project';
import { EnvironmentVariable } from './entity/EnvironmentVariable';
import { AddProjectFromTemplateInput } from './types';
import { AddProjectFromTemplateInput, AuctionParams } from './types';
const log = debug('snowball:resolver');
@ -69,6 +69,13 @@ export const createResolvers = async (service: Service): Promise<any> => {
) => {
return service.getDomainsByProjectId(projectId, filter);
},
getAuctionData: async (
_: any,
{ auctionId }: { auctionId: string },
) => {
return service.getAuctionData(auctionId);
},
},
// TODO: Return error in GQL response
@ -203,7 +210,9 @@ export const createResolvers = async (service: Service): Promise<any> => {
{
organizationSlug,
data,
}: { organizationSlug: string; data: AddProjectFromTemplateInput },
lrn,
auctionParams
}: { organizationSlug: string; data: AddProjectFromTemplateInput; lrn: string; auctionParams: AuctionParams },
context: any,
) => {
try {
@ -211,6 +220,8 @@ export const createResolvers = async (service: Service): Promise<any> => {
context.user,
organizationSlug,
data,
lrn,
auctionParams
);
} catch (err) {
log(err);
@ -223,11 +234,13 @@ export const createResolvers = async (service: Service): Promise<any> => {
{
organizationSlug,
data,
}: { organizationSlug: string; data: DeepPartial<Project> },
lrn,
auctionParams
}: { organizationSlug: string; data: DeepPartial<Project>; lrn: string; auctionParams: AuctionParams },
context: any,
) => {
try {
return await service.addProject(context.user, organizationSlug, data);
return await service.addProject(context.user, organizationSlug, data, lrn, auctionParams);
} catch (err) {
log(err);
throw err;

View File

@ -22,6 +22,13 @@ enum DeploymentStatus {
Deleting
}
enum AuctionStatus {
completed
reveal
commit
expired
}
enum DomainStatus {
Live
Pending
@ -65,6 +72,8 @@ type Project {
repository: String!
prodBranch: String!
description: String
deployerLrns: [String]
auctionId: String
template: String
framework: String
webhooks: [String!]
@ -74,7 +83,7 @@ type Project {
updatedAt: String!
organization: Organization!
icon: String
subDomain: String
baseDomains: [String!]
}
type ProjectMember {
@ -94,7 +103,9 @@ type Deployment {
commitMessage: String!
url: String
environment: Environment!
deployerLrn: String
isCurrent: Boolean!
baseDomain: String
status: DeploymentStatus!
createdAt: String!
updatedAt: String!
@ -182,6 +193,48 @@ input FilterDomainsInput {
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!]!
}
input AuctionParams {
maxPrice: String,
numProviders: Int,
}
type Query {
user: User!
organizations: [Organization!]
@ -192,6 +245,7 @@ type Query {
environmentVariables(projectId: String!): [EnvironmentVariable!]
projectMembers(projectId: String!): [ProjectMember!]
searchProjects(searchText: String!): [Project!]
getAuctionData(auctionId: String!): Auction!
domains(projectId: String!, filter: FilterDomainsInput): [Domain]
}
@ -215,8 +269,15 @@ type Mutation {
addProjectFromTemplate(
organizationSlug: String!
data: AddProjectFromTemplateInput
lrn: String
auctionParams: AuctionParams
): Project!
addProject(
organizationSlug: String!
data: AddProjectInput!
lrn: String
auctionParams: AuctionParams
): Project!
addProject(organizationSlug: String!, data: AddProjectInput): Project!
updateProject(projectId: String!, data: UpdateProjectInput): Boolean!
redeployToProd(deploymentId: String!): Boolean!
deleteProject(projectId: String!): Boolean!

View File

@ -1,12 +1,12 @@
import assert from 'assert';
import debug from 'debug';
import { DeepPartial, FindOptionsWhere } from 'typeorm';
import { DeepPartial, FindOptionsWhere, IsNull, Not } from 'typeorm';
import { Octokit, RequestError } from 'octokit';
import { OAuthApp } from '@octokit/oauth-app';
import { Database } from './database';
import { Deployment, DeploymentStatus, Environment } from './entity/Deployment';
import { ApplicationRecord, Deployment, DeploymentStatus, Environment } from './entity/Deployment';
import { Domain } from './entity/Domain';
import { EnvironmentVariable } from './entity/EnvironmentVariable';
import { Organization } from './entity/Organization';
@ -19,10 +19,11 @@ import {
AddProjectFromTemplateInput,
AppDeploymentRecord,
AppDeploymentRemovalRecord,
AuctionParams,
GitPushEventPayload,
PackageJSON,
} from './types';
import { Role } from './entity/UserOrganization';
import { getRepoDetails } from './utils';
const log = debug('snowball:service');
@ -39,15 +40,16 @@ interface Config {
export class Service {
private db: Database;
private oauthApp: OAuthApp;
private registry: Registry;
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.registry = registry;
this.laconicRegistry = registry;
this.config = config;
this.init();
}
@ -60,6 +62,8 @@ export class Service {
this.checkDeployRecordsAndUpdate();
// Start check for ApplicationDeploymentRemovalRecords asynchronously
this.checkDeploymentRemovalRecordsAndUpdate();
// Start check for Deployment Auctions asynchronously
this.checkAuctionStatus();
}
/**
@ -67,6 +71,7 @@ export class Service {
*/
destroy(): void {
clearTimeout(this.deployRecordCheckTimeout);
clearTimeout(this.auctionStatusCheckTimeout);
}
/**
@ -108,7 +113,7 @@ export class Service {
}
// Fetch ApplicationDeploymentRecord for deployments
const records = await this.registry.getDeploymentRecords(deployments);
const records = await this.laconicRegistry.getDeploymentRecords(deployments);
log(`Found ${records.length} ApplicationDeploymentRecords`);
// Update deployments for which ApplicationDeploymentRecords were returned
@ -141,7 +146,7 @@ export class Service {
// Fetch ApplicationDeploymentRemovalRecords for deployments
const records =
await this.registry.getDeploymentRemovalRecords(deployments);
await this.laconicRegistry.getDeploymentRemovalRecords(deployments);
log(`Found ${records.length} ApplicationDeploymentRemovalRecords`);
// Update deployments for which ApplicationDeploymentRemovalRecords were returned
@ -157,41 +162,24 @@ export class Service {
/**
* Update deployments with ApplicationDeploymentRecord data
* Deployments that are completed but not updated in DB
*/
async updateDeploymentsWithRecordData(
records: AppDeploymentRecord[],
): Promise<void> {
// Get deployments for ApplicationDeploymentRecords
// get and update deployments to be updated using request id
const deployments = await this.db.getDeployments({
where: records.map((record) => ({
applicationRecordId: record.attributes.application,
applicationDeploymentRequestId: record.attributes.request,
})),
order: {
createdAt: 'DESC',
},
});
// Get project IDs of deployments that are in production environment
const productionDeploymentProjectIds = deployments.reduce(
(acc, deployment): Set<string> => {
if (deployment.environment === Environment.Production) {
acc.add(deployment.projectId);
}
return acc;
},
new Set<string>(),
);
// Set old deployments isCurrent to false
await this.db.updateDeploymentsByProjectIds(
Array.from(productionDeploymentProjectIds),
{ isCurrent: false },
);
const recordToDeploymentsMap = deployments.reduce(
(acc: { [key: string]: Deployment }, deployment) => {
acc[deployment.applicationRecordId] = deployment;
acc[deployment.applicationDeploymentRequestId!] = deployment;
return acc;
},
{},
@ -199,21 +187,64 @@ export class Service {
// Update deployment data for ApplicationDeploymentRecords
const deploymentUpdatePromises = records.map(async (record) => {
const deployment = recordToDeploymentsMap[record.attributes.application];
const deployment = recordToDeploymentsMap[record.attributes.request];
const project = await this.getProjectById(deployment.projectId)
assert(project)
await this.db.updateDeploymentById(deployment.id, {
applicationDeploymentRecordId: record.id,
applicationDeploymentRecordData: record.attributes,
url: record.attributes.url,
status: DeploymentStatus.Ready,
isCurrent: deployment.environment === Environment.Production,
});
const parts = record.attributes.url.replace('https://', '').split('.');
const baseDomain = parts.slice(1).join('.');
deployment.applicationDeploymentRecordId = record.id;
deployment.applicationDeploymentRecordData = record.attributes;
deployment.url = record.attributes.url;
deployment.baseDomain = baseDomain;
deployment.status = DeploymentStatus.Ready;
deployment.isCurrent = deployment.environment === Environment.Production;
await this.db.updateDeploymentById(deployment.id, deployment);
const baseDomains = project.baseDomains || [];
if (!baseDomains.includes(baseDomain)) {
baseDomains.push(baseDomain);
}
await this.db.updateProjectById(project.id, {
baseDomains
})
log(
`Updated deployment ${deployment.id} with URL ${record.attributes.url}`,
);
});
await Promise.all(deploymentUpdatePromises);
// if iscurrent is true for this deployment then update the old ones
const prodDeployments = Object.values(recordToDeploymentsMap).filter(deployment => deployment.isCurrent);
// Get deployment IDs of deployments that are in production environment
for (const deployment of prodDeployments) {
const projectDeployments = await this.db.getDeploymentsByProjectId(deployment.projectId);
const oldDeployments = projectDeployments
.filter(projectDeployment => projectDeployment.deployerLrn === deployment.deployerLrn && projectDeployment.id !== deployment.id);
for (const oldDeployment of oldDeployments) {
await this.db.updateDeployment(
{ id: oldDeployment.id },
{ isCurrent: false }
);
}
}
// Get old deployments for ApplicationDeploymentRecords
// flter out deps with is current false
// loop over these deps
// get the project
// get all the deployemnts in that proj with the same deployer lrn (query filter not above updated dep)
// set is current to false
await Promise.all(deploymentUpdatePromises);
}
@ -262,6 +293,58 @@ export class Service {
await Promise.all(deploymentUpdatePromises);
}
/**
* Checks the status for all ongoing auctions
* Calls the createDeploymentFromAuction method for deployments with completed auctions
*/
async checkAuctionStatus(): Promise<void> {
const allProjects = await this.db.getProjects({
where: {
auctionId: Not(IsNull()),
},
relations: ['deployments'],
withDeleted: true,
});
// Should only check on the first deployment
const projects = allProjects.filter(project => {
if (project.deletedAt !== null) return false;
return project.deployments.length === 0;
});
const auctionIds = projects.map((project) => project.auctionId);
const completedAuctionIds = await this.laconicRegistry.getCompletedAuctionIds(auctionIds);
if (completedAuctionIds) {
const projectsToBedeployed = projects.filter((project) =>
completedAuctionIds.includes(project.auctionId!)
);
for (const project of projectsToBedeployed) {
const deployerLrns = await this.laconicRegistry.getAuctionWinningDeployers(project!.auctionId!);
if (!deployerLrns) {
log(`No winning deployer for auction ${project!.auctionId}`);
} else {
// Update project with deployer LRNs
await this.db.updateProjectById(project.id!, {
deployerLrns
});
for (const deployer of deployerLrns) {
log(`Creating deployment for deployer LRN ${deployer}`);
await this.createDeploymentFromAuction(project, deployer);
}
}
}
}
this.auctionStatusCheckTimeout = setTimeout(() => {
this.checkAuctionStatus();
}, this.config.registryConfig.checkAuctionStatusDelay);
}
async getUser(userId: string): Promise<User | null> {
return this.db.getUser({
where: {
@ -519,6 +602,7 @@ export class Service {
domain: prodBranchDomains[0],
commitHash: oldDeployment.commitHash,
commitMessage: oldDeployment.commitMessage,
deployerLrn: oldDeployment.deployerLrn
});
return newDeployment;
@ -527,45 +611,20 @@ export class Service {
async createDeployment(
userId: string,
octokit: Octokit,
data: DeepPartial<Deployment>,
data: DeepPartial<Deployment>
): Promise<Deployment> {
assert(data.project?.repository, 'Project repository not found');
log(
`Creating deployment in project ${data.project.name} from branch ${data.branch}`,
);
const [owner, repo] = data.project.repository.split('/');
const { data: packageJSONData } = await octokit.rest.repos.getContent({
owner,
repo,
path: 'package.json',
ref: data.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;
// TODO: Set environment variables for each deployment (environment variables can`t be set in application record)
const { applicationRecordId, applicationRecordData } =
await this.registry.createApplicationRecord({
appName: repo,
packageJSON,
await this.laconicRegistry.createApplicationRecord({
octokit,
repository: data.project.repository,
appType: data.project!.template!,
commitHash: data.commitHash!,
repoUrl,
});
// Update previous deployment with prod branch domain
@ -581,6 +640,125 @@ export class Service {
);
}
const newDeployment = await this.createDeploymentFromData(userId, data, data.deployerLrn!, applicationRecordId, applicationRecordData);
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) {
// On deleting deployment later, project DNS deployment is also deleted
// So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later
await this.laconicRegistry.createApplicationDeploymentRequest({
deployment: newDeployment,
appName: repo,
repository: repoUrl,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}`,
lrn: data.deployerLrn!
});
}
const { applicationDeploymentRequestId, applicationDeploymentRequestData } =
await this.laconicRegistry.createApplicationDeploymentRequest({
deployment: newDeployment,
appName: repo,
repository: repoUrl,
lrn: data.deployerLrn!,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}-${newDeployment.id}`,
});
await this.db.updateDeploymentById(newDeployment.id, {
applicationDeploymentRequestId,
applicationDeploymentRequestData,
});
return newDeployment;
}
async createDeploymentFromAuction(
project: DeepPartial<Project>,
deployerLrn: string
): Promise<Deployment> {
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;
// 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 newDeployment = await this.createDeploymentFromData(project.ownerId!, deploymentData, deployerLrn, applicationRecordId, applicationRecordData);
const environmentVariablesObj = await this.getEnvVariables(project!.id!);
// To set project DNS
if (deploymentData.environment === Environment.Production) {
// On deleting deployment later, project DNS deployment is also deleted
// So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later
await this.laconicRegistry.createApplicationDeploymentRequest({
deployment: newDeployment,
appName: repo,
repository: repoUrl,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}`,
auctionId: project.auctionId!,
lrn: deployerLrn,
});
}
const { applicationDeploymentRequestId, applicationDeploymentRequestData } =
// Create requests for all the deployers
await this.laconicRegistry.createApplicationDeploymentRequest({
deployment: newDeployment,
appName: repo,
repository: repoUrl,
auctionId: project.auctionId!,
lrn: deployerLrn,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}-${newDeployment.id}`,
});
await this.db.updateDeploymentById(newDeployment.id, {
applicationDeploymentRequestId,
applicationDeploymentRequestData,
});
return newDeployment;
}
async createDeploymentFromData(
userId: string,
data: DeepPartial<Deployment>,
deployerLrn: string,
applicationRecordId: string,
applicationRecordData: ApplicationRecord,
): Promise<Deployment> {
const newDeployment = await this.db.addDeployment({
project: data.project,
branch: data.branch,
@ -594,52 +772,10 @@ export class Service {
createdBy: Object.assign(new User(), {
id: userId,
}),
deployerLrn,
});
log(
`Created deployment ${newDeployment.id} and published application record ${applicationRecordId}`,
);
const environmentVariables =
await this.db.getEnvironmentVariablesByProjectId(data.project.id!, {
environment: Environment.Production,
});
const environmentVariablesObj = environmentVariables.reduce(
(acc, env) => {
acc[env.key] = env.value;
return acc;
},
{} as { [key: string]: string },
);
// To set project DNS
if (data.environment === Environment.Production) {
// On deleting deployment later, project DNS deployment is also deleted
// So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later
await this.registry.createApplicationDeploymentRequest({
deployment: newDeployment,
appName: repo,
repository: repoUrl,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}`,
});
}
const { applicationDeploymentRequestId, applicationDeploymentRequestData } =
await this.registry.createApplicationDeploymentRequest({
deployment: newDeployment,
appName: repo,
repository: repoUrl,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}-${newDeployment.id}`,
});
await this.db.updateDeploymentById(newDeployment.id, {
applicationDeploymentRequestId,
applicationDeploymentRequestData,
});
log(`Created deployment ${newDeployment.id}`);
return newDeployment;
}
@ -648,6 +784,8 @@ export class Service {
user: User,
organizationSlug: string,
data: AddProjectFromTemplateInput,
lrn?: string,
auctionParams?: AuctionParams
): Promise<Project | undefined> {
try {
const octokit = await this.getOctokit(user.id);
@ -678,7 +816,7 @@ export class Service {
repository: gitRepo.data.full_name,
// TODO: Set selected template
template: 'webapp',
});
}, lrn, auctionParams);
if (!project || !project.id) {
throw new Error('Failed to create project from template');
@ -695,6 +833,8 @@ export class Service {
user: User,
organizationSlug: string,
data: DeepPartial<Project>,
lrn?: string,
auctionParams?: AuctionParams
): Promise<Project | undefined> {
const organization = await this.db.getOrganization({
where: {
@ -706,6 +846,7 @@ export class Service {
}
const project = await this.db.addProject(user, organization.id, data);
log(`Project created ${project.id}`);
const octokit = await this.getOctokit(user.id);
const [owner, repo] = project.repository.split('/');
@ -720,19 +861,26 @@ export class Service {
});
// Create deployment with prod branch and latest commit
const deployment = await this.createDeployment(user.id, octokit, {
const deploymentData = {
project,
branch: project.prodBranch,
environment: Environment.Production,
domain: null,
commitHash: latestCommit.sha,
commitMessage: latestCommit.commit.message,
});
deployerLrn: lrn
};
if (auctionParams) {
const { applicationDeploymentAuctionId } = await this.laconicRegistry.createApplicationDeploymentAuction(repo, octokit, auctionParams!, deploymentData);
await this.updateProject(project.id, { auctionId: applicationDeploymentAuctionId })
} else {
await this.createDeployment(user.id, octokit, deploymentData);
await this.updateProject(project.id, { deployerLrns: [lrn!] })
}
await this.createRepoHook(octokit, project);
console.log('projectid is', project.id);
return project;
}
@ -798,18 +946,29 @@ export class Service {
branch,
});
// 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,
domain,
commitHash: headCommit.id,
commitMessage: headCommit.message,
});
const deployers = project.deployerLrns;
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,
domain,
commitHash: headCommit.id,
commitMessage: headCommit.message,
deployerLrn: deployer
},
);
}
}
}
@ -859,15 +1018,25 @@ export class Service {
const octokit = await this.getOctokit(user.id);
const newDeployment = await this.createDeployment(user.id, octokit, {
project: oldDeployment.project,
// TODO: Put isCurrent field in project
branch: oldDeployment.branch,
environment: Environment.Production,
domain: oldDeployment.domain,
commitHash: oldDeployment.commitHash,
commitMessage: oldDeployment.commitMessage,
});
let newDeployment: Deployment;
if (oldDeployment.project.auctionId) {
// TODO: Discuss creating applicationRecord for redeployments
newDeployment = await this.createDeploymentFromAuction(oldDeployment.project, oldDeployment.deployerLrn);
} else {
newDeployment = await this.createDeployment(user.id, octokit,
{
project: oldDeployment.project,
// TODO: Put isCurrent field in project
branch: oldDeployment.branch,
environment: Environment.Production,
domain: oldDeployment.domain,
commitHash: oldDeployment.commitHash,
commitMessage: oldDeployment.commitMessage,
deployerLrn: oldDeployment.deployerLrn
}
);
}
return newDeployment;
}
@ -919,10 +1088,11 @@ export class Service {
if (deployment && deployment.applicationDeploymentRecordId) {
// If deployment is current, remove deployment for project subdomain as well
if (deployment.isCurrent) {
const currentDeploymentURL = `https://${deployment.project.subDomain}`;
const currentDeploymentURL = `https://${(deployment.project.name).toLowerCase()}.${deployment.baseDomain}`;
// TODO: Store the latest DNS deployment record
const deploymentRecords =
await this.registry.getDeploymentRecordsByFilter({
await this.laconicRegistry.getDeploymentRecordsByFilter({
application: deployment.applicationRecordId,
url: currentDeploymentURL,
});
@ -935,14 +1105,20 @@ export class Service {
return false;
}
await this.registry.createApplicationDeploymentRemovalRequest({
deploymentId: deploymentRecords[0].id,
// 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.deployerLrn
});
}
const result =
await this.registry.createApplicationDeploymentRemovalRequest({
await this.laconicRegistry.createApplicationDeploymentRemovalRequest({
deploymentId: deployment.applicationDeploymentRecordId,
deployerLrn: deployment.deployerLrn
});
await this.db.updateDeploymentById(deployment.id, {
@ -1077,4 +1253,29 @@ export class Service {
): Promise<boolean> {
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<any> {
const auctions = await this.laconicRegistry.getAuctionData(auctionId);
return auctions[0];
}
}

View File

@ -29,6 +29,8 @@ export interface GitPushEventPayload {
export interface AppDeploymentRecordAttributes {
application: string;
auction: string;
deployer: string;
dns: string;
meta: string;
name: string;
@ -69,3 +71,8 @@ export interface AddProjectFromTemplateInput {
name: string;
isPrivate: boolean;
}
export interface AuctionParams {
maxPrice: string,
numProviders: number,
}

View File

@ -1,12 +1,14 @@
import assert from 'assert';
import debug from 'debug';
import fs from 'fs-extra';
import { Octokit } from 'octokit';
import path from 'path';
import toml from 'toml';
import debug from 'debug';
import { DataSource, DeepPartial, EntityTarget, ObjectLiteral } from 'typeorm';
import { Config } from './config';
import { DEFAULT_CONFIG_FILE_PATH } from './constants';
import { PackageJSON } from './types';
const log = debug('snowball:utils');
@ -78,3 +80,43 @@ export const loadAndSaveData = async <Entity extends ObjectLiteral>(
export const sleep = async (ms: number): Promise<void> =>
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
};
}

View File

@ -73,7 +73,7 @@ async function main() {
// Remove deployment for project subdomain if deployment is for production environment
if (deployment.environment === Environment.Production) {
applicationDeploymentRecord.url = `https://${deployment.project.subDomain}`
applicationDeploymentRecord.url = `https://${deployment.project.name}.${deployment.baseDomain}`;
await registry.setRecord(
{

View File

@ -16,8 +16,11 @@
"@bugsnag/browser-performance": "^2.4.1",
"@bugsnag/js": "^7.22.7",
"@bugsnag/plugin-react": "^7.22.7",
"@emotion/react": "^11.13.3",
"@emotion/styled": "^11.13.0",
"@fontsource-variable/jetbrains-mono": "^5.0.19",
"@fontsource/inter": "^5.0.16",
"@mui/material": "^6.1.3",
"@radix-ui/react-avatar": "^1.0.4",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",

View File

@ -0,0 +1,242 @@
import { useCallback, useState } from 'react';
import { useForm, Controller, SubmitHandler } from 'react-hook-form';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { useMediaQuery } from 'usehooks-ts';
import { AuctionParams } from 'gql-client';
import {
ArrowRightCircleFilledIcon,
LoadingIcon,
} from 'components/shared/CustomIcon';
import { Heading } from '../../shared/Heading';
import { Button } from '../../shared/Button';
import { Select, SelectOption } from 'components/shared/Select';
import { Input } from 'components/shared/Input';
import { useToast } from 'components/shared/Toast';
import { useGQLClient } from '../../../context/GQLClientContext';
type ConfigureFormValues = {
option: string;
lrn?: string;
numProviders?: number;
maxPrice?: string;
};
const Configure = () => {
const [searchParams] = useSearchParams();
const templateId = searchParams.get('templateId');
const queryParams = new URLSearchParams(location.search);
const owner = queryParams.get('owner');
const name = queryParams.get('name');
const defaultBranch = queryParams.get('defaultBranch');
const fullName = queryParams.get('fullName');
const orgSlug = queryParams.get('orgSlug');
const templateOwner = queryParams.get('templateOwner');
const templateRepo = queryParams.get('templateRepo');
const isPrivate = queryParams.get('isPrivate') === 'true';
const navigate = useNavigate();
const { toast, dismiss } = useToast();
const client = useGQLClient();
const [isLoading, setIsLoading] = useState(false);
const { handleSubmit, control, watch } = useForm<ConfigureFormValues>({
defaultValues: { option: 'LRN' },
});
const selectedOption = watch('option');
const isTabletView = useMediaQuery('(min-width: 720px)'); // md:
const buttonSize = isTabletView ? { size: 'lg' as const } : {};
const onSubmit: SubmitHandler<ConfigureFormValues> = useCallback(
async (data) => {
setIsLoading(true);
try {
let lrn: string | undefined;
let auctionParams: AuctionParams | undefined;
if (data.option === 'LRN') {
lrn = data.lrn;
} else if (data.option === 'Auction') {
auctionParams = {
numProviders: Number(data.numProviders!),
maxPrice: (data.maxPrice!).toString(),
};
}
if (templateId) {
// Template-based project creation
const projectData: any = {
templateOwner,
templateRepo,
owner,
name,
isPrivate,
};
const { addProjectFromTemplate } = await client.addProjectFromTemplate(
orgSlug!,
projectData,
lrn,
auctionParams
);
data.option === 'Auction'
? navigate(
`/${orgSlug}/projects/create/success/${addProjectFromTemplate.id}?isAuction=true`,
)
: navigate(
`/${orgSlug}/projects/create/template/deploy?projectId=${addProjectFromTemplate.id}&templateId=${templateId}`
);
} else {
const { addProject } = await client.addProject(
orgSlug!,
{
name: fullName!,
prodBranch: defaultBranch!,
repository: fullName!,
template: 'webapp',
},
lrn,
auctionParams
);
data.option === 'Auction'
? navigate(
`/${orgSlug}/projects/create/success/${addProject.id}?isAuction=true`
)
: navigate(
`/${orgSlug}/projects/create/deploy?projectId=${addProject.id}`
);
}
} catch (error) {
console.error('Error creating project:', error);
toast({
id: 'error-creating-project',
title: 'Error creating project',
variant: 'error',
onDismiss: dismiss,
});
} finally {
setIsLoading(false);
}
},
[client, isPrivate, templateId, navigate, dismiss, toast]
);
return (
<div className="space-y-7">
<div className="flex justify-between">
<div className="space-y-1.5">
<Heading as="h4" className="md:text-lg font-medium">
Configure deployment
</Heading>
<Heading as="h5" className="text-sm font-sans text-elements-low-em">
The app can be deployed by setting the deployer LRN for a single
deployment or by creating a deployer auction for multiple
deployments
</Heading>
</div>
</div>
<form onSubmit={handleSubmit(onSubmit)}>
<div className="flex flex-col gap-4 lg:gap-7 w-full">
<div className="flex flex-col justify-start gap-3">
<Controller
name="option"
control={control}
render={({ field: { value, onChange } }) => (
<Select
label="Configuration Options"
value={
{
value: value || 'LRN',
label: value === 'Auction' ? 'Create Auction' : 'Deployer LRN',
} as SelectOption
}
onChange={(value) => onChange((value as SelectOption).value)}
options={[
{ value: 'LRN', label: 'Deployer LRN' },
{ value: 'Auction', label: 'Create Auction' },
]}
/>
)}
/>
</div>
{selectedOption === 'LRN' && (
<div className="flex flex-col justify-start gap-3">
<Heading as="h5" className="text-sm font-sans text-elements-low-em">
The app will be deployed by the configured deployer
</Heading>
<span className="text-sm text-elements-high-em">
Enter LRN for deployer
</span>
<Controller
name="lrn"
control={control}
render={({ field: { value, onChange } }) => (
<Input value={value} onChange={onChange} />
)}
/>
</div>
)}
{selectedOption === 'Auction' && (
<>
<div className="flex flex-col justify-start gap-3">
<Heading as="h5" className="text-sm font-sans text-elements-low-em">
Set the number of deployers and maximum price for each deployment
</Heading>
<span className="text-sm text-elements-high-em">
Number of Deployers
</span>
<Controller
name="numProviders"
control={control}
render={({ field: { value, onChange } }) => (
<Input type="number" value={value} onChange={onChange} />
)}
/>
</div>
<div className="flex flex-col justify-start gap-3">
<span className="text-sm text-elements-high-em">
Maximum Price (alnt)
</span>
<Controller
name="maxPrice"
control={control}
render={({ field: { value, onChange } }) => (
<Input type="number" value={value} onChange={onChange} />
)}
/>
</div>
</>
)}
<div>
<Button
{...buttonSize}
type="submit"
disabled={isLoading}
rightIcon={
isLoading ? (
<LoadingIcon className="animate-spin" />
) : (
<ArrowRightCircleFilledIcon />
)
}
>
{isLoading ? 'Deploying repo' : 'Deploy repo'}
</Button>
</div>
</div>
</form>
</div>
);
};
export default Configure;

View File

@ -38,36 +38,9 @@ export const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({
});
}
try {
setIsLoading(true);
const { addProject } = await client.addProject(orgSlug, {
name: `${repository.owner?.login}-${repository.name}`,
prodBranch: repository.default_branch as string,
repository: repository.full_name,
// TODO: Compute template from repo
template: 'webapp',
});
if (addProject) {
navigate(`import?projectId=${addProject.id}`);
} else {
toast({
id: 'failed-to-create-project',
title: 'Failed to create project',
variant: 'error',
onDismiss: dismiss,
});
}
} catch (error) {
console.error((error as Error).message);
toast({
id: 'failed-to-create-project',
title: 'Failed to create project',
variant: 'error',
onDismiss: dismiss,
});
} finally {
setIsLoading(false);
}
navigate(
`configure?owner=${repository.owner?.login}&name=${repository.name}&defaultBranch=${repository.default_branch}&fullName=${repository.full_name}&orgSlug=${orgSlug}`
);
}, [client, repository, orgSlug, setIsLoading, navigate, toast]);
return (

View File

@ -83,7 +83,7 @@ const DeploymentDetailsCard = ({
return (
<div className="flex md:flex-row flex-col gap-6 py-4 px-3 pb-6 mb-2 last:mb-0 last:pb-4 border-b border-border-separator last:border-b-transparent relative">
<div className="flex-1 flex justify-between w-full md:max-w-[25%] lg:max-w-[28%]">
<div className="flex-1 flex justify-between w-full md:max-w-[30%] lg:max-w-[33%]">
<div className="flex-1 w-full space-y-2 max-w-[90%] sm:max-w-full">
{/* DEPLOYMENT URL */}
{deployment.url && (
@ -96,7 +96,12 @@ const DeploymentDetailsCard = ({
</OverflownText>
</Heading>
)}
<span className="text-sm text-elements-low-em tracking-tight">
{deployment.deployerLrn && (
<span className="text-sm text-elements-low-em tracking-tight block mt-2">
Deployer LRN: {deployment.deployerLrn}
</span>
)}
<span className="text-sm text-elements-low-em tracking-tight block">
{deployment.environment === Environment.Production
? `Production ${deployment.isCurrent ? '(Current)' : ''}`
: 'Preview'}

View File

@ -0,0 +1,117 @@
import { useCallback, useEffect, useState } from 'react';
import { Auction, Project } from 'gql-client';
import {
Dialog,
DialogTitle,
DialogContent,
DialogActions,
} from '@mui/material';
import { CheckRoundFilledIcon, LoadingIcon } from 'components/shared/CustomIcon';
import { useGQLClient } from 'context/GQLClientContext';
import { Button, Heading, Tag } from 'components/shared';
const WAIT_DURATION = 5000;
export const AuctionCard = ({ project }: { project: Project }) => {
const [auctionStatus, setAuctionStatus] = useState<string>('');
const [deployerLrns, setDeployerLrns] = useState<string[]>([]);
const [auctionDetails, setAuctionDetails] = useState<Auction | null>(null);
const [openDialog, setOpenDialog] = useState<boolean>(false);
const client = useGQLClient();
const getIconByAuctionStatus = (status: string) =>
status === 'completed' ? <CheckRoundFilledIcon /> : <LoadingIcon className="animate-spin" />;
const checkAuctionStatus = useCallback(async () => {
const result = await client.getAuctionData(project.auctionId);
setAuctionStatus(result.status);
setAuctionDetails(result);
setDeployerLrns(project.deployerLrns);
}, [client, project.auctionId, project.deployerLrns]);
useEffect(() => {
if (auctionStatus !== 'completed') {
checkAuctionStatus();
const intervalId = setInterval(checkAuctionStatus, WAIT_DURATION);
return () => clearInterval(intervalId);
}
}, [auctionStatus, checkAuctionStatus]);
useEffect(() => {
if (auctionStatus === 'completed') {
const fetchUpdatedProject = async () => {
// Wait for 5 secs since the project is not immediately updated with deployer LRNs
await new Promise((resolve) => setTimeout(resolve, WAIT_DURATION));
const updatedProject = await client.getProject(project.id);
setDeployerLrns(updatedProject.project?.deployerLrns || []);
};
fetchUpdatedProject();
}
}, [auctionStatus, client, project.id]);
const renderAuctionStatus = useCallback(
() => (
<Tag
leftIcon={getIconByAuctionStatus(auctionStatus)}
size="xs"
type={auctionStatus === 'completed' ? 'positive' : 'emphasized'}
>
{auctionStatus.toUpperCase()}
</Tag>
),
[auctionStatus]
);
const handleOpenDialog = () => setOpenDialog(true);
const handleCloseDialog = () => setOpenDialog(false);
return (
<>
<div className="p-3 gap-2 rounded-xl border border-gray-200 transition-colors hover:bg-base-bg-alternate flex flex-col mt-8">
<div className="flex justify-between items-center">
<Heading className="text-lg leading-6 font-medium">Auction details</Heading>
<Button onClick={handleOpenDialog} variant="tertiary" size="sm">
View details
</Button>
</div>
<div className="flex justify-between items-center mt-1">
<span className="text-elements-high-em text-sm font-medium tracking-tight">Auction Status</span>
<div className="ml-2">{renderAuctionStatus()}</div>
</div>
<div className="flex justify-between items-center mt-2">
<span className="text-elements-high-em text-sm font-medium tracking-tight">Auction Id</span>
<span className="text-elements-mid-em text-sm text-right">
{project.auctionId}
</span>
</div>
{deployerLrns?.length > 0 && (
<div className="mt-3">
<span className="text-elements-high-em text-sm font-medium tracking-tight">Deployer LRNs</span>
{deployerLrns.map((lrn, index) => (
<p key={index} className="text-elements-mid-em text-sm">
{'\u2022'} {lrn}
</p>
))}
</div>
)}
</div>
<Dialog open={openDialog} onClose={handleCloseDialog} fullWidth maxWidth="md">
<DialogTitle>Auction Details</DialogTitle>
<DialogContent>
{auctionDetails && <pre>{JSON.stringify(auctionDetails, null, 2)}</pre>}
</DialogContent>
<DialogActions>
<Button onClick={handleCloseDialog}>Close</Button>
</DialogActions>
</Dialog>
</>
);
};

View File

@ -60,8 +60,8 @@ const DeleteProjectDialog = ({
<Modal.Body>
<Input
label={
"Deleting your project is irreversible. Enter your project's name " +
project.name +
"Deleting your project is irreversible. Enter your project's name " + '"' +
project.name + '"' +
' below to confirm you want to permanently delete it:'
}
id="input"

View File

@ -36,6 +36,7 @@ const deployment: Deployment = {
url: 'https://deploy1.example.com',
environment: Environment.Production,
isCurrent: true,
deployerLrn: 'lrn://example/deployers/webapp-deployer-api.test.com',
status: DeploymentStatus.Ready,
createdBy: {
id: 'user1',

View File

@ -31,6 +31,11 @@ const CreateWithTemplate = () => {
},
{
step: 2,
route: `/${orgSlug}/projects/create/template/configure`,
label: 'Configure',
},
{
step: 3,
route: `/${orgSlug}/projects/create/template/deploy`,
label: 'Deploy',
},

View File

@ -2,7 +2,8 @@ import NewProject from './index';
import CreateWithTemplate from './Template';
import { templateRoutes } from './template/routes';
import Id from './success/Id';
import Import from './Import';
import Configure from 'components/projects/create/Configure';
import Deploy from 'components/projects/create/Deploy';
export const createProjectRoutes = [
{
@ -19,7 +20,11 @@ export const createProjectRoutes = [
element: <Id />,
},
{
path: 'import',
element: <Import />,
path: 'configure',
element: <Configure />,
},
{
path: 'deploy',
element: <Deploy />,
},
];

View File

@ -1,11 +1,10 @@
import { Link, useParams } from 'react-router-dom';
import { Link, useParams, useSearchParams } from 'react-router-dom';
import Lottie from 'lottie-react';
import { Badge } from 'components/shared/Badge';
import { Button } from 'components/shared/Button';
import {
ArrowLeftCircleFilledIcon,
LinkChainIcon,
QuestionMarkRoundFilledIcon,
} from 'components/shared/CustomIcon';
import { Heading } from 'components/shared/Heading';
@ -19,6 +18,8 @@ const Id = () => {
const { id, orgSlug } = useParams();
const client = useGQLClient();
const [project, setProject] = useState<Project | null>(null);
const [searchParams] = useSearchParams();
const isAuction = searchParams.get('isAuction') === 'true';
const handleSetupDomain = async () => {
if (id) {
@ -51,22 +52,8 @@ const Id = () => {
{/* Heading */}
<div className="flex flex-col items-center gap-1.5">
<Heading as="h3" className="font-medium text-xl">
Project deployed successfully.
{isAuction? 'Auction created successfully.' : 'Project deployment created successfully.'}
</Heading>
<p className="flex flex-col items-center lg:flex-row font-sans gap-0.5 lg:gap-2 text-sm text-elements-high-em">
Your project has been deployed at{' '}
<Button
className="no-underline text-elements-link"
// TODO: use dynamic value
href={project ? `https://${project.subDomain}` : ''}
as="a"
variant="link-emphasized"
external
leftIcon={<LinkChainIcon />}
>
{project.subDomain}
</Button>
</p>
</div>
{/* Card */}

View File

@ -0,0 +1,7 @@
import ConfigureComponent from '../../../../../components/projects/create/Configure';
const Configure = () => {
return <ConfigureComponent />;
};
export default Configure;

View File

@ -6,7 +6,6 @@ import { useMediaQuery } from 'usehooks-ts';
import { RequestError } from 'octokit';
import { useOctokit } from '../../../../../context/OctokitContext';
import { useGQLClient } from '../../../../../context/GQLClientContext';
import { Template } from '../../../../../types/types';
import { Heading } from 'components/shared/Heading';
import { Input } from 'components/shared/Input';
@ -31,7 +30,6 @@ type SubmitRepoValues = {
const CreateRepo = () => {
const { octokit, isAuth } = useOctokit();
const { template } = useOutletContext<{ template: Template }>();
const client = useGQLClient();
const { orgSlug } = useParams();
const { toast, dismiss } = useToast();
@ -55,19 +53,8 @@ const CreateRepo = () => {
setIsLoading(true);
const { addProjectFromTemplate } = await client.addProjectFromTemplate(
orgSlug!,
{
templateOwner: owner,
templateRepo: repo,
owner: data.account,
name: data.repoName,
isPrivate: false,
},
);
navigate(
`deploy?projectId=${addProjectFromTemplate.id}&templateId=${template.id}`,
`configure?templateId=${template.id}&templateOwner=${owner}&templateRepo=${repo}&owner=${data.account}&name=${data.repoName}&isPrivate=false&orgSlug=${orgSlug}`
);
} catch (err) {
setIsLoading(false);
@ -203,7 +190,7 @@ const CreateRepo = () => {
)
}
>
Deploy
Next
</Button>
</div>
</div>

View File

@ -1,4 +1,5 @@
import CreateRepo from './index';
import Configure from './Configure';
import Deploy from './Deploy';
export const templateRoutes = [
@ -6,6 +7,10 @@ export const templateRoutes = [
index: true,
element: <CreateRepo />,
},
{
path: 'configure',
element: <Configure />,
},
{
path: 'deploy',
element: <Deploy />,

View File

@ -21,6 +21,7 @@ import { Activity } from 'components/projects/project/overview/Activity';
import { OverviewInfo } from 'components/projects/project/overview/OverviewInfo';
import { relativeTimeMs } from 'utils/time';
import { Domain, DomainStatus } from 'gql-client';
import { AuctionCard } from 'components/projects/project/overview/Activity/AuctionCard';
const COMMITS_PER_PAGE = 4;
@ -128,12 +129,15 @@ const OverviewTabPanel = () => {
<Heading className="text-lg leading-6 font-medium truncate">
{project.name}
</Heading>
<a
href={`https://${project.subDomain}`}
className="text-sm text-elements-low-em tracking-tight truncate"
>
{project.subDomain}
</a>
{project.baseDomains && project.baseDomains.length > 0 && project.baseDomains.map((baseDomain, index) => (
<a
key={index}
href={`https://${project.name}.${baseDomain}`}
className="text-sm text-elements-low-em tracking-tight truncate"
>
{baseDomain}
</a>
))}
</div>
</div>
<OverviewInfo label="Domain" icon={<GlobeIcon />}>
@ -205,6 +209,7 @@ const OverviewTabPanel = () => {
No current deployment found.
</p>
)}
{project.auctionId && <AuctionCard project={project}/>}
</div>
<Activity activities={activities} isLoading={fetchingActivities} />
</div>

View File

@ -2,7 +2,7 @@ import { useCallback, useEffect, useMemo, useState } from 'react';
import { useFieldArray, useForm } from 'react-hook-form';
import { useParams } from 'react-router-dom';
import { Collapse } from '@snowballtools/material-tailwind-react-fork';
import { Collapse, Checkbox } from '@snowballtools/material-tailwind-react-fork';
import AddEnvironmentVariableRow from 'components/projects/project/settings/AddEnvironmentVariableRow';
import DisplayEnvironmentVariables from 'components/projects/project/settings/DisplayEnvironmentVariables';
@ -11,7 +11,7 @@ import { EnvironmentVariablesFormValues } from '../../../../../types';
import HorizontalLine from 'components/HorizontalLine';
import { Heading } from 'components/shared/Heading';
import { Button } from 'components/shared/Button';
import { Checkbox } from 'components/shared/Checkbox';
// import { Checkbox } from 'components/shared/Checkbox';
import { PlusIcon } from 'components/shared/CustomIcon';
import { InlineNotification } from 'components/shared/InlineNotification';
import { ProjectSettingContainer } from 'components/projects/project/settings/ProjectSettingContainer';

View File

@ -102,6 +102,7 @@ export const deployment0: Deployment = {
domain: domain0,
commitMessage: 'Commit Message',
createdBy: user,
deployerLrn: 'lrn://deployer.apps.snowballtools.com ',
};
export const project: Project = {
@ -119,7 +120,9 @@ export const project: Project = {
organization: organization,
template: 'Template',
members: [member],
auctionId: '7553538436710373822151221341b43f577e07b0525d083cc9b2de98890138a1',
deployerLrns: ['lrn://deployer.apps.snowballtools.com '],
webhooks: ['beepboop'],
icon: 'Icon',
subDomain: 'SubDomain',
baseDomains: ['baseDomain'],
};

View File

@ -1 +1 @@
# dist
dist

View File

@ -1,295 +0,0 @@
declare enum Role {
Owner = "Owner",
Maintainer = "Maintainer",
Reader = "Reader"
}
declare enum Permission {
View = "View",
Edit = "Edit"
}
declare enum Environment {
Production = "Production",
Preview = "Preview",
Development = "Development"
}
declare enum DeploymentStatus {
Building = "Building",
Ready = "Ready",
Error = "Error",
Deleting = "Deleting"
}
declare enum DomainStatus {
Live = "Live",
Pending = "Pending"
}
type EnvironmentVariable = {
id: string;
environment: Environment;
key: string;
value: string;
createdAt: string;
updatedAt: string;
};
type Domain = {
id: string;
branch: string;
name: string;
status: DomainStatus;
redirectTo: Domain | null;
createdAt: string;
updatedAt: string;
};
type User = {
id: string;
name: string | null;
email: string;
isVerified: boolean;
createdAt: string;
updatedAt: string;
gitHubToken: string | null;
};
type Deployment = {
id: string;
domain: Domain;
branch: string;
commitHash: string;
commitMessage: string;
url?: string;
environment: Environment;
isCurrent: boolean;
status: DeploymentStatus;
createdBy: User;
createdAt: string;
updatedAt: string;
};
type OrganizationMember = {
id: string;
member: User;
role: Role;
createdAt: string;
updatedAt: string;
};
type ProjectMember = {
id: string;
member: User;
permissions: Permission[];
isPending: boolean;
createdAt: string;
updatedAt: string;
};
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;
};
type Organization = {
id: string;
name: string;
slug: string;
projects: OrganizationProject[];
createdAt: string;
updatedAt: string;
members: OrganizationMember[];
};
type Project = {
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;
organization: Organization;
icon: string;
subDomain: string;
};
type GetProjectMembersResponse = {
projectMembers: ProjectMember[];
};
type AddProjectMemberResponse = {
addProjectMember: boolean;
};
type RemoveProjectMemberResponse = {
removeProjectMember: boolean;
};
type UpdateProjectMemberResponse = {
updateProjectMember: boolean;
};
type GetDeploymentsResponse = {
deployments: Deployment[];
};
type GetEnvironmentVariablesResponse = {
environmentVariables: EnvironmentVariable[];
};
type GetOrganizationsResponse = {
organizations: Organization[];
};
type GetUserResponse = {
user: User;
};
type GetProjectResponse = {
project: Project | null;
};
type GetProjectsInOrganizationResponse = {
projectsInOrganization: Project[];
};
type GetDomainsResponse = {
domains: Domain[];
};
type SearchProjectsResponse = {
searchProjects: Project[];
};
type AddEnvironmentVariablesResponse = {
addEnvironmentVariables: boolean;
};
type AddEnvironmentVariableInput = {
environments: string[];
key: string;
value: string;
};
type UpdateEnvironmentVariableInput = {
key: string;
value: string;
};
type UpdateProjectMemberInput = {
permissions: Permission[];
};
type AddProjectMemberInput = {
email: string;
permissions: Permission[];
};
type UpdateEnvironmentVariableResponse = {
updateEnvironmentVariable: boolean;
};
type RemoveEnvironmentVariableResponse = {
removeEnvironmentVariable: boolean;
};
type UpdateDeploymentToProdResponse = {
updateDeploymentToProd: boolean;
};
type AddProjectFromTemplateResponse = {
addProjectFromTemplate: Project;
};
type AddProjectResponse = {
addProject: Project;
};
type UpdateProjectResponse = {
updateProject: boolean;
};
type UpdateDomainResponse = {
updateDomain: boolean;
};
type DeleteProjectResponse = {
deleteProject: boolean;
};
type DeleteDomainResponse = {
deleteDomain: boolean;
};
type AddProjectFromTemplateInput = {
templateOwner: string;
templateRepo: string;
owner: string;
name: string;
isPrivate: boolean;
};
type AddProjectInput = {
name: string;
repository: string;
prodBranch: string;
template?: string;
};
type UpdateProjectInput = {
name?: string;
description?: string;
prodBranch?: string;
webhooks?: string[];
organizationId?: string;
};
type UpdateDomainInput = {
name?: string;
branch?: string;
redirectToId?: string | null;
};
type RedeployToProdResponse = {
redeployToProd: boolean;
};
type RollbackDeploymentResponse = {
rollbackDeployment: boolean;
};
type DeleteDeploymentResponse = {
deleteDeployment: boolean;
};
type AddDomainInput = {
name: string;
};
type FilterDomainInput = {
branch?: string;
status?: DomainStatus;
};
type AddDomainResponse = {
addDomain: true;
};
type AuthenticateGitHubResponse = {
authenticateGitHub: {
token: string;
};
};
type UnauthenticateGitHubResponse = {
unauthenticateGitHub: boolean;
};
interface GraphQLConfig {
gqlEndpoint: string;
}
declare class GQLClient {
private client;
constructor(config: GraphQLConfig);
getUser(): Promise<GetUserResponse>;
getProject(projectId: string): Promise<GetProjectResponse>;
getProjectsInOrganization(organizationSlug: string): Promise<GetProjectsInOrganizationResponse>;
getOrganizations(): Promise<GetOrganizationsResponse>;
getDeployments(projectId: string): Promise<GetDeploymentsResponse>;
getEnvironmentVariables(projectId: string): Promise<GetEnvironmentVariablesResponse>;
getProjectMembers(projectId: string): Promise<GetProjectMembersResponse>;
addProjectMember(projectId: string, data: AddProjectMemberInput): Promise<AddProjectMemberResponse>;
updateProjectMember(projectMemberId: string, data: UpdateProjectMemberInput): Promise<UpdateProjectMemberResponse>;
removeProjectMember(projectMemberId: string): Promise<RemoveProjectMemberResponse>;
searchProjects(searchText: string): Promise<SearchProjectsResponse>;
addEnvironmentVariables(projectId: string, data: AddEnvironmentVariableInput[]): Promise<AddEnvironmentVariablesResponse>;
updateEnvironmentVariable(environmentVariableId: string, data: UpdateEnvironmentVariableInput): Promise<UpdateEnvironmentVariableResponse>;
removeEnvironmentVariable(environmentVariableId: string): Promise<RemoveEnvironmentVariableResponse>;
updateDeploymentToProd(deploymentId: string): Promise<UpdateDeploymentToProdResponse>;
addProjectFromTemplate(organizationSlug: string, data: AddProjectFromTemplateInput): Promise<AddProjectFromTemplateResponse>;
addProject(organizationSlug: string, data: AddProjectInput): Promise<AddProjectResponse>;
updateProject(projectId: string, data: UpdateProjectInput): Promise<UpdateProjectResponse>;
updateDomain(domainId: string, data: UpdateDomainInput): Promise<UpdateDomainResponse>;
redeployToProd(deploymentId: string): Promise<RedeployToProdResponse>;
deleteProject(projectId: string): Promise<DeleteProjectResponse>;
deleteDomain(domainId: string): Promise<DeleteDomainResponse>;
rollbackDeployment(projectId: string, deploymentId: string): Promise<RollbackDeploymentResponse>;
deleteDeployment(deploymentId: string): Promise<DeleteDeploymentResponse>;
addDomain(projectId: string, data: AddDomainInput): Promise<AddDomainResponse>;
getDomains(projectId: string, filter?: FilterDomainInput): Promise<GetDomainsResponse>;
authenticateGitHub(code: string): Promise<AuthenticateGitHubResponse>;
unauthenticateGithub(): Promise<UnauthenticateGitHubResponse>;
}
export { type AddDomainInput, type AddDomainResponse, type AddEnvironmentVariableInput, type AddEnvironmentVariablesResponse, type AddProjectFromTemplateInput, type AddProjectFromTemplateResponse, type AddProjectInput, type AddProjectMemberInput, type AddProjectMemberResponse, type AddProjectResponse, type AuthenticateGitHubResponse, type DeleteDeploymentResponse, type DeleteDomainResponse, type DeleteProjectResponse, type Deployment, DeploymentStatus, type Domain, DomainStatus, Environment, type EnvironmentVariable, type FilterDomainInput, GQLClient, type GetDeploymentsResponse, type GetDomainsResponse, type GetEnvironmentVariablesResponse, type GetOrganizationsResponse, type GetProjectMembersResponse, type GetProjectResponse, type GetProjectsInOrganizationResponse, type GetUserResponse, type GraphQLConfig, type Organization, type OrganizationMember, type OrganizationProject, Permission, type Project, type ProjectMember, type RedeployToProdResponse, type RemoveEnvironmentVariableResponse, type RemoveProjectMemberResponse, Role, type RollbackDeploymentResponse, type SearchProjectsResponse, type UnauthenticateGitHubResponse, type UpdateDeploymentToProdResponse, type UpdateDomainInput, type UpdateDomainResponse, type UpdateEnvironmentVariableInput, type UpdateEnvironmentVariableResponse, type UpdateProjectInput, type UpdateProjectMemberInput, type UpdateProjectMemberResponse, type UpdateProjectResponse, type User };

View File

@ -1,295 +0,0 @@
declare enum Role {
Owner = "Owner",
Maintainer = "Maintainer",
Reader = "Reader"
}
declare enum Permission {
View = "View",
Edit = "Edit"
}
declare enum Environment {
Production = "Production",
Preview = "Preview",
Development = "Development"
}
declare enum DeploymentStatus {
Building = "Building",
Ready = "Ready",
Error = "Error",
Deleting = "Deleting"
}
declare enum DomainStatus {
Live = "Live",
Pending = "Pending"
}
type EnvironmentVariable = {
id: string;
environment: Environment;
key: string;
value: string;
createdAt: string;
updatedAt: string;
};
type Domain = {
id: string;
branch: string;
name: string;
status: DomainStatus;
redirectTo: Domain | null;
createdAt: string;
updatedAt: string;
};
type User = {
id: string;
name: string | null;
email: string;
isVerified: boolean;
createdAt: string;
updatedAt: string;
gitHubToken: string | null;
};
type Deployment = {
id: string;
domain: Domain;
branch: string;
commitHash: string;
commitMessage: string;
url?: string;
environment: Environment;
isCurrent: boolean;
status: DeploymentStatus;
createdBy: User;
createdAt: string;
updatedAt: string;
};
type OrganizationMember = {
id: string;
member: User;
role: Role;
createdAt: string;
updatedAt: string;
};
type ProjectMember = {
id: string;
member: User;
permissions: Permission[];
isPending: boolean;
createdAt: string;
updatedAt: string;
};
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;
};
type Organization = {
id: string;
name: string;
slug: string;
projects: OrganizationProject[];
createdAt: string;
updatedAt: string;
members: OrganizationMember[];
};
type Project = {
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;
organization: Organization;
icon: string;
subDomain: string;
};
type GetProjectMembersResponse = {
projectMembers: ProjectMember[];
};
type AddProjectMemberResponse = {
addProjectMember: boolean;
};
type RemoveProjectMemberResponse = {
removeProjectMember: boolean;
};
type UpdateProjectMemberResponse = {
updateProjectMember: boolean;
};
type GetDeploymentsResponse = {
deployments: Deployment[];
};
type GetEnvironmentVariablesResponse = {
environmentVariables: EnvironmentVariable[];
};
type GetOrganizationsResponse = {
organizations: Organization[];
};
type GetUserResponse = {
user: User;
};
type GetProjectResponse = {
project: Project | null;
};
type GetProjectsInOrganizationResponse = {
projectsInOrganization: Project[];
};
type GetDomainsResponse = {
domains: Domain[];
};
type SearchProjectsResponse = {
searchProjects: Project[];
};
type AddEnvironmentVariablesResponse = {
addEnvironmentVariables: boolean;
};
type AddEnvironmentVariableInput = {
environments: string[];
key: string;
value: string;
};
type UpdateEnvironmentVariableInput = {
key: string;
value: string;
};
type UpdateProjectMemberInput = {
permissions: Permission[];
};
type AddProjectMemberInput = {
email: string;
permissions: Permission[];
};
type UpdateEnvironmentVariableResponse = {
updateEnvironmentVariable: boolean;
};
type RemoveEnvironmentVariableResponse = {
removeEnvironmentVariable: boolean;
};
type UpdateDeploymentToProdResponse = {
updateDeploymentToProd: boolean;
};
type AddProjectFromTemplateResponse = {
addProjectFromTemplate: Project;
};
type AddProjectResponse = {
addProject: Project;
};
type UpdateProjectResponse = {
updateProject: boolean;
};
type UpdateDomainResponse = {
updateDomain: boolean;
};
type DeleteProjectResponse = {
deleteProject: boolean;
};
type DeleteDomainResponse = {
deleteDomain: boolean;
};
type AddProjectFromTemplateInput = {
templateOwner: string;
templateRepo: string;
owner: string;
name: string;
isPrivate: boolean;
};
type AddProjectInput = {
name: string;
repository: string;
prodBranch: string;
template?: string;
};
type UpdateProjectInput = {
name?: string;
description?: string;
prodBranch?: string;
webhooks?: string[];
organizationId?: string;
};
type UpdateDomainInput = {
name?: string;
branch?: string;
redirectToId?: string | null;
};
type RedeployToProdResponse = {
redeployToProd: boolean;
};
type RollbackDeploymentResponse = {
rollbackDeployment: boolean;
};
type DeleteDeploymentResponse = {
deleteDeployment: boolean;
};
type AddDomainInput = {
name: string;
};
type FilterDomainInput = {
branch?: string;
status?: DomainStatus;
};
type AddDomainResponse = {
addDomain: true;
};
type AuthenticateGitHubResponse = {
authenticateGitHub: {
token: string;
};
};
type UnauthenticateGitHubResponse = {
unauthenticateGitHub: boolean;
};
interface GraphQLConfig {
gqlEndpoint: string;
}
declare class GQLClient {
private client;
constructor(config: GraphQLConfig);
getUser(): Promise<GetUserResponse>;
getProject(projectId: string): Promise<GetProjectResponse>;
getProjectsInOrganization(organizationSlug: string): Promise<GetProjectsInOrganizationResponse>;
getOrganizations(): Promise<GetOrganizationsResponse>;
getDeployments(projectId: string): Promise<GetDeploymentsResponse>;
getEnvironmentVariables(projectId: string): Promise<GetEnvironmentVariablesResponse>;
getProjectMembers(projectId: string): Promise<GetProjectMembersResponse>;
addProjectMember(projectId: string, data: AddProjectMemberInput): Promise<AddProjectMemberResponse>;
updateProjectMember(projectMemberId: string, data: UpdateProjectMemberInput): Promise<UpdateProjectMemberResponse>;
removeProjectMember(projectMemberId: string): Promise<RemoveProjectMemberResponse>;
searchProjects(searchText: string): Promise<SearchProjectsResponse>;
addEnvironmentVariables(projectId: string, data: AddEnvironmentVariableInput[]): Promise<AddEnvironmentVariablesResponse>;
updateEnvironmentVariable(environmentVariableId: string, data: UpdateEnvironmentVariableInput): Promise<UpdateEnvironmentVariableResponse>;
removeEnvironmentVariable(environmentVariableId: string): Promise<RemoveEnvironmentVariableResponse>;
updateDeploymentToProd(deploymentId: string): Promise<UpdateDeploymentToProdResponse>;
addProjectFromTemplate(organizationSlug: string, data: AddProjectFromTemplateInput): Promise<AddProjectFromTemplateResponse>;
addProject(organizationSlug: string, data: AddProjectInput): Promise<AddProjectResponse>;
updateProject(projectId: string, data: UpdateProjectInput): Promise<UpdateProjectResponse>;
updateDomain(domainId: string, data: UpdateDomainInput): Promise<UpdateDomainResponse>;
redeployToProd(deploymentId: string): Promise<RedeployToProdResponse>;
deleteProject(projectId: string): Promise<DeleteProjectResponse>;
deleteDomain(domainId: string): Promise<DeleteDomainResponse>;
rollbackDeployment(projectId: string, deploymentId: string): Promise<RollbackDeploymentResponse>;
deleteDeployment(deploymentId: string): Promise<DeleteDeploymentResponse>;
addDomain(projectId: string, data: AddDomainInput): Promise<AddDomainResponse>;
getDomains(projectId: string, filter?: FilterDomainInput): Promise<GetDomainsResponse>;
authenticateGitHub(code: string): Promise<AuthenticateGitHubResponse>;
unauthenticateGithub(): Promise<UnauthenticateGitHubResponse>;
}
export { type AddDomainInput, type AddDomainResponse, type AddEnvironmentVariableInput, type AddEnvironmentVariablesResponse, type AddProjectFromTemplateInput, type AddProjectFromTemplateResponse, type AddProjectInput, type AddProjectMemberInput, type AddProjectMemberResponse, type AddProjectResponse, type AuthenticateGitHubResponse, type DeleteDeploymentResponse, type DeleteDomainResponse, type DeleteProjectResponse, type Deployment, DeploymentStatus, type Domain, DomainStatus, Environment, type EnvironmentVariable, type FilterDomainInput, GQLClient, type GetDeploymentsResponse, type GetDomainsResponse, type GetEnvironmentVariablesResponse, type GetOrganizationsResponse, type GetProjectMembersResponse, type GetProjectResponse, type GetProjectsInOrganizationResponse, type GetUserResponse, type GraphQLConfig, type Organization, type OrganizationMember, type OrganizationProject, Permission, type Project, type ProjectMember, type RedeployToProdResponse, type RemoveEnvironmentVariableResponse, type RemoveProjectMemberResponse, Role, type RollbackDeploymentResponse, type SearchProjectsResponse, type UnauthenticateGitHubResponse, type UpdateDeploymentToProdResponse, type UpdateDomainInput, type UpdateDomainResponse, type UpdateEnvironmentVariableInput, type UpdateEnvironmentVariableResponse, type UpdateProjectInput, type UpdateProjectMemberInput, type UpdateProjectMemberResponse, type UpdateProjectResponse, type User };

View File

@ -1,748 +0,0 @@
"use strict";
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/index.ts
var src_exports = {};
__export(src_exports, {
DeploymentStatus: () => DeploymentStatus,
DomainStatus: () => DomainStatus,
Environment: () => Environment,
GQLClient: () => GQLClient,
Permission: () => Permission,
Role: () => Role
});
module.exports = __toCommonJS(src_exports);
// src/client.ts
var import_client3 = require("@apollo/client");
// src/queries.ts
var import_client = require("@apollo/client");
var getUser = import_client.gql`
query {
user {
id
name
email
createdAt
updatedAt
gitHubToken
}
}
`;
var getProject = import_client.gql`
query ($projectId: String!) {
project(projectId: $projectId) {
createdAt
description
id
name
template
updatedAt
prodBranch
framework
repository
webhooks
icon
subDomain
organization {
id
name
}
owner {
id
name
email
}
deployments {
id
branch
isCurrent
status
updatedAt
commitHash
createdAt
environment
domain {
status
branch
createdAt
updatedAt
id
name
}
createdBy {
id
name
}
}
}
}
`;
var getProjectsInOrganization = import_client.gql`
query ($organizationSlug: String!) {
projectsInOrganization(organizationSlug: $organizationSlug) {
id
name
createdAt
description
framework
prodBranch
webhooks
repository
updatedAt
icon
subDomain
deployments {
id
branch
isCurrent
status
updatedAt
commitHash
commitMessage
createdAt
environment
domain {
status
branch
createdAt
updatedAt
id
name
}
}
}
}
`;
var getOrganizations = import_client.gql`
query {
organizations {
id
name
slug
createdAt
updatedAt
}
}
`;
var getDeployments = import_client.gql`
query ($projectId: String!) {
deployments(projectId: $projectId) {
id
domain{
branch
createdAt
id
name
status
updatedAt
}
branch
commitHash
commitMessage
url
environment
isCurrent
status
createdAt
updatedAt
createdBy {
id
name
email
}
}
}
`;
var getEnvironmentVariables = import_client.gql`
query ($projectId: String!) {
environmentVariables(projectId: $projectId) {
createdAt
environment
id
key
updatedAt
value
}
}
`;
var getProjectMembers = import_client.gql`
query ($projectId: String!) {
projectMembers(projectId: $projectId) {
id
member {
id
name
email
isVerified
}
isPending
createdAt
updatedAt
permissions
}
}
`;
var searchProjects = import_client.gql`
query ($searchText: String!) {
searchProjects(searchText: $searchText) {
id
name
prodBranch
repository
createdAt
description
framework
prodBranch
webhooks
updatedAt
template
repository
organization {
id
name
slug
createdAt
updatedAt
}
}
}
`;
var getDomains = import_client.gql`
query ($projectId: String!, $filter: FilterDomainsInput) {
domains(projectId: $projectId, filter: $filter) {
branch
createdAt
redirectTo {
id
name
branch
status
}
id
name
status
updatedAt
}
}
`;
// src/mutations.ts
var import_client2 = require("@apollo/client");
var removeProjectMember = import_client2.gql`
mutation ($projectMemberId: String!) {
removeProjectMember(projectMemberId: $projectMemberId)
}
`;
var updateProjectMember = import_client2.gql`
mutation ($projectMemberId: String!, $data: UpdateProjectMemberInput) {
updateProjectMember(projectMemberId: $projectMemberId, data: $data)
}
`;
var addProjectMember = import_client2.gql`
mutation ($projectId: String!, $data: AddProjectMemberInput) {
addProjectMember(projectId: $projectId, data: $data)
}
`;
var addEnvironmentVariables = import_client2.gql`
mutation ($projectId: String!, $data: [AddEnvironmentVariableInput!]) {
addEnvironmentVariables(projectId: $projectId, data: $data)
}
`;
var updateEnvironmentVariable = import_client2.gql`
mutation (
$environmentVariableId: String!
$data: UpdateEnvironmentVariableInput!
) {
updateEnvironmentVariable(
environmentVariableId: $environmentVariableId
data: $data
)
}
`;
var removeEnvironmentVariable = import_client2.gql`
mutation ($environmentVariableId: String!) {
removeEnvironmentVariable(environmentVariableId: $environmentVariableId)
}
`;
var updateDeploymentToProd = import_client2.gql`
mutation ($deploymentId: String!) {
updateDeploymentToProd(deploymentId: $deploymentId)
}
`;
var addProjectFromTemplate = import_client2.gql`
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput) {
addProjectFromTemplate(organizationSlug: $organizationSlug, data: $data) {
id
}
}
`;
var addProject = import_client2.gql`
mutation ($organizationSlug: String!, $data: AddProjectInput) {
addProject(organizationSlug: $organizationSlug, data: $data) {
id
}
}
`;
var updateProjectMutation = import_client2.gql`
mutation ($projectId: String!, $data: UpdateProjectInput) {
updateProject(projectId: $projectId, data: $data)
}
`;
var updateDomainMutation = import_client2.gql`
mutation ($domainId: String!, $data: UpdateDomainInput!) {
updateDomain(domainId: $domainId, data: $data)
}
`;
var redeployToProd = import_client2.gql`
mutation ($deploymentId: String!) {
redeployToProd(deploymentId: $deploymentId)
}
`;
var deleteProject = import_client2.gql`
mutation ($projectId: String!) {
deleteProject(projectId: $projectId)
}
`;
var deleteDomain = import_client2.gql`
mutation ($domainId: String!) {
deleteDomain(domainId: $domainId)
}
`;
var rollbackDeployment = import_client2.gql`
mutation ($projectId: String!, $deploymentId: String!) {
rollbackDeployment(projectId: $projectId, deploymentId: $deploymentId)
}
`;
var deleteDeployment = import_client2.gql`
mutation ($deploymentId: String!) {
deleteDeployment(deploymentId: $deploymentId)
}
`;
var addDomain = import_client2.gql`
mutation ($projectId: String!, $data: AddDomainInput!) {
addDomain(projectId: $projectId, data: $data)
}
`;
var authenticateGitHub = import_client2.gql`
mutation ($code: String!) {
authenticateGitHub(code: $code) {
token
}
}
`;
var unauthenticateGitHub = import_client2.gql`
mutation {
unauthenticateGitHub
}
`;
// src/client.ts
var defaultOptions = {
watchQuery: {
fetchPolicy: "no-cache",
errorPolicy: "ignore"
},
query: {
fetchPolicy: "no-cache",
errorPolicy: "all"
}
};
var GQLClient = class {
constructor(config) {
this.client = new import_client3.ApolloClient({
uri: config.gqlEndpoint,
cache: new import_client3.InMemoryCache(),
defaultOptions,
credentials: "include"
});
}
getUser() {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getUser
});
return data;
});
}
getProject(projectId) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getProject,
variables: {
projectId
}
});
return data;
});
}
getProjectsInOrganization(organizationSlug) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getProjectsInOrganization,
variables: {
organizationSlug
}
});
return data;
});
}
getOrganizations() {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getOrganizations
});
return data;
});
}
getDeployments(projectId) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getDeployments,
variables: {
projectId
}
});
return data;
});
}
getEnvironmentVariables(projectId) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getEnvironmentVariables,
variables: {
projectId
}
});
return data;
});
}
getProjectMembers(projectId) {
return __async(this, null, function* () {
const result = yield this.client.query({
query: getProjectMembers,
variables: {
projectId
}
});
return result.data;
});
}
addProjectMember(projectId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addProjectMember,
variables: {
projectId,
data
}
});
return result.data;
});
}
updateProjectMember(projectMemberId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: updateProjectMember,
variables: {
projectMemberId,
data
}
});
return result.data;
});
}
removeProjectMember(projectMemberId) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: removeProjectMember,
variables: {
projectMemberId
}
});
return result.data;
});
}
searchProjects(searchText) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: searchProjects,
variables: {
searchText
}
});
return data;
});
}
addEnvironmentVariables(projectId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addEnvironmentVariables,
variables: {
projectId,
data
}
});
return result.data;
});
}
updateEnvironmentVariable(environmentVariableId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: updateEnvironmentVariable,
variables: {
environmentVariableId,
data
}
});
return result.data;
});
}
removeEnvironmentVariable(environmentVariableId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: removeEnvironmentVariable,
variables: {
environmentVariableId
}
});
return data;
});
}
updateDeploymentToProd(deploymentId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: updateDeploymentToProd,
variables: {
deploymentId
}
});
return data;
});
}
addProjectFromTemplate(organizationSlug, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addProjectFromTemplate,
variables: {
organizationSlug,
data
}
});
return result.data;
});
}
addProject(organizationSlug, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addProject,
variables: {
organizationSlug,
data
}
});
return result.data;
});
}
updateProject(projectId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: updateProjectMutation,
variables: {
projectId,
data
}
});
return result.data;
});
}
updateDomain(domainId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: updateDomainMutation,
variables: {
domainId,
data
}
});
return result.data;
});
}
redeployToProd(deploymentId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: redeployToProd,
variables: {
deploymentId
}
});
return data;
});
}
deleteProject(projectId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: deleteProject,
variables: {
projectId
}
});
return data;
});
}
deleteDomain(domainId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: deleteDomain,
variables: {
domainId
}
});
return data;
});
}
rollbackDeployment(projectId, deploymentId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: rollbackDeployment,
variables: {
projectId,
deploymentId
}
});
return data;
});
}
deleteDeployment(deploymentId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: deleteDeployment,
variables: {
deploymentId
}
});
return data;
});
}
addDomain(projectId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addDomain,
variables: {
projectId,
data
}
});
return result.data;
});
}
getDomains(projectId, filter) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getDomains,
variables: {
projectId,
filter
}
});
return data;
});
}
authenticateGitHub(code) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: authenticateGitHub,
variables: {
code
}
});
return data;
});
}
unauthenticateGithub() {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: unauthenticateGitHub
});
return data;
});
}
};
// src/types.ts
var Role = /* @__PURE__ */ ((Role2) => {
Role2["Owner"] = "Owner";
Role2["Maintainer"] = "Maintainer";
Role2["Reader"] = "Reader";
return Role2;
})(Role || {});
var Permission = /* @__PURE__ */ ((Permission2) => {
Permission2["View"] = "View";
Permission2["Edit"] = "Edit";
return Permission2;
})(Permission || {});
var Environment = /* @__PURE__ */ ((Environment2) => {
Environment2["Production"] = "Production";
Environment2["Preview"] = "Preview";
Environment2["Development"] = "Development";
return Environment2;
})(Environment || {});
var DeploymentStatus = /* @__PURE__ */ ((DeploymentStatus2) => {
DeploymentStatus2["Building"] = "Building";
DeploymentStatus2["Ready"] = "Ready";
DeploymentStatus2["Error"] = "Error";
DeploymentStatus2["Deleting"] = "Deleting";
return DeploymentStatus2;
})(DeploymentStatus || {});
var DomainStatus = /* @__PURE__ */ ((DomainStatus2) => {
DomainStatus2["Live"] = "Live";
DomainStatus2["Pending"] = "Pending";
return DomainStatus2;
})(DomainStatus || {});
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
DeploymentStatus,
DomainStatus,
Environment,
GQLClient,
Permission,
Role
});
//# sourceMappingURL=index.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,720 +0,0 @@
var __async = (__this, __arguments, generator) => {
return new Promise((resolve, reject) => {
var fulfilled = (value) => {
try {
step(generator.next(value));
} catch (e) {
reject(e);
}
};
var rejected = (value) => {
try {
step(generator.throw(value));
} catch (e) {
reject(e);
}
};
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
step((generator = generator.apply(__this, __arguments)).next());
});
};
// src/client.ts
import {
ApolloClient,
InMemoryCache
} from "@apollo/client";
// src/queries.ts
import { gql } from "@apollo/client";
var getUser = gql`
query {
user {
id
name
email
createdAt
updatedAt
gitHubToken
}
}
`;
var getProject = gql`
query ($projectId: String!) {
project(projectId: $projectId) {
createdAt
description
id
name
template
updatedAt
prodBranch
framework
repository
webhooks
icon
subDomain
organization {
id
name
}
owner {
id
name
email
}
deployments {
id
branch
isCurrent
status
updatedAt
commitHash
createdAt
environment
domain {
status
branch
createdAt
updatedAt
id
name
}
createdBy {
id
name
}
}
}
}
`;
var getProjectsInOrganization = gql`
query ($organizationSlug: String!) {
projectsInOrganization(organizationSlug: $organizationSlug) {
id
name
createdAt
description
framework
prodBranch
webhooks
repository
updatedAt
icon
subDomain
deployments {
id
branch
isCurrent
status
updatedAt
commitHash
commitMessage
createdAt
environment
domain {
status
branch
createdAt
updatedAt
id
name
}
}
}
}
`;
var getOrganizations = gql`
query {
organizations {
id
name
slug
createdAt
updatedAt
}
}
`;
var getDeployments = gql`
query ($projectId: String!) {
deployments(projectId: $projectId) {
id
domain{
branch
createdAt
id
name
status
updatedAt
}
branch
commitHash
commitMessage
url
environment
isCurrent
status
createdAt
updatedAt
createdBy {
id
name
email
}
}
}
`;
var getEnvironmentVariables = gql`
query ($projectId: String!) {
environmentVariables(projectId: $projectId) {
createdAt
environment
id
key
updatedAt
value
}
}
`;
var getProjectMembers = gql`
query ($projectId: String!) {
projectMembers(projectId: $projectId) {
id
member {
id
name
email
isVerified
}
isPending
createdAt
updatedAt
permissions
}
}
`;
var searchProjects = gql`
query ($searchText: String!) {
searchProjects(searchText: $searchText) {
id
name
prodBranch
repository
createdAt
description
framework
prodBranch
webhooks
updatedAt
template
repository
organization {
id
name
slug
createdAt
updatedAt
}
}
}
`;
var getDomains = gql`
query ($projectId: String!, $filter: FilterDomainsInput) {
domains(projectId: $projectId, filter: $filter) {
branch
createdAt
redirectTo {
id
name
branch
status
}
id
name
status
updatedAt
}
}
`;
// src/mutations.ts
import { gql as gql2 } from "@apollo/client";
var removeProjectMember = gql2`
mutation ($projectMemberId: String!) {
removeProjectMember(projectMemberId: $projectMemberId)
}
`;
var updateProjectMember = gql2`
mutation ($projectMemberId: String!, $data: UpdateProjectMemberInput) {
updateProjectMember(projectMemberId: $projectMemberId, data: $data)
}
`;
var addProjectMember = gql2`
mutation ($projectId: String!, $data: AddProjectMemberInput) {
addProjectMember(projectId: $projectId, data: $data)
}
`;
var addEnvironmentVariables = gql2`
mutation ($projectId: String!, $data: [AddEnvironmentVariableInput!]) {
addEnvironmentVariables(projectId: $projectId, data: $data)
}
`;
var updateEnvironmentVariable = gql2`
mutation (
$environmentVariableId: String!
$data: UpdateEnvironmentVariableInput!
) {
updateEnvironmentVariable(
environmentVariableId: $environmentVariableId
data: $data
)
}
`;
var removeEnvironmentVariable = gql2`
mutation ($environmentVariableId: String!) {
removeEnvironmentVariable(environmentVariableId: $environmentVariableId)
}
`;
var updateDeploymentToProd = gql2`
mutation ($deploymentId: String!) {
updateDeploymentToProd(deploymentId: $deploymentId)
}
`;
var addProjectFromTemplate = gql2`
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput) {
addProjectFromTemplate(organizationSlug: $organizationSlug, data: $data) {
id
}
}
`;
var addProject = gql2`
mutation ($organizationSlug: String!, $data: AddProjectInput) {
addProject(organizationSlug: $organizationSlug, data: $data) {
id
}
}
`;
var updateProjectMutation = gql2`
mutation ($projectId: String!, $data: UpdateProjectInput) {
updateProject(projectId: $projectId, data: $data)
}
`;
var updateDomainMutation = gql2`
mutation ($domainId: String!, $data: UpdateDomainInput!) {
updateDomain(domainId: $domainId, data: $data)
}
`;
var redeployToProd = gql2`
mutation ($deploymentId: String!) {
redeployToProd(deploymentId: $deploymentId)
}
`;
var deleteProject = gql2`
mutation ($projectId: String!) {
deleteProject(projectId: $projectId)
}
`;
var deleteDomain = gql2`
mutation ($domainId: String!) {
deleteDomain(domainId: $domainId)
}
`;
var rollbackDeployment = gql2`
mutation ($projectId: String!, $deploymentId: String!) {
rollbackDeployment(projectId: $projectId, deploymentId: $deploymentId)
}
`;
var deleteDeployment = gql2`
mutation ($deploymentId: String!) {
deleteDeployment(deploymentId: $deploymentId)
}
`;
var addDomain = gql2`
mutation ($projectId: String!, $data: AddDomainInput!) {
addDomain(projectId: $projectId, data: $data)
}
`;
var authenticateGitHub = gql2`
mutation ($code: String!) {
authenticateGitHub(code: $code) {
token
}
}
`;
var unauthenticateGitHub = gql2`
mutation {
unauthenticateGitHub
}
`;
// src/client.ts
var defaultOptions = {
watchQuery: {
fetchPolicy: "no-cache",
errorPolicy: "ignore"
},
query: {
fetchPolicy: "no-cache",
errorPolicy: "all"
}
};
var GQLClient = class {
constructor(config) {
this.client = new ApolloClient({
uri: config.gqlEndpoint,
cache: new InMemoryCache(),
defaultOptions,
credentials: "include"
});
}
getUser() {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getUser
});
return data;
});
}
getProject(projectId) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getProject,
variables: {
projectId
}
});
return data;
});
}
getProjectsInOrganization(organizationSlug) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getProjectsInOrganization,
variables: {
organizationSlug
}
});
return data;
});
}
getOrganizations() {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getOrganizations
});
return data;
});
}
getDeployments(projectId) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getDeployments,
variables: {
projectId
}
});
return data;
});
}
getEnvironmentVariables(projectId) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getEnvironmentVariables,
variables: {
projectId
}
});
return data;
});
}
getProjectMembers(projectId) {
return __async(this, null, function* () {
const result = yield this.client.query({
query: getProjectMembers,
variables: {
projectId
}
});
return result.data;
});
}
addProjectMember(projectId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addProjectMember,
variables: {
projectId,
data
}
});
return result.data;
});
}
updateProjectMember(projectMemberId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: updateProjectMember,
variables: {
projectMemberId,
data
}
});
return result.data;
});
}
removeProjectMember(projectMemberId) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: removeProjectMember,
variables: {
projectMemberId
}
});
return result.data;
});
}
searchProjects(searchText) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: searchProjects,
variables: {
searchText
}
});
return data;
});
}
addEnvironmentVariables(projectId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addEnvironmentVariables,
variables: {
projectId,
data
}
});
return result.data;
});
}
updateEnvironmentVariable(environmentVariableId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: updateEnvironmentVariable,
variables: {
environmentVariableId,
data
}
});
return result.data;
});
}
removeEnvironmentVariable(environmentVariableId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: removeEnvironmentVariable,
variables: {
environmentVariableId
}
});
return data;
});
}
updateDeploymentToProd(deploymentId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: updateDeploymentToProd,
variables: {
deploymentId
}
});
return data;
});
}
addProjectFromTemplate(organizationSlug, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addProjectFromTemplate,
variables: {
organizationSlug,
data
}
});
return result.data;
});
}
addProject(organizationSlug, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addProject,
variables: {
organizationSlug,
data
}
});
return result.data;
});
}
updateProject(projectId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: updateProjectMutation,
variables: {
projectId,
data
}
});
return result.data;
});
}
updateDomain(domainId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: updateDomainMutation,
variables: {
domainId,
data
}
});
return result.data;
});
}
redeployToProd(deploymentId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: redeployToProd,
variables: {
deploymentId
}
});
return data;
});
}
deleteProject(projectId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: deleteProject,
variables: {
projectId
}
});
return data;
});
}
deleteDomain(domainId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: deleteDomain,
variables: {
domainId
}
});
return data;
});
}
rollbackDeployment(projectId, deploymentId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: rollbackDeployment,
variables: {
projectId,
deploymentId
}
});
return data;
});
}
deleteDeployment(deploymentId) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: deleteDeployment,
variables: {
deploymentId
}
});
return data;
});
}
addDomain(projectId, data) {
return __async(this, null, function* () {
const result = yield this.client.mutate({
mutation: addDomain,
variables: {
projectId,
data
}
});
return result.data;
});
}
getDomains(projectId, filter) {
return __async(this, null, function* () {
const { data } = yield this.client.query({
query: getDomains,
variables: {
projectId,
filter
}
});
return data;
});
}
authenticateGitHub(code) {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: authenticateGitHub,
variables: {
code
}
});
return data;
});
}
unauthenticateGithub() {
return __async(this, null, function* () {
const { data } = yield this.client.mutate({
mutation: unauthenticateGitHub
});
return data;
});
}
};
// src/types.ts
var Role = /* @__PURE__ */ ((Role2) => {
Role2["Owner"] = "Owner";
Role2["Maintainer"] = "Maintainer";
Role2["Reader"] = "Reader";
return Role2;
})(Role || {});
var Permission = /* @__PURE__ */ ((Permission2) => {
Permission2["View"] = "View";
Permission2["Edit"] = "Edit";
return Permission2;
})(Permission || {});
var Environment = /* @__PURE__ */ ((Environment2) => {
Environment2["Production"] = "Production";
Environment2["Preview"] = "Preview";
Environment2["Development"] = "Development";
return Environment2;
})(Environment || {});
var DeploymentStatus = /* @__PURE__ */ ((DeploymentStatus2) => {
DeploymentStatus2["Building"] = "Building";
DeploymentStatus2["Ready"] = "Ready";
DeploymentStatus2["Error"] = "Error";
DeploymentStatus2["Deleting"] = "Deleting";
return DeploymentStatus2;
})(DeploymentStatus || {});
var DomainStatus = /* @__PURE__ */ ((DomainStatus2) => {
DomainStatus2["Live"] = "Live";
DomainStatus2["Pending"] = "Pending";
return DomainStatus2;
})(DomainStatus || {});
export {
DeploymentStatus,
DomainStatus,
Environment,
GQLClient,
Permission,
Role
};
//# sourceMappingURL=index.mjs.map

File diff suppressed because one or more lines are too long

View File

@ -16,4 +16,4 @@
"dependencies": {
"@apollo/client": "^3.8.9"
}
}
}

View File

@ -230,13 +230,17 @@ export class GQLClient {
async addProjectFromTemplate(
organizationSlug: string,
data: types.AddProjectFromTemplateInput
data: types.AddProjectFromTemplateInput,
lrn?: string,
auctionParams?: types.AuctionParams,
): Promise<types.AddProjectFromTemplateResponse> {
const result = await this.client.mutate({
mutation: mutations.addProjectFromTemplate,
variables: {
organizationSlug,
data,
lrn,
auctionParams
},
});
@ -245,13 +249,17 @@ export class GQLClient {
async addProject(
organizationSlug: string,
data: types.AddProjectInput
data: types.AddProjectInput,
lrn?: string,
auctionParams?: types.AuctionParams,
): Promise<types.AddProjectResponse> {
const result = await this.client.mutate({
mutation: mutations.addProject,
variables: {
organizationSlug,
data,
lrn,
auctionParams
},
});
@ -401,4 +409,15 @@ export class GQLClient {
return data;
}
async getAuctionData(auctionId: string): Promise<types.Auction> {
const { data } = await this.client.query({
query: queries.getAuctionData,
variables: {
auctionId,
},
});
return data.getAuctionData;
}
}

View File

@ -49,16 +49,16 @@ export const updateDeploymentToProd = gql`
`;
export const addProjectFromTemplate = gql`
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput) {
addProjectFromTemplate(organizationSlug: $organizationSlug, data: $data) {
mutation ($organizationSlug: String!, $data: AddProjectFromTemplateInput, $lrn: String, $auctionParams: AuctionParams) {
addProjectFromTemplate(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionParams: $auctionParams) {
id
}
}
`;
export const addProject = gql`
mutation ($organizationSlug: String!, $data: AddProjectInput) {
addProject(organizationSlug: $organizationSlug, data: $data) {
mutation ($organizationSlug: String!, $data: AddProjectInput!, $lrn: String, $auctionParams: AuctionParams) {
addProject(organizationSlug: $organizationSlug, data: $data, lrn: $lrn, auctionParams: $auctionParams) {
id
}
}

View File

@ -23,11 +23,13 @@ query ($projectId: String!) {
template
updatedAt
prodBranch
auctionId
deployerLrns
framework
repository
webhooks
icon
subDomain
baseDomains
organization {
id
name
@ -41,6 +43,7 @@ query ($projectId: String!) {
id
branch
isCurrent
baseDomain
status
updatedAt
commitHash
@ -71,16 +74,19 @@ query ($organizationSlug: String!) {
createdAt
description
framework
auctionId
deployerLrns
prodBranch
webhooks
repository
updatedAt
icon
subDomain
baseDomains
deployments {
id
branch
isCurrent
baseDomain
status
updatedAt
commitHash
@ -128,8 +134,10 @@ query ($projectId: String!) {
commitHash
commitMessage
url
deployerLrn
environment
isCurrent
baseDomain
status
createdAt
updatedAt
@ -183,6 +191,8 @@ query ($searchText: String!) {
createdAt
description
framework
auctionId
deployerLrns
prodBranch
webhooks
updatedAt
@ -217,3 +227,63 @@ query ($projectId: String!, $filter: FilterDomainsInput) {
}
}
`;
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
}
}
}
}
`;

View File

@ -25,6 +25,45 @@ export enum DeploymentStatus {
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",
@ -66,8 +105,10 @@ export type Deployment = {
commitHash: string;
commitMessage: string;
url?: string;
deployerLrn: string;
environment: Environment;
isCurrent: boolean;
baseDomain?: string;
status: DeploymentStatus;
createdBy: User;
createdAt: string;
@ -128,6 +169,8 @@ export type Project = {
description: string;
template: string;
framework: string;
deployerLrns: string[];
auctionId: string;
webhooks: string[];
members: ProjectMember[];
environmentVariables: EnvironmentVariable[];
@ -135,7 +178,7 @@ export type Project = {
updatedAt: string;
organization: Organization;
icon: string;
subDomain: string;
baseDomains?: string[] | null;
};
export type GetProjectMembersResponse = {
@ -309,3 +352,8 @@ export type AuthenticateGitHubResponse = {
export type UnauthenticateGitHubResponse = {
unauthenticateGitHub: boolean;
};
export type AuctionParams = {
maxPrice: string;
numProviders: number;
};

372
yarn.lock
View File

@ -213,6 +213,14 @@
"@babel/highlight" "^7.24.2"
picocolors "^1.0.0"
"@babel/code-frame@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.25.7.tgz#438f2c524071531d643c6f0188e1e28f130cebc7"
integrity sha512-0xZJFNE5XMpENsgfHYTw8FbX4kv53mFLn2i3XPoq69LyhYSCBJtitaHx9QnsVTrsogI4Z3+HtEfZ2/GFPOtf5g==
dependencies:
"@babel/highlight" "^7.25.7"
picocolors "^1.0.0"
"@babel/compat-data@^7.22.6", "@babel/compat-data@^7.23.5", "@babel/compat-data@^7.24.4":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.24.4.tgz#6f102372e9094f25d908ca0d34fc74c74606059a"
@ -280,6 +288,16 @@
"@jridgewell/trace-mapping" "^0.3.25"
jsesc "^2.5.1"
"@babel/generator@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.25.7.tgz#de86acbeb975a3e11ee92dd52223e6b03b479c56"
integrity sha512-5Dqpl5fyV9pIAD62yK9P7fcA768uVPUyrQmqpqstHWgMma4feF1x/oFysBCVZLY5wJ2GkMUCdsNDnGZrPoR6rA==
dependencies:
"@babel/types" "^7.25.7"
"@jridgewell/gen-mapping" "^0.3.5"
"@jridgewell/trace-mapping" "^0.3.25"
jsesc "^3.0.2"
"@babel/helper-annotate-as-pure@^7.22.5":
version "7.22.5"
resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882"
@ -367,6 +385,14 @@
dependencies:
"@babel/types" "^7.24.5"
"@babel/helper-module-imports@^7.16.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.7.tgz#dba00d9523539152906ba49263e36d7261040472"
integrity sha512-o0xCgpNmRohmnoWKQ0Ij8IdddjyBFE4T2kagL/x6M3+4zUgc+4qTOUBoNe4XxDskt1HPKO007ZPiMgLDq2s7Kw==
dependencies:
"@babel/traverse" "^7.25.7"
"@babel/types" "^7.25.7"
"@babel/helper-module-imports@^7.22.15", "@babel/helper-module-imports@^7.24.1", "@babel/helper-module-imports@^7.24.3":
version "7.24.3"
resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.24.3.tgz#6ac476e6d168c7c23ff3ba3cf4f7841d46ac8128"
@ -471,6 +497,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.1.tgz#f99c36d3593db9540705d0739a1f10b5e20c696e"
integrity sha512-2ofRCjnnA9y+wk8b9IAREroeUP02KHp431N2mhKniy2yKIDKpbrHv9eXwm8cBeWQYcJmzv5qKCu65P47eCF7CQ==
"@babel/helper-string-parser@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.7.tgz#d50e8d37b1176207b4fe9acedec386c565a44a54"
integrity sha512-CbkjYdsJNHFk8uqpEkpCvRs3YRp9tY6FmFY7wLMSYuGYkrdUi7r2lc4/wqsvlHoMznX3WJ9IP8giGPq68T/Y6g==
"@babel/helper-validator-identifier@^7.22.20":
version "7.22.20"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0"
@ -481,6 +512,11 @@
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.5.tgz#918b1a7fa23056603506370089bd990d8720db62"
integrity sha512-3q93SSKX2TWCG30M2G2kwaKeTYgEUp5Snjuj8qm729SObL6nbtUldAi37qbxkD5gg3xnBio+f9nqpSepGZMvxA==
"@babel/helper-validator-identifier@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.7.tgz#77b7f60c40b15c97df735b38a66ba1d7c3e93da5"
integrity sha512-AM6TzwYqGChO45oiuPqwL2t20/HdMC1rTPAesnBCgPCSF1x3oN9MVUwQV2iyz4xqWrctwK5RNC8LV22kaQCNYg==
"@babel/helper-validator-option@^7.23.5":
version "7.23.5"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz#907a3fbd4523426285365d1206c423c4c5520307"
@ -523,6 +559,16 @@
js-tokens "^4.0.0"
picocolors "^1.0.0"
"@babel/highlight@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.25.7.tgz#20383b5f442aa606e7b5e3043b0b1aafe9f37de5"
integrity sha512-iYyACpW3iW8Fw+ZybQK+drQre+ns/tKpXbNESfrhNnPLIklLbXr7MYJ6gPEd0iETGLOK+SxMjVvKb/ffmk+FEw==
dependencies:
"@babel/helper-validator-identifier" "^7.25.7"
chalk "^2.4.2"
js-tokens "^4.0.0"
picocolors "^1.0.0"
"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.0", "@babel/parser@^7.24.0", "@babel/parser@^7.24.1", "@babel/parser@^7.24.4":
version "7.24.4"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.4.tgz#234487a110d89ad5a3ed4a8a566c36b9453e8c88"
@ -533,6 +579,13 @@
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.5.tgz#4a4d5ab4315579e5398a82dcf636ca80c3392790"
integrity sha512-EOv5IK8arwh3LI47dz1b0tKUb/1uhHAnHJOrjgtQMIpu1uXd9mlFrJg9IUgGUgZ41Ch0K8REPTYpO7B76b4vJg==
"@babel/parser@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.25.7.tgz#99b927720f4ddbfeb8cd195a363ed4532f87c590"
integrity sha512-aZn7ETtQsjjGG5HruveUK06cU3Hljuhd9Iojm4M8WWv3wLE6OkE5PWbDUkItmMgegmccaITudyuW5RPYrYlgWw==
dependencies:
"@babel/types" "^7.25.7"
"@babel/plugin-bugfix-firefox-class-in-computed-class-key@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.24.5.tgz#4c3685eb9cd790bcad2843900fe0250c91ccf895"
@ -1283,6 +1336,13 @@
dependencies:
regenerator-runtime "^0.14.0"
"@babel/runtime@^7.18.3", "@babel/runtime@^7.25.6", "@babel/runtime@^7.5.5", "@babel/runtime@^7.8.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.25.7.tgz#7ffb53c37a8f247c8c4d335e89cdf16a2e0d0fb6"
integrity sha512-FjoyLe754PMiYsFaN5C94ttGiOmBNYTf6pLr4xXHAT5uctHb092PBszndLDR5XA/jghQvn4n7JMHl7dmTgbm9w==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/template@^7.22.15", "@babel/template@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.24.0.tgz#c6a524aa93a4a05d66aaf31654258fae69d87d50"
@ -1292,6 +1352,15 @@
"@babel/parser" "^7.24.0"
"@babel/types" "^7.24.0"
"@babel/template@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.7.tgz#27f69ce382855d915b14ab0fe5fb4cbf88fa0769"
integrity sha512-wRwtAgI3bAS+JGU2upWNL9lSlDcRCqD05BZ1n3X2ONLH1WilFP6O1otQjeMK/1g0pvYcXC7b/qVUB1keofjtZA==
dependencies:
"@babel/code-frame" "^7.25.7"
"@babel/parser" "^7.25.7"
"@babel/types" "^7.25.7"
"@babel/traverse@^7.18.9", "@babel/traverse@^7.24.5":
version "7.24.5"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.24.5.tgz#972aa0bc45f16983bf64aa1f877b2dd0eea7e6f8"
@ -1324,6 +1393,19 @@
debug "^4.3.1"
globals "^11.1.0"
"@babel/traverse@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.25.7.tgz#83e367619be1cab8e4f2892ef30ba04c26a40fa8"
integrity sha512-jatJPT1Zjqvh/1FyJs6qAHL+Dzb7sTb+xr7Q+gM1b+1oBsMsQQ4FkVKb6dFlJvLlVssqkRzV05Jzervt9yhnzg==
dependencies:
"@babel/code-frame" "^7.25.7"
"@babel/generator" "^7.25.7"
"@babel/parser" "^7.25.7"
"@babel/template" "^7.25.7"
"@babel/types" "^7.25.7"
debug "^4.3.1"
globals "^11.1.0"
"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.23.0", "@babel/types@^7.24.0":
version "7.24.0"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.0.tgz#3b951f435a92e7333eba05b7566fd297960ea1bf"
@ -1342,6 +1424,15 @@
"@babel/helper-validator-identifier" "^7.24.5"
to-fast-properties "^2.0.0"
"@babel/types@^7.25.7":
version "7.25.7"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.25.7.tgz#1b7725c1d3a59f328cb700ce704c46371e6eef9b"
integrity sha512-vwIVdXG+j+FOpkwqHRcBgHLYNL7XMkufrlaFvL9o6Ai9sJn9+PdyIL5qa0XzTZw084c+u9LOls53eoZWP/W5WQ==
dependencies:
"@babel/helper-string-parser" "^7.25.7"
"@babel/helper-validator-identifier" "^7.25.7"
to-fast-properties "^2.0.0"
"@base2/pretty-print-object@1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@base2/pretty-print-object/-/pretty-print-object-1.0.1.tgz#371ba8be66d556812dc7fb169ebc3c08378f69d4"
@ -1431,10 +1522,10 @@
resolved "https://registry.yarnpkg.com/@bugsnag/safe-json-stringify/-/safe-json-stringify-6.0.0.tgz#22abdcd83e008c369902976730c34c150148a758"
integrity sha512-htzFO1Zc57S8kgdRK9mLcPVTW1BY2ijfH7Dk2CeZmspTWKdKqSo1iwmqrq2WtRjFlo8aRZYgLX0wFrDXF/9DLA==
"@cerc-io/registry-sdk@^0.2.5":
version "0.2.10"
resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fregistry-sdk/-/0.2.10/registry-sdk-0.2.10.tgz#15773ea36a862585cdcb0991cbf075736f845f96"
integrity sha512-xxVD7ylrN951TFoSFbluz7mt4SwSCv7z+yry3jGd8v8TWnycoBMMrrYSTfETs6Ydxwziiz/uLrRwk59vFZxLEA==
"@cerc-io/registry-sdk@^0.2.11":
version "0.2.11"
resolved "https://git.vdb.to/api/packages/cerc-io/npm/%40cerc-io%2Fregistry-sdk/-/0.2.11/registry-sdk-0.2.11.tgz#019b792c68f440f2cfca5af2f49e1205bb33ba72"
integrity sha512-IipqJzaBQEXMNH6yWFG2E/o0U6IAXw35PBMHx6QIboVu/sMNLIsWy1P8MmR8C8xYsmHOhgXLsC4hYSeFMXrqFw==
dependencies:
"@cosmjs/amino" "^0.28.1"
"@cosmjs/crypto" "^0.28.1"
@ -1848,6 +1939,39 @@
resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70"
integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==
"@emotion/babel-plugin@^11.12.0":
version "11.12.0"
resolved "https://registry.yarnpkg.com/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz#7b43debb250c313101b3f885eba634f1d723fcc2"
integrity sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==
dependencies:
"@babel/helper-module-imports" "^7.16.7"
"@babel/runtime" "^7.18.3"
"@emotion/hash" "^0.9.2"
"@emotion/memoize" "^0.9.0"
"@emotion/serialize" "^1.2.0"
babel-plugin-macros "^3.1.0"
convert-source-map "^1.5.0"
escape-string-regexp "^4.0.0"
find-root "^1.1.0"
source-map "^0.5.7"
stylis "4.2.0"
"@emotion/cache@^11.13.0", "@emotion/cache@^11.13.1":
version "11.13.1"
resolved "https://registry.yarnpkg.com/@emotion/cache/-/cache-11.13.1.tgz#fecfc54d51810beebf05bf2a161271a1a91895d7"
integrity sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==
dependencies:
"@emotion/memoize" "^0.9.0"
"@emotion/sheet" "^1.4.0"
"@emotion/utils" "^1.4.0"
"@emotion/weak-memoize" "^0.4.0"
stylis "4.2.0"
"@emotion/hash@^0.9.2":
version "0.9.2"
resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.9.2.tgz#ff9221b9f58b4dfe61e619a7788734bd63f6898b"
integrity sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==
"@emotion/is-prop-valid@1.2.1":
version "1.2.1"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.2.1.tgz#23116cf1ed18bfeac910ec6436561ecb1a3885cc"
@ -1862,6 +1986,13 @@
dependencies:
"@emotion/memoize" "0.7.4"
"@emotion/is-prop-valid@^1.3.0":
version "1.3.1"
resolved "https://registry.yarnpkg.com/@emotion/is-prop-valid/-/is-prop-valid-1.3.1.tgz#8d5cf1132f836d7adbe42cf0b49df7816fc88240"
integrity sha512-/ACwoqx7XQi9knQs/G0qKvv5teDMhD7bXYns9N/wM8ah8iNb8jZ2uNO0YOgiq2o2poIvVtJS2YALasQuMSQ7Kw==
dependencies:
"@emotion/memoize" "^0.9.0"
"@emotion/memoize@0.7.4":
version "0.7.4"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.7.4.tgz#19bf0f5af19149111c40d98bb0cf82119f5d9eeb"
@ -1872,16 +2003,83 @@
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.8.1.tgz#c1ddb040429c6d21d38cc945fe75c818cfb68e17"
integrity sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==
"@emotion/memoize@^0.9.0":
version "0.9.0"
resolved "https://registry.yarnpkg.com/@emotion/memoize/-/memoize-0.9.0.tgz#745969d649977776b43fc7648c556aaa462b4102"
integrity sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==
"@emotion/react@^11.13.3":
version "11.13.3"
resolved "https://registry.yarnpkg.com/@emotion/react/-/react-11.13.3.tgz#a69d0de2a23f5b48e0acf210416638010e4bd2e4"
integrity sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==
dependencies:
"@babel/runtime" "^7.18.3"
"@emotion/babel-plugin" "^11.12.0"
"@emotion/cache" "^11.13.0"
"@emotion/serialize" "^1.3.1"
"@emotion/use-insertion-effect-with-fallbacks" "^1.1.0"
"@emotion/utils" "^1.4.0"
"@emotion/weak-memoize" "^0.4.0"
hoist-non-react-statics "^3.3.1"
"@emotion/serialize@^1.2.0", "@emotion/serialize@^1.3.0", "@emotion/serialize@^1.3.1", "@emotion/serialize@^1.3.2":
version "1.3.2"
resolved "https://registry.yarnpkg.com/@emotion/serialize/-/serialize-1.3.2.tgz#e1c1a2e90708d5d85d81ccaee2dfeb3cc0cccf7a"
integrity sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==
dependencies:
"@emotion/hash" "^0.9.2"
"@emotion/memoize" "^0.9.0"
"@emotion/unitless" "^0.10.0"
"@emotion/utils" "^1.4.1"
csstype "^3.0.2"
"@emotion/sheet@^1.4.0":
version "1.4.0"
resolved "https://registry.yarnpkg.com/@emotion/sheet/-/sheet-1.4.0.tgz#c9299c34d248bc26e82563735f78953d2efca83c"
integrity sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==
"@emotion/styled@^11.13.0":
version "11.13.0"
resolved "https://registry.yarnpkg.com/@emotion/styled/-/styled-11.13.0.tgz#633fd700db701472c7a5dbef54d6f9834e9fb190"
integrity sha512-tkzkY7nQhW/zC4hztlwucpT8QEZ6eUzpXDRhww/Eej4tFfO0FxQYWRyg/c5CCXa4d/f174kqeXYjuQRnhzf6dA==
dependencies:
"@babel/runtime" "^7.18.3"
"@emotion/babel-plugin" "^11.12.0"
"@emotion/is-prop-valid" "^1.3.0"
"@emotion/serialize" "^1.3.0"
"@emotion/use-insertion-effect-with-fallbacks" "^1.1.0"
"@emotion/utils" "^1.4.0"
"@emotion/unitless@0.8.0":
version "0.8.0"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.8.0.tgz#a4a36e9cbdc6903737cd20d38033241e1b8833db"
integrity sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==
"@emotion/unitless@^0.10.0":
version "0.10.0"
resolved "https://registry.yarnpkg.com/@emotion/unitless/-/unitless-0.10.0.tgz#2af2f7c7e5150f497bdabd848ce7b218a27cf745"
integrity sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==
"@emotion/use-insertion-effect-with-fallbacks@^1.0.1":
version "1.0.1"
resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.0.1.tgz#08de79f54eb3406f9daaf77c76e35313da963963"
integrity sha512-jT/qyKZ9rzLErtrjGgdkMBn2OP8wl0G3sQlBb3YPryvKHsjvINUhVaPFfP+fpBcOkmrVOVEEHQFJ7nbj2TH2gw==
"@emotion/use-insertion-effect-with-fallbacks@^1.1.0":
version "1.1.0"
resolved "https://registry.yarnpkg.com/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz#1a818a0b2c481efba0cf34e5ab1e0cb2dcb9dfaf"
integrity sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==
"@emotion/utils@^1.4.0", "@emotion/utils@^1.4.1":
version "1.4.1"
resolved "https://registry.yarnpkg.com/@emotion/utils/-/utils-1.4.1.tgz#b3adbb43de12ee2149541c4f1337d2eb7774f0ad"
integrity sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA==
"@emotion/weak-memoize@^0.4.0":
version "0.4.0"
resolved "https://registry.yarnpkg.com/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz#5e13fac887f08c44f76b0ccaf3370eb00fec9bb6"
integrity sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==
"@esbuild/aix-ppc64@0.19.12":
version "0.19.12"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.12.tgz#d1bc06aedb6936b3b6d313bf809a5a40387d2b7f"
@ -4107,6 +4305,81 @@
"@motionone/dom" "^10.16.4"
tslib "^2.3.1"
"@mui/core-downloads-tracker@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@mui/core-downloads-tracker/-/core-downloads-tracker-6.1.3.tgz#54e22bf569a7764dff36697778cc0ae4591c7ec9"
integrity sha512-ajMUgdfhTb++rwqj134Cq9f4SRN8oXUqMRnY72YBnXiXai3olJLLqETheRlq3MM8wCKrbq7g6j7iWL1VvP44VQ==
"@mui/material@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@mui/material/-/material-6.1.3.tgz#1d17bb2a6aedfa78a1a7a7f3a3a2d0023427a996"
integrity sha512-loV5MBoMKLrK80JeWINmQ1A4eWoLv51O2dBPLJ260IAhupkB3Wol8lEQTEvvR2vO3o6xRHuXe1WaQEP6N3riqg==
dependencies:
"@babel/runtime" "^7.25.6"
"@mui/core-downloads-tracker" "^6.1.3"
"@mui/system" "^6.1.3"
"@mui/types" "^7.2.18"
"@mui/utils" "^6.1.3"
"@popperjs/core" "^2.11.8"
"@types/react-transition-group" "^4.4.11"
clsx "^2.1.1"
csstype "^3.1.3"
prop-types "^15.8.1"
react-is "^18.3.1"
react-transition-group "^4.4.5"
"@mui/private-theming@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@mui/private-theming/-/private-theming-6.1.3.tgz#ec225ec2814e89a1ce9a194809d607116885020f"
integrity sha512-XK5OYCM0x7gxWb/WBEySstBmn+dE3YKX7U7jeBRLm6vHU5fGUd7GiJWRirpivHjOK9mRH6E1MPIVd+ze5vguKQ==
dependencies:
"@babel/runtime" "^7.25.6"
"@mui/utils" "^6.1.3"
prop-types "^15.8.1"
"@mui/styled-engine@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@mui/styled-engine/-/styled-engine-6.1.3.tgz#f5e655f59836a5f9fce7b96cd889eee9804d277d"
integrity sha512-i4yh9m+eMZE3cNERpDhVr6Wn73Yz6C7MH0eE2zZvw8d7EFkIJlCQNZd1xxGZqarD2DDq2qWHcjIOucWGhxACtA==
dependencies:
"@babel/runtime" "^7.25.6"
"@emotion/cache" "^11.13.1"
"@emotion/serialize" "^1.3.2"
"@emotion/sheet" "^1.4.0"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/system@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@mui/system/-/system-6.1.3.tgz#64158d2feefb2e470d36c20fd144ac0a140a35fb"
integrity sha512-ILaD9UsLTBLjMcep3OumJMXh1PYr7aqnkHm/L47bH46+YmSL1zWAX6tWG8swEQROzW2GvYluEMp5FreoxOOC6w==
dependencies:
"@babel/runtime" "^7.25.6"
"@mui/private-theming" "^6.1.3"
"@mui/styled-engine" "^6.1.3"
"@mui/types" "^7.2.18"
"@mui/utils" "^6.1.3"
clsx "^2.1.1"
csstype "^3.1.3"
prop-types "^15.8.1"
"@mui/types@^7.2.18":
version "7.2.18"
resolved "https://registry.yarnpkg.com/@mui/types/-/types-7.2.18.tgz#4b6385ed2f7828ef344113cdc339d6fdf8e4bc23"
integrity sha512-uvK9dWeyCJl/3ocVnTOS6nlji/Knj8/tVqVX03UVTpdmTJYu/s4jtDd9Kvv0nRGE0CUSNW1UYAci7PYypjealg==
"@mui/utils@^6.1.3":
version "6.1.3"
resolved "https://registry.yarnpkg.com/@mui/utils/-/utils-6.1.3.tgz#edb63cbd18fea2341efc6d4d087dd48075fc9dba"
integrity sha512-4JBpLkjprlKjN10DGb1aiy/ii9TKbQ601uSHtAmYFAS879QZgAD7vRnv/YBE4iBbc7NXzFgbQMCOFrupXWekIA==
dependencies:
"@babel/runtime" "^7.25.6"
"@mui/types" "^7.2.18"
"@types/prop-types" "^15.7.13"
clsx "^2.1.1"
prop-types "^15.8.1"
react-is "^18.3.1"
"@multiformats/murmur3@^2.0.0":
version "2.1.8"
resolved "https://registry.yarnpkg.com/@multiformats/murmur3/-/murmur3-2.1.8.tgz#81c1c15b6391109f3febfca4b3205196615a04e9"
@ -4815,6 +5088,11 @@
resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33"
integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==
"@popperjs/core@^2.11.8":
version "2.11.8"
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.11.8.tgz#6b79032e760a0899cd4204710beede972a3a185f"
integrity sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==
"@protobufjs/aspromise@^1.1.1", "@protobufjs/aspromise@^1.1.2":
version "1.1.2"
resolved "https://registry.yarnpkg.com/@protobufjs/aspromise/-/aspromise-1.1.2.tgz#9b8b0cc663d669a7d8f6f5d0893a14d348f30fbf"
@ -7143,6 +7421,11 @@
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.12.tgz#12bb1e2be27293c1406acb6af1c3f3a1481d98c6"
integrity sha512-5zvhXYtRNRluoE/jAp4GVsSduVUzNWKkOZrCDBWYtE7biZywwdC2AcEzg+cSMLFRfVgeAFqpfNabiPjxFddV1Q==
"@types/prop-types@^15.7.13":
version "15.7.13"
resolved "https://registry.yarnpkg.com/@types/prop-types/-/prop-types-15.7.13.tgz#2af91918ee12d9d32914feb13f5326658461b451"
integrity sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA==
"@types/qs@*", "@types/qs@^6.9.5":
version "6.9.15"
resolved "https://registry.yarnpkg.com/@types/qs/-/qs-6.9.15.tgz#adde8a060ec9c305a82de1babc1056e73bd64dce"
@ -7160,6 +7443,13 @@
dependencies:
"@types/react" "*"
"@types/react-transition-group@^4.4.11":
version "4.4.11"
resolved "https://registry.yarnpkg.com/@types/react-transition-group/-/react-transition-group-4.4.11.tgz#d963253a611d757de01ebb241143b1017d5d63d5"
integrity sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==
dependencies:
"@types/react" "*"
"@types/react@*", "@types/react@^18.2.66":
version "18.2.79"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.79.tgz#c40efb4f255711f554d47b449f796d1c7756d865"
@ -8484,6 +8774,15 @@ babel-core@^7.0.0-bridge.0:
resolved "https://registry.yarnpkg.com/babel-core/-/babel-core-7.0.0-bridge.0.tgz#95a492ddd90f9b4e9a4a1da14eb335b87b634ece"
integrity sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==
babel-plugin-macros@^3.1.0:
version "3.1.0"
resolved "https://registry.yarnpkg.com/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz#9ef6dc74deb934b4db344dc973ee851d148c50c1"
integrity sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==
dependencies:
"@babel/runtime" "^7.12.5"
cosmiconfig "^7.0.0"
resolve "^1.19.0"
babel-plugin-polyfill-corejs2@^0.4.10:
version "0.4.11"
resolved "https://registry.yarnpkg.com/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz#30320dfe3ffe1a336c15afdcdafd6fd615b25e33"
@ -9243,7 +9542,7 @@ clone@^1.0.2:
resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e"
integrity sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==
clsx@^2.0.0, clsx@^2.1.0:
clsx@^2.0.0, clsx@^2.1.0, clsx@^2.1.1:
version "2.1.1"
resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999"
integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==
@ -9480,6 +9779,11 @@ conventional-recommended-bump@7.0.1:
git-semver-tags "^5.0.0"
meow "^8.1.2"
convert-source-map@^1.5.0:
version "1.9.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f"
integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==
convert-source-map@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
@ -9556,7 +9860,7 @@ cors@^2.8.5:
object-assign "^4"
vary "^1"
cosmiconfig@^7.1.0:
cosmiconfig@^7.0.0, cosmiconfig@^7.1.0:
version "7.1.0"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-7.1.0.tgz#1443b9afa596b670082ea46cbd8f6a62b84635f6"
integrity sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==
@ -9728,7 +10032,7 @@ csstype@3.1.2:
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.2.tgz#1d4bf9d572f11c14031f0436e1c10bc1f571f50b"
integrity sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==
csstype@^3.0.2:
csstype@^3.0.2, csstype@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
@ -10105,6 +10409,14 @@ dom-accessibility-api@^0.6.3:
resolved "https://registry.yarnpkg.com/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz#993e925cc1d73f2c662e7d75dd5a5445259a8fd8"
integrity sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==
dom-helpers@^5.0.1:
version "5.2.1"
resolved "https://registry.yarnpkg.com/dom-helpers/-/dom-helpers-5.2.1.tgz#d9400536b2bf8225ad98fe052e029451ac40e902"
integrity sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==
dependencies:
"@babel/runtime" "^7.8.7"
csstype "^3.0.2"
dot-prop@^5.1.0:
version "5.3.0"
resolved "https://registry.yarnpkg.com/dot-prop/-/dot-prop-5.3.0.tgz#90ccce708cd9cd82cc4dc8c3ddd9abdd55b20e88"
@ -10464,6 +10776,11 @@ escape-string-regexp@^2.0.0:
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz#a30304e99daa32e23b2fd20f51babd07cffca344"
integrity sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==
escape-string-regexp@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34"
integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==
escodegen@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/escodegen/-/escodegen-2.1.0.tgz#ba93bbb7a43986d29d6041f99f5262da773e2e17"
@ -10985,6 +11302,11 @@ find-cache-dir@^3.0.0:
make-dir "^3.0.2"
pkg-dir "^4.1.0"
find-root@^1.1.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/find-root/-/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
integrity sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==
find-up@^2.0.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/find-up/-/find-up-2.1.0.tgz#45d1b7e506c717ddd482775a2b77920a3c0c57a7"
@ -11688,7 +12010,7 @@ hmac-drbg@^1.0.1:
minimalistic-assert "^1.0.0"
minimalistic-crypto-utils "^1.0.1"
hoist-non-react-statics@^3.3.2:
hoist-non-react-statics@^3.3.1, hoist-non-react-statics@^3.3.2:
version "3.3.2"
resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45"
integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==
@ -12811,6 +13133,11 @@ jsesc@^2.5.1:
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-2.5.2.tgz#80564d2e483dacf6e8ef209650a67df3f0c283a4"
integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==
jsesc@^3.0.2:
version "3.0.2"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.0.2.tgz#bb8b09a6597ba426425f2e4a07245c3d00b9343e"
integrity sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==
jsesc@~0.5.0:
version "0.5.0"
resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-0.5.0.tgz#e7dee66e35d6fc16f710fe91d5cf69f70f08911d"
@ -15238,7 +15565,7 @@ promzard@^1.0.0:
dependencies:
read "^3.0.1"
prop-types@15.8.1, prop-types@^15.6.0, prop-types@^15.7.2, prop-types@^15.8.1:
prop-types@15.8.1, prop-types@^15.6.0, prop-types@^15.6.2, prop-types@^15.7.2, prop-types@^15.8.1:
version "15.8.1"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
@ -15573,6 +15900,11 @@ react-is@^18.0.0, react-is@^18.2.0:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
react-is@^18.3.1:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
react-native-fetch-api@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/react-native-fetch-api/-/react-native-fetch-api-3.0.0.tgz#81e1bb6562c292521bc4eca52fe1097f4c1ebab5"
@ -15649,6 +15981,16 @@ react-timer-hook@^3.0.7:
resolved "https://registry.yarnpkg.com/react-timer-hook/-/react-timer-hook-3.0.7.tgz#ac42c43d0034b873cbf97b44eb34ccb2b11fe5e0"
integrity sha512-ATpNcU+PQRxxfNBPVqce2+REtjGAlwmfoNQfcEBMZFxPj0r3GYdKhyPHdStvqrejejEi0QvqaJZjy2lBlFvAsA==
react-transition-group@^4.4.5:
version "4.4.5"
resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.5.tgz#e53d4e3f3344da8521489fbef8f2581d42becdd1"
integrity sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==
dependencies:
"@babel/runtime" "^7.5.5"
dom-helpers "^5.0.1"
loose-envify "^1.4.0"
prop-types "^15.6.2"
react@18.2.0, react@^18.2.0:
version "18.2.0"
resolved "https://registry.yarnpkg.com/react/-/react-18.2.0.tgz#555bd98592883255fa00de14f1151a917b5d77d5"
@ -15980,7 +16322,7 @@ resolve-from@^4.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6"
integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==
resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.3, resolve@^1.22.8:
resolve@^1.1.6, resolve@^1.1.7, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.22.1, resolve@^1.22.2, resolve@^1.22.3, resolve@^1.22.8:
version "1.22.8"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d"
integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==
@ -16486,6 +16828,11 @@ source-map@0.8.0-beta.0:
dependencies:
whatwg-url "^7.0.0"
source-map@^0.5.7:
version "0.5.7"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc"
integrity sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==
source-map@^0.6.0, source-map@^0.6.1, source-map@~0.6.1:
version "0.6.1"
resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263"
@ -16808,6 +17155,11 @@ styled-components@^6.1.0:
stylis "4.3.1"
tslib "2.5.0"
stylis@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.2.0.tgz#79daee0208964c8fe695a42fcffcac633a211a51"
integrity sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==
stylis@4.3.1:
version "4.3.1"
resolved "https://registry.yarnpkg.com/stylis/-/stylis-4.3.1.tgz#ed8a9ebf9f76fe1e12d462f5cc3c4c980b23a7eb"