Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graphql, Web: Add remotes tab, list, add, and delete remotes #313

Merged
merged 19 commits into from
Dec 4, 2024
15 changes: 15 additions & 0 deletions graphql-server/schema.gql
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,18 @@ type TagList {
list: [Tag!]!
}

type Remote {
_id: ID!
name: String!
url: String!
fetchSpecs: [String!]
}

type RemoteList {
nextOffset: Int
list: [Remote!]!
}

type Query {
branch(databaseName: String!, branchName: String!): Branch
branchOrDefault(databaseName: String!, branchName: String): Branch
Expand All @@ -298,6 +310,7 @@ type Query {
docs(databaseName: String!, refName: String!): DocList!
docOrDefaultDoc(refName: String!, databaseName: String!, docType: DocType): Doc
pullWithDetails(databaseName: String!, fromBranchName: String!, toBranchName: String!): PullWithDetails!
remotes(databaseName: String!, offset: Int): RemoteList!
rowDiffs(offset: Int, databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, filterByRowType: DiffRowType, type: CommitDiffType): RowDiffList!
rows(schemaName: String, refName: String!, databaseName: String!, tableName: String!, offset: Int): RowList!
schemaDiff(databaseName: String!, fromRefName: String!, toRefName: String!, refName: String, tableName: String!, type: CommitDiffType): SchemaDiff
Expand Down Expand Up @@ -348,6 +361,8 @@ type Mutation {
resetDatabase(newDatabase: String): Boolean!
loadDataFile(schemaName: String, tableName: String!, refName: String!, databaseName: String!, importOp: ImportOperation!, fileType: FileType!, file: Upload!, modifier: LoadDataModifier): Boolean!
mergePull(fromBranchName: String!, toBranchName: String!, databaseName: String!, author: AuthorInfo): Boolean!
addRemote(databaseName: String!, remoteName: String!, remoteUrl: String!): String!
deleteRemote(databaseName: String!, remoteName: String!): Boolean!
restoreAllTables(databaseName: String!, refName: String!): Boolean!
createTag(tagName: String!, databaseName: String!, message: String, fromRefName: String!, author: AuthorInfo): String!
deleteTag(databaseName: String!, tagName: String!): Boolean!
Expand Down
10 changes: 10 additions & 0 deletions graphql-server/src/queryFactory/dolt/doltEntityManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,3 +138,13 @@ export async function getDoltTags(em: EntityManager): t.PR {
.orderBy("dolt_tags.date", "DESC")
.getRawMany();
}

export async function getDoltRemotesPaginated(
em: EntityManager,
args: t.ListRemotesArgs,
): t.PR {
let sel = em.createQueryBuilder().select("*").from("dolt_remotes", "");
sel = sel.offset(args.offset);

return sel.limit(ROW_LIMIT + 1).getRawMany();
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need the let here? It can all just be chained together?

}
23 changes: 23 additions & 0 deletions graphql-server/src/queryFactory/dolt/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -393,14 +393,14 @@
async restoreAllTables(args: t.RefArgs): t.PR {
return this.queryQR(
async qr => {
console.log("[restore_all]: starting transaction");

Check warning on line 396 in graphql-server/src/queryFactory/dolt/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
await qr.query("BEGIN");

console.log("[restore_all]: calling");

Check warning on line 399 in graphql-server/src/queryFactory/dolt/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
const res = await qr.query(qh.callResetHard);

if (res.length && res[0].status !== "0") {
console.log("[restore_all]: reset not successful, rolling back");

Check warning on line 403 in graphql-server/src/queryFactory/dolt/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
await qr.query("ROLLBACK");
throw new Error("Reset --hard not successful");
}
Expand All @@ -410,12 +410,12 @@

if (status.length) {
status.forEach(async r => {
console.log("[restore_all]: checking out new table", r.table_name);

Check warning on line 413 in graphql-server/src/queryFactory/dolt/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
const checkRes = await qr.query(qh.callCheckoutTable, [
r.table_name,
]);
if (checkRes.length && checkRes[0].status !== "0") {
console.log(

Check warning on line 418 in graphql-server/src/queryFactory/dolt/index.ts

View workflow job for this annotation

GitHub Actions / ci

Unexpected console statement
"[restore_all]: checkout not successful, rolling back",
);
await qr.query("ROLLBACK");
Expand All @@ -434,6 +434,29 @@
args.refName,
);
}

async getRemotes(args: t.ListRemotesArgs): t.PR {
return this.queryForBuilder(
async em => dem.getDoltRemotesPaginated(em, args),
args.databaseName,
);
}

async addRemote(args: t.AddRemoteArgs): t.PR {
return this.query(
qh.callAddRemote,
[args.remoteName, args.remoteUrl],
args.databaseName,
);
}

async callDeleteRemote(args: t.RemoteArgs): t.PR {
return this.query(
qh.callDeleteRemote,
[args.remoteName],
args.databaseName,
);
}
}

async function getTableInfoWithQR(
Expand Down
6 changes: 6 additions & 0 deletions graphql-server/src/queryFactory/dolt/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,12 @@ export const threeDotSchemaDiffQuery = `SELECT * FROM DOLT_SCHEMA_DIFF(?, ?)`;
export const getCallMerge = (hasAuthor = false) =>
`CALL DOLT_MERGE(?, "--no-ff", "-m", ?${getAuthorNameString(hasAuthor)})`;

// REMOTES

export const callAddRemote = `CALL DOLT_REMOTE("add", ?, ?)`;

export const callDeleteRemote = `CALL DOLT_REMOTE("remove", ?)`;

// TAGS

export const callDeleteTag = `CALL DOLT_TAG("-d", ?)`;
Expand Down
23 changes: 23 additions & 0 deletions graphql-server/src/queryFactory/doltgres/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,29 @@ export class DoltgresQueryFactory
args.refName,
);
}

async getRemotes(args: t.ListRemotesArgs): t.PR {
return this.queryForBuilder(
async em => dem.getDoltRemotesPaginated(em, args),
args.databaseName,
);
}

async addRemote(args: t.AddRemoteArgs): t.PR {
return this.query(
qh.callAddRemote,
[args.remoteName, args.remoteUrl],
args.databaseName,
);
}

async callDeleteRemote(args: t.RemoteArgs): t.PR {
return this.query(
qh.callDeleteRemote,
[args.remoteName],
args.databaseName,
);
}
}

async function getTableInfoWithQR(
Expand Down
6 changes: 6 additions & 0 deletions graphql-server/src/queryFactory/doltgres/queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,3 +160,9 @@ export function getOrderByFromDiffCols(cols: t.RawRows): string {
export const callResetHard = `SELECT DOLT_RESET('--hard')`;

export const callCheckoutTable = `SELECT DOLT_CHECKOUT($1::text)`;

// REMOTES

export const callAddRemote = `SELECT DOLT_REMOTE('add', $1::text, $2::text)`;

export const callDeleteRemote = `SELECT DOLT_REMOTE('remove', $1::text)`;
6 changes: 6 additions & 0 deletions graphql-server/src/queryFactory/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,4 +144,10 @@ export declare class QueryFactory {
getRowDiffs(args: t.RowDiffArgs): t.DiffRes;

restoreAllTables(args: t.RefArgs): t.PR;

getRemotes(args: t.ListRemotesArgs): t.PR;

addRemote(args: t.AddRemoteArgs): t.PR;

callDeleteRemote(args: t.RemoteArgs): t.PR;
}
12 changes: 12 additions & 0 deletions graphql-server/src/queryFactory/mysql/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -301,4 +301,16 @@ export class MySQLQueryFactory
async restoreAllTables(_args: t.RefArgs): t.PR {
throw notDoltError("restore all tables");
}

async getRemotes(_args: t.ListRemotesArgs): t.PR {
throw notDoltError("get remotes");
}

async addRemote(_: t.AddRemoteArgs): t.PR {
throw notDoltError("add remote");
}

async callDeleteRemote(_: t.RemoteArgs): t.PR {
throw notDoltError("delete remote");
}
}
6 changes: 6 additions & 0 deletions graphql-server/src/queryFactory/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ export type RefArgs = DBArgs & { refName: string };
export type RefSchemaArgs = RefArgs & { schemaName: string };
export type RefMaybeSchemaArgs = RefArgs & { schemaName?: string };
export type BranchArgs = DBArgs & { branchName: string };
export type RemoteArgs = DBArgs & { remoteName: string };
export type AddRemoteArgs = RemoteArgs & { remoteUrl: string };
export type TagArgs = DBArgs & { tagName: string };
export type TableArgs = RefArgs & { tableName: string };
export type TableMaybeSchemaArgs = TableArgs & { schemaName?: string };
Expand Down Expand Up @@ -40,6 +42,10 @@ export type RowDiffArgs = DBArgs & {
filterByRowType?: DiffRowType;
};

export type ListRemotesArgs = DBArgs & {
offset: number;
};

export type RawRow = Record<string, any>;
export type RawRows = RawRow[];
export type PR = Promise<RawRows>;
Expand Down
47 changes: 47 additions & 0 deletions graphql-server/src/remotes/remote.model.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { Field, ID, ObjectType } from "@nestjs/graphql";
import { __Type } from "graphql";
import { getNextOffset, ROW_LIMIT } from "../utils";
import { RawRow } from "../queryFactory/types";
import { DBArgsWithOffset, ListOffsetRes } from "../utils/commonTypes";

@ObjectType()
export class Remote {
@Field(_type => ID)
_id: string;

@Field()
name: string;

@Field()
url: string;

@Field(_type => [String], { nullable: true })
fetchSpecs?: string[];
}

@ObjectType()
export class RemoteList extends ListOffsetRes {
@Field(_type => [Remote])
list: Remote[];
}

export function fromDoltRemotesRow(databaseName: string, r: RawRow): Remote {
return {
_id: `databases/${databaseName}/remotes/${r.name}`,
name: r.name,
url: r.url,
fetchSpecs: r.fetch_specs,
};
}

export function getRemoteListRes(
remotes: RawRow[],
args: DBArgsWithOffset,
): RemoteList {
return {
list: remotes
.slice(0, ROW_LIMIT)
.map(l => fromDoltRemotesRow(args.databaseName, l)),
nextOffset: getNextOffset(remotes.length, args.offset ?? 0),
};
}
47 changes: 47 additions & 0 deletions graphql-server/src/remotes/remote.resolver.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import {
Args,
ArgsType,
Field,
Mutation,
Query,
Resolver,
} from "@nestjs/graphql";
import { ConnectionProvider } from "../connections/connection.provider";
import { DBArgs, DBArgsWithOffset, RemoteArgs } from "../utils/commonTypes";
import { getRemoteListRes, Remote, RemoteList } from "./remote.model";

@ArgsType()
export class AddRemoteArgs extends DBArgs {
@Field()
remoteName: string;

@Field()
remoteUrl: string;
}

@Resolver(_of => Remote)
export class RemoteResolver {
constructor(private readonly conn: ConnectionProvider) {}

@Query(_returns => RemoteList)
async remotes(@Args() args: DBArgsWithOffset): Promise<RemoteList> {
tbantle22 marked this conversation as resolved.
Show resolved Hide resolved
const conn = this.conn.connection();

const res = await conn.getRemotes({ ...args, offset: args.offset ?? 0 });
return getRemoteListRes(res, args);
}

@Mutation(_returns => String)
async addRemote(@Args() args: AddRemoteArgs): Promise<string> {
const conn = this.conn.connection();
await conn.addRemote(args);
return args.remoteName;
}

@Mutation(_returns => Boolean)
async deleteRemote(@Args() args: RemoteArgs): Promise<boolean> {
const conn = this.conn.connection();
await conn.callDeleteRemote(args);
return true;
}
}
2 changes: 2 additions & 0 deletions graphql-server/src/resolvers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { StatusResolver } from "./status/status.resolver";
import { TableResolver } from "./tables/table.resolver";
import { FileUploadResolver } from "./tables/upload.resolver";
import { TagResolver } from "./tags/tag.resolver";
import { RemoteResolver } from "./remotes/remote.resolver";

const resolvers = [
BranchResolver,
Expand All @@ -24,6 +25,7 @@ const resolvers = [
DocsResolver,
FileUploadResolver,
PullResolver,
RemoteResolver,
RowDiffResolver,
RowResolver,
SchemaDiffResolver,
Expand Down
6 changes: 6 additions & 0 deletions graphql-server/src/utils/commonTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ export class TagArgs extends DBArgs {
tagName: string;
}

@ArgsType()
export class RemoteArgs extends DBArgs {
@Field()
remoteName: string;
}

@InputType()
export class AuthorInfo {
@Field()
Expand Down
1 change: 1 addition & 0 deletions web/renderer/components/DatabaseNav/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@ export const tabs = [
"Commit Log",
"Releases",
"Pull Requests",
"Remotes",
];
3 changes: 3 additions & 0 deletions web/renderer/components/DatabaseNav/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
ref,
RefUrl,
releases,
remotes,
} from "@lib/urls";

function getUrlFromName(name: string): [DatabaseUrl, RefUrl?] {
Expand All @@ -23,6 +24,8 @@ function getUrlFromName(name: string): [DatabaseUrl, RefUrl?] {
return [releases];
case "Pull Requests":
return [pulls];
case "Remotes":
return [remotes];
default:
return [database, ref];
}
Expand Down
19 changes: 19 additions & 0 deletions web/renderer/components/breadcrumbs/RemotesBreadcrumbs.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { DatabaseParams } from "@lib/params";
import Breadcrumbs from ".";
import { remoteBreadcrumbDetails } from "./breadcrumbDetails";

type Props = {
params: DatabaseParams;
className?: string;
};

export default function RemotesBreadcrumbs(props: Props) {
return (
<Breadcrumbs
{...props}
aria-label="db-remotes-breadcrumbs"
data-cy="db-remotes-breadcrumbs"
breadcrumbs={remoteBreadcrumbDetails(props.params)}
/>
);
}
13 changes: 13 additions & 0 deletions web/renderer/components/breadcrumbs/breadcrumbDetails.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,19 @@ export function commitLogBreadcrumbDetails(
];
}

export function remoteBreadcrumbDetails(
params: DatabaseParams,
): BreadcrumbDetails[] {
return [
...databaseBreadcrumbs(params),
{
child: <span>remotes</span>,
name: BreadcrumbName.DBRemote,
type: BreadcrumbType.Text,
},
];
}

export function tableBreadcrumbsDetails(
params: TableParams,
): BreadcrumbDetails[] {
Expand Down
1 change: 1 addition & 0 deletions web/renderer/components/breadcrumbs/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export enum BreadcrumbName {
DBSchema = "db-schema",
DBCommitGraph = "db-commit-graph",
DBNew = "db-new",
DBRemote = "db-remote",
}

export enum BreadcrumbType {
Expand Down
Loading
Loading