Skip to content

Commit 2e1a8e7

Browse files
committed
feat: enhance SQL source management with PostgreSQL support and improve UI components
1 parent b11f0f6 commit 2e1a8e7

75 files changed

Lines changed: 10150 additions & 764 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.dockerignore

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
node_modules
2+
packages/*/node_modules
3+
packages/*/dist
4+
packages/electron/.vite
5+
.git
6+
.github
7+
.DS_Store
8+
npm-debug.log*
9+
pnpm-debug.log*
10+
docker/mysql
11+
docker/postgres

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ dist
1010
.npmrc
1111

1212
packages/electron/out
13+
packages/backend/.starquery/
1314

1415
logs
1516
*.log

Dockerfile.backend

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
FROM node:24-alpine
2+
3+
WORKDIR /app
4+
5+
RUN corepack enable
6+
7+
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
8+
COPY packages/backend/package.json packages/backend/package.json
9+
10+
RUN pnpm install --filter backend... --frozen-lockfile --prod
11+
12+
COPY packages/backend packages/backend
13+
14+
WORKDIR /app/packages/backend
15+
16+
EXPOSE 3000
17+
18+
CMD ["pnpm", "start"]

Dockerfile.frontend

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
FROM node:24-alpine AS build
2+
3+
WORKDIR /app
4+
5+
RUN corepack enable
6+
7+
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
8+
COPY packages/frontend/package.json packages/frontend/package.json
9+
10+
RUN pnpm install --filter frontend... --frozen-lockfile
11+
12+
COPY packages/frontend packages/frontend
13+
14+
WORKDIR /app/packages/frontend
15+
16+
RUN pnpm build
17+
18+
FROM nginx:1.27-alpine
19+
20+
COPY docker/nginx/starquery.conf /etc/nginx/conf.d/default.conf
21+
COPY --from=build /app/packages/frontend/dist /usr/share/nginx/html
22+
23+
EXPOSE 80

README.md

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,5 +59,54 @@ docker compose down -v
5959

6060
Use `docker compose down -v` if you want to wipe the database and re-run the seed from scratch.
6161

62+
## Self-Hosted Deployment
63+
There is now a dedicated Docker deployment for the hosted web version with:
64+
65+
- a Vite-built frontend served by Nginx
66+
- a Node backend
67+
- a MySQL metastore for projects, datasources, and users
68+
69+
Start it with:
70+
71+
```bash
72+
docker compose -f docker-compose.hosted.yml up -d --build
73+
```
74+
75+
Then open:
76+
77+
- Frontend: `http://localhost:8080`
78+
79+
The frontend proxies `/api` to the backend internally, so in production mode the browser app automatically uses the same origin as its default hosted server.
80+
81+
If you want the frontend to use exactly one backend and disable server switching entirely, set:
82+
83+
```bash
84+
VITE_LOCKED_SERVER_URL=https://your-server.example.com
85+
```
86+
87+
Optional label:
88+
89+
```bash
90+
VITE_LOCKED_SERVER_NAME="Production Server"
91+
```
92+
93+
Services in the hosted stack:
94+
95+
- `frontend`: public web UI on port `8080`
96+
- `backend`: internal StarQuery API in `hosted` mode
97+
- `meta-db`: MySQL database used by the backend as its metastore
98+
99+
Stop it with:
100+
101+
```bash
102+
docker compose -f docker-compose.hosted.yml down
103+
```
104+
105+
Reset the hosted metastore volume with:
106+
107+
```bash
108+
docker compose -f docker-compose.hosted.yml down -v
109+
```
110+
62111
## Backlog
63112
- [ ] Add OpenID Connect support

docker-compose.hosted.yml

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
services:
2+
frontend:
3+
build:
4+
context: .
5+
dockerfile: Dockerfile.frontend
6+
depends_on:
7+
- backend
8+
ports:
9+
- '8080:80'
10+
restart: unless-stopped
11+
12+
backend:
13+
build:
14+
context: .
15+
dockerfile: Dockerfile.backend
16+
depends_on:
17+
meta-db:
18+
condition: service_healthy
19+
environment:
20+
HOST: 0.0.0.0
21+
PORT: 3000
22+
STARQUERY_MODE: hosted
23+
STARQUERY_SERVER_NAME: StarQuery Hosted
24+
STARQUERY_META_DRIVER: mysql
25+
STARQUERY_META_MYSQL_HOST: meta-db
26+
STARQUERY_META_MYSQL_PORT: 3306
27+
STARQUERY_META_MYSQL_USER: starquery
28+
STARQUERY_META_MYSQL_PASSWORD: starquery
29+
STARQUERY_META_MYSQL_DATABASE: starquery
30+
expose:
31+
- '3000'
32+
restart: unless-stopped
33+
34+
meta-db:
35+
image: mysql:8.4
36+
environment:
37+
MYSQL_ROOT_PASSWORD: root
38+
MYSQL_DATABASE: starquery
39+
MYSQL_USER: starquery
40+
MYSQL_PASSWORD: starquery
41+
volumes:
42+
- starquery-meta-data:/var/lib/mysql
43+
healthcheck:
44+
test: ['CMD-SHELL', 'mysqladmin ping -h 127.0.0.1 -uroot -p$$MYSQL_ROOT_PASSWORD']
45+
interval: 10s
46+
timeout: 5s
47+
retries: 12
48+
start_period: 20s
49+
restart: unless-stopped
50+
51+
volumes:
52+
starquery-meta-data:

docker-compose.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,26 @@ services:
2020
retries: 20
2121
start_period: 15s
2222

23+
postgres:
24+
image: postgres:17
25+
container_name: starquery-postgres
26+
restart: unless-stopped
27+
ports:
28+
- "5433:5432"
29+
environment:
30+
POSTGRES_DB: pastefy
31+
POSTGRES_USER: pastefy
32+
POSTGRES_PASSWORD: pastefy
33+
volumes:
34+
- postgres-data:/var/lib/postgresql/data
35+
- ./docker/postgres/init:/docker-entrypoint-initdb.d:ro
36+
healthcheck:
37+
test: ["CMD-SHELL", "pg_isready -h 127.0.0.1 -U pastefy -d pastefy"]
38+
interval: 5s
39+
timeout: 5s
40+
retries: 20
41+
start_period: 15s
42+
2343
volumes:
2444
mysql-data:
45+
postgres-data:

docker/nginx/starquery.conf

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
server {
2+
listen 80;
3+
server_name _;
4+
5+
root /usr/share/nginx/html;
6+
index index.html;
7+
8+
location /api/ {
9+
proxy_pass http://backend:3000;
10+
proxy_http_version 1.1;
11+
proxy_set_header Host $host;
12+
proxy_set_header X-Real-IP $remote_addr;
13+
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
14+
proxy_set_header X-Forwarded-Proto $scheme;
15+
}
16+
17+
location / {
18+
try_files $uri $uri/ /index.html;
19+
}
20+
}

docker/postgres/init/001-seed.sql

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

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33
"version": "1.0.0",
44
"description": "",
55
"main": "index.js",
6+
"pnpm": {
7+
"onlyBuiltDependencies": [
8+
"electron",
9+
"electron-winstaller"
10+
]
11+
},
612
"scripts": {
713
"test": "echo \"Error: no test specified\" && exit 1"
814
},

0 commit comments

Comments
 (0)