Compare commits

..
Author SHA1 Message Date
Vivian Phung efc5a45bac Fix Input component react hook 2024-05-22 19:04:59 +00:00
12 changed files with 292 additions and 449 deletions

No files matched your search

+38 -56
View File
@@ -25,15 +25,8 @@ export const createResolvers = async (service: Service): Promise<any> => {
return service.getProjectById(projectId);
},
projectsInOrganization: async (
_: any,
{ organizationSlug }: { organizationSlug: string },
context: any,
) => {
return service.getProjectsInOrganization(
context.user,
organizationSlug,
);
projectsInOrganization: async (_: any, { organizationSlug }: {organizationSlug: string }, context: any) => {
return service.getProjectsInOrganization(context.user, organizationSlug);
},
deployments: async (_: any, { projectId }: { projectId: string }) => {
@@ -42,7 +35,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
environmentVariables: async (
_: any,
{ projectId }: { projectId: string },
{ projectId }: { projectId: string }
) => {
return service.getEnvironmentVariablesByProjectId(projectId);
},
@@ -51,11 +44,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
return service.getProjectMembersByProjectId(projectId);
},
searchProjects: async (
_: any,
{ searchText }: { searchText: string },
context: any,
) => {
searchProjects: async (_: any, { searchText }: { searchText: string }, context: any) => {
return service.searchProjects(context.user, searchText);
},
@@ -63,11 +52,11 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any,
{
projectId,
filter,
}: { projectId: string; filter?: FindOptionsWhere<Domain> },
filter
}: { projectId: string; filter?: FindOptionsWhere<Domain> }
) => {
return service.getDomainsByProjectId(projectId, filter);
},
}
},
// TODO: Return error in GQL response
@@ -75,13 +64,10 @@ export const createResolvers = async (service: Service): Promise<any> => {
removeProjectMember: async (
_: any,
{ projectMemberId }: { projectMemberId: string },
context: any,
context: any
) => {
try {
return await service.removeProjectMember(
context.user,
projectMemberId,
);
return await service.removeProjectMember(context.user, projectMemberId);
} catch (err) {
log(err);
return false;
@@ -92,13 +78,13 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any,
{
projectMemberId,
data,
data
}: {
projectMemberId: string;
data: {
permissions: Permission[];
};
},
}
) => {
try {
return await service.updateProjectMember(projectMemberId, data);
@@ -112,14 +98,14 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any,
{
projectId,
data,
data
}: {
projectId: string;
data: {
email: string;
permissions: Permission[];
};
},
}
) => {
try {
return Boolean(await service.addProjectMember(projectId, data));
@@ -133,15 +119,15 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any,
{
projectId,
data,
data
}: {
projectId: string;
data: { environments: string[]; key: string; value: string }[];
},
}
) => {
try {
return Boolean(
await service.addEnvironmentVariables(projectId, data),
await service.addEnvironmentVariables(projectId, data)
);
} catch (err) {
log(err);
@@ -153,16 +139,16 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any,
{
environmentVariableId,
data,
data
}: {
environmentVariableId: string;
data: DeepPartial<EnvironmentVariable>;
},
}
) => {
try {
return await service.updateEnvironmentVariable(
environmentVariableId,
data,
data
);
} catch (err) {
log(err);
@@ -172,7 +158,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
removeEnvironmentVariable: async (
_: any,
{ environmentVariableId }: { environmentVariableId: string },
{ environmentVariableId }: { environmentVariableId: string }
) => {
try {
return await service.removeEnvironmentVariable(environmentVariableId);
@@ -185,12 +171,10 @@ export const createResolvers = async (service: Service): Promise<any> => {
updateDeploymentToProd: async (
_: any,
{ deploymentId }: { deploymentId: string },
context: any,
context: any
) => {
try {
return Boolean(
await service.updateDeploymentToProd(context.user, deploymentId),
);
return Boolean(await service.updateDeploymentToProd(context.user, deploymentId));
} catch (err) {
log(err);
return false;
@@ -201,9 +185,9 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any,
{
organizationSlug,
data,
data
}: { organizationSlug: string; data: DeepPartial<Project> },
context: any,
context: any
) => {
try {
return await service.addProject(context.user, organizationSlug, data);
@@ -215,7 +199,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
updateProject: async (
_: any,
{ projectId, data }: { projectId: string; data: DeepPartial<Project> },
{ projectId, data }: { projectId: string; data: DeepPartial<Project> }
) => {
try {
return await service.updateProject(projectId, data);
@@ -228,12 +212,10 @@ export const createResolvers = async (service: Service): Promise<any> => {
redeployToProd: async (
_: any,
{ deploymentId }: { deploymentId: string },
context: any,
context: any
) => {
try {
return Boolean(
await service.redeployToProd(context.user, deploymentId),
);
return Boolean(await service.redeployToProd(context.user, deploymentId));
} catch (err) {
log(err);
return false;
@@ -262,8 +244,8 @@ export const createResolvers = async (service: Service): Promise<any> => {
_: any,
{
projectId,
deploymentId,
}: { deploymentId: string; projectId: string },
deploymentId
}: { deploymentId: string; projectId: string }
) => {
try {
return await service.rollbackDeployment(projectId, deploymentId);
@@ -275,7 +257,9 @@ export const createResolvers = async (service: Service): Promise<any> => {
deleteDeployment: async (
_: any,
{ deploymentId }: { deploymentId: string },
{
deploymentId
}: { deploymentId: string; }
) => {
try {
return await service.deleteDeployment(deploymentId);
@@ -287,7 +271,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
addDomain: async (
_: any,
{ projectId, data }: { projectId: string; data: { name: string } },
{ projectId, data }: { projectId: string; data: { name: string } }
) => {
try {
return Boolean(await service.addDomain(projectId, data));
@@ -299,7 +283,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
updateDomain: async (
_: any,
{ domainId, data }: { domainId: string; data: DeepPartial<Domain> },
{ domainId, data }: { domainId: string; data: DeepPartial<Domain> }
) => {
try {
return await service.updateDomain(domainId, data);
@@ -312,7 +296,7 @@ export const createResolvers = async (service: Service): Promise<any> => {
authenticateGitHub: async (
_: any,
{ code }: { code: string },
context: any,
context: any
) => {
try {
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) => {
try {
return service.unauthenticateGitHub(context.user, {
gitHubToken: null,
});
return service.unauthenticateGitHub(context.user, { gitHubToken: null });
} catch (err) {
log(err);
return false;
}
},
},
}
}
};
};
-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.2' });
});
export default router;
-2
View File
@@ -17,7 +17,6 @@ import { ServerConfig } from './config';
import { DEFAULT_GQL_PATH } from './constants';
import githubRouter from './routes/github';
import authRouter from './routes/auth';
import stagingRouter from './routes/staging';
import { Service } from './service';
const log = debug('snowball:server');
@@ -110,7 +109,6 @@ export const createAndStartServer = async (
app.set('service', service);
app.use('/auth', authRouter);
app.use('/api/github', githubRouter);
app.use('/staging', stagingRouter);
httpServer.listen(port, host, () => {
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 { Registry } from './registry';
import { GitHubConfig, RegistryConfig } from './config';
import {
AppDeploymentRecord,
AppDeploymentRemovalRecord,
GitPushEventPayload,
PackageJSON,
} from './types';
import { AppDeploymentRecord, AppDeploymentRemovalRecord, GitPushEventPayload, PackageJSON } from './types';
import { Role } from './entity/UserOrganization';
const log = debug('snowball:service');
@@ -76,32 +71,33 @@ export class Service {
// Fetch deployments in building state
const deployments = await this.db.getDeployments({
where: {
status: DeploymentStatus.Building,
},
status: DeploymentStatus.Building
}
});
if (deployments.length) {
log(
`Found ${deployments.length} deployments in ${DeploymentStatus.Building} state`,
`Found ${deployments.length} deployments in ${DeploymentStatus.Building} state`
);
// Calculate a timestamp for one hour ago
const anHourAgo = Date.now() - HOUR;
// Filter out deployments started more than an hour ago and mark them as Error
const oldDeploymentsToUpdate = deployments
.filter((deployment) => Number(deployment.updatedAt) < anHourAgo)
const oldDeploymentsToUpdate = deployments.filter(
deployment => (Number(deployment.updatedAt) < anHourAgo)
)
.map((deployment) => {
return this.db.updateDeploymentById(deployment.id, {
status: DeploymentStatus.Error,
isCurrent: false,
isCurrent: false
});
});
// If there are old deployments to update, log and perform the updates
if (oldDeploymentsToUpdate.length > 0) {
log(
`Cleaning up ${oldDeploymentsToUpdate.length} deployments stuck in ${DeploymentStatus.Building} state for over an hour`,
`Cleaning up ${oldDeploymentsToUpdate.length} deployments stuck in ${DeploymentStatus.Building} state for over an hour`
);
await Promise.all(oldDeploymentsToUpdate);
}
@@ -129,18 +125,17 @@ export class Service {
// Fetch deployments in deleting state
const deployments = await this.db.getDeployments({
where: {
status: DeploymentStatus.Deleting,
},
status: DeploymentStatus.Deleting
}
});
if (deployments.length) {
log(
`Found ${deployments.length} deployments in ${DeploymentStatus.Deleting} state`,
`Found ${deployments.length} deployments in ${DeploymentStatus.Deleting} state`
);
// Fetch ApplicationDeploymentRemovalRecords for deployments
const records =
await this.registry.getDeploymentRemovalRecords(deployments);
const records = await this.registry.getDeploymentRemovalRecords(deployments);
log(`Found ${records.length} ApplicationDeploymentRemovalRecords`);
// Update deployments for which ApplicationDeploymentRemovalRecords were returned
@@ -158,16 +153,16 @@ export class Service {
* Update deployments with ApplicationDeploymentRecord data
*/
async updateDeploymentsWithRecordData (
records: AppDeploymentRecord[],
records: AppDeploymentRecord[]
): Promise<void> {
// Get deployments for ApplicationDeploymentRecords
const deployments = await this.db.getDeployments({
where: records.map((record) => ({
applicationRecordId: record.attributes.application,
applicationRecordId: record.attributes.application
})),
order: {
createdAt: 'DESC',
},
createdAt: 'DESC'
}
});
// Get project IDs of deployments that are in production environment
@@ -179,13 +174,13 @@ export class Service {
return acc;
},
new Set<string>(),
new Set<string>()
);
// Set old deployments isCurrent to false
await this.db.updateDeploymentsByProjectIds(
Array.from(productionDeploymentProjectIds),
{ isCurrent: false },
{ isCurrent: false }
);
const recordToDeploymentsMap = deployments.reduce(
@@ -193,7 +188,7 @@ export class Service {
acc[deployment.applicationRecordId] = deployment;
return acc;
},
{},
{}
);
// Update deployment data for ApplicationDeploymentRecords
@@ -205,11 +200,11 @@ export class Service {
applicationDeploymentRecordData: record.attributes,
url: record.attributes.url,
status: DeploymentStatus.Ready,
isCurrent: deployment.environment === Environment.Production,
isCurrent: deployment.environment === Environment.Production
});
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[],
deployments: Deployment[],
): Promise<void> {
const removedApplicationDeploymentRecordIds = records.map(
(record) => record.attributes.deployment,
);
const removedApplicationDeploymentRecordIds = records.map(record => record.attributes.deployment);
// Get removed deployments for ApplicationDeploymentRecords
const removedDeployments = deployments.filter((deployment) =>
removedApplicationDeploymentRecordIds.includes(
deployment.applicationDeploymentRecordId!,
),
);
const removedDeployments = deployments.filter(deployment => removedApplicationDeploymentRecordIds.includes(deployment.applicationDeploymentRecordId!))
const recordToDeploymentsMap = removedDeployments.reduce(
(acc: { [key: string]: Deployment }, deployment) => {
acc[deployment.applicationDeploymentRecordId!] = deployment;
return acc;
},
{},
{}
);
// Update deployment data for ApplicationDeploymentRecords and delete
@@ -252,10 +241,10 @@ export class Service {
});
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);
@@ -264,41 +253,41 @@ export class Service {
async getUser (userId: string): Promise<User | null> {
return this.db.getUser({
where: {
id: userId,
},
id: userId
}
});
}
async getUserByEmail(email: string): Promise<User | null> {
return await this.db.getUser({
where: {
email,
},
email
}
});
}
async getUserBySubOrgId(subOrgId: string): Promise<User | null> {
return await this.db.getUser({
where: {
subOrgId,
},
subOrgId
}
});
}
async getUserByEthAddress (ethAddress: string): Promise<User | null> {
return await this.db.getUser({
where: {
ethAddress,
},
ethAddress
}
});
}
async createUser (params: {
name: string;
email: string;
subOrgId: string;
ethAddress: string;
turnkeyWalletId: string;
name: string
email: string
subOrgId: string
ethAddress: string
turnkeyWalletId: string
}): Promise<User> {
const [org] = await this.db.getOrganizations({});
assert(org, 'No organizations exists in database');
@@ -316,7 +305,7 @@ export class Service {
await this.db.addUserOrganization({
member: user,
organization: org,
role: Role.Owner,
role: Role.Owner
});
return user;
@@ -326,7 +315,7 @@ export class Service {
const user = await this.db.getUser({ where: { id: userId } });
assert(
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 });
@@ -342,14 +331,8 @@ export class Service {
return dbProject;
}
async getProjectsInOrganization(
user: User,
organizationSlug: string,
): Promise<Project[]> {
const dbProjects = await this.db.getProjectsInOrganization(
user.id,
organizationSlug,
);
async getProjectsInOrganization (user: User, organizationSlug: string): Promise<Project[]> {
const dbProjects = await this.db.getProjectsInOrganization(user.id, organizationSlug);
return dbProjects;
}
@@ -359,7 +342,7 @@ export class Service {
}
async getEnvironmentVariablesByProjectId (
projectId: string,
projectId: string
): Promise<EnvironmentVariable[]> {
const dbEnvironmentVariables =
await this.db.getEnvironmentVariablesByProjectId(projectId);
@@ -367,7 +350,7 @@ export class Service {
}
async getProjectMembersByProjectId (
projectId: string,
projectId: string
): Promise<ProjectMember[]> {
const dbProjectMembers =
await this.db.getProjectMembersByProjectId(projectId);
@@ -375,16 +358,13 @@ export class Service {
}
async searchProjects (user: User, searchText: string): Promise<Project[]> {
const dbProjects = await this.db.getProjectsBySearchText(
user.id,
searchText,
);
const dbProjects = await this.db.getProjectsBySearchText(user.id, searchText);
return dbProjects;
}
async getDomainsByProjectId (
projectId: string,
filter?: FindOptionsWhere<Domain>,
filter?: FindOptionsWhere<Domain>
): Promise<Domain[]> {
const dbDomains = await this.db.getDomainsByProjectId(projectId, filter);
return dbDomains;
@@ -392,7 +372,7 @@ export class Service {
async updateProjectMember (
projectMemberId: string,
data: { permissions: Permission[] },
data: { permissions: Permission[] }
): Promise<boolean> {
return this.db.updateProjectMemberById(projectMemberId, data);
}
@@ -402,39 +382,36 @@ export class Service {
data: {
email: string;
permissions: Permission[];
},
}
): Promise<ProjectMember> {
// TODO: Send invitation
let user = await this.db.getUser({
where: {
email: data.email,
},
email: data.email
}
});
if (!user) {
user = await this.db.addUser({
email: data.email,
email: data.email
});
}
const newProjectMember = await this.db.addProjectMember({
project: {
id: projectId,
id: projectId
},
permissions: data.permissions,
isPending: true,
member: {
id: user.id,
},
id: user.id
}
});
return newProjectMember;
}
async removeProjectMember(
user: User,
projectMemberId: string,
): Promise<boolean> {
async removeProjectMember (user: User, projectMemberId: string): Promise<boolean> {
const member = await this.db.getProjectMemberById(projectMemberId);
if (String(member.member.id) === user.id) {
@@ -453,7 +430,7 @@ export class Service {
async addEnvironmentVariables (
projectId: string,
data: { environments: string[]; key: string; value: string }[],
data: { environments: string[]; key: string; value: string }[]
): Promise<EnvironmentVariable[]> {
const formattedEnvironmentVariables = data
.map((environmentVariable) => {
@@ -463,41 +440,38 @@ export class Service {
value: environmentVariable.value,
environment: environment as Environment,
project: Object.assign(new Project(), {
id: projectId,
}),
id: projectId
})
};
});
})
.flat();
const savedEnvironmentVariables = await this.db.addEnvironmentVariables(
formattedEnvironmentVariables,
formattedEnvironmentVariables
);
return savedEnvironmentVariables;
}
async updateEnvironmentVariable (
environmentVariableId: string,
data: DeepPartial<EnvironmentVariable>,
data: DeepPartial<EnvironmentVariable>
): Promise<boolean> {
return this.db.updateEnvironmentVariable(environmentVariableId, data);
}
async removeEnvironmentVariable (
environmentVariableId: string,
environmentVariableId: string
): Promise<boolean> {
return this.db.deleteEnvironmentVariable(environmentVariableId);
}
async updateDeploymentToProd(
user: User,
deploymentId: string,
): Promise<Deployment> {
async updateDeploymentToProd (user: User, deploymentId: string): Promise<Deployment> {
const oldDeployment = await this.db.getDeployment({
where: { id: deploymentId },
relations: {
project: true,
},
project: true
}
});
if (!oldDeployment) {
@@ -506,18 +480,20 @@ export class Service {
const prodBranchDomains = await this.db.getDomainsByProjectId(
oldDeployment.project.id,
{ branch: oldDeployment.project.prodBranch },
{ branch: oldDeployment.project.prodBranch }
);
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,
branch: oldDeployment.branch,
environment: Environment.Production,
domain: prodBranchDomains[0],
commitHash: oldDeployment.commitHash,
commitMessage: oldDeployment.commitMessage,
commitMessage: oldDeployment.commitMessage
});
return newDeployment;
@@ -526,11 +502,11 @@ 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}`,
`Creating deployment in project ${data.project.name} from branch ${data.branch}`
);
const [owner, repo] = data.project.repository.split('/');
@@ -538,7 +514,7 @@ export class Service {
owner,
repo,
path: 'package.json',
ref: data.commitHash,
ref: data.commitHash
});
if (!packageJSONData) {
@@ -550,12 +526,10 @@ export class Service {
assert(packageJSON.name, "name field doesn't exist in package.json");
const repoUrl = (
await octokit.rest.repos.get({
const repoUrl = (await octokit.rest.repos.get({
owner,
repo,
})
).data.html_url;
repo
})).data.html_url;
// TODO: Set environment variables for each deployment (environment variables can`t be set in application record)
const { applicationRecordId, applicationRecordData } =
@@ -564,20 +538,17 @@ export class Service {
packageJSON,
appType: data.project!.template!,
commitHash: data.commitHash!,
repoUrl,
repoUrl
});
// Update previous deployment with prod branch domain
// TODO: Fix unique constraint error for domain
if (data.domain) {
await this.db.updateDeployment(
{
domainId: data.domain.id,
},
{
domain: null,
},
);
await this.db.updateDeployment({
domainId: data.domain.id
}, {
domain: null
});
}
const newDeployment = await this.db.addDeployment({
@@ -591,67 +562,53 @@ export class Service {
applicationRecordData,
domain: data.domain,
createdBy: Object.assign(new User(), {
id: userId,
}),
id: userId
})
});
log(
`Created deployment ${newDeployment.id} and published application record ${applicationRecordId}`,
);
log(`Created deployment ${newDeployment.id} and published application record ${applicationRecordId}`);
const environmentVariables =
await this.db.getEnvironmentVariablesByProjectId(data.project.id!, {
environment: Environment.Production,
});
const environmentVariables = await this.db.getEnvironmentVariablesByProjectId(data.project.id!, { environment: Environment.Production });
const environmentVariablesObj = environmentVariables.reduce(
(acc, env) => {
const environmentVariablesObj = environmentVariables.reduce((acc, env) => {
acc[env.key] = env.value;
return acc;
},
{} as { [key: string]: string },
);
}, {} 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({
await this.registry.createApplicationDeploymentRequest(
{
deployment: newDeployment,
appName: repo,
repository: repoUrl,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}`,
dns: `${newDeployment.project.name}`
});
}
const { applicationDeploymentRequestId, applicationDeploymentRequestData } =
await this.registry.createApplicationDeploymentRequest({
const { applicationDeploymentRequestId, applicationDeploymentRequestData } = await this.registry.createApplicationDeploymentRequest(
{
deployment: newDeployment,
appName: repo,
repository: repoUrl,
environmentVariables: environmentVariablesObj,
dns: `${newDeployment.project.name}-${newDeployment.id}`,
dns: `${newDeployment.project.name}-${newDeployment.id}`
});
await this.db.updateDeploymentById(newDeployment.id, {
applicationDeploymentRequestId,
applicationDeploymentRequestData,
});
await this.db.updateDeploymentById(newDeployment.id, { applicationDeploymentRequestId, applicationDeploymentRequestData });
return newDeployment;
}
async addProject(
user: User,
organizationSlug: string,
data: DeepPartial<Project>,
): Promise<Project | undefined> {
async addProject (user: User, organizationSlug: string, data: DeepPartial<Project>): Promise<Project | undefined> {
const organization = await this.db.getOrganization({
where: {
slug: organizationSlug,
},
slug: organizationSlug
}
});
if (!organization) {
throw new Error('Organization does not exist');
@@ -663,23 +620,26 @@ export class Service {
const [owner, repo] = project.repository.split('/');
const {
data: [latestCommit],
data: [latestCommit]
} = await octokit.rest.repos.listCommits({
owner,
repo,
sha: project.prodBranch,
per_page: 1,
per_page: 1
});
// Create deployment with prod branch and latest commit
await this.createDeployment(user.id, octokit, {
await this.createDeployment(user.id,
octokit,
{
project,
branch: project.prodBranch,
environment: Environment.Production,
domain: null,
commitHash: latestCommit.sha,
commitMessage: latestCommit.commit.message,
});
commitMessage: latestCommit.commit.message
}
);
await this.createRepoHook(octokit, project);
@@ -695,11 +655,11 @@ export class Service {
config: {
url: new URL(
'api/github/webhook',
this.config.gitHubConfig.webhookUrl,
this.config.gitHubConfig.webhookUrl
).href,
content_type: 'json',
content_type: 'json'
},
events: ['push'],
events: ['push']
});
} catch (err) {
// 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.status === 422 &&
(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;
}
log(
`Handling GitHub push event from repository: ${repository.full_name}, branch: ${ref}`,
);
log(`Handling GitHub push event from repository: ${repository.full_name}, branch: ${ref}`);
const projects = await this.db.getProjects({
where: { repository: repository.full_name },
where: { repository: repository.full_name }
});
if (!projects.length) {
@@ -745,7 +703,7 @@ export class Service {
for await (const project of projects) {
const octokit = await this.getOctokit(project.ownerId);
const [domain] = await this.db.getDomainsByProjectId(project.id, {
branch,
branch
});
// Create deployment with branch and latest commit in GitHub data
@@ -758,14 +716,14 @@ export class Service {
: Environment.Preview,
domain,
commitHash: headCommit.id,
commitMessage: headCommit.message,
commitMessage: headCommit.message
});
}
}
async updateProject (
projectId: string,
data: DeepPartial<Project>,
data: DeepPartial<Project>
): Promise<boolean> {
return this.db.updateProjectById(projectId, data);
}
@@ -778,13 +736,13 @@ export class Service {
async deleteDomain (domainId: string): Promise<boolean> {
const domainsRedirectedFrom = await this.db.getDomains({
where: {
redirectToId: domainId,
},
redirectToId: domainId
}
});
if (domainsRedirectedFrom.length > 0) {
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: {
project: true,
domain: true,
createdBy: true,
createdBy: true
},
where: {
id: deploymentId,
},
id: deploymentId
}
});
if (oldDeployment === null) {
@@ -809,14 +767,16 @@ export class Service {
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,
// TODO: Put isCurrent field in project
branch: oldDeployment.branch,
environment: Environment.Production,
domain: oldDeployment.domain,
commitHash: oldDeployment.commitHash,
commitMessage: oldDeployment.commitMessage,
commitMessage: oldDeployment.commitMessage
});
return newDeployment;
@@ -824,19 +784,19 @@ export class Service {
async rollbackDeployment (
projectId: string,
deploymentId: string,
deploymentId: string
): Promise<boolean> {
// TODO: Implement transactions
const oldCurrentDeployment = await this.db.getDeployment({
relations: {
domain: true,
domain: true
},
where: {
project: {
id: projectId,
},
isCurrent: true,
id: projectId
},
isCurrent: true
}
});
if (!oldCurrentDeployment) {
@@ -845,12 +805,12 @@ export class Service {
const oldCurrentDeploymentUpdate = await this.db.updateDeploymentById(
oldCurrentDeployment.id,
{ isCurrent: false, domain: null },
{ isCurrent: false, domain: null }
);
const newCurrentDeploymentUpdate = await this.db.updateDeploymentById(
deploymentId,
{ isCurrent: true, domain: oldCurrentDeployment?.domain },
{ isCurrent: true, domain: oldCurrentDeployment?.domain }
);
return newCurrentDeploymentUpdate && oldCurrentDeploymentUpdate;
@@ -859,11 +819,11 @@ export class Service {
async deleteDeployment (deploymentId: string): Promise<boolean> {
const deployment = await this.db.getDeployment({
where: {
id: deploymentId,
id: deploymentId
},
relations: {
project: true,
},
project: true
}
});
if (deployment && deployment.applicationDeploymentRecordId) {
@@ -871,39 +831,31 @@ export class Service {
if (deployment.isCurrent) {
const currentDeploymentURL = `https://${deployment.project.subDomain}`;
const deploymentRecords =
await this.registry.getDeploymentRecordsByFilter({
const deploymentRecords = await this.registry.getDeploymentRecordsByFilter({
application: deployment.applicationRecordId,
url: currentDeploymentURL,
});
url: currentDeploymentURL
})
if (!deploymentRecords.length) {
log(
`No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}`,
);
log(`No ApplicationDeploymentRecord found for URL ${currentDeploymentURL} and ApplicationDeploymentRecord id ${deployment.applicationDeploymentRecordId}`);
return false;
}
await this.registry.createApplicationDeploymentRemovalRequest({
deploymentId: deploymentRecords[0].id,
});
await this.registry.createApplicationDeploymentRemovalRequest({ deploymentId: deploymentRecords[0].id });
}
const result =
await this.registry.createApplicationDeploymentRemovalRequest({
deploymentId: deployment.applicationDeploymentRecordId,
});
const result = await this.registry.createApplicationDeploymentRemovalRequest({ deploymentId: deployment.applicationDeploymentRecordId });
await this.db.updateDeploymentById(deployment.id, {
await this.db.updateDeploymentById(
deployment.id,
{
status: DeploymentStatus.Deleting,
applicationDeploymentRemovalRequestId:
result.applicationDeploymentRemovalRequestId,
applicationDeploymentRemovalRequestData:
result.applicationDeploymentRemovalRequestData,
});
applicationDeploymentRemovalRequestId: result.applicationDeploymentRemovalRequestId,
applicationDeploymentRemovalRequestData: result.applicationDeploymentRemovalRequestData
}
);
return result !== undefined || result !== null;
return (result !== undefined || result !== null);
}
return false;
@@ -911,7 +863,7 @@ export class Service {
async addDomain (
projectId: string,
data: { name: string },
data: { name: string }
): Promise<{
primaryDomain: Domain;
redirectedDomain: Domain;
@@ -925,7 +877,7 @@ export class Service {
const primaryDomainDetails = {
...data,
branch: currentProject.prodBranch,
project: currentProject,
project: currentProject
};
const savedPrimaryDomain = await this.db.addDomain(primaryDomainDetails);
@@ -936,27 +888,27 @@ export class Service {
name: domainArr.length > 1 ? domainArr[1] : `www.${domainArr[0]}`,
branch: currentProject.prodBranch,
project: currentProject,
redirectTo: savedPrimaryDomain,
redirectTo: savedPrimaryDomain
};
const savedRedirectedDomain = await this.db.addDomain(
redirectedDomainDetails,
redirectedDomainDetails
);
return {
primaryDomain: savedPrimaryDomain,
redirectedDomain: savedRedirectedDomain,
redirectedDomain: savedRedirectedDomain
};
}
async updateDomain (
domainId: string,
data: DeepPartial<Domain>,
data: DeepPartial<Domain>
): Promise<boolean> {
const domain = await this.db.getDomain({
where: {
id: domainId,
},
id: domainId
}
});
if (domain === null) {
@@ -964,16 +916,16 @@ export class Service {
}
const newDomain = {
...data,
...data
};
const domainsRedirectedFrom = await this.db.getDomains({
where: {
project: {
id: domain.projectId,
},
redirectToId: domain.id,
id: domain.projectId
},
redirectToId: domain.id
}
});
// 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) {
const redirectedDomain = await this.db.getDomain({
where: {
id: data.redirectToId,
},
id: data.redirectToId
}
});
if (redirectedDomain === null) {
@@ -994,7 +946,7 @@ export class Service {
if (redirectedDomain.redirectToId) {
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;
}
async authenticateGitHub(
code: string,
user: User,
): Promise<{ token: string }> {
const {
authentication: { token },
} = await this.oauthApp.createToken({
code,
async authenticateGitHub (code:string, user: User): Promise<{token: string}> {
const { authentication: { token } } = await this.oauthApp.createToken({
code
});
await this.db.updateUser(user, { gitHubToken: token });
@@ -1021,10 +968,7 @@ export class Service {
return { token };
}
async unauthenticateGitHub(
user: User,
data: DeepPartial<User>,
): Promise<boolean> {
async unauthenticateGitHub (user: User, data: DeepPartial<User>): Promise<boolean> {
return this.db.updateUser(user, data);
}
}
-3
View File
@@ -15,9 +15,6 @@ import { SERVER_GQL_PATH } from './constants';
import { Toaster } from 'components/shared/Toast';
import { LogErrorBoundary } from 'utils/log-error';
// @ts-ignore
console.log(`v-${__VERSION__}`);
const root = ReactDOM.createRoot(
document.getElementById('root') as HTMLElement,
);
@@ -47,9 +47,7 @@ export const Login = ({ onDone }: Props) => {
console.log('Handling google redirect back');
try {
await google.handleOAuthRedirectBack();
// @ts-ignore
wallet = await google.getEthersWallet();
// @ts-ignore
const result = await signInWithEthereum(1, 'login', wallet);
if (result.error) {
setError(result.error);
@@ -45,9 +45,7 @@ export const SignUp = ({ onDone }: Props) => {
setProvider('google');
try {
await google.handleOAuthRedirectBack();
// @ts-ignore
wallet = await google.getEthersWallet();
// @ts-ignore
const result = await signInWithEthereum(1, 'signup', wallet);
if (result.error) {
setError({ type: 'provider', message: result.error });
-5
View File
@@ -1,7 +1,5 @@
import { defineConfig, PluginOption } from 'vite';
import react from '@vitejs/plugin-react';
import { exec } from 'child_process';
import { promisify } from 'util';
// https://vitejs.dev/config/
export default defineConfig({
@@ -18,8 +16,5 @@ export default defineConfig({
},
define: {
'process.env': {},
__VERSION__: JSON.stringify(
(await promisify(exec)('git rev-parse --short HEAD')).stdout.trim(),
),
},
});
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/queries.ts","../src/mutations.ts","../src/types.ts"],"sourcesContent":["export * from \"./client\";\nexport * from \"./types\";\n","import {\n ApolloClient,\n DefaultOptions,\n InMemoryCache,\n NormalizedCacheObject,\n} from \"@apollo/client\";\n\nimport * as queries from \"./queries\";\nimport * as types from \"./types\";\nimport * as mutations from \"./mutations\";\n\nexport interface GraphQLConfig {\n gqlEndpoint: string;\n}\n\n// TODO: check options\nconst defaultOptions: DefaultOptions = {\n watchQuery: {\n fetchPolicy: \"no-cache\",\n errorPolicy: \"ignore\",\n },\n query: {\n fetchPolicy: \"no-cache\",\n errorPolicy: \"all\",\n },\n};\n\nexport class GQLClient {\n private client: ApolloClient<NormalizedCacheObject>;\n\n constructor(config: GraphQLConfig) {\n this.client = new ApolloClient({\n uri: config.gqlEndpoint,\n cache: new InMemoryCache(),\n defaultOptions,\n credentials: \"include\",\n });\n }\n\n async getUser(): Promise<types.GetUserResponse> {\n const { data } = await this.client.query({\n query: queries.getUser,\n });\n\n return data;\n }\n\n async getProject(projectId: string): Promise<types.GetProjectResponse> {\n const { data } = await this.client.query({\n query: queries.getProject,\n variables: {\n projectId,\n },\n });\n\n return data;\n }\n\n async getProjectsInOrganization(\n organizationSlug: string\n ): Promise<types.GetProjectsInOrganizationResponse> {\n const { data } = await this.client.query({\n query: queries.getProjectsInOrganization,\n variables: {\n organizationSlug,\n },\n });\n\n return data;\n }\n\n async getOrganizations(): Promise<types.GetOrganizationsResponse> {\n const { data } = await this.client.query({\n query: queries.getOrganizations,\n });\n\n return data;\n }\n\n async getDeployments(\n projectId: string\n ): Promise<types.GetDeploymentsResponse> {\n const { data } = await this.client.query({\n query: queries.getDeployments,\n variables: {\n projectId,\n },\n });\n\n return data;\n }\n\n async getEnvironmentVariables(\n projectId: string\n ): Promise<types.GetEnvironmentVariablesResponse> {\n const { data } = await this.client.query({\n query: queries.getEnvironmentVariables,\n variables: {\n projectId,\n },\n });\n\n return data;\n }\n\n async getProjectMembers(\n projectId: string\n ): Promise<types.GetProjectMembersResponse> {\n const result = await this.client.query({\n query: queries.getProjectMembers,\n variables: {\n projectId,\n },\n });\n\n return result.data;\n }\n\n async addProjectMember(\n projectId: string,\n data: types.AddProjectMemberInput\n ): Promise<types.AddProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.addProjectMember,\n variables: {\n projectId,\n data,\n },\n });\n\n return result.data;\n }\n\n async updateProjectMember(\n projectMemberId: string,\n data: types.UpdateProjectMemberInput\n ): Promise<types.UpdateProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.updateProjectMember,\n variables: {\n projectMemberId,\n data,\n },\n });\n\n return result.data;\n }\n\n async removeProjectMember(\n projectMemberId: string\n ): Promise<types.RemoveProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.removeProjectMember,\n variables: {\n projectMemberId,\n },\n });\n\n return result.data;\n }\n\n async searchProjects(\n searchText: string\n ): Promise<types.SearchProjectsResponse> {\n const { data } = await this.client.query({\n query: queries.searchProjects,\n variables: {\n searchText,\n },\n });\n\n return data;\n }\n\n async addEnvironmentVariables(\n projectId: string,\n data: types.AddEnvironmentVariableInput[]\n ): Promise<types.AddEnvironmentVariablesResponse> {\n const result = await this.client.mutate({\n mutation: mutations.addEnvironmentVariables,\n variables: {\n projectId,\n data,\n },\n });\n\n return result.data;\n }\n\n async updateEnvironmentVariable(\n environmentVariableId: string,\n data: types.UpdateEnvironmentVariableInput\n ): Promise<types.UpdateEnvironmentVariableResponse> {\n const result = await this.client.mutate({\n mutation: mutations.updateEnvironmentVariable,\n variables: {\n environmentVariableId,\n data,\n },\n });\n\n return result.data;\n }\n\n async removeEnvironmentVariable(\n environmentVariableId: string\n ): Promise<types.RemoveEnvironmentVariableResponse> {\n const { data } = await thisLine truncated
{"version":3,"sources":["../src/index.ts","../src/client.ts","../src/queries.ts","../src/mutations.ts","../src/types.ts"],"sourcesContent":["export * from \"./client\";\nexport * from \"./types\";\n","import { ApolloClient, DefaultOptions, InMemoryCache, NormalizedCacheObject } from '@apollo/client';\n\nimport * as queries from './queries';\nimport * as types from './types';\nimport * as mutations from './mutations';\n\nexport interface GraphQLConfig {\n gqlEndpoint: string;\n}\n\n// TODO: check options\nconst defaultOptions: DefaultOptions = {\n watchQuery: {\n fetchPolicy: 'no-cache',\n errorPolicy: 'ignore'\n },\n query: {\n fetchPolicy: 'no-cache',\n errorPolicy: 'all'\n }\n};\n\nexport class GQLClient {\n private client: ApolloClient<NormalizedCacheObject>;\n\n constructor (config: GraphQLConfig) {\n this.client = new ApolloClient({\n uri: config.gqlEndpoint,\n cache: new InMemoryCache(),\n defaultOptions,\n credentials: 'include'\n });\n }\n\n async getUser () : Promise<types.GetUserResponse> {\n const { data } = await this.client.query({\n query: queries.getUser\n });\n\n return data;\n }\n\n async getProject (projectId: string) : Promise<types.GetProjectResponse> {\n const { data } = await this.client.query({\n query: queries.getProject,\n variables: {\n projectId\n }\n });\n\n return data;\n }\n\n async getProjectsInOrganization (organizationSlug: string) : Promise<types.GetProjectsInOrganizationResponse> {\n const { data } = await this.client.query({\n query: queries.getProjectsInOrganization,\n variables: {\n organizationSlug\n }\n });\n\n return data;\n }\n\n async getOrganizations () : Promise<types.GetOrganizationsResponse> {\n const { data } = await this.client.query({\n query: queries.getOrganizations\n });\n\n return data;\n }\n\n async getDeployments (projectId: string) : Promise<types.GetDeploymentsResponse> {\n const { data } = await this.client.query({\n query: queries.getDeployments,\n variables: {\n projectId\n }\n });\n\n return data;\n }\n\n async getEnvironmentVariables (projectId: string) : Promise<types.GetEnvironmentVariablesResponse> {\n const { data } = await this.client.query({\n query: queries.getEnvironmentVariables,\n variables: {\n projectId\n }\n });\n\n return data;\n }\n\n async getProjectMembers (projectId: string) : Promise<types.GetProjectMembersResponse> {\n const result = await this.client.query({\n query: queries.getProjectMembers,\n variables: {\n projectId\n }\n });\n\n return result.data;\n }\n\n async addProjectMember (projectId: string, data: types.AddProjectMemberInput) : Promise<types.AddProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.addProjectMember,\n variables: {\n projectId,\n data\n }\n });\n\n return result.data;\n }\n\n async updateProjectMember (projectMemberId: string, data: types.UpdateProjectMemberInput): Promise<types.UpdateProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.updateProjectMember,\n variables: {\n projectMemberId,\n data\n }\n });\n\n return result.data;\n }\n\n async removeProjectMember (projectMemberId: string): Promise<types.RemoveProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.removeProjectMember,\n variables: {\n projectMemberId\n }\n });\n\n return result.data;\n }\n\n async searchProjects (searchText: string) : Promise<types.SearchProjectsResponse> {\n const { data } = await this.client.query({\n query: queries.searchProjects,\n variables: {\n searchText\n }\n });\n\n return data;\n }\n\n async addEnvironmentVariables (projectId: string, data: types.AddEnvironmentVariableInput[]): Promise<types.AddEnvironmentVariablesResponse> {\n const result = await this.client.mutate({\n mutation: mutations.addEnvironmentVariables,\n variables: {\n projectId,\n data\n }\n });\n\n return result.data;\n }\n\n async updateEnvironmentVariable (environmentVariableId: string, data: types.UpdateEnvironmentVariableInput): Promise<types.UpdateEnvironmentVariableResponse> {\n const result = await this.client.mutate({\n mutation: mutations.updateEnvironmentVariable,\n variables: {\n environmentVariableId,\n data\n }\n });\n\n return result.data;\n }\n\n async removeEnvironmentVariable (environmentVariableId: string): Promise<types.RemoveEnvironmentVariableResponse> {\n const { data } = await this.client.mutate({\n mutation: mutations.removeEnvironmentVariable,\n variables: {\n environmentVariableId\n }\n });\n\n return data;\n }\nLine truncated
+1 -4
View File
@@ -20,10 +20,7 @@ var __async = (__this, __arguments, generator) => {
};
// src/client.ts
import {
ApolloClient,
InMemoryCache
} from "@apollo/client";
import { ApolloClient, InMemoryCache } from "@apollo/client";
// src/queries.ts
import { gql } from "@apollo/client";
+1 -1
View File
@@ -1 +1 @@
{"version":3,"sources":["../src/client.ts","../src/queries.ts","../src/mutations.ts","../src/types.ts"],"sourcesContent":["import {\n ApolloClient,\n DefaultOptions,\n InMemoryCache,\n NormalizedCacheObject,\n} from \"@apollo/client\";\n\nimport * as queries from \"./queries\";\nimport * as types from \"./types\";\nimport * as mutations from \"./mutations\";\n\nexport interface GraphQLConfig {\n gqlEndpoint: string;\n}\n\n// TODO: check options\nconst defaultOptions: DefaultOptions = {\n watchQuery: {\n fetchPolicy: \"no-cache\",\n errorPolicy: \"ignore\",\n },\n query: {\n fetchPolicy: \"no-cache\",\n errorPolicy: \"all\",\n },\n};\n\nexport class GQLClient {\n private client: ApolloClient<NormalizedCacheObject>;\n\n constructor(config: GraphQLConfig) {\n this.client = new ApolloClient({\n uri: config.gqlEndpoint,\n cache: new InMemoryCache(),\n defaultOptions,\n credentials: \"include\",\n });\n }\n\n async getUser(): Promise<types.GetUserResponse> {\n const { data } = await this.client.query({\n query: queries.getUser,\n });\n\n return data;\n }\n\n async getProject(projectId: string): Promise<types.GetProjectResponse> {\n const { data } = await this.client.query({\n query: queries.getProject,\n variables: {\n projectId,\n },\n });\n\n return data;\n }\n\n async getProjectsInOrganization(\n organizationSlug: string\n ): Promise<types.GetProjectsInOrganizationResponse> {\n const { data } = await this.client.query({\n query: queries.getProjectsInOrganization,\n variables: {\n organizationSlug,\n },\n });\n\n return data;\n }\n\n async getOrganizations(): Promise<types.GetOrganizationsResponse> {\n const { data } = await this.client.query({\n query: queries.getOrganizations,\n });\n\n return data;\n }\n\n async getDeployments(\n projectId: string\n ): Promise<types.GetDeploymentsResponse> {\n const { data } = await this.client.query({\n query: queries.getDeployments,\n variables: {\n projectId,\n },\n });\n\n return data;\n }\n\n async getEnvironmentVariables(\n projectId: string\n ): Promise<types.GetEnvironmentVariablesResponse> {\n const { data } = await this.client.query({\n query: queries.getEnvironmentVariables,\n variables: {\n projectId,\n },\n });\n\n return data;\n }\n\n async getProjectMembers(\n projectId: string\n ): Promise<types.GetProjectMembersResponse> {\n const result = await this.client.query({\n query: queries.getProjectMembers,\n variables: {\n projectId,\n },\n });\n\n return result.data;\n }\n\n async addProjectMember(\n projectId: string,\n data: types.AddProjectMemberInput\n ): Promise<types.AddProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.addProjectMember,\n variables: {\n projectId,\n data,\n },\n });\n\n return result.data;\n }\n\n async updateProjectMember(\n projectMemberId: string,\n data: types.UpdateProjectMemberInput\n ): Promise<types.UpdateProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.updateProjectMember,\n variables: {\n projectMemberId,\n data,\n },\n });\n\n return result.data;\n }\n\n async removeProjectMember(\n projectMemberId: string\n ): Promise<types.RemoveProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.removeProjectMember,\n variables: {\n projectMemberId,\n },\n });\n\n return result.data;\n }\n\n async searchProjects(\n searchText: string\n ): Promise<types.SearchProjectsResponse> {\n const { data } = await this.client.query({\n query: queries.searchProjects,\n variables: {\n searchText,\n },\n });\n\n return data;\n }\n\n async addEnvironmentVariables(\n projectId: string,\n data: types.AddEnvironmentVariableInput[]\n ): Promise<types.AddEnvironmentVariablesResponse> {\n const result = await this.client.mutate({\n mutation: mutations.addEnvironmentVariables,\n variables: {\n projectId,\n data,\n },\n });\n\n return result.data;\n }\n\n async updateEnvironmentVariable(\n environmentVariableId: string,\n data: types.UpdateEnvironmentVariableInput\n ): Promise<types.UpdateEnvironmentVariableResponse> {\n const result = await this.client.mutate({\n mutation: mutations.updateEnvironmentVariable,\n variables: {\n environmentVariableId,\n data,\n },\n });\n\n return result.data;\n }\n\n async removeEnvironmentVariable(\n environmentVariableId: string\n ): Promise<types.RemoveEnvironmentVariableResponse> {\n const { data } = await this.client.mutate({\n mutation: mutations.removeEnvironmentVariable,\n Line truncated
{"version":3,"sources":["../src/client.ts","../src/queries.ts","../src/mutations.ts","../src/types.ts"],"sourcesContent":["import { ApolloClient, DefaultOptions, InMemoryCache, NormalizedCacheObject } from '@apollo/client';\n\nimport * as queries from './queries';\nimport * as types from './types';\nimport * as mutations from './mutations';\n\nexport interface GraphQLConfig {\n gqlEndpoint: string;\n}\n\n// TODO: check options\nconst defaultOptions: DefaultOptions = {\n watchQuery: {\n fetchPolicy: 'no-cache',\n errorPolicy: 'ignore'\n },\n query: {\n fetchPolicy: 'no-cache',\n errorPolicy: 'all'\n }\n};\n\nexport class GQLClient {\n private client: ApolloClient<NormalizedCacheObject>;\n\n constructor (config: GraphQLConfig) {\n this.client = new ApolloClient({\n uri: config.gqlEndpoint,\n cache: new InMemoryCache(),\n defaultOptions,\n credentials: 'include'\n });\n }\n\n async getUser () : Promise<types.GetUserResponse> {\n const { data } = await this.client.query({\n query: queries.getUser\n });\n\n return data;\n }\n\n async getProject (projectId: string) : Promise<types.GetProjectResponse> {\n const { data } = await this.client.query({\n query: queries.getProject,\n variables: {\n projectId\n }\n });\n\n return data;\n }\n\n async getProjectsInOrganization (organizationSlug: string) : Promise<types.GetProjectsInOrganizationResponse> {\n const { data } = await this.client.query({\n query: queries.getProjectsInOrganization,\n variables: {\n organizationSlug\n }\n });\n\n return data;\n }\n\n async getOrganizations () : Promise<types.GetOrganizationsResponse> {\n const { data } = await this.client.query({\n query: queries.getOrganizations\n });\n\n return data;\n }\n\n async getDeployments (projectId: string) : Promise<types.GetDeploymentsResponse> {\n const { data } = await this.client.query({\n query: queries.getDeployments,\n variables: {\n projectId\n }\n });\n\n return data;\n }\n\n async getEnvironmentVariables (projectId: string) : Promise<types.GetEnvironmentVariablesResponse> {\n const { data } = await this.client.query({\n query: queries.getEnvironmentVariables,\n variables: {\n projectId\n }\n });\n\n return data;\n }\n\n async getProjectMembers (projectId: string) : Promise<types.GetProjectMembersResponse> {\n const result = await this.client.query({\n query: queries.getProjectMembers,\n variables: {\n projectId\n }\n });\n\n return result.data;\n }\n\n async addProjectMember (projectId: string, data: types.AddProjectMemberInput) : Promise<types.AddProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.addProjectMember,\n variables: {\n projectId,\n data\n }\n });\n\n return result.data;\n }\n\n async updateProjectMember (projectMemberId: string, data: types.UpdateProjectMemberInput): Promise<types.UpdateProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.updateProjectMember,\n variables: {\n projectMemberId,\n data\n }\n });\n\n return result.data;\n }\n\n async removeProjectMember (projectMemberId: string): Promise<types.RemoveProjectMemberResponse> {\n const result = await this.client.mutate({\n mutation: mutations.removeProjectMember,\n variables: {\n projectMemberId\n }\n });\n\n return result.data;\n }\n\n async searchProjects (searchText: string) : Promise<types.SearchProjectsResponse> {\n const { data } = await this.client.query({\n query: queries.searchProjects,\n variables: {\n searchText\n }\n });\n\n return data;\n }\n\n async addEnvironmentVariables (projectId: string, data: types.AddEnvironmentVariableInput[]): Promise<types.AddEnvironmentVariablesResponse> {\n const result = await this.client.mutate({\n mutation: mutations.addEnvironmentVariables,\n variables: {\n projectId,\n data\n }\n });\n\n return result.data;\n }\n\n async updateEnvironmentVariable (environmentVariableId: string, data: types.UpdateEnvironmentVariableInput): Promise<types.UpdateEnvironmentVariableResponse> {\n const result = await this.client.mutate({\n mutation: mutations.updateEnvironmentVariable,\n variables: {\n environmentVariableId,\n data\n }\n });\n\n return result.data;\n }\n\n async removeEnvironmentVariable (environmentVariableId: string): Promise<types.RemoveEnvironmentVariableResponse> {\n const { data } = await this.client.mutate({\n mutation: mutations.removeEnvironmentVariable,\n variables: {\n environmentVariableId\n }\n });\n\n return data;\n }\n\n async updateDeploymentToProd (deploymentId: string): Promise<types.UpdateDLine truncated
+82 -139
View File
@@ -1,13 +1,8 @@
import {
ApolloClient,
DefaultOptions,
InMemoryCache,
NormalizedCacheObject,
} from "@apollo/client";
import { ApolloClient, DefaultOptions, InMemoryCache, NormalizedCacheObject } from '@apollo/client';
import * as queries from "./queries";
import * as types from "./types";
import * as mutations from "./mutations";
import * as queries from './queries';
import * as types from './types';
import * as mutations from './mutations';
export interface GraphQLConfig {
gqlEndpoint: string;
@@ -16,13 +11,13 @@ export interface GraphQLConfig {
// TODO: check options
const defaultOptions: DefaultOptions = {
watchQuery: {
fetchPolicy: "no-cache",
errorPolicy: "ignore",
fetchPolicy: 'no-cache',
errorPolicy: 'ignore'
},
query: {
fetchPolicy: "no-cache",
errorPolicy: "all",
},
fetchPolicy: 'no-cache',
errorPolicy: 'all'
}
};
export class GQLClient {
@@ -33,13 +28,13 @@ export class GQLClient {
uri: config.gqlEndpoint,
cache: new InMemoryCache(),
defaultOptions,
credentials: "include",
credentials: 'include'
});
}
async getUser () : Promise<types.GetUserResponse> {
const { data } = await this.client.query({
query: queries.getUser,
query: queries.getUser
});
return data;
@@ -49,21 +44,19 @@ export class GQLClient {
const { data } = await this.client.query({
query: queries.getProject,
variables: {
projectId,
},
projectId
}
});
return data;
}
async getProjectsInOrganization(
organizationSlug: string
): Promise<types.GetProjectsInOrganizationResponse> {
async getProjectsInOrganization (organizationSlug: string) : Promise<types.GetProjectsInOrganizationResponse> {
const { data } = await this.client.query({
query: queries.getProjectsInOrganization,
variables: {
organizationSlug,
},
organizationSlug
}
});
return data;
@@ -71,216 +64,179 @@ export class GQLClient {
async getOrganizations () : Promise<types.GetOrganizationsResponse> {
const { data } = await this.client.query({
query: queries.getOrganizations,
query: queries.getOrganizations
});
return data;
}
async getDeployments(
projectId: string
): Promise<types.GetDeploymentsResponse> {
async getDeployments (projectId: string) : Promise<types.GetDeploymentsResponse> {
const { data } = await this.client.query({
query: queries.getDeployments,
variables: {
projectId,
},
projectId
}
});
return data;
}
async getEnvironmentVariables(
projectId: string
): Promise<types.GetEnvironmentVariablesResponse> {
async getEnvironmentVariables (projectId: string) : Promise<types.GetEnvironmentVariablesResponse> {
const { data } = await this.client.query({
query: queries.getEnvironmentVariables,
variables: {
projectId,
},
projectId
}
});
return data;
}
async getProjectMembers(
projectId: string
): Promise<types.GetProjectMembersResponse> {
async getProjectMembers (projectId: string) : Promise<types.GetProjectMembersResponse> {
const result = await this.client.query({
query: queries.getProjectMembers,
variables: {
projectId,
},
projectId
}
});
return result.data;
}
async addProjectMember(
projectId: string,
data: types.AddProjectMemberInput
): Promise<types.AddProjectMemberResponse> {
async addProjectMember (projectId: string, data: types.AddProjectMemberInput) : Promise<types.AddProjectMemberResponse> {
const result = await this.client.mutate({
mutation: mutations.addProjectMember,
variables: {
projectId,
data,
},
data
}
});
return result.data;
}
async updateProjectMember(
projectMemberId: string,
data: types.UpdateProjectMemberInput
): Promise<types.UpdateProjectMemberResponse> {
async updateProjectMember (projectMemberId: string, data: types.UpdateProjectMemberInput): Promise<types.UpdateProjectMemberResponse> {
const result = await this.client.mutate({
mutation: mutations.updateProjectMember,
variables: {
projectMemberId,
data,
},
data
}
});
return result.data;
}
async removeProjectMember(
projectMemberId: string
): Promise<types.RemoveProjectMemberResponse> {
async removeProjectMember (projectMemberId: string): Promise<types.RemoveProjectMemberResponse> {
const result = await this.client.mutate({
mutation: mutations.removeProjectMember,
variables: {
projectMemberId,
},
projectMemberId
}
});
return result.data;
}
async searchProjects(
searchText: string
): Promise<types.SearchProjectsResponse> {
async searchProjects (searchText: string) : Promise<types.SearchProjectsResponse> {
const { data } = await this.client.query({
query: queries.searchProjects,
variables: {
searchText,
},
searchText
}
});
return data;
}
async addEnvironmentVariables(
projectId: string,
data: types.AddEnvironmentVariableInput[]
): Promise<types.AddEnvironmentVariablesResponse> {
async addEnvironmentVariables (projectId: string, data: types.AddEnvironmentVariableInput[]): Promise<types.AddEnvironmentVariablesResponse> {
const result = await this.client.mutate({
mutation: mutations.addEnvironmentVariables,
variables: {
projectId,
data,
},
data
}
});
return result.data;
}
async updateEnvironmentVariable(
environmentVariableId: string,
data: types.UpdateEnvironmentVariableInput
): Promise<types.UpdateEnvironmentVariableResponse> {
async updateEnvironmentVariable (environmentVariableId: string, data: types.UpdateEnvironmentVariableInput): Promise<types.UpdateEnvironmentVariableResponse> {
const result = await this.client.mutate({
mutation: mutations.updateEnvironmentVariable,
variables: {
environmentVariableId,
data,
},
data
}
});
return result.data;
}
async removeEnvironmentVariable(
environmentVariableId: string
): Promise<types.RemoveEnvironmentVariableResponse> {
async removeEnvironmentVariable (environmentVariableId: string): Promise<types.RemoveEnvironmentVariableResponse> {
const { data } = await this.client.mutate({
mutation: mutations.removeEnvironmentVariable,
variables: {
environmentVariableId,
},
environmentVariableId
}
});
return data;
}
async updateDeploymentToProd(
deploymentId: string
): Promise<types.UpdateDeploymentToProdResponse> {
async updateDeploymentToProd (deploymentId: string): Promise<types.UpdateDeploymentToProdResponse> {
const { data } = await this.client.mutate({
mutation: mutations.updateDeploymentToProd,
variables: {
deploymentId,
},
deploymentId
}
});
return data;
}
async addProject(
organizationSlug: string,
data: types.AddProjectInput
): Promise<types.AddProjectResponse> {
async addProject (organizationSlug: string, data: types.AddProjectInput): Promise<types.AddProjectResponse> {
const result = await this.client.mutate({
mutation: mutations.addProject,
variables: {
organizationSlug,
data,
},
data
}
});
return result.data;
}
async updateProject(
projectId: string,
data: types.UpdateProjectInput
): Promise<types.UpdateProjectResponse> {
async updateProject (projectId: string, data: types.UpdateProjectInput): Promise<types.UpdateProjectResponse> {
const result = await this.client.mutate({
mutation: mutations.updateProjectMutation,
variables: {
projectId,
data,
},
data
}
});
return result.data;
}
async updateDomain(
domainId: string,
data: types.UpdateDomainInput
): Promise<types.UpdateDomainResponse> {
async updateDomain (domainId: string, data: types.UpdateDomainInput): Promise<types.UpdateDomainResponse> {
const result = await this.client.mutate({
mutation: mutations.updateDomainMutation,
variables: {
domainId,
data,
},
data
}
});
return result.data;
}
async redeployToProd(
deploymentId: string
): Promise<types.RedeployToProdResponse> {
async redeployToProd (deploymentId: string): Promise<types.RedeployToProdResponse> {
const { data } = await this.client.mutate({
mutation: mutations.redeployToProd,
variables: {
deploymentId,
},
deploymentId
}
});
return data;
@@ -290,8 +246,8 @@ export class GQLClient {
const { data } = await this.client.mutate({
mutation: mutations.deleteProject,
variables: {
projectId,
},
projectId
}
});
return data;
@@ -301,79 +257,66 @@ export class GQLClient {
const { data } = await this.client.mutate({
mutation: mutations.deleteDomain,
variables: {
domainId,
},
domainId
}
});
return data;
}
async rollbackDeployment(
projectId: string,
deploymentId: string
): Promise<types.RollbackDeploymentResponse> {
async rollbackDeployment (projectId: string, deploymentId: string): Promise<types.RollbackDeploymentResponse> {
const { data } = await this.client.mutate({
mutation: mutations.rollbackDeployment,
variables: {
projectId,
deploymentId,
},
deploymentId
}
});
return data;
}
async deleteDeployment(
deploymentId: string
): Promise<types.DeleteDeploymentResponse> {
async deleteDeployment (deploymentId: string): Promise<types.DeleteDeploymentResponse> {
const { data } = await this.client.mutate({
mutation: mutations.deleteDeployment,
variables: {
deploymentId,
},
deploymentId
}
});
return data;
}
async addDomain(
projectId: string,
data: types.AddDomainInput
): Promise<types.AddDomainResponse> {
async addDomain (projectId: string, data: types.AddDomainInput): Promise<types.AddDomainResponse> {
const result = await this.client.mutate({
mutation: mutations.addDomain,
variables: {
projectId,
data,
},
data
}
});
return result.data;
}
async getDomains(
projectId: string,
filter?: types.FilterDomainInput
): Promise<types.GetDomainsResponse> {
async getDomains (projectId: string, filter?: types.FilterDomainInput): Promise<types.GetDomainsResponse> {
const { data } = await this.client.query({
query: queries.getDomains,
variables: {
projectId,
filter,
},
filter
}
});
return data;
}
async authenticateGitHub(
code: string
): Promise<types.AuthenticateGitHubResponse> {
async authenticateGitHub (code: string): Promise<types.AuthenticateGitHubResponse> {
const { data } = await this.client.mutate({
mutation: mutations.authenticateGitHub,
variables: {
code,
},
code
}
});
return data;
@@ -381,7 +324,7 @@ export class GQLClient {
async unauthenticateGithub (): Promise<types.UnauthenticateGitHubResponse> {
const { data } = await this.client.mutate({
mutation: mutations.unauthenticateGitHub,
mutation: mutations.unauthenticateGitHub
});
return data;