aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib/config.js9
-rw-r--r--src/lib/db.js51
-rw-r--r--src/lib/stores/widgets.js57
-rw-r--r--src/routes/+page.svelte8
4 files changed, 93 insertions, 32 deletions
diff --git a/src/lib/config.js b/src/lib/config.js
index dbbe7fc..9532cde 100644
--- a/src/lib/config.js
+++ b/src/lib/config.js
@@ -1,7 +1,10 @@
export const coordinateLength = 4;
export const maxSize = Math.pow(16, coordinateLength);
-export const supabase = {
- url: import.meta.env.VITE_SUPABASE_URL,
- key: import.meta.env.VITE_SUPABASE_KEY
+export const database = {
+ host: import.meta.env.VITE_DB_HOST || 'localhost',
+ port: import.meta.env.VITE_DB_PORT || 5432,
+ database: import.meta.env.VITE_DB_DATABASE || 'canvas',
+ user: import.meta.env.VITE_DB_USER || 'canvas',
+ password: import.meta.env.VITE_DB_PASSWORD
};
diff --git a/src/lib/db.js b/src/lib/db.js
new file mode 100644
index 0000000..d6adcdf
--- /dev/null
+++ b/src/lib/db.js
@@ -0,0 +1,51 @@
+import pg from 'pg';
+import { database } from '$lib/config';
+
+const { Pool } = pg;
+
+const pool = new Pool(database);
+
+export async function query(text, params) {
+ const client = await pool.connect();
+ try {
+ const result = await client.query(text, params);
+ return result;
+ } finally {
+ client.release();
+ }
+}
+
+export async function queryWithAbort(text, params, signal) {
+ if (signal?.aborted) {
+ throw new Error('Query aborted');
+ }
+
+ const client = await pool.connect();
+
+ const queryPromise = client.query(text, params);
+
+ if (signal) {
+ const abortPromise = new Promise((_, reject) => {
+ signal.addEventListener('abort', () => {
+ client.release();
+ reject(new Error('Query aborted'));
+ }, { once: true });
+ });
+
+ try {
+ const result = await Promise.race([queryPromise, abortPromise]);
+ return result;
+ } finally {
+ client.release();
+ }
+ }
+
+ try {
+ const result = await queryPromise;
+ return result;
+ } finally {
+ client.release();
+ }
+}
+
+export default pool; \ No newline at end of file
diff --git a/src/lib/stores/widgets.js b/src/lib/stores/widgets.js
index 372cad1..2796a7b 100644
--- a/src/lib/stores/widgets.js
+++ b/src/lib/stores/widgets.js
@@ -1,25 +1,23 @@
import { derived, readable, writable } from 'svelte/store';
-import { createClient } from '@supabase/supabase-js';
-import { supabase } from '$lib/config';
+import { queryWithAbort } from '$lib/db';
import { maxSize } from '$lib/config';
const boxParser = /\(([0-9]+),([0-9]+)\),\(([0-9]+),([0-9]+)\)/;
-const client = createClient(supabase.url, supabase.key);
export const sensor = writable({ left: 0, top: 0, right: 0, bottom: 0 });
-const getBoxes = function getBoxes({ left, top, right, bottom }) {
- const results = [
- `box.ov."((${left},${top}),(${right},${bottom}))"`,
- `box.ov."((${left + maxSize},${top + maxSize}),(${right + maxSize},${bottom + maxSize}))"`,
- `box.ov."((${left + maxSize},${top}),(${right + maxSize},${bottom}))"`,
- `box.ov."((${left},${top + maxSize}),(${right},${bottom + maxSize}))"`,
- `box.ov."((${left - maxSize},${top - maxSize}),(${right - maxSize},${bottom - maxSize}))"`,
- `box.ov."((${left - maxSize},${top}),(${right - maxSize},${bottom}))"`,
- `box.ov."((${left},${top - maxSize}),(${right},${bottom - maxSize}))"`
+const getBoxQuery = function getBoxQuery({ left, top, right, bottom }) {
+ const boxes = [
+ `box && box '((${left},${top}),(${right},${bottom}))'`,
+ `box && box '((${left + maxSize},${top + maxSize}),(${right + maxSize},${bottom + maxSize}))'`,
+ `box && box '((${left + maxSize},${top}),(${right + maxSize},${bottom}))'`,
+ `box && box '((${left},${top + maxSize}),(${right},${bottom + maxSize}))'`,
+ `box && box '((${left - maxSize},${top - maxSize}),(${right - maxSize},${bottom - maxSize}))'`,
+ `box && box '((${left - maxSize},${top}),(${right - maxSize},${bottom}))'`,
+ `box && box '((${left},${top - maxSize}),(${right},${bottom - maxSize}))'`
];
- return results;
+ return `SELECT * FROM widgets WHERE ${boxes.join(' OR ')}`;
};
const serialize = function serialize(widget) {
@@ -35,13 +33,19 @@ const serialize = function serialize(widget) {
};
let ac = null;
-export const widgets = derived(sensor, async function ($sensor, set) {
- const boxes = getBoxes($sensor);
+export const widgets = derived(sensor, async ($sensor, set) => {
+ const query = getBoxQuery($sensor);
ac && ac.abort();
ac = new AbortController();
- const { data } = await client.from('widgets').select().or(boxes.join(',')).abortSignal(ac.signal);
- if (data) {
- return set(data.map(serialize));
+ try {
+ const { rows } = await queryWithAbort(query, [], ac.signal);
+ if (rows) {
+ return set(rows.map(serialize));
+ }
+ } catch (error) {
+ if (error.message !== 'Query aborted') {
+ console.error('Error fetching widgets:', error);
+ }
}
});
@@ -51,13 +55,16 @@ export const countElements = function countElements(left, top, right, bottom) {
(async function () {
countAc && countAc.abort();
countAc = new AbortController();
- const { data } = await client
- .from('widgets')
- .select('*', { head: true, count: 'estimated' })
- .or(`box.ov."((${left},${top}),(${right},${bottom}))"`)
- .abortSignal(countAc.signal);
- if (data) {
- return set(data);
+ try {
+ const countQuery = `SELECT COUNT(*) FROM widgets WHERE box && box '((${left},${top}),(${right},${bottom}))'`;
+ const { rows } = await queryWithAbort(countQuery, [], countAc.signal);
+ if (rows && rows[0]) {
+ return set(parseInt(rows[0].count));
+ }
+ } catch (error) {
+ if (error.message !== 'Query aborted') {
+ console.error('Error counting widgets:', error);
+ }
}
})();
});
diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte
index 8dd0a16..a0a9065 100644
--- a/src/routes/+page.svelte
+++ b/src/routes/+page.svelte
@@ -17,10 +17,10 @@
const moveCanvas = function moveCanvas(event) {
if (dragging) {
- let deltaX = event.x - dragging.x;
- let deltaY = event.y - dragging.y;
- let x = modulo($canvas.x - deltaX, maxSize);
- let y = modulo($canvas.y - deltaY, maxSize);
+ const deltaX = event.x - dragging.x;
+ const deltaY = event.y - dragging.y;
+ const x = modulo($canvas.x - deltaX, maxSize);
+ const y = modulo($canvas.y - deltaY, maxSize);
dragging.x = event.x;
dragging.y = event.y;
canvas.set({ x, y });