Refactor database access to use a unified dbAdapter for SQLite and PostgreSQL
- Replaced direct database calls with dbAdapter methods in fieldRoutes, itemRoutes, listRoutes, syncRoutes, and webRoutes. - Implemented a new db.ts file to handle database interactions for both SQLite and PostgreSQL. - Added WebSocket support for real-time synchronization in WebSocketSyncClient and ws.ts. - Updated TypeScript configuration to include WebSocket types. - Created a new WebSocket server for handling sync requests and responses. - Ensured compatibility with both SQLite and PostgreSQL by using parameterized queries.
This commit is contained in:
@@ -1,12 +1,12 @@
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { db } from '../database';
|
||||
import { dbAdapter } from '../db';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// Get fields for a list
|
||||
router.get('/list/:listId', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const fields = db.prepare('SELECT * FROM fields WHERE listId = ? AND isDeleted = 0 ORDER BY `order` ASC').all(req.params.listId);
|
||||
const fields = await dbAdapter.queryAll('SELECT * FROM fields WHERE listId = ? AND isDeleted = 0 ORDER BY "order" ASC', [req.params.listId]);
|
||||
const formattedFields = (fields as any[]).map(field => ({ ...field, isDeleted: !!field.isDeleted }));
|
||||
res.json(formattedFields);
|
||||
} catch (error) {
|
||||
@@ -18,12 +18,11 @@ router.get('/list/:listId', async (req: Request, res: Response) => {
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id, name, fieldType, fieldOptions, listId, order, createdAt, updatedAt, isDeleted } = req.body;
|
||||
db.prepare(`
|
||||
INSERT INTO fields (id, name, fieldType, fieldOptions, listId, \`order\`, createdAt, updatedAt, isDeleted)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
`).run(id, name, fieldType, fieldOptions, listId, order, createdAt, updatedAt, isDeleted ? 1 : 0);
|
||||
|
||||
const field = db.prepare('SELECT * FROM fields WHERE id = ?').get(id);
|
||||
await dbAdapter.execute(
|
||||
'INSERT INTO fields (id, name, fieldType, fieldOptions, listId, "order", createdAt, updatedAt, isDeleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)',
|
||||
[id, name, fieldType, fieldOptions, listId, order, createdAt, updatedAt, isDeleted ? 1 : 0]
|
||||
);
|
||||
const field = await dbAdapter.queryOne('SELECT * FROM fields WHERE id = ?', [id]);
|
||||
res.status(201).json({ ...(field as any), isDeleted: !!(field as any).isDeleted });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to create field' });
|
||||
@@ -35,17 +34,16 @@ router.put('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const updatedAt = Date.now();
|
||||
const { name, fieldType, fieldOptions, order } = req.body;
|
||||
const result = db.prepare(`
|
||||
UPDATE fields
|
||||
SET name = ?, fieldType = ?, fieldOptions = ?, \`order\` = ?, updatedAt = ?
|
||||
WHERE id = ?
|
||||
`).run(name, fieldType, fieldOptions, order, updatedAt, req.params.id);
|
||||
const result = await dbAdapter.execute(
|
||||
'UPDATE fields SET name = ?, fieldType = ?, fieldOptions = ?, "order" = ?, updatedAt = ? WHERE id = ?',
|
||||
[name, fieldType, fieldOptions, order, updatedAt, req.params.id]
|
||||
);
|
||||
|
||||
if (result.changes === 0) {
|
||||
return res.status(404).json({ error: 'Field not found' });
|
||||
}
|
||||
|
||||
const field = db.prepare('SELECT * FROM fields WHERE id = ?').get(req.params.id);
|
||||
const field = await dbAdapter.queryOne('SELECT * FROM fields WHERE id = ?', [req.params.id]);
|
||||
res.json({ ...(field as any), isDeleted: !!(field as any).isDeleted });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to update field' });
|
||||
@@ -56,11 +54,10 @@ router.put('/:id', async (req: Request, res: Response) => {
|
||||
router.delete('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const updatedAt = Date.now();
|
||||
const result = db.prepare(`
|
||||
UPDATE fields
|
||||
SET isDeleted = 1, updatedAt = ?
|
||||
WHERE id = ?
|
||||
`).run(updatedAt, req.params.id);
|
||||
const result = await dbAdapter.execute(
|
||||
'UPDATE fields SET isDeleted = 1, updatedAt = ? WHERE id = ?',
|
||||
[updatedAt, req.params.id]
|
||||
);
|
||||
|
||||
if (result.changes === 0) {
|
||||
return res.status(404).json({ error: 'Field not found' });
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { db } from '../database';
|
||||
import { dbAdapter } from '../db';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// Get items for a list
|
||||
router.get('/list/:listId', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const items = db.prepare('SELECT * FROM items WHERE listId = ? AND isDeleted = 0 ORDER BY updatedAt DESC').all(req.params.listId);
|
||||
const items = await dbAdapter.queryAll('SELECT * FROM items WHERE listId = ? AND isDeleted = 0 ORDER BY updatedAt DESC', [req.params.listId]);
|
||||
const formattedItems = (items as any[]).map(item => ({ ...item, isDeleted: !!item.isDeleted }));
|
||||
res.json(formattedItems);
|
||||
} catch (error) {
|
||||
@@ -17,7 +17,7 @@ router.get('/list/:listId', async (req: Request, res: Response) => {
|
||||
// Get item values
|
||||
router.get('/:itemId/values', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const values = db.prepare('SELECT * FROM item_values WHERE itemId = ?').all(req.params.itemId);
|
||||
const values = await dbAdapter.queryAll('SELECT * FROM item_values WHERE itemId = ?', [req.params.itemId]);
|
||||
res.json(values);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to fetch item values' });
|
||||
@@ -28,12 +28,11 @@ router.get('/:itemId/values', async (req: Request, res: Response) => {
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id, listId, createdAt, updatedAt, isDeleted } = req.body;
|
||||
db.prepare(`
|
||||
INSERT INTO items (id, listId, createdAt, updatedAt, isDeleted)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`).run(id, listId, createdAt, updatedAt, isDeleted ? 1 : 0);
|
||||
|
||||
const item = db.prepare('SELECT * FROM items WHERE id = ?').get(id);
|
||||
await dbAdapter.execute(
|
||||
'INSERT INTO items (id, listId, createdAt, updatedAt, isDeleted) VALUES (?, ?, ?, ?, ?)',
|
||||
[id, listId, createdAt, updatedAt, isDeleted ? 1 : 0]
|
||||
);
|
||||
const item = await dbAdapter.queryOne('SELECT * FROM items WHERE id = ?', [id]);
|
||||
res.status(201).json({ ...(item as any), isDeleted: !!(item as any).isDeleted });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to create item' });
|
||||
@@ -44,15 +43,11 @@ router.post('/', async (req: Request, res: Response) => {
|
||||
router.post('/values', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id, itemId, fieldId, value, updatedAt } = req.body;
|
||||
db.prepare(`
|
||||
INSERT INTO item_values (id, itemId, fieldId, value, updatedAt)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
value = ?,
|
||||
updatedAt = ?
|
||||
`).run(id, itemId, fieldId, value, updatedAt, value, updatedAt);
|
||||
|
||||
const itemValue = db.prepare('SELECT * FROM item_values WHERE id = ?').get(id);
|
||||
await dbAdapter.execute(
|
||||
'INSERT INTO item_values (id, itemId, fieldId, value, updatedAt) VALUES (?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET value = ?, updatedAt = ?',
|
||||
[id, itemId, fieldId, value, updatedAt, value, updatedAt]
|
||||
);
|
||||
const itemValue = await dbAdapter.queryOne('SELECT * FROM item_values WHERE id = ?', [id]);
|
||||
res.json(itemValue);
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to save item value' });
|
||||
@@ -63,17 +58,16 @@ router.post('/values', async (req: Request, res: Response) => {
|
||||
router.put('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const updatedAt = Date.now();
|
||||
const result = db.prepare(`
|
||||
UPDATE items
|
||||
SET updatedAt = ?
|
||||
WHERE id = ?
|
||||
`).run(updatedAt, req.params.id);
|
||||
const result = await dbAdapter.execute(
|
||||
'UPDATE items SET updatedAt = ? WHERE id = ?',
|
||||
[updatedAt, req.params.id]
|
||||
);
|
||||
|
||||
if (result.changes === 0) {
|
||||
return res.status(404).json({ error: 'Item not found' });
|
||||
}
|
||||
|
||||
const item = db.prepare('SELECT * FROM items WHERE id = ?').get(req.params.id);
|
||||
const item = await dbAdapter.queryOne('SELECT * FROM items WHERE id = ?', [req.params.id]);
|
||||
res.json({ ...(item as any), isDeleted: !!(item as any).isDeleted });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to update item' });
|
||||
@@ -84,11 +78,10 @@ router.put('/:id', async (req: Request, res: Response) => {
|
||||
router.delete('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const updatedAt = Date.now();
|
||||
const result = db.prepare(`
|
||||
UPDATE items
|
||||
SET isDeleted = 1, updatedAt = ?
|
||||
WHERE id = ?
|
||||
`).run(updatedAt, req.params.id);
|
||||
const result = await dbAdapter.execute(
|
||||
'UPDATE items SET isDeleted = 1, updatedAt = ? WHERE id = ?',
|
||||
[updatedAt, req.params.id]
|
||||
);
|
||||
|
||||
if (result.changes === 0) {
|
||||
return res.status(404).json({ error: 'Item not found' });
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { db } from '../database';
|
||||
import { dbAdapter } from '../db';
|
||||
|
||||
const router = Router();
|
||||
|
||||
// Get all lists
|
||||
router.get('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const lists = db.prepare('SELECT * FROM lists WHERE isDeleted = 0 ORDER BY updatedAt DESC').all();
|
||||
const lists = await dbAdapter.queryAll('SELECT * FROM lists WHERE isDeleted = 0 ORDER BY updatedAt DESC');
|
||||
// Convert isDeleted from INTEGER to BOOLEAN
|
||||
const formattedLists = (lists as any[]).map(list => ({ ...list, isDeleted: !!list.isDeleted }));
|
||||
res.json(formattedLists);
|
||||
@@ -18,7 +18,7 @@ router.get('/', async (req: Request, res: Response) => {
|
||||
// Get single list
|
||||
router.get('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const list = db.prepare('SELECT * FROM lists WHERE id = ? AND isDeleted = 0').get(req.params.id);
|
||||
const list = await dbAdapter.queryOne('SELECT * FROM lists WHERE id = ? AND isDeleted = 0', [req.params.id]);
|
||||
if (!list) {
|
||||
return res.status(404).json({ error: 'List not found' });
|
||||
}
|
||||
@@ -32,12 +32,11 @@ router.get('/:id', async (req: Request, res: Response) => {
|
||||
router.post('/', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const { id, name, createdAt, updatedAt, isDeleted } = req.body;
|
||||
db.prepare(`
|
||||
INSERT INTO lists (id, name, createdAt, updatedAt, isDeleted)
|
||||
VALUES (?, ?, ?, ?, ?)
|
||||
`).run(id, name, createdAt, updatedAt, isDeleted ? 1 : 0);
|
||||
|
||||
const list = db.prepare('SELECT * FROM lists WHERE id = ?').get(id);
|
||||
await dbAdapter.execute(
|
||||
'INSERT INTO lists (id, name, createdAt, updatedAt, isDeleted) VALUES (?, ?, ?, ?, ?)',
|
||||
[id, name, createdAt, updatedAt, isDeleted ? 1 : 0]
|
||||
);
|
||||
const list = await dbAdapter.queryOne('SELECT * FROM lists WHERE id = ?', [id]);
|
||||
res.status(201).json({ ...(list as any), isDeleted: !!(list as any).isDeleted });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to create list' });
|
||||
@@ -48,17 +47,15 @@ router.post('/', async (req: Request, res: Response) => {
|
||||
router.put('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const updatedAt = Date.now();
|
||||
const result = db.prepare(`
|
||||
UPDATE lists
|
||||
SET name = ?, updatedAt = ?
|
||||
WHERE id = ?
|
||||
`).run(req.body.name, updatedAt, req.params.id);
|
||||
|
||||
const result = await dbAdapter.execute(
|
||||
'UPDATE lists SET name = ?, updatedAt = ? WHERE id = ?',
|
||||
[req.body.name, updatedAt, req.params.id]
|
||||
);
|
||||
|
||||
if (result.changes === 0) {
|
||||
return res.status(404).json({ error: 'List not found' });
|
||||
}
|
||||
|
||||
const list = db.prepare('SELECT * FROM lists WHERE id = ?').get(req.params.id);
|
||||
const list = await dbAdapter.queryOne('SELECT * FROM lists WHERE id = ?', [req.params.id]);
|
||||
res.json({ ...(list as any), isDeleted: !!(list as any).isDeleted });
|
||||
} catch (error) {
|
||||
res.status(500).json({ error: 'Failed to update list' });
|
||||
@@ -69,12 +66,11 @@ router.put('/:id', async (req: Request, res: Response) => {
|
||||
router.delete('/:id', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const updatedAt = Date.now();
|
||||
const result = db.prepare(`
|
||||
UPDATE lists
|
||||
SET isDeleted = 1, updatedAt = ?
|
||||
WHERE id = ?
|
||||
`).run(updatedAt, req.params.id);
|
||||
|
||||
const result = await dbAdapter.execute(
|
||||
'UPDATE lists SET isDeleted = 1, updatedAt = ? WHERE id = ?',
|
||||
[updatedAt, req.params.id]
|
||||
);
|
||||
|
||||
if (result.changes === 0) {
|
||||
return res.status(404).json({ error: 'List not found' });
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { db } from '../database';
|
||||
import { dbAdapter } from '../db';
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -57,43 +57,11 @@ setInterval(() => {
|
||||
}, 60000); // Changed from 30s to 60s
|
||||
|
||||
// Helper function to get prepared statements (lazy initialization)
|
||||
function getUpsertStatements() {
|
||||
return {
|
||||
upsertList: db.prepare(`
|
||||
INSERT INTO lists (id, name, createdAt, updatedAt, isDeleted)
|
||||
VALUES (@id, @name, @createdAt, @updatedAt, @isDeleted)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
name = @name,
|
||||
updatedAt = @updatedAt,
|
||||
isDeleted = @isDeleted
|
||||
`),
|
||||
upsertField: db.prepare(`
|
||||
INSERT INTO fields (id, name, fieldType, fieldOptions, listId, \`order\`, createdAt, updatedAt, isDeleted)
|
||||
VALUES (@id, @name, @fieldType, @fieldOptions, @listId, @order, @createdAt, @updatedAt, @isDeleted)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
name = @name,
|
||||
fieldType = @fieldType,
|
||||
fieldOptions = @fieldOptions,
|
||||
\`order\` = @order,
|
||||
updatedAt = @updatedAt,
|
||||
isDeleted = @isDeleted
|
||||
`),
|
||||
upsertItem: db.prepare(`
|
||||
INSERT INTO items (id, listId, createdAt, updatedAt, isDeleted)
|
||||
VALUES (@id, @listId, @createdAt, @updatedAt, @isDeleted)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
updatedAt = @updatedAt,
|
||||
isDeleted = @isDeleted
|
||||
`),
|
||||
upsertItemValue: db.prepare(`
|
||||
INSERT INTO item_values (id, itemId, fieldId, value, updatedAt)
|
||||
VALUES (@id, @itemId, @fieldId, @value, @updatedAt)
|
||||
ON CONFLICT(id) DO UPDATE SET
|
||||
value = @value,
|
||||
updatedAt = @updatedAt
|
||||
`)
|
||||
};
|
||||
}
|
||||
// We'll perform upserts with positional params for cross-DB portability
|
||||
const UPSERT_LIST = 'INSERT INTO lists (id, name, createdAt, updatedAt, isDeleted) VALUES (?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET name = EXCLUDED.name, updatedAt = EXCLUDED.updatedAt, isDeleted = EXCLUDED.isDeleted';
|
||||
const UPSERT_FIELD = 'INSERT INTO fields (id, name, fieldType, fieldOptions, listId, "order", createdAt, updatedAt, isDeleted) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET name = EXCLUDED.name, fieldType = EXCLUDED.fieldType, fieldOptions = EXCLUDED.fieldOptions, "order" = EXCLUDED."order", updatedAt = EXCLUDED.updatedAt, isDeleted = EXCLUDED.isDeleted';
|
||||
const UPSERT_ITEM = 'INSERT INTO items (id, listId, createdAt, updatedAt, isDeleted) VALUES (?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET updatedAt = EXCLUDED.updatedAt, isDeleted = EXCLUDED.isDeleted';
|
||||
const UPSERT_ITEM_VALUE = 'INSERT INTO item_values (id, itemId, fieldId, value, updatedAt) VALUES (?, ?, ?, ?, ?) ON CONFLICT(id) DO UPDATE SET value = EXCLUDED.value, updatedAt = EXCLUDED.updatedAt';
|
||||
|
||||
router.post('/sync', async (req: Request, res: Response) => {
|
||||
try {
|
||||
@@ -144,65 +112,60 @@ router.post('/sync', async (req: Request, res: Response) => {
|
||||
}
|
||||
|
||||
// Save incoming data from client using a transaction
|
||||
const transaction = db.transaction((data: SyncRequest) => {
|
||||
// Get prepared statements lazily
|
||||
const { upsertList, upsertField, upsertItem, upsertItemValue } = getUpsertStatements();
|
||||
|
||||
if (data.lists && data.lists.length > 0) {
|
||||
for (const list of data.lists) {
|
||||
upsertList.run({
|
||||
id: list.id,
|
||||
name: list.name,
|
||||
createdAt: list.createdAt,
|
||||
updatedAt: list.updatedAt,
|
||||
isDeleted: list.isDeleted ? 1 : 0
|
||||
});
|
||||
await dbAdapter.transaction(async (tx) => {
|
||||
if (lists && lists.length > 0) {
|
||||
for (const list of lists) {
|
||||
await tx.execute(UPSERT_LIST, [
|
||||
list.id,
|
||||
list.name,
|
||||
list.createdAt,
|
||||
list.updatedAt,
|
||||
list.isDeleted ? 1 : 0
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.fields && data.fields.length > 0) {
|
||||
for (const field of data.fields) {
|
||||
upsertField.run({
|
||||
id: field.id,
|
||||
name: field.name,
|
||||
fieldType: field.fieldType,
|
||||
fieldOptions: field.fieldOptions,
|
||||
listId: field.listId,
|
||||
order: field.order,
|
||||
createdAt: field.createdAt,
|
||||
updatedAt: field.updatedAt,
|
||||
isDeleted: field.isDeleted ? 1 : 0
|
||||
});
|
||||
if (fields && fields.length > 0) {
|
||||
for (const field of fields) {
|
||||
await tx.execute(UPSERT_FIELD, [
|
||||
field.id,
|
||||
field.name,
|
||||
field.fieldType,
|
||||
field.fieldOptions,
|
||||
field.listId,
|
||||
field.order,
|
||||
field.createdAt,
|
||||
field.updatedAt,
|
||||
field.isDeleted ? 1 : 0
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.items && data.items.length > 0) {
|
||||
for (const item of data.items) {
|
||||
upsertItem.run({
|
||||
id: item.id,
|
||||
listId: item.listId,
|
||||
createdAt: item.createdAt,
|
||||
updatedAt: item.updatedAt,
|
||||
isDeleted: item.isDeleted ? 1 : 0
|
||||
});
|
||||
if (items && items.length > 0) {
|
||||
for (const item of items) {
|
||||
await tx.execute(UPSERT_ITEM, [
|
||||
item.id,
|
||||
item.listId,
|
||||
item.createdAt,
|
||||
item.updatedAt,
|
||||
item.isDeleted ? 1 : 0
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
if (data.itemValues && data.itemValues.length > 0) {
|
||||
for (const value of data.itemValues) {
|
||||
upsertItemValue.run({
|
||||
id: value.id,
|
||||
itemId: value.itemId,
|
||||
fieldId: value.fieldId,
|
||||
value: value.value,
|
||||
updatedAt: value.updatedAt
|
||||
});
|
||||
if (itemValues && itemValues.length > 0) {
|
||||
for (const value of itemValues) {
|
||||
await tx.execute(UPSERT_ITEM_VALUE, [
|
||||
value.id,
|
||||
value.itemId,
|
||||
value.fieldId,
|
||||
value.value,
|
||||
value.updatedAt
|
||||
]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
transaction({ lastSyncTimestamp, lists, fields, items, itemValues });
|
||||
|
||||
// IMPORTANT: Get updates from server AFTER saving incoming data
|
||||
// This ensures clients receive back any data they just sent (for confirmation)
|
||||
// If lastSyncTimestamp is 0, get all data (initial sync)
|
||||
@@ -210,17 +173,15 @@ router.post('/sync', async (req: Request, res: Response) => {
|
||||
let serverLists, serverFields, serverItems, serverItemValues;
|
||||
|
||||
if (lastSyncTimestamp === 0) {
|
||||
// Initial sync: send all non-deleted items (AFTER processing incoming data)
|
||||
serverLists = db.prepare('SELECT * FROM lists WHERE isDeleted = 0').all();
|
||||
serverFields = db.prepare('SELECT * FROM fields WHERE isDeleted = 0').all();
|
||||
serverItems = db.prepare('SELECT * FROM items WHERE isDeleted = 0').all();
|
||||
serverItemValues = db.prepare('SELECT * FROM item_values').all();
|
||||
serverLists = await dbAdapter.queryAll('SELECT * FROM lists WHERE isDeleted = 0');
|
||||
serverFields = await dbAdapter.queryAll('SELECT * FROM fields WHERE isDeleted = 0');
|
||||
serverItems = await dbAdapter.queryAll('SELECT * FROM items WHERE isDeleted = 0');
|
||||
serverItemValues = await dbAdapter.queryAll('SELECT * FROM item_values');
|
||||
} else {
|
||||
// Incremental sync: send all updates including deletions (use >= to include items updated exactly at lastSyncTimestamp)
|
||||
serverLists = db.prepare('SELECT * FROM lists WHERE updatedAt >= ?').all(lastSyncTimestamp);
|
||||
serverFields = db.prepare('SELECT * FROM fields WHERE updatedAt >= ?').all(lastSyncTimestamp);
|
||||
serverItems = db.prepare('SELECT * FROM items WHERE updatedAt >= ?').all(lastSyncTimestamp);
|
||||
serverItemValues = db.prepare('SELECT * FROM item_values WHERE updatedAt >= ?').all(lastSyncTimestamp);
|
||||
serverLists = await dbAdapter.queryAll('SELECT * FROM lists WHERE updatedAt >= ?', [lastSyncTimestamp]);
|
||||
serverFields = await dbAdapter.queryAll('SELECT * FROM fields WHERE updatedAt >= ?', [lastSyncTimestamp]);
|
||||
serverItems = await dbAdapter.queryAll('SELECT * FROM items WHERE updatedAt >= ?', [lastSyncTimestamp]);
|
||||
serverItemValues = await dbAdapter.queryAll('SELECT * FROM item_values WHERE updatedAt >= ?', [lastSyncTimestamp]);
|
||||
}
|
||||
|
||||
// Convert isDeleted from INTEGER (0/1) to BOOLEAN
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Router, Request, Response } from 'express';
|
||||
import { db } from '../database';
|
||||
import { dbAdapter } from '../db';
|
||||
|
||||
const router = Router();
|
||||
|
||||
@@ -306,10 +306,11 @@ router.get('/web/data', async (req: Request, res: Response) => {
|
||||
res.setHeader('Pragma', 'no-cache');
|
||||
res.setHeader('Expires', '0');
|
||||
|
||||
const lists = db.prepare('SELECT * FROM lists ORDER BY updatedAt DESC').all();
|
||||
const fields = db.prepare('SELECT * FROM fields ORDER BY listId ASC, `order` ASC').all();
|
||||
const items = db.prepare('SELECT * FROM items ORDER BY listId ASC, updatedAt DESC').all();
|
||||
const values = db.prepare('SELECT * FROM item_values').all();
|
||||
// Exclude deleted lists and items from web UI
|
||||
const lists = await dbAdapter.queryAll('SELECT * FROM lists WHERE isDeleted = 0 ORDER BY updatedAt DESC');
|
||||
const fields = await dbAdapter.queryAll('SELECT * FROM fields ORDER BY listId ASC, "order" ASC');
|
||||
const items = await dbAdapter.queryAll('SELECT * FROM items WHERE isDeleted = 0 ORDER BY listId ASC, updatedAt DESC');
|
||||
const values = await dbAdapter.queryAll('SELECT * FROM item_values');
|
||||
|
||||
// Convert isDeleted from INTEGER to BOOLEAN
|
||||
const formattedLists = (lists as any[]).map(list => ({ ...list, isDeleted: !!list.isDeleted }));
|
||||
|
||||
Reference in New Issue
Block a user