Skip to content

Commit b11f0f6

Browse files
committed
feat: implement SQL source management and connection handling
- Added `Channel` class for WebSocket communication. - Introduced `connections-store` for managing active connections. - Created `SourcesSidebar` and `SidebarSQLSource` components for displaying and interacting with SQL sources. - Integrated `SQLColumnEditor` for editing SQL column properties. - Updated `HomeView` to include a dialog for editing columns. - Enhanced `App.vue` with a new `SourcesSidebar` component. - Added support for dynamic table retrieval from SQL sources. - Included loading indicators and connection status in UI components.
1 parent 4692060 commit b11f0f6

5 files changed

Lines changed: 157 additions & 7 deletions

File tree

README.md

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,35 @@
2929
- [ ] Add projects
3030
- [ ] Electron save passwords via npm package `keytar`
3131

32+
## Local MySQL Test Database
33+
Run a local MySQL instance with seeded test data:
34+
35+
```bash
36+
docker compose up -d
37+
```
38+
39+
This starts MySQL on `127.0.0.1:3307` with credentials that already match the backend defaults in `packages/backend/src/index.ts`:
40+
41+
- Database: `pastefy`
42+
- User: `pastefy`
43+
- Password: `pastefy`
44+
- Root password: `root`
45+
46+
Seed data is loaded on first startup from `docker/mysql/init/001-seed.sql` and creates these tables:
47+
48+
- `customers`
49+
- `products`
50+
- `orders`
51+
- `order_items`
52+
53+
Useful commands:
54+
55+
```bash
56+
docker compose down
57+
docker compose down -v
58+
```
59+
60+
Use `docker compose down -v` if you want to wipe the database and re-run the seed from scratch.
61+
3262
## Backlog
33-
- [ ] Add OpenID Connect support
63+
- [ ] Add OpenID Connect support

docker-compose.yml

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
services:
2+
mysql:
3+
image: mysql:8.4
4+
container_name: starquery-mysql
5+
restart: unless-stopped
6+
ports:
7+
- "3307:3306"
8+
environment:
9+
MYSQL_ROOT_PASSWORD: root
10+
MYSQL_DATABASE: pastefy
11+
MYSQL_USER: pastefy
12+
MYSQL_PASSWORD: pastefy
13+
volumes:
14+
- mysql-data:/var/lib/mysql
15+
- ./docker/mysql/init:/docker-entrypoint-initdb.d:ro
16+
healthcheck:
17+
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-proot"]
18+
interval: 5s
19+
timeout: 5s
20+
retries: 20
21+
start_period: 15s
22+
23+
volumes:
24+
mysql-data:

docker/mysql/init/001-seed.sql

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
USE pastefy;
2+
3+
CREATE TABLE IF NOT EXISTS customers (
4+
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
5+
email VARCHAR(255) NOT NULL,
6+
full_name VARCHAR(255) NOT NULL,
7+
country_code CHAR(2) NOT NULL,
8+
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
9+
PRIMARY KEY (id),
10+
UNIQUE KEY uq_customers_email (email)
11+
);
12+
13+
CREATE TABLE IF NOT EXISTS products (
14+
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
15+
sku VARCHAR(64) NOT NULL,
16+
name VARCHAR(255) NOT NULL,
17+
category VARCHAR(120) NOT NULL,
18+
price DECIMAL(10, 2) NOT NULL,
19+
stock INT NOT NULL DEFAULT 0,
20+
PRIMARY KEY (id),
21+
UNIQUE KEY uq_products_sku (sku)
22+
);
23+
24+
CREATE TABLE IF NOT EXISTS orders (
25+
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
26+
customer_id INT UNSIGNED NOT NULL,
27+
order_number VARCHAR(40) NOT NULL,
28+
status ENUM('pending', 'paid', 'shipped', 'cancelled') NOT NULL DEFAULT 'pending',
29+
ordered_at DATETIME NOT NULL,
30+
PRIMARY KEY (id),
31+
UNIQUE KEY uq_orders_order_number (order_number),
32+
KEY idx_orders_customer_id (customer_id),
33+
CONSTRAINT fk_orders_customer
34+
FOREIGN KEY (customer_id) REFERENCES customers(id)
35+
ON DELETE CASCADE
36+
);
37+
38+
CREATE TABLE IF NOT EXISTS order_items (
39+
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
40+
order_id INT UNSIGNED NOT NULL,
41+
product_id INT UNSIGNED NOT NULL,
42+
quantity INT NOT NULL,
43+
unit_price DECIMAL(10, 2) NOT NULL,
44+
PRIMARY KEY (id),
45+
UNIQUE KEY uq_order_items_order_product (order_id, product_id),
46+
KEY idx_order_items_order_id (order_id),
47+
KEY idx_order_items_product_id (product_id),
48+
CONSTRAINT fk_order_items_order
49+
FOREIGN KEY (order_id) REFERENCES orders(id)
50+
ON DELETE CASCADE,
51+
CONSTRAINT fk_order_items_product
52+
FOREIGN KEY (product_id) REFERENCES products(id)
53+
ON DELETE RESTRICT
54+
);
55+
56+
INSERT INTO customers (email, full_name, country_code, created_at) VALUES
57+
('ava@example.com', 'Ava Johnson', 'US', '2026-01-04 09:15:00'),
58+
('liam@example.com', 'Liam Carter', 'DE', '2026-01-08 13:42:00'),
59+
('mia@example.com', 'Mia Chen', 'GB', '2026-01-12 17:05:00')
60+
ON DUPLICATE KEY UPDATE
61+
full_name = VALUES(full_name),
62+
country_code = VALUES(country_code),
63+
created_at = VALUES(created_at);
64+
65+
INSERT INTO products (sku, name, category, price, stock) VALUES
66+
('LAP-14-PRO', 'StarQuery Laptop Pro 14', 'hardware', 1499.00, 12),
67+
('MON-27-IPS', 'Nebula Monitor 27', 'hardware', 329.90, 24),
68+
('DOCK-USB-C', 'Orbit USB-C Dock', 'accessories', 119.50, 50),
69+
('MOU-WL-ERG', 'Comet Ergonomic Mouse', 'accessories', 59.99, 80)
70+
ON DUPLICATE KEY UPDATE
71+
name = VALUES(name),
72+
category = VALUES(category),
73+
price = VALUES(price),
74+
stock = VALUES(stock);
75+
76+
INSERT INTO orders (customer_id, order_number, status, ordered_at) VALUES
77+
(1, 'SQ-1001', 'paid', '2026-02-02 10:30:00'),
78+
(2, 'SQ-1002', 'shipped', '2026-02-05 15:10:00'),
79+
(1, 'SQ-1003', 'pending', '2026-02-17 08:00:00')
80+
ON DUPLICATE KEY UPDATE
81+
customer_id = VALUES(customer_id),
82+
status = VALUES(status),
83+
ordered_at = VALUES(ordered_at);
84+
85+
INSERT INTO order_items (order_id, product_id, quantity, unit_price) VALUES
86+
(1, 1, 1, 1499.00),
87+
(1, 3, 1, 119.50),
88+
(2, 2, 2, 329.90),
89+
(2, 4, 1, 59.99),
90+
(3, 3, 3, 119.50)
91+
ON DUPLICATE KEY UPDATE
92+
quantity = VALUES(quantity),
93+
unit_price = VALUES(unit_price);

packages/backend/src/adapters/database/sql/mysql-adapter/MySQLAdapter.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export class MySQLAdapter extends DefaultSQLAdapter {
66

77
constructor(private options: {
88
host: string
9+
port?: number
910
user: string
1011
password: string
1112
database: string
@@ -16,6 +17,7 @@ export class MySQLAdapter extends DefaultSQLAdapter {
1617
async connect() {
1718
this.connection = await mysql.createConnection({
1819
host: this.options.host,
20+
port: this.options.port,
1921
user: this.options.user,
2022
password: this.options.password,
2123
database: this.options.database,
@@ -55,4 +57,4 @@ export class MySQLAdapter extends DefaultSQLAdapter {
5557
result: res[0]
5658
}
5759
}
58-
}
60+
}

packages/backend/src/index.ts

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,11 @@ export const sources = {
1010
type: 'mysql',
1111
options: {
1212
adapter: MySQLAdapter,
13-
host: 'localhost',
14-
user: 'pastefy',
15-
password: 'pastefy',
16-
database: 'pastefy',
13+
host: process.env.PASTEFY_DB_HOST ?? '127.0.0.1',
14+
port: Number(process.env.PASTEFY_DB_PORT ?? '3307'),
15+
user: process.env.PASTEFY_DB_USER ?? 'pastefy',
16+
password: process.env.PASTEFY_DB_PASSWORD ?? 'pastefy',
17+
database: process.env.PASTEFY_DB_NAME ?? 'pastefy',
1718
}
1819
}
1920
}
@@ -30,4 +31,4 @@ async function main() {
3031

3132

3233
main().catch(console.error);
33-
export {Channel} from "./ws/Channel";
34+
export {Channel} from "./ws/Channel";

0 commit comments

Comments
 (0)