Skip to content

Commit

Permalink
refactor: remove sqlc, refactor application (#120)
Browse files Browse the repository at this point in the history
  • Loading branch information
ChristianChiarulli authored Dec 31, 2024
1 parent a007722 commit a3ef207
Show file tree
Hide file tree
Showing 304 changed files with 11,368 additions and 15,729 deletions.
21 changes: 0 additions & 21 deletions LICENSE

This file was deleted.

86 changes: 58 additions & 28 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,37 +1,67 @@
<div align="center">
<h1>Comet Notes ☄️</h1>
<a href="https://github.com/nodetec/comet/releases/latest">
<img alt="Latest release" src="https://img.shields.io/github/v/release/nodetec/comet?style=for-the-badge&logo=starship&color=C9CBFF&logoColor=D9E0EE&labelColor=302D41" />
</a>
<a href="https://github.com/nodetec/comet/pulse">
<img alt="Last commit" src="https://img.shields.io/github/last-commit/nodetec/comet?style=for-the-badge&logo=starship&color=8bd5ca&logoColor=D9E0EE&labelColor=302D41"/>
</a>
<a href="https://github.com/nodetec/comet/stargazers">
<img alt="Stars" src="https://img.shields.io/github/stars/nodetec/comet?style=for-the-badge&logo=starship&color=c69ff5&logoColor=D9E0EE&labelColor=302D41" />
</a>
<a href="https://github.com/nodetec/comet/issues">
<img alt="Issues" src="https://img.shields.io/github/issues/nodetec/comet?style=for-the-badge&logo=bilibili&color=F5E0DC&logoColor=D9E0EE&labelColor=302D41" />
</a>
<a href="https://github.com/nodetec/comet">
<img alt="Repo size" src="https://img.shields.io/github/repo-size/nodetec/comet?color=%23DDB6F2&label=SIZE&logo=codesandbox&style=for-the-badge&logoColor=D9E0EE&labelColor=302D41" />
</a>
# Comet

</div>
Comet is a desktop app for taking and publishing notes for nostr.

![demo](https://private-user-images.githubusercontent.com/29136904/342766691-5ccfc513-665d-4231-9962-52443a00639c.gif?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3MjA0OTczOTMsIm5iZiI6MTcyMDQ5NzA5MywicGF0aCI6Ii8yOTEzNjkwNC8zNDI3NjY2OTEtNWNjZmM1MTMtNjY1ZC00MjMxLTk5NjItNTI0NDNhMDA2MzljLmdpZj9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNDA3MDklMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjQwNzA5VDAzNTEzM1omWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTU0ZDA4NmE4ZmMwYTY0M2M0OTJjODRiZTBhODZlZTkwYzFiNWJiM2NiNjZiNjlmMDQ5YzBiYjU3ZmM4ODE4ZjgmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0JmFjdG9yX2lkPTAma2V5X2lkPTAmcmVwb19pZD0wIn0.sQvPZ7pIRBhQodFBgUwnjrfjaRxYu77MJZNuXJtHjCo)
## Development

[Comet Notes](https://comet.md/ "Comet Notes") is a note-taking app with [Nostr](https://nostr.com/ "Nostr") integration.
### Keep go modules up to date

## Download
```sh
go mod tidy
```

You can download the app from the [Comet Notes](https://comet.md/ "Comet Notes") website.
## Getting Started

You can also download Comet Notes by navigating to the [Releases](https://github.com/nodetec/comet/releases "Releases") page and clicking on the release you want to download.
1. Navigate to your project directory in the terminal.

## Contribute
2. To run your application in development mode, use the following command:

To install the dependencies and start the app in development mode, run the following command:
```
wails3 dev
```

```bash
wails3 dev
```
This will start your application and enable hot-reloading for both frontend and backend changes.

3. To build your application for production, use:

```
wails3 build
```

This will create a production-ready executable in the `build` directory.

## Exploring Wails3 Features

Now that you have your project set up, it's time to explore the features that Wails3 offers:

1. **Check out the examples**: The best way to learn is by example. Visit the `examples` directory in the `v3/examples` directory to see various sample applications.

2. **Run an example**: To run any of the examples, navigate to the example's directory and use:

```
go run .
```

Note: Some examples may be under development during the alpha phase.

3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3alpha.wails.io/) for in-depth guides and API references.

4. **Join the community**: Have questions or want to share your progress? Join the [Wails Discord](https://discord.gg/JDdSxwjhGf) or visit the [Wails discussions on GitHub](https://github.com/wailsapp/wails/discussions).

## Project Structure

Take a moment to familiarize yourself with your project structure:

- `frontend/`: Contains your frontend code (HTML, CSS, JavaScript/TypeScript)
- `main.go`: The entry point of your Go backend
- `app.go`: Define your application structure and methods here
- `wails.json`: Configuration file for your Wails project

## Next Steps

1. Modify the frontend in the `frontend/` directory to create your desired UI.
2. Add backend functionality in `main.go`.
3. Use `wails3 dev` to see your changes in real-time.
4. When ready, build your application with `wails3 build`.

Happy coding with Wails3! If you encounter any issues or have questions, don't hesitate to consult the documentation or reach out to the Wails community.
30 changes: 25 additions & 5 deletions Taskfile.yml
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
version: '3'

includes:
common: ./build/Taskfile.yml
windows: ./build/windows/Taskfile.yml
darwin: ./build/darwin/Taskfile.yml
linux: ./build/linux/Taskfile.yml
common: ./build/Taskfile.common.yml
windows: ./build/Taskfile.windows.yml
darwin: ./build/Taskfile.darwin.yml
linux: ./build/Taskfile.linux.yml

vars:
APP_NAME: "asdf"
APP_NAME: "comet"
BIN_DIR: "bin"
VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}'

Expand All @@ -32,3 +32,23 @@ tasks:
cmds:
- wails3 dev -config ./build/config.yml -port {{.VITE_PORT}}

darwin:build:universal:
summary: Builds darwin universal binary (arm64 + amd64)
cmds:
- task: darwin:build
vars:
ARCH: amd64
- mv {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}-amd64
- task: darwin:build
vars:
ARCH: arm64
- mv {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}-arm64
- lipo -create -output {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}-amd64 {{.BIN_DIR}}/{{.APP_NAME}}-arm64
- rm {{.BIN_DIR}}/{{.APP_NAME}}-amd64 {{.BIN_DIR}}/{{.APP_NAME}}-arm64

darwin:package:universal:
summary: Packages darwin universal binary (arm64 + amd64)
deps:
- darwin:build:universal
cmds:
- task: darwin:create:app:bundle
85 changes: 85 additions & 0 deletions backend/db/init.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package db

import (
"log"
"path/filepath"

"comet/backend/db/schemas"

"embed"

"github.com/adrg/xdg"
"github.com/jmoiron/sqlx"
_ "github.com/mattn/go-sqlite3"
"github.com/pressly/goose/v3"
)

// Database instance
var DB *sqlx.DB

// Init initializes the SQLite database and creates tables
func Init(embedMigrations embed.FS) {
var err error

// Get the data home directory
dbPath := filepath.Join(xdg.DataHome, "comet", "comet.db")

// Set PRAGMAs in the connection string
dbConn, err := sqlx.Open("sqlite3", dbPath+"?_foreign_keys=on&_journal_mode=WAL&_synchronous=NORMAL&_temp_store=MEMORY&_cache_size=-2000")
if err != nil {
log.Fatalf("Failed to connect to database: %v", err)
}
DB = dbConn

goose.SetBaseFS(embedMigrations)

if err := goose.SetDialect("sqlite3"); err != nil {
panic(err)
}

// Perform migrations
if err := goose.Up(DB.DB, "migrations"); err != nil {
log.Fatalf("Failed to apply migrations: %v", err)
}

// List of table schemas
tableSchemas := []string{
schemas.NotesTableSchema,
schemas.TagsTableSchema,
schemas.NotebooksTableSchema,
schemas.NotesTagsTableSchema,
schemas.NotebookTagsTableSchema,
schemas.RelaysTableSchema,
schemas.UsersTableSchema,
schemas.SettingsTableSchema,
}

// Create tables
for _, schema := range tableSchemas {
_, err := DB.Exec(schema)
if err != nil {
log.Fatalf("Failed to execute schema: %v", err)
}
}

// List of triggers
triggers := []string{
schemas.UpdateNotesModifiedAtTrigger,
schemas.UpdateTagsModifiedAtTrigger,
schemas.UpdateNotebooksModifiedAtTrigger,
schemas.UpdateRelaysModifiedAtTrigger,
schemas.UpdateUsersModifiedAtTrigger,
schemas.UpdateSettingsModifiedAtTrigger,
schemas.EnsureOnlyOneActiveNoteTrigger,
}

// Create triggers
for _, trigger := range triggers {
_, err := DB.Exec(trigger)
if err != nil {
log.Fatalf("Failed to execute trigger: %v", err)
}
}

log.Println("All tables created or already exist.")
}
22 changes: 22 additions & 0 deletions backend/db/schemas/notebook_tags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package schemas

// NotebookTagsTableSchema defines the schema for the notebook_tags junction table
const NotebookTagsTableSchema = `
CREATE TABLE IF NOT EXISTS notebook_tags (
notebook_id INTEGER NOT NULL,
tag_id INTEGER NOT NULL,
PRIMARY KEY (notebook_id, tag_id),
FOREIGN KEY (notebook_id) REFERENCES notebooks(id) ON DELETE CASCADE,
FOREIGN KEY (tag_id) REFERENCES tags(id) ON DELETE CASCADE,
CHECK (notebook_id > 0),
CHECK (tag_id > 0)
);
CREATE INDEX IF NOT EXISTS idx_notebook_id ON notebook_tags(notebook_id);
CREATE INDEX IF NOT EXISTS idx_tag_id ON notebook_tags(tag_id);`

// NotebookTag represents a junction between a notebook and a tag
type NotebookTag struct {
NotebookID int `db:"notebook_id"`
TagID int `db:"tag_id"`
}
36 changes: 36 additions & 0 deletions backend/db/schemas/notebooks.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package schemas

// NotebooksTableSchema defines the schema for the notebooks table
const NotebooksTableSchema = `
CREATE TABLE IF NOT EXISTS notebooks (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
modified_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
pinned BOOLEAN NOT NULL DEFAULT 1,
active BOOLEAN NOT NULL DEFAULT 0,
UNIQUE (name),
CHECK (name <> '')
);
CREATE INDEX IF NOT EXISTS idx_name ON notebooks(name);
CREATE INDEX IF NOT EXISTS idx_created_at ON notebooks(created_at);`

// UpdateNotebooksModifiedAtTrigger defines the trigger for updating modified_at on update
const UpdateNotebooksModifiedAtTrigger = `
CREATE TRIGGER IF NOT EXISTS update_notebooks_modified_at
AFTER UPDATE ON notebooks
FOR EACH ROW
BEGIN
UPDATE notebooks SET modified_at = CURRENT_TIMESTAMP WHERE id = OLD.id;
END;`

// Notebook represents a notebook in the application
type Notebook struct {
ID int `db:"id"`
Name string `db:"name"`
CreatedAt string `db:"created_at"`
ModifiedAt string `db:"modified_at"`
Pinned bool `db:"pinned"`
Active bool `db:"active"`
}
83 changes: 83 additions & 0 deletions backend/db/schemas/notes.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package schemas

// Note represents a note in the application
type Note struct {
ID int `db:"id"`
NotebookID *int `db:"notebook_id"`
Content string `db:"content"`
Title string `db:"title"`
CreatedAt string `db:"created_at"`
ModifiedAt string `db:"modified_at"`
PublishedAt *string `db:"published_at"`
EventAddress *string `db:"event_address"`
Identifier *string `db:"identifier"`
Pinned bool `db:"pinned"`
TrashedAt *string `db:"trashed_at"`
ArchivedAt *string `db:"archived_at"`
Active bool `db:"active"`
Author *string `db:"author"`
}

// NotesTableSchema defines the schema for the notes table
const NotesTableSchema = `
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
notebook_id INTEGER,
content TEXT NOT NULL,
title TEXT NOT NULL,
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
modified_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP,
published_at TEXT,
event_address TEXT,
identifier TEXT,
pinned BOOLEAN NOT NULL DEFAULT FALSE,
trashed_at TEXT,
archived_at TEXT,
active BOOLEAN NOT NULL DEFAULT TRUE,
author TEXT,
FOREIGN KEY (notebook_id) REFERENCES notebooks(id) ON DELETE SET NULL,
CHECK (pinned IN (0, 1)),
CHECK (active IN (0, 1))
);
CREATE VIRTUAL TABLE IF NOT EXISTS notes_fts USING fts5(content);
CREATE TRIGGER IF NOT EXISTS notes_fts_insert AFTER INSERT ON notes BEGIN
INSERT INTO notes_fts(rowid, content) VALUES (new.id, new.content);
END;
CREATE TRIGGER IF NOT EXISTS notes_fts_delete AFTER DELETE ON notes BEGIN
DELETE FROM notes_fts WHERE rowid = old.id;
END;
CREATE TRIGGER IF NOT EXISTS notes_fts_update AFTER UPDATE ON notes BEGIN
DELETE FROM notes_fts WHERE rowid = old.id;
INSERT INTO notes_fts(rowid, content) VALUES (new.id, new.content);
END;
CREATE INDEX IF NOT EXISTS idx_notebook_id ON notes(notebook_id);
CREATE INDEX IF NOT EXISTS idx_created_at ON notes(created_at);
CREATE INDEX IF NOT EXISTS idx_modified_at ON notes(modified_at);
CREATE INDEX IF NOT EXISTS idx_pinned ON notes(pinned);
CREATE INDEX IF NOT EXISTS idx_trashed_at ON notes(trashed_at);
CREATE INDEX IF NOT EXISTS idx_archived_at ON notes(archived_at);
CREATE INDEX IF NOT EXISTS idx_active ON notes(active);`

// UpdateNotesModifiedAtTrigger defines the trigger for updating modified_at on update
const UpdateNotesModifiedAtTrigger = `
CREATE TRIGGER IF NOT EXISTS update_notes_modified_at
AFTER UPDATE OF content ON notes
FOR EACH ROW
BEGIN
UPDATE notes SET modified_at = CURRENT_TIMESTAMP WHERE id = OLD.id;
END;`

// EnsureOnlyOneActiveNoteTrigger defines the trigger to ensure only one active note
const EnsureOnlyOneActiveNoteTrigger = `
CREATE TRIGGER IF NOT EXISTS ensure_only_one_active_note
BEFORE UPDATE OF active ON notes
FOR EACH ROW
WHEN NEW.active = TRUE
BEGIN
UPDATE notes SET active = FALSE WHERE active = TRUE AND id != NEW.id;
END;`
Loading

0 comments on commit a3ef207

Please sign in to comment.