Compare commits

..
Author SHA1 Message Date
Vivian Phung efc5a45bac Fix Input component react hook 2024-05-22 19:04:59 +00:00
25 changed files with 434 additions and 701 deletions
-1
View File
@@ -19,7 +19,6 @@
"cors": "^2.8.5", "cors": "^2.8.5",
"debug": "^4.3.1", "debug": "^4.3.1",
"express": "^4.18.2", "express": "^4.18.2",
"express-async-errors": "^3.1.1",
"express-session": "^1.18.0", "express-session": "^1.18.0",
"fs-extra": "^11.2.0", "fs-extra": "^11.2.0",
"graphql": "^16.8.1", "graphql": "^16.8.1",
-1
View File
@@ -1,4 +1,3 @@
import 'express-async-errors';
import 'reflect-metadata'; import 'reflect-metadata';
import debug from 'debug'; import debug from 'debug';
import fs from 'fs'; import fs from 'fs';
+38 -56
View File
@@ -25,15 +25,8 @@ export const createResolvers = async (service: Service): Promise<any> => {
return service.getProjectById(projectId); return service.getProjectById(projectId);
}, },
projectsInOrganization: async ( projectsInOrganization: async (_: any, { organizationSlug }: {organizationSlug: string }, context: any) => {
_: any, return service.getProjectsInOrganization(context.user, organizationSlug);
{ organizationSlug }: { organizationSlug: string },
context: any,
) => {
return service.getProjectsInOrganization(
context.user,
organizationSlug,
);
}, },
deployments: async (_: any, { projectId }: { projectId: string }) => { deployments: async (_: any, { projectId }: { projectId: string }) => {
@@ -42,7 +35,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
environmentVariables: async ( environmentVariables: async (
_: any, _: any,
{ projectId }: { projectId: string }, { projectId }: { projectId: string }
) => { ) => {
return service.getEnvironmentVariablesByProjectId(projectId); return service.getEnvironmentVariablesByProjectId(projectId);
}, },
@@ -51,11 +44,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
return service.getProjectMembersByProjectId(projectId); return service.getProjectMembersByProjectId(projectId);
}, },
searchProjects: async ( searchProjects: async (_: any, { searchText }: { searchText: string }, context: any) => {
_: any,
{ searchText }: { searchText: string },
context: any,
) => {
return service.searchProjects(context.user, searchText); return service.searchProjects(context.user, searchText);
}, },
@@ -63,11 +52,11 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any, _: any,
{ {
projectId, projectId,
filter, filter
}: { projectId: string; filter?: FindOptionsWhere<Domain> }, }: { projectId: string; filter?: FindOptionsWhere<Domain> }
) => { ) => {
return service.getDomainsByProjectId(projectId, filter); return service.getDomainsByProjectId(projectId, filter);
}, }
}, },
// TODO: Return error in GQL response // TODO: Return error in GQL response
@@ -75,13 +64,10 @@ export const createResolvers = async (service: Service): Promise<any> => {
removeProjectMember: async ( removeProjectMember: async (
_: any, _: any,
{ projectMemberId }: { projectMemberId: string }, { projectMemberId }: { projectMemberId: string },
context: any, context: any
) => { ) => {
try { try {
return await service.removeProjectMember( return await service.removeProjectMember(context.user, projectMemberId);
context.user,
projectMemberId,
);
} catch (err) { } catch (err) {
log(err); log(err);
return false; return false;
@@ -92,13 +78,13 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any, _: any,
{ {
projectMemberId, projectMemberId,
data, data
}: { }: {
projectMemberId: string; projectMemberId: string;
data: { data: {
permissions: Permission[]; permissions: Permission[];
}; };
}, }
) => { ) => {
try { try {
return await service.updateProjectMember(projectMemberId, data); return await service.updateProjectMember(projectMemberId, data);
@@ -112,14 +98,14 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any, _: any,
{ {
projectId, projectId,
data, data
}: { }: {
projectId: string; projectId: string;
data: { data: {
email: string; email: string;
permissions: Permission[]; permissions: Permission[];
}; };
}, }
) => { ) => {
try { try {
return Boolean(await service.addProjectMember(projectId, data)); return Boolean(await service.addProjectMember(projectId, data));
@@ -133,15 +119,15 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any, _: any,
{ {
projectId, projectId,
data, data
}: { }: {
projectId: string; projectId: string;
data: { environments: string[]; key: string; value: string }[]; data: { environments: string[]; key: string; value: string }[];
}, }
) => { ) => {
try { try {
return Boolean( return Boolean(
await service.addEnvironmentVariables(projectId, data), await service.addEnvironmentVariables(projectId, data)
); );
} catch (err) { } catch (err) {
log(err); log(err);
@@ -153,16 +139,16 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any, _: any,
{ {
environmentVariableId, environmentVariableId,
data, data
}: { }: {
environmentVariableId: string; environmentVariableId: string;
data: DeepPartial<EnvironmentVariable>; data: DeepPartial<EnvironmentVariable>;
}, }
) => { ) => {
try { try {
return await service.updateEnvironmentVariable( return await service.updateEnvironmentVariable(
environmentVariableId, environmentVariableId,
data, data
); );
} catch (err) { } catch (err) {
log(err); log(err);
@@ -172,7 +158,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
removeEnvironmentVariable: async ( removeEnvironmentVariable: async (
_: any, _: any,
{ environmentVariableId }: { environmentVariableId: string }, { environmentVariableId }: { environmentVariableId: string }
) => { ) => {
try { try {
return await service.removeEnvironmentVariable(environmentVariableId); return await service.removeEnvironmentVariable(environmentVariableId);
@@ -185,12 +171,10 @@ export const createResolvers = async (service: Service): Promise<any> => {
updateDeploymentToProd: async ( updateDeploymentToProd: async (
_: any, _: any,
{ deploymentId }: { deploymentId: string }, { deploymentId }: { deploymentId: string },
context: any, context: any
) => { ) => {
try { try {
return Boolean( return Boolean(await service.updateDeploymentToProd(context.user, deploymentId));
await service.updateDeploymentToProd(context.user, deploymentId),
);
} catch (err) { } catch (err) {
log(err); log(err);
return false; return false;
@@ -201,9 +185,9 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any, _: any,
{ {
organizationSlug, organizationSlug,
data, data
}: { organizationSlug: string; data: DeepPartial<Project> }, }: { organizationSlug: string; data: DeepPartial<Project> },
context: any, context: any
) => { ) => {
try { try {
return await service.addProject(context.user, organizationSlug, data); return await service.addProject(context.user, organizationSlug, data);
@@ -215,7 +199,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
updateProject: async ( updateProject: async (
_: any, _: any,
{ projectId, data }: { projectId: string; data: DeepPartial<Project> }, { projectId, data }: { projectId: string; data: DeepPartial<Project> }
) => { ) => {
try { try {
return await service.updateProject(projectId, data); return await service.updateProject(projectId, data);
@@ -228,12 +212,10 @@ export const createResolvers = async (service: Service): Promise<any> => {
redeployToProd: async ( redeployToProd: async (
_: any, _: any,
{ deploymentId }: { deploymentId: string }, { deploymentId }: { deploymentId: string },
context: any, context: any
) => { ) => {
try { try {
return Boolean( return Boolean(await service.redeployToProd(context.user, deploymentId));
await service.redeployToProd(context.user, deploymentId),
);
} catch (err) { } catch (err) {
log(err); log(err);
return false; return false;
@@ -262,8 +244,8 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any, _: any,
{ {
projectId, projectId,
deploymentId, deploymentId
}: { deploymentId: string; projectId: string }, }: { deploymentId: string; projectId: string }
) => { ) => {
try { try {
return await service.rollbackDeployment(projectId, deploymentId); return await service.rollbackDeployment(projectId, deploymentId);
@@ -275,7 +257,9 @@ export const createResolvers = async (service: Service): Promise<any> => {
deleteDeployment: async ( deleteDeployment: async (
_: any, _: any,
{ deploymentId }: { deploymentId: string }, {
deploymentId
}: { deploymentId: string; }
) => { ) => {
try { try {
return await service.deleteDeployment(deploymentId); return await service.deleteDeployment(deploymentId);
@@ -287,7 +271,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
addDomain: async ( addDomain: async (
_: any, _: any,
{ projectId, data }: { projectId: string; data: { name: string } }, { projectId, data }: { projectId: string; data: { name: string } }
) => { ) => {
try { try {
return Boolean(await service.addDomain(projectId, data)); return Boolean(await service.addDomain(projectId, data));
@@ -299,7 +283,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
updateDomain: async ( updateDomain: async (
_: any, _: any,
{ domainId, data }: { domainId: string; data: DeepPartial<Domain> }, { domainId, data }: { domainId: string; data: DeepPartial<Domain> }
) => { ) => {
try { try {
return await service.updateDomain(domainId, data); return await service.updateDomain(domainId, data);
@@ -312,7 +296,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
authenticateGitHub: async ( authenticateGitHub: async (
_: any, _: any,
{ code }: { code: string }, { code }: { code: string },
context: any, context: any
) => { ) => {
try { try {
return await service.authenticateGitHub(code, context.user); return await service.authenticateGitHub(code, context.user);
@@ -324,14 +308,12 @@ export const createResolvers = async (service: Service): Promise<any> => {
unauthenticateGitHub: async (_: any, __: object, context: any) => { unauthenticateGitHub: async (_: any, __: object, context: any) => {
try { try {
return service.unauthenticateGitHub(context.user, { return service.unauthenticateGitHub(context.user, { gitHubToken: null });
gitHubToken: null,
});
} catch (err) { } catch (err) {
log(err); log(err);
return false; return false;
} }
}, }
}, }
}; };
}; };
-2
View File
@@ -19,7 +19,6 @@ router.get('/registration/:email', async (req, res) => {
}); });
router.post('/register', async (req, res) => { router.post('/register', async (req, res) => {
console.log('Register', req.body);
const { email, challenge, attestation } = req.body; const { email, challenge, attestation } = req.body;
const user = await createUser(req.app.get('service'), { const user = await createUser(req.app.get('service'), {
challenge, challenge,
@@ -32,7 +31,6 @@ router.post('/register', async (req, res) => {
}); });
router.post('/authenticate', async (req, res) => { router.post('/authenticate', async (req, res) => {
console.log('Authenticate', req.body);
const { signedWhoamiRequest } = req.body; const { signedWhoamiRequest } = req.body;
const user = await authenticateUser( const user = await authenticateUser(
req.app.get('service'), req.app.get('service'),
-9
View File
@@ -1,9 +0,0 @@
import { Router } from 'express';
const router = Router();
router.get('/version', async (req, res) => {
return res.send({ version: '0.0.7' });
});
export default router;
-7
View File
@@ -17,7 +17,6 @@ import { ServerConfig } from './config';
import { DEFAULT_GQL_PATH } from './constants'; import { DEFAULT_GQL_PATH } from './constants';
import githubRouter from './routes/github'; import githubRouter from './routes/github';
import authRouter from './routes/auth'; import authRouter from './routes/auth';
import stagingRouter from './routes/staging';
import { Service } from './service'; import { Service } from './service';
const log = debug('snowball:server'); const log = debug('snowball:server');
@@ -110,12 +109,6 @@ export const createAndStartServer = async (
app.set('service', service); app.set('service', service);
app.use('/auth', authRouter); app.use('/auth', authRouter);
app.use('/api/github', githubRouter); app.use('/api/github', githubRouter);
app.use('/staging', stagingRouter);
app.use((err: any, req: any, res: any, next: any) => {
console.error(err);
res.status(500).json({ error: err.message });
});
httpServer.listen(port, host, () => { httpServer.listen(port, host, () => {
log(`Server is listening on ${host}:${port}${server.graphqlPath}`); log(`Server is listening on ${host}:${port}${server.graphqlPath}`);
+169 -225
View File
@@ -15,12 +15,7 @@ import { Permission, ProjectMember } from './entity/ProjectMember';
import { User } from './entity/User'; import { User } from './entity/User';
import { Registry } from './registry'; import { Registry } from './registry';
import { GitHubConfig, RegistryConfig } from './config'; import { GitHubConfig, RegistryConfig } from './config';
import { import { AppDeploymentRecord, AppDeploymentRemovalRecord, GitPushEventPayload, PackageJSON } from './types';
AppDeploymentRecord,
AppDeploymentRemovalRecord,
GitPushEventPayload,
PackageJSON,
} from './types';
import { Role } from './entity/UserOrganization'; import { Role } from './entity/UserOrganization';
const log = debug('snowball:service'); const log = debug('snowball:service');
@@ -76,32 +71,33 @@ export class Service {
// Fetch deployments in building state // Fetch deployments in building state
const deployments = await this.db.getDeployments({ const deployments = await this.db.getDeployments({
where: { where: {
status: DeploymentStatus.Building, status: DeploymentStatus.Building
}, }
}); });
if (deployments.length) { if (deployments.length) {
log( log(
`Found ${deployments.length} deployments in ${DeploymentStatus.Building} state`, `Found ${deployments.length} deployments in ${DeploymentStatus.Building} state`
); );
// Calculate a timestamp for one hour ago // Calculate a timestamp for one hour ago
const anHourAgo = Date.now() - HOUR; const anHourAgo = Date.now() - HOUR;
// Filter out deployments started more than an hour ago and mark them as Error // Filter out deployments started more than an hour ago and mark them as Error
const oldDeploymentsToUpdate = deployments const oldDeploymentsToUpdate = deployments.filter(
.filter((deployment) => Number(deployment.updatedAt) < anHourAgo) deployment => (Number(deployment.updatedAt) < anHourAgo)
)
.map((deployment) => { .map((deployment) => {
return this.db.updateDeploymentById(deployment.id, { return this.db.updateDeploymentById(deployment.id, {
status: DeploymentStatus.Error, status: DeploymentStatus.Error,
isCurrent: false, isCurrent: false
}); });
}); });
// If there are old deployments to update, log and perform the updates // If there are old deployments to update, log and perform the updates
if (oldDeploymentsToUpdate.length > 0) { if (oldDeploymentsToUpdate.length > 0) {
log( log(
`Cleaning up ${oldDeploymentsToUpdate.length} deployments stuck in ${DeploymentStatus.Building} state for over an hour`, `Cleaning up ${oldDeploymentsToUpdate.length} deployments stuck in ${DeploymentStatus.Building} state for over an hour`
); );
await Promise.all(oldDeploymentsToUpdate); await Promise.all(oldDeploymentsToUpdate);
} }
@@ -129,18 +125,17 @@ export class Service {
// Fetch deployments in deleting state // Fetch deployments in deleting state
const deployments = await this.db.getDeployments({ const deployments = await this.db.getDeployments({
where: { where: {
status: DeploymentStatus.Deleting, status: DeploymentStatus.Deleting
}, }
}); });
if (deployments.length) { if (deployments.length) {
log( log(
`Found ${deployments.length} deployments in ${DeploymentStatus.Deleting} state`, `Found ${deployments.length} deployments in ${DeploymentStatus.Deleting} state`
); );
// Fetch ApplicationDeploymentRemovalRecords for deployments // Fetch ApplicationDeploymentRemovalRecords for deployments
const records = const records = await this.registry.getDeploymentRemovalRecords(deployments);
await this.registry.getDeploymentRemovalRecords(deployments);
log(`Found ${records.length} ApplicationDeploymentRemovalRecords`); log(`Found ${records.length} ApplicationDeploymentRemovalRecords`);
// Update deployments for which ApplicationDeploymentRemovalRecords were returned // Update deployments for which ApplicationDeploymentRemovalRecords were returned
@@ -158,16 +153,16 @@ export class Service {
* Update deployments with ApplicationDeploymentRecord data * Update deployments with ApplicationDeploymentRecord data
*/ */
async updateDeploymentsWithRecordData ( async updateDeploymentsWithRecordData (
records: AppDeploymentRecord[], records: AppDeploymentRecord[]
): Promise<void> { ): Promise<void> {
// Get deployments for ApplicationDeploymentRecords // Get deployments for ApplicationDeploymentRecords
const deployments = await this.db.getDeployments({ const deployments = await this.db.getDeployments({
where: records.map((record) => ({ where: records.map((record) => ({
applicationRecordId: record.attributes.application, applicationRecordId: record.attributes.application
})), })),
order: { order: {
createdAt: 'DESC', createdAt: 'DESC'
}, }
}); });
// Get project IDs of deployments that are in production environment // Get project IDs of deployments that are in production environment
@@ -179,13 +174,13 @@ export class Service {
return acc; return acc;
}, },
new Set<string>(), new Set<string>()
); );
// Set old deployments isCurrent to false // Set old deployments isCurrent to false
await this.db.updateDeploymentsByProjectIds( await this.db.updateDeploymentsByProjectIds(
Array.from(productionDeploymentProjectIds), Array.from(productionDeploymentProjectIds),
{ isCurrent: false }, { isCurrent: false }
); );
const recordToDeploymentsMap = deployments.reduce( const recordToDeploymentsMap = deployments.reduce(
@@ -193,7 +188,7 @@ export class Service {
acc[deployment.applicationRecordId] = deployment; acc[deployment.applicationRecordId] = deployment;
return acc; return acc;
}, },
{}, {}
); );
// Update deployment data for ApplicationDeploymentRecords // Update deployment data for ApplicationDeploymentRecords
@@ -205,11 +200,11 @@ export class Service {
applicationDeploymentRecordData: record.attributes, applicationDeploymentRecordData: record.attributes,
url: record.attributes.url, url: record.attributes.url,
status: DeploymentStatus.Ready, status: DeploymentStatus.Ready,
isCurrent: deployment.environment === Environment.Production, isCurrent: deployment.environment === Environment.Production
}); });
log( log(
`Updated deployment ${deployment.id} with URL ${record.attributes.url}`, `Updated deployment ${deployment.id} with URL ${record.attributes.url}`
); );
}); });
@@ -223,23 +218,17 @@ export class Service {
records: AppDeploymentRemovalRecord[], records: AppDeploymentRemovalRecord[],
deployments: Deployment[], deployments: Deployment[],
): Promise<void> { ): Promise<void> {
const removedApplicationDeploymentRecordIds = records.map( const removedApplicationDeploymentRecordIds = records.map(record => record.attributes.deployment);
(record) => record.attributes.deployment,
);
// Get removed deployments for ApplicationDeploymentRecords // Get removed deployments for ApplicationDeploymentRecords
const removedDeployments = deployments.filter((deployment) => const removedDeployments = deployments.filter(deployment => removedApplicationDeploymentRecordIds.includes(deployment.applicationDeploymentRecordId!))
removedApplicationDeploymentRecordIds.includes(
deployment.applicationDeploymentRecordId!,
),
);
const recordToDeploymentsMap = removedDeployments.reduce( const recordToDeploymentsMap = removedDeployments.reduce(
(acc: { [key: string]: Deployment }, deployment) => { (acc: { [key: string]: Deployment }, deployment) => {
acc[deployment.applicationDeploymentRecordId!] = deployment; acc[deployment.applicationDeploymentRecordId!] = deployment;
return acc; return acc;
}, },
{}, {}
); );
// Update deployment data for ApplicationDeploymentRecords and delete // Update deployment data for ApplicationDeploymentRecords and delete
@@ -252,10 +241,10 @@ export class Service {
}); });
log( log(
`Updated deployment ${deployment.id} with ApplicationDeploymentRemovalRecord ${record.id}`, `Updated deployment ${deployment.id} with ApplicationDeploymentRemovalRecord ${record.id}`
); );
await this.db.deleteDeploymentById(deployment.id); await this.db.deleteDeploymentById(deployment.id)
}); });
await Promise.all(deploymentUpdatePromises); await Promise.all(deploymentUpdatePromises);
@@ -264,41 +253,41 @@ export class Service {
async getUser (userId: string): Promise<User | null> { async getUser (userId: string): Promise<User | null> {
return this.db.getUser({ return this.db.getUser({
where: { where: {
id: userId, id: userId
}, }
}); });
} }
async getUserByEmail(email: string): Promise<User | null> { async getUserByEmail(email: string): Promise<User | null> {
return await this.db.getUser({ return await this.db.getUser({
where: { where: {
email, email
}, }
}); });
} }
async getUserBySubOrgId(subOrgId: string): Promise<User | null> { async getUserBySubOrgId(subOrgId: string): Promise<User | null> {
return await this.db.getUser({ return await this.db.getUser({
where: { where: {
subOrgId, subOrgId
}, }
}); });
} }
async getUserByEthAddress (ethAddress: string): Promise<User | null> { async getUserByEthAddress (ethAddress: string): Promise<User | null> {
return await this.db.getUser({ return await this.db.getUser({
where: { where: {
ethAddress, ethAddress
}, }
}); });
} }
async createUser (params: { async createUser (params: {
name: string; name: string
email: string; email: string
subOrgId: string; subOrgId: string
ethAddress: string; ethAddress: string
turnkeyWalletId: string; turnkeyWalletId: string
}): Promise<User> { }): Promise<User> {
const [org] = await this.db.getOrganizations({}); const [org] = await this.db.getOrganizations({});
assert(org, 'No organizations exists in database'); assert(org, 'No organizations exists in database');
@@ -316,7 +305,7 @@ export class Service {
await this.db.addUserOrganization({ await this.db.addUserOrganization({
member: user, member: user,
organization: org, organization: org,
role: Role.Owner, role: Role.Owner
}); });
return user; return user;
@@ -326,7 +315,7 @@ export class Service {
const user = await this.db.getUser({ where: { id: userId } }); const user = await this.db.getUser({ where: { id: userId } });
assert( assert(
user && user.gitHubToken, user && user.gitHubToken,
'User needs to be authenticated with GitHub token', 'User needs to be authenticated with GitHub token'
); );
return new Octokit({ auth: user.gitHubToken }); return new Octokit({ auth: user.gitHubToken });
@@ -342,14 +331,8 @@ export class Service {
return dbProject; return dbProject;
} }
async getProjectsInOrganization( async getProjectsInOrganization (user: User, organizationSlug: string): Promise<Project[]> {
user: User, const dbProjects = await this.db.getProjectsInOrganization(user.id, organizationSlug);
organizationSlug: string,
): Promise<Project[]> {
const dbProjects = await this.db.getProjectsInOrganization(
user.id,
organizationSlug,
);
return dbProjects; return dbProjects;
} }
@@ -359,7 +342,7 @@ export class Service {
} }
async getEnvironmentVariablesByProjectId ( async getEnvironmentVariablesByProjectId (
projectId: string, projectId: string
): Promise<EnvironmentVariable[]> { ): Promise<EnvironmentVariable[]> {
const dbEnvironmentVariables = const dbEnvironmentVariables =
await this.db.getEnvironmentVariablesByProjectId(projectId); await this.db.getEnvironmentVariablesByProjectId(projectId);
@@ -367,7 +350,7 @@ export class Service {
} }
async getProjectMembersByProjectId ( async getProjectMembersByProjectId (
projectId: string, projectId: string
): Promise<ProjectMember[]> { ): Promise<ProjectMember[]> {
const dbProjectMembers = const dbProjectMembers =
await this.db.getProjectMembersByProjectId(projectId); await this.db.getProjectMembersByProjectId(projectId);
@@ -375,16 +358,13 @@ export class Service {
} }
async searchProjects (user: User, searchText: string): Promise<Project[]> { async searchProjects (user: User, searchText: string): Promise<Project[]> {
const dbProjects = await this.db.getProjectsBySearchText( const dbProjects = await this.db.getProjectsBySearchText(user.id, searchText);
user.id,
searchText,
);
return dbProjects; return dbProjects;
} }
async getDomainsByProjectId ( async getDomainsByProjectId (
projectId: string, projectId: string,
filter?: FindOptionsWhere<Domain>, filter?: FindOptionsWhere<Domain>
): Promise<Domain[]> { ): Promise<Domain[]> {
const dbDomains = await this.db.getDomainsByProjectId(projectId, filter); const dbDomains = await this.db.getDomainsByProjectId(projectId, filter);
return dbDomains; return dbDomains;
@@ -392,7 +372,7 @@ export class Service {
async updateProjectMember ( async updateProjectMember (
projectMemberId: string, projectMemberId: string,
data: { permissions: Permission[] }, data: { permissions: Permission[] }
): Promise<boolean> { ): Promise<boolean> {
return this.db.updateProjectMemberById(projectMemberId, data); return this.db.updateProjectMemberById(projectMemberId, data);
} }
@@ -402,39 +382,36 @@ export class Service {
data: { data: {
email: string; email: string;
permissions: Permission[]; permissions: Permission[];
}, }
): Promise<ProjectMember> { ): Promise<ProjectMember> {
// TODO: Send invitation // TODO: Send invitation
let user = await this.db.getUser({ let user = await this.db.getUser({
where: { where: {
email: data.email, email: data.email
}, }
}); });
if (!user) { if (!user) {
user = await this.db.addUser({ user = await this.db.addUser({
email: data.email, email: data.email
}); });
} }
const newProjectMember = await this.db.addProjectMember({ const newProjectMember = await this.db.addProjectMember({
project: { project: {
id: projectId, id: projectId
}, },
permissions: data.permissions, permissions: data.permissions,
isPending: true, isPending: true,
member: { member: {
id: user.id, id: user.id
}, }
}); });
return newProjectMember; return newProjectMember;
} }
async removeProjectMember( async removeProjectMember (user: User, projectMemberId: string): Promise<boolean> {
user: User,
projectMemberId: string,
): Promise<boolean> {
const member = await this.db.getProjectMemberById(projectMemberId); const member = await this.db.getProjectMemberById(projectMemberId);
if (String(member.member.id) === user.id) { if (String(member.member.id) === user.id) {
@@ -453,7 +430,7 @@ export class Service {
async addEnvironmentVariables ( async addEnvironmentVariables (
projectId: string, projectId: string,
data: { environments: string[]; key: string; value: string }[], data: { environments: string[]; key: string; value: string }[]
): Promise<EnvironmentVariable[]> { ): Promise<EnvironmentVariable[]> {
const formattedEnvironmentVariables = data const formattedEnvironmentVariables = data
.map((environmentVariable) => { .map((environmentVariable) => {
@@ -463,41 +440,38 @@ export class Service {
value: environmentVariable.value, value: environmentVariable.value,
environment: environment as Environment, environment: environment as Environment,
project: Object.assign(new Project(), { project: Object.assign(new Project(), {
id: projectId, id: projectId
}), })
}; };
}); });
}) })
.flat(); .flat();
const savedEnvironmentVariables = await this.db.addEnvironmentVariables( const savedEnvironmentVariables = await this.db.addEnvironmentVariables(
formattedEnvironmentVariables, formattedEnvironmentVariables
); );
return savedEnvironmentVariables; return savedEnvironmentVariables;
} }
async updateEnvironmentVariable ( async updateEnvironmentVariable (
environmentVariableId: string, environmentVariableId: string,
data: DeepPartial<EnvironmentVariable>, data: DeepPartial<EnvironmentVariable>
): Promise<boolean> { ): Promise<boolean> {
return this.db.updateEnvironmentVariable(environmentVariableId, data); return this.db.updateEnvironmentVariable(environmentVariableId, data);
} }
async removeEnvironmentVariable ( async removeEnvironmentVariable (
environmentVariableId: string, environmentVariableId: string
): Promise<boolean> { ): Promise<boolean> {
return this.db.deleteEnvironmentVariable(environmentVariableId); return this.db.deleteEnvironmentVariable(environmentVariableId);
} }
async updateDeploymentToProd( async updateDeploymentToProd (user: User, deploymentId: string): Promise<Deployment> {
user: User,
deploymentId: string,
): Promise<Deployment> {
const oldDeployment = await this.db.getDeployment({ const oldDeployment = await this.db.getDeployment({
where: { id: deploymentId }, where: { id: deploymentId },
relations: { relations: {
project: true, project: true
}, }
}); });
if (!oldDeployment) { if (!oldDeployment) {
@@ -506,18 +480,20 @@ export class Service {
const prodBranchDomains = await this.db.getDomainsByProjectId( const prodBranchDomains = await this.db.getDomainsByProjectId(
oldDeployment.project.id, oldDeployment.project.id,
{ branch: oldDeployment.project.prodBranch }, { branch: oldDeployment.project.prodBranch }
); );
const octokit = await this.getOctokit(user.id); const octokit = await this.getOctokit(user.id);
const newDeployment = await this.createDeployment(user.id, octokit, { const newDeployment = await this.createDeployment(user.id,
octokit,
{
project: oldDeployment.project, project: oldDeployment.project,
branch: oldDeployment.branch, branch: oldDeployment.branch,
environment: Environment.Production, environment: Environment.Production,
domain: prodBranchDomains[0], domain: prodBranchDomains[0],
commitHash: oldDeployment.commitHash, commitHash: oldDeployment.commitHash,
commitMessage: oldDeployment.commitMessage, commitMessage: oldDeployment.commitMessage
}); });
return newDeployment; return newDeployment;
@@ -526,11 +502,11 @@ export class Service {
async createDeployment ( async createDeployment (
userId: string, userId: string,
octokit: Octokit, octokit: Octokit,
data: DeepPartial<Deployment>, data: DeepPartial<Deployment>
): Promise<Deployment> { ): Promise<Deployment> {
assert(data.project?.repository, 'Project repository not found'); assert(data.project?.repository, 'Project repository not found');
log( log(
`Creating deployment in project ${data.project.name} from branch ${data.branch}`, `Creating deployment in project ${data.project.name} from branch ${data.branch}`
); );
const [owner, repo] = data.project.repository.split('/'); const [owner, repo] = data.project.repository.split('/');
@@ -538,7 +514,7 @@ export class Service {
owner, owner,
repo, repo,
path: 'package.json', path: 'package.json',
ref: data.commitHash, ref: data.commitHash
}); });
if (!packageJSONData) { if (!packageJSONData) {
@@ -550,12 +526,10 @@ export class Service {
assert(packageJSON.name, "name field doesn't exist in package.json"); assert(packageJSON.name, "name field doesn't exist in package.json");
const repoUrl = ( const repoUrl = (await octokit.rest.repos.get({
await octokit.rest.repos.get({
owner, owner,
repo, repo
}) })).data.html_url;
).data.html_url;
// TODO: Set environment variables for each deployment (environment variables can`t be set in application record) // TODO: Set environment variables for each deployment (environment variables can`t be set in application record)
const { applicationRecordId, applicationRecordData } = const { applicationRecordId, applicationRecordData } =
@@ -564,20 +538,17 @@ export class Service {
packageJSON, packageJSON,
appType: data.project!.template!, appType: data.project!.template!,
commitHash: data.commitHash!, commitHash: data.commitHash!,
repoUrl, repoUrl
}); });
// Update previous deployment with prod branch domain // Update previous deployment with prod branch domain
// TODO: Fix unique constraint error for domain // TODO: Fix unique constraint error for domain
if (data.domain) { if (data.domain) {
await this.db.updateDeployment( await this.db.updateDeployment({
{ domainId: data.domain.id
domainId: data.domain.id, }, {
}, domain: null
{ });
domain: null,
},
);
} }
const newDeployment = await this.db.addDeployment({ const newDeployment = await this.db.addDeployment({
@@ -591,67 +562,53 @@ export class Service {
applicationRecordData, applicationRecordData,
domain: data.domain, domain: data.domain,
createdBy: Object.assign(new User(), { createdBy: Object.assign(new User(), {
id: userId, id: userId
}), })
}); });
log( log(`Created deployment ${newDeployment.id} and published application record ${applicationRecordId}`);
`Created deployment ${newDeployment.id} and published application record ${applicationRecordId}`,
);
const environmentVariables = const environmentVariables = await this.db.getEnvironmentVariablesByProjectId(data.project.id!, { environment: Environment.Production });
await this.db.getEnvironmentVariablesByProjectId(data.project.id!, {
environment: Environment.Production,
});
const environmentVariablesObj = environmentVariables.reduce( const environmentVariablesObj = environmentVariables.reduce((acc, env) => {
(acc, env) => {
acc[env.key] = env.value; acc[env.key] = env.value;
return acc; return acc;
}, }, {} as { [key: string]: string });
{} as { [key: string]: string },
);
// To set project DNS // To set project DNS
if (data.environment === Environment.Production) { if (data.environment === Environment.Production) {
// On deleting deployment later, project DNS deployment is also deleted // 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 // So publish project DNS deployment first so that ApplicationDeploymentRecord for the same is available when deleting deployment later
await this.registry.createApplicationDeploymentRequest({ await this.registry.createApplicationDeploymentRequest(
{
deployment: newDeployment, deployment: newDeployment,
appName: repo, appName: repo,
repository: repoUrl, repository: repoUrl,
environmentVariables: environmentVariablesObj, environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}`, dns: `${newDeployment.project.name}`
}); });
} }
const { applicationDeploymentRequestId, applicationDeploymentRequestData } = const { applicationDeploymentRequestId, applicationDeploymentRequestData } = await this.registry.createApplicationDeploymentRequest(
await this.registry.createApplicationDeploymentRequest({ {
deployment: newDeployment, deployment: newDeployment,
appName: repo, appName: repo,
repository: repoUrl, repository: repoUrl,
environmentVariables: environmentVariablesObj, environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}-${newDeployment.id}`, dns: `${newDeployment.project.name}-${newDeployment.id}`
}); });
await this.db.updateDeploymentById(newDeployment.id, { await this.db.updateDeploymentById(newDeployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData });
applicationDeploymentRequestId,
applicationDeploymentRequestData,
});
return newDeployment; return newDeployment;
} }
async addProject( async addProject (user: User, organizationSlug: string, data: DeepPartial<Project>): Promise<Project | undefined> {
user: User,
organizationSlug: string,
data: DeepPartial<Project>,
): Promise<Project | undefined> {
const organization = await this.db.getOrganization({ const organization = await this.db.getOrganization({
where: { where: {
slug: organizationSlug, slug: organizationSlug
}, }
}); });
if (!organization) { if (!organization) {
throw new Error('Organization does not exist'); throw new Error('Organization does not exist');
@@ -663,23 +620,26 @@ export class Service {
const [owner, repo] = project.repository.split('/'); const [owner, repo] = project.repository.split('/');
const { const {
data: [latestCommit], data: [latestCommit]
} = await octokit.rest.repos.listCommits({ } = await octokit.rest.repos.listCommits({
owner, owner,
repo, repo,
sha: project.prodBranch, sha: project.prodBranch,
per_page: 1, per_page: 1
}); });
// Create deployment with prod branch and latest commit // Create deployment with prod branch and latest commit
await this.createDeployment(user.id, octokit, { await this.createDeployment(user.id,
octokit,
{
project, project,
branch: project.prodBranch, branch: project.prodBranch,
environment: Environment.Production, environment: Environment.Production,
domain: null, domain: null,
commitHash: latestCommit.sha, commitHash: latestCommit.sha,
commitMessage: latestCommit.commit.message, commitMessage: latestCommit.commit.message
}); }
);
await this.createRepoHook(octokit, project); await this.createRepoHook(octokit, project);
@@ -695,11 +655,11 @@ export class Service {
config: { config: {
url: new URL( url: new URL(
'api/github/webhook', 'api/github/webhook',
this.config.gitHubConfig.webhookUrl, this.config.gitHubConfig.webhookUrl
).href, ).href,
content_type: 'json', content_type: 'json'
}, },
events: ['push'], events: ['push']
}); });
} catch (err) { } catch (err) {
// https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook--status-codes // https://docs.github.com/en/rest/repos/webhooks?apiVersion=2022-11-28#create-a-repository-webhook--status-codes
@@ -708,7 +668,7 @@ export class Service {
err instanceof RequestError && err instanceof RequestError &&
err.status === 422 && err.status === 422 &&
(err.response?.data as any).errors.some( (err.response?.data as any).errors.some(
(err: any) => err.message === GITHUB_UNIQUE_WEBHOOK_ERROR, (err: any) => err.message === GITHUB_UNIQUE_WEBHOOK_ERROR
) )
) )
) { ) {
@@ -727,11 +687,9 @@ export class Service {
return; return;
} }
log( log(`Handling GitHub push event from repository: ${repository.full_name}, branch: ${ref}`);
`Handling GitHub push event from repository: ${repository.full_name}, branch: ${ref}`,
);
const projects = await this.db.getProjects({ const projects = await this.db.getProjects({
where: { repository: repository.full_name }, where: { repository: repository.full_name }
}); });
if (!projects.length) { if (!projects.length) {
@@ -745,7 +703,7 @@ export class Service {
for await (const project of projects) { for await (const project of projects) {
const octokit = await this.getOctokit(project.ownerId); const octokit = await this.getOctokit(project.ownerId);
const [domain] = await this.db.getDomainsByProjectId(project.id, { const [domain] = await this.db.getDomainsByProjectId(project.id, {
branch, branch
}); });
// Create deployment with branch and latest commit in GitHub data // Create deployment with branch and latest commit in GitHub data
@@ -758,14 +716,14 @@ export class Service {
: Environment.Preview, : Environment.Preview,
domain, domain,
commitHash: headCommit.id, commitHash: headCommit.id,
commitMessage: headCommit.message, commitMessage: headCommit.message
}); });
} }
} }
async updateProject ( async updateProject (
projectId: string, projectId: string,
data: DeepPartial<Project>, data: DeepPartial<Project>
): Promise<boolean> { ): Promise<boolean> {
return this.db.updateProjectById(projectId, data); return this.db.updateProjectById(projectId, data);
} }
@@ -778,13 +736,13 @@ export class Service {
async deleteDomain (domainId: string): Promise<boolean> { async deleteDomain (domainId: string): Promise<boolean> {
const domainsRedirectedFrom = await this.db.getDomains({ const domainsRedirectedFrom = await this.db.getDomains({
where: { where: {
redirectToId: domainId, redirectToId: domainId
}, }
}); });
if (domainsRedirectedFrom.length > 0) { if (domainsRedirectedFrom.length > 0) {
throw new Error( throw new Error(
'Cannot delete domain since it has redirects from other domains', 'Cannot delete domain since it has redirects from other domains'
); );
} }
@@ -796,11 +754,11 @@ export class Service {
relations: { relations: {
project: true, project: true,
domain: true, domain: true,
createdBy: true, createdBy: true
}, },
where: { where: {
id: deploymentId, id: deploymentId
}, }
}); });
if (oldDeployment === null) { if (oldDeployment === null) {
@@ -809,14 +767,16 @@ export class Service {
const octokit = await this.getOctokit(user.id); const octokit = await this.getOctokit(user.id);
const newDeployment = await this.createDeployment(user.id, octokit, { const newDeployment = await this.createDeployment(user.id,
octokit,
{
project: oldDeployment.project, project: oldDeployment.project,
// TODO: Put isCurrent field in project // TODO: Put isCurrent field in project
branch: oldDeployment.branch, branch: oldDeployment.branch,
environment: Environment.Production, environment: Environment.Production,
domain: oldDeployment.domain, domain: oldDeployment.domain,
commitHash: oldDeployment.commitHash, commitHash: oldDeployment.commitHash,
commitMessage: oldDeployment.commitMessage, commitMessage: oldDeployment.commitMessage
}); });
return newDeployment; return newDeployment;
@@ -824,19 +784,19 @@ export class Service {
async rollbackDeployment ( async rollbackDeployment (
projectId: string, projectId: string,
deploymentId: string, deploymentId: string
): Promise<boolean> { ): Promise<boolean> {
// TODO: Implement transactions // TODO: Implement transactions
const oldCurrentDeployment = await this.db.getDeployment({ const oldCurrentDeployment = await this.db.getDeployment({
relations: { relations: {
domain: true, domain: true
}, },
where: { where: {
project: { project: {
id: projectId, id: projectId
},
isCurrent: true,
}, },
isCurrent: true
}
}); });
if (!oldCurrentDeployment) { if (!oldCurrentDeployment) {
@@ -845,12 +805,12 @@ export class Service {
const oldCurrentDeploymentUpdate = await this.db.updateDeploymentById( const oldCurrentDeploymentUpdate = await this.db.updateDeploymentById(
oldCurrentDeployment.id, oldCurrentDeployment.id,
{ isCurrent: false, domain: null }, { isCurrent: false, domain: null }
); );
const newCurrentDeploymentUpdate = await this.db.updateDeploymentById( const newCurrentDeploymentUpdate = await this.db.updateDeploymentById(
deploymentId, deploymentId,
{ isCurrent: true, domain: oldCurrentDeployment?.domain }, { isCurrent: true, domain: oldCurrentDeployment?.domain }
); );
return newCurrentDeploymentUpdate && oldCurrentDeploymentUpdate; return newCurrentDeploymentUpdate && oldCurrentDeploymentUpdate;
@@ -859,11 +819,11 @@ export class Service {
async deleteDeployment (deploymentId: string): Promise<boolean> { async deleteDeployment (deploymentId: string): Promise<boolean> {
const deployment = await this.db.getDeployment({ const deployment = await this.db.getDeployment({
where: { where: {
id: deploymentId, id: deploymentId
}, },
relations: { relations: {
project: true, project: true
}, }
}); });
if (deployment && deployment.applicationDeploymentRecordId) { if (deployment && deployment.applicationDeploymentRecordId) {
@@ -871,39 +831,31 @@ export class Service {
if (deployment.isCurrent) { if (deployment.isCurrent) {
const currentDeploymentURL = `https://${deployment.project.subDomain}`; const currentDeploymentURL = `https://${deployment.project.subDomain}`;
const deploymentRecords = const deploymentRecords = await this.registry.getDeploymentRecordsByFilter({
await this.registry.getDeploymentRecordsByFilter({
application: deployment.applicationRecordId, application: deployment.applicationRecordId,
url: currentDeploymentURL, url: currentDeploymentURL
}); })
if (!deploymentRecords.length) { if (!deploymentRecords.length) {
log( log(`No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}`);
`No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}`,
);
return false; return false;
} }
await this.registry.createApplicationDeploymentRemovalRequest({ await this.registry.createApplicationDeploymentRemovalRequest({ deploymentId: deploymentRecords[0].id });
deploymentId: deploymentRecords[0].id,
});
} }
const result = const result = await this.registry.createApplicationDeploymentRemovalRequest({ deploymentId: deployment.applicationDeploymentRecordId });
await this.registry.createApplicationDeploymentRemovalRequest({
deploymentId: deployment.applicationDeploymentRecordId,
});
await this.db.updateDeploymentById(deployment.id, { await this.db.updateDeploymentById(
deployment.id,
{
status: DeploymentStatus.Deleting, status: DeploymentStatus.Deleting,
applicationDeploymentRemovalRequestId: applicationDeploymentRemovalRequestId: result.applicationDeploymentRemovalRequestId,
result.applicationDeploymentRemovalRequestId, applicationDeploymentRemovalRequestData: result.applicationDeploymentRemovalRequestData
applicationDeploymentRemovalRequestData: }
result.applicationDeploymentRemovalRequestData, );
});
return result !== undefined || result !== null; return (result !== undefined || result !== null);
} }
return false; return false;
@@ -911,7 +863,7 @@ export class Service {
async addDomain ( async addDomain (
projectId: string, projectId: string,
data: { name: string }, data: { name: string }
): Promise<{ ): Promise<{
primaryDomain: Domain; primaryDomain: Domain;
redirectedDomain: Domain; redirectedDomain: Domain;
@@ -925,7 +877,7 @@ export class Service {
const primaryDomainDetails = { const primaryDomainDetails = {
...data, ...data,
branch: currentProject.prodBranch, branch: currentProject.prodBranch,
project: currentProject, project: currentProject
}; };
const savedPrimaryDomain = await this.db.addDomain(primaryDomainDetails); const savedPrimaryDomain = await this.db.addDomain(primaryDomainDetails);
@@ -936,27 +888,27 @@ export class Service {
name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`, name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`,
branch: currentProject.prodBranch, branch: currentProject.prodBranch,
project: currentProject, project: currentProject,
redirectTo: savedPrimaryDomain, redirectTo: savedPrimaryDomain
}; };
const savedRedirectedDomain = await this.db.addDomain( const savedRedirectedDomain = await this.db.addDomain(
redirectedDomainDetails, redirectedDomainDetails
); );
return { return {
primaryDomain: savedPrimaryDomain, primaryDomain: savedPrimaryDomain,
redirectedDomain: savedRedirectedDomain, redirectedDomain: savedRedirectedDomain
}; };
} }
async updateDomain ( async updateDomain (
domainId: string, domainId: string,
data: DeepPartial<Domain>, data: DeepPartial<Domain>
): Promise<boolean> { ): Promise<boolean> {
const domain = await this.db.getDomain({ const domain = await this.db.getDomain({
where: { where: {
id: domainId, id: domainId
}, }
}); });
if (domain === null) { if (domain === null) {
@@ -964,16 +916,16 @@ export class Service {
} }
const newDomain = { const newDomain = {
...data, ...data
}; };
const domainsRedirectedFrom = await this.db.getDomains({ const domainsRedirectedFrom = await this.db.getDomains({
where: { where: {
project: { project: {
id: domain.projectId, id: domain.projectId
},
redirectToId: domain.id,
}, },
redirectToId: domain.id
}
}); });
// If there are domains redirecting to current domain, only branch of current domain can be updated // If there are domains redirecting to current domain, only branch of current domain can be updated
@@ -984,8 +936,8 @@ export class Service {
if (data.redirectToId) { if (data.redirectToId) {
const redirectedDomain = await this.db.getDomain({ const redirectedDomain = await this.db.getDomain({
where: { where: {
id: data.redirectToId, id: data.redirectToId
}, }
}); });
if (redirectedDomain === null) { if (redirectedDomain === null) {
@@ -994,7 +946,7 @@ export class Service {
if (redirectedDomain.redirectToId) { if (redirectedDomain.redirectToId) {
throw new Error( throw new Error(
'Unable to redirect to the domain because it is already redirecting elsewhere. Redirects cannot be chained.', 'Unable to redirect to the domain because it is already redirecting elsewhere. Redirects cannot be chained.'
); );
} }
@@ -1006,14 +958,9 @@ export class Service {
return updateResult; return updateResult;
} }
async authenticateGitHub( async authenticateGitHub (code:string, user: User): Promise<{token: string}> {
code: string, const { authentication: { token } } = await this.oauthApp.createToken({
user: User, code
): Promise<{ token: string }> {
const {
authentication: { token },
} = await this.oauthApp.createToken({
code,
}); });
await this.db.updateUser(user, { gitHubToken: token }); await this.db.updateUser(user, { gitHubToken: token });
@@ -1021,10 +968,7 @@ export class Service {
return { token }; return { token };
} }
async unauthenticateGitHub( async unauthenticateGitHub (user: User, data: DeepPartial<User>): Promise<boolean> {
user: User,
data: DeepPartial<User>,
): Promise<boolean> {
return this.db.updateUser(user, data); return this.db.updateUser(user, data);
} }
} }
+2 -2
View File
@@ -3,7 +3,7 @@ services:
restEndpoint: 'http://console.laconic.com:1317' restEndpoint: 'http://console.laconic.com:1317'
gqlEndpoint: 'http://console.laconic.com:9473/api' gqlEndpoint: 'http://console.laconic.com:9473/api'
userKey: 87d00f66a73e2ca428adeb49ba9164d0ad9a87edc60e33d46ad3031b9c5701fe userKey: 87d00f66a73e2ca428adeb49ba9164d0ad9a87edc60e33d46ad3031b9c5701fe
bondId: 89c75c7bc5759861d10285aff6f9e7227d6855e446b77ad5d8324822dfec7deb bondId: 098c906850b87412f02200e41f449bc79e055eab77acfef32c0b22443bb46661
chainId: laconic_9000-1 chainId: laconic_9000-1
gas: 1200000 gas: 550000
fees: 200000aphoton fees: 200000aphoton
+4 -36
View File
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Repository URL # Repository URL
REPO_URL="https://github.com/snowball-tools/snowballtools-base" REPO_URL="https://git.vdb.to/cerc-io/snowballtools-base"
# Get the latest commit hash from the repository # Get the latest commit hash from the repository
LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}') LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}')
@@ -64,13 +64,7 @@ echo "Files generated successfully."
RECORD_FILE=records/application-record.yml RECORD_FILE=records/application-record.yml
# Publish ApplicationRecord # Publish ApplicationRecord
publish_response=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE) RECORD_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to publish record"
exit $rc
fi
RECORD_ID=$(echo $publish_response | jq -r '.id')
echo "ApplicationRecord published" echo "ApplicationRecord published"
echo $RECORD_ID echo $RECORD_ID
@@ -79,36 +73,15 @@ REGISTRY_APP_CRN="crn://snowballtools/applications/snowballtools-base-frontend"
sleep 2 sleep 2
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${PACKAGE_VERSION}" "$RECORD_ID" yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${PACKAGE_VERSION}" "$RECORD_ID"
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to set name: $REGISTRY_APP_CRN@${PACKAGE_VERSION}"
exit $rc
fi
sleep 2 sleep 2
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${LATEST_HASH}" "$RECORD_ID" yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${LATEST_HASH}" "$RECORD_ID"
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to set hash"
exit $rc
fi
sleep 2 sleep 2
# Set name if latest release # Set name if latest release
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN" "$RECORD_ID" yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN" "$RECORD_ID"
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to set release"
exit $rc
fi
echo "$REGISTRY_APP_CRN set for ApplicationRecord" echo "$REGISTRY_APP_CRN set for ApplicationRecord"
# Check if record found for REGISTRY_APP_CRN # Check if record found for REGISTRY_APP_CRN
query_response=$(yarn --silent laconic -c $CONFIG_FILE cns name resolve "$REGISTRY_APP_CRN") APP_RECORD=$(yarn --silent laconic -c $CONFIG_FILE cns name resolve "$REGISTRY_APP_CRN" | jq '.[0]')
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to query name"
exit $rc
fi
APP_RECORD=$(echo $query_response | jq '.[0]')
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
echo "No record found for $REGISTRY_APP_CRN." echo "No record found for $REGISTRY_APP_CRN."
exit 1 exit 1
@@ -117,11 +90,6 @@ fi
RECORD_FILE=records/application-deployment-request.yml RECORD_FILE=records/application-deployment-request.yml
sleep 2 sleep 2
deployment_response=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE) DEPLOYMENT_REQUEST_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to query deployment request"
exit $rc
fi
DEPLOYMENT_REQUEST_ID=$(echo $deployment_response | jq -r '.id')
echo "ApplicationDeploymentRequest published" echo "ApplicationDeploymentRequest published"
echo $DEPLOYMENT_REQUEST_ID echo $DEPLOYMENT_REQUEST_ID
+6 -38
View File
@@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Repository URL # Repository URL
REPO_URL="https://github.com/snowball-tools/snowballtools-base" REPO_URL="https://git.vdb.to/cerc-io/snowballtools-base"
# Get the latest commit hash from the repository # Get the latest commit hash from the repository
LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}') LATEST_HASH=$(git ls-remote $REPO_URL HEAD | awk '{print $1}')
@@ -44,8 +44,8 @@ record:
LACONIC_HOSTED_CONFIG_lit_relay_api_key: 15DDD969-E75F-404D-AAD9-58A37C4FD354_snowball LACONIC_HOSTED_CONFIG_lit_relay_api_key: 15DDD969-E75F-404D-AAD9-58A37C4FD354_snowball
LACONIC_HOSTED_CONFIG_aplchemy_api_key: THvPart_gqI5x02RNYSBntlmwA66I_qc LACONIC_HOSTED_CONFIG_aplchemy_api_key: THvPart_gqI5x02RNYSBntlmwA66I_qc
LACONIC_HOSTED_CONFIG_bugsnag_api_key: 8c480cd5386079f9dd44f9581264a073 LACONIC_HOSTED_CONFIG_bugsnag_api_key: 8c480cd5386079f9dd44f9581264a073
LACONIC_HOSTED_CONFIG_passkey_wallet_rpid: dashboard.staging.apps.snowballtools.com LACONIC_HOSTED_CONFIG_passkey_wallet_rpid: localhost
LACONIC_HOSTED_CONFIG_turnkey_api_base_url: https://api.turnkey.com LACONIC_HOSTED_CONFIG_turnkey_api_base_url: https://api.turnkey.com/
LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591 LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591
meta: meta:
note: Added by Snowball @ $CURRENT_DATE_TIME note: Added by Snowball @ $CURRENT_DATE_TIME
@@ -70,13 +70,7 @@ echo "Files generated successfully."
RECORD_FILE=staging-records/application-record.yml RECORD_FILE=staging-records/application-record.yml
# Publish ApplicationRecord # Publish ApplicationRecord
publish_response=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE) RECORD_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to publish record"
exit $rc
fi
RECORD_ID=$(echo $publish_response | jq -r '.id')
echo "ApplicationRecord published" echo "ApplicationRecord published"
echo $RECORD_ID echo $RECORD_ID
@@ -85,36 +79,15 @@ REGISTRY_APP_CRN="crn://staging-snowballtools/applications/staging-snowballtools
sleep 2 sleep 2
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${PACKAGE_VERSION}" "$RECORD_ID" yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${PACKAGE_VERSION}" "$RECORD_ID"
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to set name: $REGISTRY_APP_CRN@${PACKAGE_VERSION}"
exit $rc
fi
sleep 2 sleep 2
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${LATEST_HASH}" "$RECORD_ID" yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN@${LATEST_HASH}" "$RECORD_ID"
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to set hash"
exit $rc
fi
sleep 2 sleep 2
# Set name if latest release # Set name if latest release
yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN" "$RECORD_ID" yarn --silent laconic -c $CONFIG_FILE cns name set "$REGISTRY_APP_CRN" "$RECORD_ID"
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to set release"
exit $rc
fi
echo "$REGISTRY_APP_CRN set for ApplicationRecord" echo "$REGISTRY_APP_CRN set for ApplicationRecord"
# Check if record found for REGISTRY_APP_CRN # Check if record found for REGISTRY_APP_CRN
query_response=$(yarn --silent laconic -c $CONFIG_FILE cns name resolve "$REGISTRY_APP_CRN") APP_RECORD=$(yarn --silent laconic -c $CONFIG_FILE cns name resolve "$REGISTRY_APP_CRN" | jq '.[0]')
rc=$?
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to query name"
exit $rc
fi
APP_RECORD=$(echo $query_response | jq '.[0]')
if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then if [ -z "$APP_RECORD" ] || [ "null" == "$APP_RECORD" ]; then
echo "No record found for $REGISTRY_APP_CRN." echo "No record found for $REGISTRY_APP_CRN."
exit 1 exit 1
@@ -123,11 +96,6 @@ fi
RECORD_FILE=staging-records/application-deployment-request.yml RECORD_FILE=staging-records/application-deployment-request.yml
sleep 2 sleep 2
deployment_response=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE) DEPLOYMENT_REQUEST_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
if [ $rc -ne 0 ]; then
echo "FATAL: Failed to query deployment request"
exit $rc
fi
DEPLOYMENT_REQUEST_ID=$(echo $deployment_response | jq -r '.id')
echo "ApplicationDeploymentRequest published" echo "ApplicationDeploymentRequest published"
echo $DEPLOYMENT_REQUEST_ID echo $DEPLOYMENT_REQUEST_ID
@@ -14,5 +14,5 @@ record:
LACONIC_HOSTED_CONFIG_app_wallet_connect_id: eda9ba18042a5ea500f358194611ece2 LACONIC_HOSTED_CONFIG_app_wallet_connect_id: eda9ba18042a5ea500f358194611ece2
meta: meta:
note: Added by Snowball @ Thu Apr 4 14:49:41 UTC 2024 note: Added by Snowball @ Thu Apr 4 14:49:41 UTC 2024
repository: "https://github.com/snowball-tools/snowballtools-base" repository: "https://git.vdb.to/cerc-io/snowballtools-base"
repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e
@@ -2,7 +2,7 @@ record:
type: ApplicationRecord type: ApplicationRecord
version: 0.0.2 version: 0.0.2
repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e repository_ref: 351db16336eacc3e1f9119ceb8d1282b8e27a27e
repository: ["https://github.com/snowball-tools/snowballtools-base"] repository: ["https://git.vdb.to/cerc-io/snowballtools-base"]
app_type: webapp app_type: webapp
name: snowballtools-base-frontend name: snowballtools-base-frontend
app_version: 0.1.8 app_version: 0.1.8
@@ -20,5 +20,5 @@ record:
LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591 LACONIC_HOSTED_CONFIG_turnkey_organization_id: 5049ae99-5bca-40b3-8317-504384d4e591
meta: meta:
note: Added by Snowball @ Tuesday 21 May 2024 06:17:23 AM UTC note: Added by Snowball @ Tuesday 21 May 2024 06:17:23 AM UTC
repository: "https://github.com/snowball-tools/snowballtools-base" repository: "https://git.vdb.to/cerc-io/snowballtools-base"
repository_ref: 8488cfab8353321ed05c4234bf1b914c9ad3aa99 repository_ref: 8488cfab8353321ed05c4234bf1b914c9ad3aa99
@@ -2,7 +2,7 @@ record:
type: ApplicationRecord type: ApplicationRecord
version: 0.0.2 version: 0.0.2
repository_ref: 8488cfab8353321ed05c4234bf1b914c9ad3aa99 repository_ref: 8488cfab8353321ed05c4234bf1b914c9ad3aa99
repository: ["https://github.com/snowball-tools/snowballtools-base"] repository: ["https://git.vdb.to/cerc-io/snowballtools-base"]
app_type: webapp app_type: webapp
name: staging-snowballtools-base-frontend name: staging-snowballtools-base-frontend
app_version: 0.0.0 app_version: 0.0.0
@@ -1,8 +1,13 @@
import { CopyBlock, atomOneLight } from 'react-code-blocks'; import { CopyBlock, atomOneLight } from 'react-code-blocks';
import { Link } from 'react-router-dom'; import { Link } from 'react-router-dom';
import { Modal } from 'components/shared/Modal'; import {
import { Button } from 'components/shared/Button'; Button,
Dialog,
DialogHeader,
DialogBody,
DialogFooter,
} from '@snowballtools/material-tailwind-react-fork';
interface AssignDomainProps { interface AssignDomainProps {
open: boolean; open: boolean;
@@ -11,12 +16,11 @@ interface AssignDomainProps {
const AssignDomainDialog = ({ open, handleOpen }: AssignDomainProps) => { const AssignDomainDialog = ({ open, handleOpen }: AssignDomainProps) => {
return ( return (
<Modal open={open} onOpenChange={handleOpen}> <Dialog open={open} handler={handleOpen}>
<Modal.Content> <DialogHeader>Assign Domain</DialogHeader>
<Modal.Header>Assign Domain</Modal.Header> <DialogBody>
<Modal.Body> In order to assign a domain to your production deployments, configure it
In order to assign a domain to your production deployments, configure in the{' '}
it in the{' '}
{/* TODO: Fix selection of project settings tab on navigation to domains */} {/* TODO: Fix selection of project settings tab on navigation to domains */}
<Link to="../settings/domains" className="text-light-blue-800 inline"> <Link to="../settings/domains" className="text-light-blue-800 inline">
project settings{' '} project settings{' '}
@@ -30,12 +34,18 @@ const AssignDomainDialog = ({ open, handleOpen }: AssignDomainProps) => {
showLineNumbers={false} showLineNumbers={false}
theme={atomOneLight} theme={atomOneLight}
/> />
</Modal.Body> </DialogBody>
<Modal.Footer className="flex justify-start"> <DialogFooter className="flex justify-start">
<Button onClick={handleOpen}>Okay</Button> <Button
</Modal.Footer> className="rounded-3xl"
</Modal.Content> variant="gradient"
</Modal> color="blue"
onClick={handleOpen}
>
<span>Okay</span>
</Button>
</DialogFooter>
</Dialog>
); );
}; };
@@ -1,12 +1,5 @@
import { useState, ComponentPropsWithRef } from 'react'; import { useState } from 'react';
import toast from 'react-hot-toast';
import {
Menu,
MenuHandler,
MenuItem,
MenuList,
} from '@snowballtools/material-tailwind-react-fork';
import { Deployment, Domain, Environment, Project } from 'gql-client'; import { Deployment, Domain, Environment, Project } from 'gql-client';
import { Button } from 'components/shared/Button'; import { Button } from 'components/shared/Button';
import { import {
@@ -18,11 +11,17 @@ import {
UndoIcon, UndoIcon,
CrossCircleIcon, CrossCircleIcon,
} from 'components/shared/CustomIcon'; } from 'components/shared/CustomIcon';
import {
Menu,
MenuHandler,
MenuItem,
MenuList,
} from '@snowballtools/material-tailwind-react-fork';
import { ComponentPropsWithRef } from 'react';
import AssignDomainDialog from './AssignDomainDialog'; import AssignDomainDialog from './AssignDomainDialog';
import { useGQLClient } from 'context/GQLClientContext'; import { useGQLClient } from 'context/GQLClientContext';
import { cn } from 'utils/classnames'; import { cn } from 'utils/classnames';
import { ChangeStateToProductionDialog } from 'components/projects/Dialog/ChangeStateToProductionDialog'; import { ChangeStateToProductionDialog } from 'components/projects/Dialog/ChangeStateToProductionDialog';
import { useToast } from 'components/shared/Toast';
interface DeploymentMenuProps extends ComponentPropsWithRef<'div'> { interface DeploymentMenuProps extends ComponentPropsWithRef<'div'> {
deployment: Deployment; deployment: Deployment;
@@ -42,7 +41,6 @@ export const DeploymentMenu = ({
...props ...props
}: DeploymentMenuProps) => { }: DeploymentMenuProps) => {
const client = useGQLClient(); const client = useGQLClient();
const { toast, dismiss } = useToast();
const [changeToProduction, setChangeToProduction] = useState(false); const [changeToProduction, setChangeToProduction] = useState(false);
const [redeployToProduction, setRedeployToProduction] = useState(false); const [redeployToProduction, setRedeployToProduction] = useState(false);
@@ -53,19 +51,9 @@ export const DeploymentMenu = ({
const isUpdated = await client.updateDeploymentToProd(deployment.id); const isUpdated = await client.updateDeploymentToProd(deployment.id);
if (isUpdated) { if (isUpdated) {
await onUpdate(); await onUpdate();
toast({ toast.success('Deployment changed to production');
id: 'deployment_changed_to_production',
title: 'Deployment changed to production',
variant: 'success',
onDismiss: dismiss,
});
} else { } else {
toast({ toast.error('Unable to change deployment to production');
id: 'deployment_not_changed_to_production',
title: 'Error changing deployment to production',
variant: 'error',
onDismiss: dismiss,
});
} }
}; };
@@ -73,19 +61,9 @@ export const DeploymentMenu = ({
const isRedeployed = await client.redeployToProd(deployment.id); const isRedeployed = await client.redeployToProd(deployment.id);
if (isRedeployed) { if (isRedeployed) {
await onUpdate(); await onUpdate();
toast({ toast.success('Redeployed to production');
id: 'redeployed_to_production',
title: 'Redeployed to production',
variant: 'success',
onDismiss: dismiss,
});
} else { } else {
toast({ toast.error('Unable to redeploy to production');
id: 'redeployed_to_production_failed',
title: 'Error redeploying to production',
variant: 'error',
onDismiss: dismiss,
});
} }
}; };
@@ -96,19 +74,9 @@ export const DeploymentMenu = ({
); );
if (isRollbacked) { if (isRollbacked) {
await onUpdate(); await onUpdate();
toast({ toast.success('Deployment rolled back');
id: 'deployment_rolled_back',
title: 'Deployment rolled back',
variant: 'success',
onDismiss: dismiss,
});
} else { } else {
toast({ toast.error('Unable to rollback deployment');
id: 'deployment_rollback_failed',
title: 'Error rolling back deployment',
variant: 'error',
onDismiss: dismiss,
});
} }
}; };
@@ -116,19 +84,9 @@ export const DeploymentMenu = ({
const isDeleted = await client.deleteDeployment(deployment.id); const isDeleted = await client.deleteDeployment(deployment.id);
if (isDeleted) { if (isDeleted) {
await onUpdate(); await onUpdate();
toast({ toast.success('Deleted deployment');
id: 'deployment_deleted',
title: 'Deployment deleted',
variant: 'success',
onDismiss: dismiss,
});
} else { } else {
toast({ toast.error('Unable to delete deployment');
id: 'deployment_not_deleted',
title: 'Error deleting deployment',
variant: 'error',
onDismiss: dismiss,
});
} }
}; };
-3
View File
@@ -15,9 +15,6 @@ import { SERVER_GQL_PATH } from './constants';
import { Toaster } from 'components/shared/Toast'; import { Toaster } from 'components/shared/Toast';
import { LogErrorBoundary } from 'utils/log-error'; import { LogErrorBoundary } from 'utils/log-error';
// @ts-ignore
console.log(`v-${__VERSION__}`);
const root = ReactDOM.createRoot( const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement, document.getElementById('root') as HTMLElement,
); );
@@ -47,9 +47,7 @@ export const Login = ({ onDone }: Props) => {
console.log('Handling google redirect back'); console.log('Handling google redirect back');
try { try {
await google.handleOAuthRedirectBack(); await google.handleOAuthRedirectBack();
// @ts-ignore
wallet = await google.getEthersWallet(); wallet = await google.getEthersWallet();
// @ts-ignore
const result = await signInWithEthereum(1, 'login', wallet); const result = await signInWithEthereum(1, 'login', wallet);
if (result.error) { if (result.error) {
setError(result.error); setError(result.error);
@@ -45,9 +45,7 @@ export const SignUp = ({ onDone }: Props) => {
setProvider('google'); setProvider('google');
try { try {
await google.handleOAuthRedirectBack(); await google.handleOAuthRedirectBack();
// @ts-ignore
wallet = await google.getEthersWallet(); wallet = await google.getEthersWallet();
// @ts-ignore
const result = await signInWithEthereum(1, 'signup', wallet); const result = await signInWithEthereum(1, 'signup', wallet);
if (result.error) { if (result.error) {
setError({ type: 'provider', message: result.error }); setError({ type: 'provider', message: result.error });
-5
View File
@@ -1,7 +1,5 @@
import { defineConfig, PluginOption } from 'vite'; import { defineConfig, PluginOption } from 'vite';
import react from '@vitejs/plugin-react'; import react from '@vitejs/plugin-react';
import { exec } from 'child_process';
import { promisify } from 'util';
// https://vitejs.dev/config/ // https://vitejs.dev/config/
export default defineConfig({ export default defineConfig({
@@ -18,8 +16,5 @@ export default defineConfig({
}, },
define: { define: {
'process.env': {}, 'process.env': {},
__VERSION__: JSON.stringify(
(await promisify(exec)('git rev-parse --short HEAD')).stdout.trim(),
),
}, },
}); });
File diff suppressed because one or more lines are too long
+1 -4
View File
@@ -20,10 +20,7 @@ var __async = (__this, __arguments, generator) => {
}; };
// src/client.ts // src/client.ts
import { import { ApolloClient, InMemoryCache } from "@apollo/client";
ApolloClient,
InMemoryCache
} from "@apollo/client";
// src/queries.ts // src/queries.ts
import { gql } from "@apollo/client"; import { gql } from "@apollo/client";
File diff suppressed because one or more lines are too long
+82 -139
View File
@@ -1,13 +1,8 @@
import { import { ApolloClient, DefaultOptions, InMemoryCache, NormalizedCacheObject } from '@apollo/client';
ApolloClient,
DefaultOptions,
InMemoryCache,
NormalizedCacheObject,
} from "@apollo/client";
import * as queries from "./queries"; import * as queries from './queries';
import * as types from "./types"; import * as types from './types';
import * as mutations from "./mutations"; import * as mutations from './mutations';
export interface GraphQLConfig { export interface GraphQLConfig {
gqlEndpoint: string; gqlEndpoint: string;
@@ -16,13 +11,13 @@ export interface GraphQLConfig {
// TODO: check options // TODO: check options
const defaultOptions: DefaultOptions = { const defaultOptions: DefaultOptions = {
watchQuery: { watchQuery: {
fetchPolicy: "no-cache", fetchPolicy: 'no-cache',
errorPolicy: "ignore", errorPolicy: 'ignore'
}, },
query: { query: {
fetchPolicy: "no-cache", fetchPolicy: 'no-cache',
errorPolicy: "all", errorPolicy: 'all'
}, }
}; };
export class GQLClient { export class GQLClient {
@@ -33,13 +28,13 @@ export class GQLClient {
uri: config.gqlEndpoint, uri: config.gqlEndpoint,
cache: new InMemoryCache(), cache: new InMemoryCache(),
defaultOptions, defaultOptions,
credentials: "include", credentials: 'include'
}); });
} }
async getUser () : Promise<types.GetUserResponse> { async getUser () : Promise<types.GetUserResponse> {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: queries.getUser, query: queries.getUser
}); });
return data; return data;
@@ -49,21 +44,19 @@ export class GQLClient {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: queries.getProject, query: queries.getProject,
variables: { variables: {
projectId, projectId
}, }
}); });
return data; return data;
} }
async getProjectsInOrganization( async getProjectsInOrganization (organizationSlug: string) : Promise<types.GetProjectsInOrganizationResponse> {
organizationSlug: string
): Promise<types.GetProjectsInOrganizationResponse> {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: queries.getProjectsInOrganization, query: queries.getProjectsInOrganization,
variables: { variables: {
organizationSlug, organizationSlug
}, }
}); });
return data; return data;
@@ -71,216 +64,179 @@ export class GQLClient {
async getOrganizations () : Promise<types.GetOrganizationsResponse> { async getOrganizations () : Promise<types.GetOrganizationsResponse> {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: queries.getOrganizations, query: queries.getOrganizations
}); });
return data; return data;
} }
async getDeployments( async getDeployments (projectId: string) : Promise<types.GetDeploymentsResponse> {
projectId: string
): Promise<types.GetDeploymentsResponse> {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: queries.getDeployments, query: queries.getDeployments,
variables: { variables: {
projectId, projectId
}, }
}); });
return data; return data;
} }
async getEnvironmentVariables( async getEnvironmentVariables (projectId: string) : Promise<types.GetEnvironmentVariablesResponse> {
projectId: string
): Promise<types.GetEnvironmentVariablesResponse> {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: queries.getEnvironmentVariables, query: queries.getEnvironmentVariables,
variables: { variables: {
projectId, projectId
}, }
}); });
return data; return data;
} }
async getProjectMembers( async getProjectMembers (projectId: string) : Promise<types.GetProjectMembersResponse> {
projectId: string
): Promise<types.GetProjectMembersResponse> {
const result = await this.client.query({ const result = await this.client.query({
query: queries.getProjectMembers, query: queries.getProjectMembers,
variables: { variables: {
projectId, projectId
}, }
}); });
return result.data; return result.data;
} }
async addProjectMember( async addProjectMember (projectId: string, data: types.AddProjectMemberInput) : Promise<types.AddProjectMemberResponse> {
projectId: string,
data: types.AddProjectMemberInput
): Promise<types.AddProjectMemberResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.addProjectMember, mutation: mutations.addProjectMember,
variables: { variables: {
projectId, projectId,
data, data
}, }
}); });
return result.data; return result.data;
} }
async updateProjectMember( async updateProjectMember (projectMemberId: string, data: types.UpdateProjectMemberInput): Promise<types.UpdateProjectMemberResponse> {
projectMemberId: string,
data: types.UpdateProjectMemberInput
): Promise<types.UpdateProjectMemberResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.updateProjectMember, mutation: mutations.updateProjectMember,
variables: { variables: {
projectMemberId, projectMemberId,
data, data
}, }
}); });
return result.data; return result.data;
} }
async removeProjectMember( async removeProjectMember (projectMemberId: string): Promise<types.RemoveProjectMemberResponse> {
projectMemberId: string
): Promise<types.RemoveProjectMemberResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.removeProjectMember, mutation: mutations.removeProjectMember,
variables: { variables: {
projectMemberId, projectMemberId
}, }
}); });
return result.data; return result.data;
} }
async searchProjects( async searchProjects (searchText: string) : Promise<types.SearchProjectsResponse> {
searchText: string
): Promise<types.SearchProjectsResponse> {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: queries.searchProjects, query: queries.searchProjects,
variables: { variables: {
searchText, searchText
}, }
}); });
return data; return data;
} }
async addEnvironmentVariables( async addEnvironmentVariables (projectId: string, data: types.AddEnvironmentVariableInput[]): Promise<types.AddEnvironmentVariablesResponse> {
projectId: string,
data: types.AddEnvironmentVariableInput[]
): Promise<types.AddEnvironmentVariablesResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.addEnvironmentVariables, mutation: mutations.addEnvironmentVariables,
variables: { variables: {
projectId, projectId,
data, data
}, }
}); });
return result.data; return result.data;
} }
async updateEnvironmentVariable( async updateEnvironmentVariable (environmentVariableId: string, data: types.UpdateEnvironmentVariableInput): Promise<types.UpdateEnvironmentVariableResponse> {
environmentVariableId: string,
data: types.UpdateEnvironmentVariableInput
): Promise<types.UpdateEnvironmentVariableResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.updateEnvironmentVariable, mutation: mutations.updateEnvironmentVariable,
variables: { variables: {
environmentVariableId, environmentVariableId,
data, data
}, }
}); });
return result.data; return result.data;
} }
async removeEnvironmentVariable( async removeEnvironmentVariable (environmentVariableId: string): Promise<types.RemoveEnvironmentVariableResponse> {
environmentVariableId: string
): Promise<types.RemoveEnvironmentVariableResponse> {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.removeEnvironmentVariable, mutation: mutations.removeEnvironmentVariable,
variables: { variables: {
environmentVariableId, environmentVariableId
}, }
}); });
return data; return data;
} }
async updateDeploymentToProd( async updateDeploymentToProd (deploymentId: string): Promise<types.UpdateDeploymentToProdResponse> {
deploymentId: string
): Promise<types.UpdateDeploymentToProdResponse> {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.updateDeploymentToProd, mutation: mutations.updateDeploymentToProd,
variables: { variables: {
deploymentId, deploymentId
}, }
}); });
return data; return data;
} }
async addProject( async addProject (organizationSlug: string, data: types.AddProjectInput): Promise<types.AddProjectResponse> {
organizationSlug: string,
data: types.AddProjectInput
): Promise<types.AddProjectResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.addProject, mutation: mutations.addProject,
variables: { variables: {
organizationSlug, organizationSlug,
data, data
}, }
}); });
return result.data; return result.data;
} }
async updateProject( async updateProject (projectId: string, data: types.UpdateProjectInput): Promise<types.UpdateProjectResponse> {
projectId: string,
data: types.UpdateProjectInput
): Promise<types.UpdateProjectResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.updateProjectMutation, mutation: mutations.updateProjectMutation,
variables: { variables: {
projectId, projectId,
data, data
}, }
}); });
return result.data; return result.data;
} }
async updateDomain( async updateDomain (domainId: string, data: types.UpdateDomainInput): Promise<types.UpdateDomainResponse> {
domainId: string,
data: types.UpdateDomainInput
): Promise<types.UpdateDomainResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.updateDomainMutation, mutation: mutations.updateDomainMutation,
variables: { variables: {
domainId, domainId,
data, data
}, }
}); });
return result.data; return result.data;
} }
async redeployToProd( async redeployToProd (deploymentId: string): Promise<types.RedeployToProdResponse> {
deploymentId: string
): Promise<types.RedeployToProdResponse> {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.redeployToProd, mutation: mutations.redeployToProd,
variables: { variables: {
deploymentId, deploymentId
}, }
}); });
return data; return data;
@@ -290,8 +246,8 @@ export class GQLClient {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.deleteProject, mutation: mutations.deleteProject,
variables: { variables: {
projectId, projectId
}, }
}); });
return data; return data;
@@ -301,79 +257,66 @@ export class GQLClient {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.deleteDomain, mutation: mutations.deleteDomain,
variables: { variables: {
domainId, domainId
}, }
}); });
return data; return data;
} }
async rollbackDeployment( async rollbackDeployment (projectId: string, deploymentId: string): Promise<types.RollbackDeploymentResponse> {
projectId: string,
deploymentId: string
): Promise<types.RollbackDeploymentResponse> {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.rollbackDeployment, mutation: mutations.rollbackDeployment,
variables: { variables: {
projectId, projectId,
deploymentId, deploymentId
}, }
}); });
return data; return data;
} }
async deleteDeployment( async deleteDeployment (deploymentId: string): Promise<types.DeleteDeploymentResponse> {
deploymentId: string
): Promise<types.DeleteDeploymentResponse> {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.deleteDeployment, mutation: mutations.deleteDeployment,
variables: { variables: {
deploymentId, deploymentId
}, }
}); });
return data; return data;
} }
async addDomain( async addDomain (projectId: string, data: types.AddDomainInput): Promise<types.AddDomainResponse> {
projectId: string,
data: types.AddDomainInput
): Promise<types.AddDomainResponse> {
const result = await this.client.mutate({ const result = await this.client.mutate({
mutation: mutations.addDomain, mutation: mutations.addDomain,
variables: { variables: {
projectId, projectId,
data, data
}, }
}); });
return result.data; return result.data;
} }
async getDomains( async getDomains (projectId: string, filter?: types.FilterDomainInput): Promise<types.GetDomainsResponse> {
projectId: string,
filter?: types.FilterDomainInput
): Promise<types.GetDomainsResponse> {
const { data } = await this.client.query({ const { data } = await this.client.query({
query: queries.getDomains, query: queries.getDomains,
variables: { variables: {
projectId, projectId,
filter, filter
}, }
}); });
return data; return data;
} }
async authenticateGitHub( async authenticateGitHub (code: string): Promise<types.AuthenticateGitHubResponse> {
code: string
): Promise<types.AuthenticateGitHubResponse> {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.authenticateGitHub, mutation: mutations.authenticateGitHub,
variables: { variables: {
code, code
}, }
}); });
return data; return data;
@@ -381,7 +324,7 @@ export class GQLClient {
async unauthenticateGithub (): Promise<types.UnauthenticateGitHubResponse> { async unauthenticateGithub (): Promise<types.UnauthenticateGitHubResponse> {
const { data } = await this.client.mutate({ const { data } = await this.client.mutate({
mutation: mutations.unauthenticateGitHub, mutation: mutations.unauthenticateGitHub
}); });
return data; return data;
-5
View File
@@ -10575,11 +10575,6 @@ exponential-backoff@^3.1.1:
resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6" resolved "https://registry.yarnpkg.com/exponential-backoff/-/exponential-backoff-3.1.1.tgz#64ac7526fe341ab18a39016cd22c787d01e00bf6"
integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw== integrity sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==
express-async-errors@^3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/express-async-errors/-/express-async-errors-3.1.1.tgz#6053236d61d21ddef4892d6bd1d736889fc9da41"
integrity sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==
express-session@^1.18.0: express-session@^1.18.0:
version "1.18.0" version "1.18.0"
resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.0.tgz#a6ae39d9091f2efba5f20fc5c65a3ce7c9ce16a3" resolved "https://registry.yarnpkg.com/express-session/-/express-session-1.18.0.tgz#a6ae39d9091f2efba5f20fc5c65a3ce7c9ce16a3"