Skip to content

Commit

Permalink
Replace SQLite with BadgerDB
Browse files Browse the repository at this point in the history
  • Loading branch information
dstotijn committed Jan 21, 2022
1 parent 8a3b3cb commit d84d2d0
Show file tree
Hide file tree
Showing 49 changed files with 2,488 additions and 2,669 deletions.
3 changes: 0 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ linters:
- metalinter
- module
- performance
- sql
- style
- test
- unused
Expand All @@ -28,8 +27,6 @@ linters:
- wrapcheck

linters-settings:
errcheck:
ignore: "database/sql:Rollback"
gci:
local-prefixes: github.com/dstotijn/hetty
godot:
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ ARG GO_VERSION=1.16
ARG NODE_VERSION=14.11
ARG ALPINE_VERSION=3.12

ARG CGO_ENABLED=1
ARG CGO_ENABLED=0

FROM node:${NODE_VERSION}-alpine AS node-builder
WORKDIR /app
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ build-admin:

.PHONY: build
build: build-admin
CGO_ENABLED=1 mv admin/dist cmd/hetty/admin && go build ./cmd/hetty
CGO_ENABLED=0 mv admin/dist cmd/hetty/admin && go build ./cmd/hetty

.PHONY: release-dry-run
release-dry-run: build-admin
Expand Down
17 changes: 8 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ for details.

## Installation

Hetty compiles to a self-contained binary, with an embedded SQLite database
Hetty compiles to a self-contained binary, with an embedded BadgerDB database
and web based admin interface.

### Install pre-built release (recommended)
Expand All @@ -47,11 +47,10 @@ and web based admin interface.
- [Go 1.16](https://golang.org/)
- [Yarn](https://yarnpkg.com/)

Hetty depends on SQLite (via [mattn/go-sqlite3](https://github.com/mattn/go-sqlite3))
and needs `cgo` to compile. Additionally, the static resources for the admin interface
When building from source, the static resources for the admin interface
(Next.js) need to be generated via [Yarn](https://yarnpkg.com/). The generated
files will be embedded (using the [embed](https://golang.org/pkg/embed/) package)
when you use the `build` Makefile target.
files will be embedded (using the [embed](https://golang.org/pkg/embed/)
package) when you use the `build` Makefile target.

Clone the repository and use the `build` make target to create a binary:

Expand All @@ -64,7 +63,7 @@ $ make build
### Docker

A Docker image is available on Docker Hub: [`dstotijn/hetty`](https://hub.docker.com/r/dstotijn/hetty).
For persistent storage of CA certificates and project databases, mount a volume:
For persistent storage of CA certificates and projects database, mount a volume:

```
$ mkdir -p $HOME/.hetty
Expand All @@ -77,7 +76,7 @@ When Hetty is run, by default it listens on `:8080` and is accessible via
http://localhost:8080. Depending on incoming HTTP requests, it either acts as a
MITM proxy, or it serves the API and web interface.

By default, project database files and CA certificates are stored in a `.hetty`
By default, the projects database files and CA certificates are stored in a `.hetty`
directory under the user's home directory (`$HOME` on Linux/macOS, `%USERPROFILE%`
on Windows).

Expand All @@ -101,8 +100,8 @@ Usage of ./hetty:
CA certificate filepath. Creates a new CA certificate if file doesn't exist (default "~/.hetty/hetty_cert.pem")
-key string
CA private key filepath. Creates a new CA private key if file doesn't exist (default "~/.hetty/hetty_key.pem")
-projects string
Projects directory path (default "~/.hetty/projects")
-db string
Database directory path (default "~/.hetty/db")
```

You should see:
Expand Down
45 changes: 32 additions & 13 deletions admin/src/components/projects/NewProject.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,19 @@ const useStyles = makeStyles((theme: Theme) =>
})
);

const CREATE_PROJECT = gql`
mutation CreateProject($name: String!) {
createProject(name: $name) {
id
name
}
}
`;

const OPEN_PROJECT = gql`
mutation OpenProject($name: String!) {
openProject(name: $name) {
mutation OpenProject($id: ID!) {
openProject(id: $id) {
id
name
isActive
}
Expand All @@ -37,8 +47,15 @@ function NewProject(): JSX.Element {
const classes = useStyles();
const [input, setInput] = useState(null);

const [openProject, { error, loading }] = useMutation(OPEN_PROJECT, {
onError: () => {},
const [createProject, { error: createProjErr, loading: createProjLoading }] = useMutation(CREATE_PROJECT, {
onError: () => { },
onCompleted(data) {
input.value = "";
openProject({ variables: { id: data.createProject.id } });
},
});
const [openProject, { error: openProjErr, loading: openProjLoading }] = useMutation(OPEN_PROJECT, {
onError: () => { },
onCompleted() {
input.value = "";
},
Expand All @@ -47,10 +64,11 @@ function NewProject(): JSX.Element {
fields: {
activeProject() {
const activeProjRef = cache.writeFragment({
id: openProject.name,
id: openProject.id,
data: openProject,
fragment: gql`
fragment ActiveProject on Project {
id
name
isActive
type
Expand All @@ -61,10 +79,11 @@ function NewProject(): JSX.Element {
},
projects(_, { DELETE }) {
cache.writeFragment({
id: openProject.name,
id: openProject.id,
data: openProject,
fragment: gql`
fragment OpenProject on Project {
id
name
isActive
type
Expand All @@ -78,17 +97,17 @@ function NewProject(): JSX.Element {
},
});

const handleNewProjectForm = (e: React.SyntheticEvent) => {
const handleCreateAndOpenProjectForm = (e: React.SyntheticEvent) => {
e.preventDefault();
openProject({ variables: { name: input.value } });
createProject({ variables: { name: input.value } });
};

return (
<div>
<Box mb={3}>
<Typography variant="h6">New project</Typography>
</Box>
<form onSubmit={handleNewProjectForm} autoComplete="off">
<form onSubmit={handleCreateAndOpenProjectForm} autoComplete="off">
<TextField
className={classes.projectName}
color="secondary"
Expand All @@ -100,17 +119,17 @@ function NewProject(): JSX.Element {
}}
label="Project name"
placeholder="Project name…"
error={Boolean(error)}
helperText={error && error.message}
error={Boolean(createProjErr || openProjErr)}
helperText={createProjErr && createProjErr.message || openProjErr && openProjErr.message}
/>
<Button
className={classes.button}
type="submit"
variant="contained"
color="secondary"
size="large"
disabled={loading}
startIcon={loading ? <CircularProgress size={22} /> : <AddIcon />}
disabled={createProjLoading || openProjLoading}
startIcon={createProjLoading || openProjLoading ? <CircularProgress size={22} /> : <AddIcon />}
>
Create & open project
</Button>
Expand Down
38 changes: 21 additions & 17 deletions admin/src/components/projects/ProjectList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,17 @@ const useStyles = makeStyles((theme: Theme) =>
const PROJECTS = gql`
query Projects {
projects {
id
name
isActive
}
}
`;

const OPEN_PROJECT = gql`
mutation OpenProject($name: String!) {
openProject(name: $name) {
mutation OpenProject($id: ID!) {
openProject(id: $id) {
id
name
isActive
}
Expand All @@ -72,8 +74,8 @@ const CLOSE_PROJECT = gql`
`;

const DELETE_PROJECT = gql`
mutation DeleteProject($name: String!) {
deleteProject(name: $name) {
mutation DeleteProject($id: ID!) {
deleteProject(id: $id) {
success
}
}
Expand All @@ -89,7 +91,7 @@ function ProjectList(): JSX.Element {
{ error: openProjErr, loading: openProjLoading },
] = useMutation(OPEN_PROJECT, {
errorPolicy: "all",
onError: () => {},
onError: () => { },
update(cache, { data: { openProject } }) {
cache.modify({
fields: {
Expand All @@ -98,6 +100,7 @@ function ProjectList(): JSX.Element {
data: openProject,
fragment: gql`
fragment ActiveProject on Project {
id
name
isActive
type
Expand All @@ -108,10 +111,11 @@ function ProjectList(): JSX.Element {
},
projects(_, { DELETE }) {
cache.writeFragment({
id: openProject.name,
id: openProject.id,
data: openProject,
fragment: gql`
fragment OpenProject on Project {
id
name
isActive
type
Expand All @@ -129,7 +133,7 @@ function ProjectList(): JSX.Element {
});
const [closeProject, { error: closeProjErr }] = useMutation(CLOSE_PROJECT, {
errorPolicy: "all",
onError: () => {},
onError: () => { },
update(cache) {
cache.modify({
fields: {
Expand All @@ -151,7 +155,7 @@ function ProjectList(): JSX.Element {
{ loading: deleteProjLoading, error: deleteProjErr },
] = useMutation(DELETE_PROJECT, {
errorPolicy: "all",
onError: () => {},
onError: () => { },
update(cache) {
cache.modify({
fields: {
Expand All @@ -165,14 +169,14 @@ function ProjectList(): JSX.Element {
},
});

const [deleteProjName, setDeleteProjName] = useState(null);
const [deleteProj, setDeleteProj] = useState(null);
const [deleteDiagOpen, setDeleteDiagOpen] = useState(false);
const handleDeleteButtonClick = (name: string) => {
setDeleteProjName(name);
const handleDeleteButtonClick = (project: any) => {
setDeleteProj(project);
setDeleteDiagOpen(true);
};
const handleDeleteConfirm = () => {
deleteProject({ variables: { name: deleteProjName } });
deleteProject({ variables: { id: deleteProj.id } });
};
const handleDeleteCancel = () => {
setDeleteDiagOpen(false);
Expand All @@ -190,7 +194,7 @@ function ProjectList(): JSX.Element {
<div>
<Dialog open={deleteDiagOpen} onClose={handleDeleteCancel}>
<DialogTitle>
Delete project “<strong>{deleteProjName}</strong>”?
Delete project “<strong>{deleteProj?.name}</strong>”?
</DialogTitle>
<DialogContent>
<DialogContentText>
Expand Down Expand Up @@ -223,7 +227,7 @@ function ProjectList(): JSX.Element {
onClose={handleCloseDeleteNotif}
>
<Alert onClose={handleCloseDeleteNotif} severity="info">
Project <strong>{deleteProjName}</strong> was deleted.
Project <strong>{deleteProj?.name}</strong> was deleted.
</Alert>
</Snackbar>

Expand Down Expand Up @@ -253,7 +257,7 @@ function ProjectList(): JSX.Element {
{projData?.projects.length > 0 && (
<List className={classes.projectsList}>
{projData.projects.map((project) => (
<ListItem key={project.name}>
<ListItem key={project.id}>
<ListItemAvatar>
<Avatar
className={
Expand Down Expand Up @@ -281,7 +285,7 @@ function ProjectList(): JSX.Element {
disabled={openProjLoading || projLoading}
onClick={() =>
openProject({
variables: { name: project.name },
variables: { id: project.id },
})
}
>
Expand All @@ -293,7 +297,7 @@ function ProjectList(): JSX.Element {
<Tooltip title="Delete project">
<span>
<IconButton
onClick={() => handleDeleteButtonClick(project.name)}
onClick={() => handleDeleteButtonClick(project)}
disabled={project.isActive}
>
<DeleteIcon />
Expand Down
2 changes: 1 addition & 1 deletion admin/src/components/reqlog/LogDetail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ const HTTP_REQUEST_LOG = gql`
`;

interface Props {
requestId: number;
requestId: string;
}

function LogDetail({ requestId: id }: Props): JSX.Element {
Expand Down
6 changes: 2 additions & 4 deletions admin/src/components/reqlog/LogsOverview.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,10 @@ import { useHttpRequestLogs } from "./hooks/useHttpRequestLogs";

function LogsOverview(): JSX.Element {
const router = useRouter();
const detailReqLogId =
router.query.id && parseInt(router.query.id as string, 10);

const detailReqLogId = router.query.id as string | undefined;
const { loading, error, data } = useHttpRequestLogs();

const handleLogClick = (reqId: number) => {
const handleLogClick = (reqId: string) => {
router.push("/proxy/logs?id=" + reqId, undefined, {
shallow: false,
});
Expand Down
8 changes: 4 additions & 4 deletions admin/src/components/reqlog/RequestList.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@ const useStyles = makeStyles((theme: Theme) =>

interface Props {
logs: Array<any>;
selectedReqLogId?: number;
onLogClick(requestId: number): void;
selectedReqLogId?: string;
onLogClick(requestId: string): void;
theme: Theme;
}

Expand Down Expand Up @@ -63,8 +63,8 @@ function RequestList({

interface RequestListTableProps {
logs?: any;
selectedReqLogId?: number;
onLogClick(requestId: number): void;
selectedReqLogId?: string;
onLogClick(requestId: string): void;
theme: Theme;
}

Expand Down
Loading

0 comments on commit d84d2d0

Please sign in to comment.