Skip to content

Commit 34ac1c3

Browse files
committed
update build scripts
1 parent 06ac14c commit 34ac1c3

File tree

5 files changed

+162
-107
lines changed

5 files changed

+162
-107
lines changed

forge.config.ts

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { MakerZIP } from '@electron-forge/maker-zip';
77
// import { AutoUnpackNativesPlugin } from '@electron-forge/plugin-auto-unpack-natives';
88
import { WebpackPlugin } from '@electron-forge/plugin-webpack';
99
import { PublisherGithub } from '@electron-forge/publisher-github';
10-
import MakerAppImage from 'electron-forge-maker-appimage';
10+
// import MakerAppImage from 'electron-forge-maker-appimage';
1111
import { move, pathExists, remove } from 'fs-extra';
1212
// import PublisherGithubLatestYml from 'publisher-github-latest-yml';
1313

@@ -101,15 +101,15 @@ const config: ForgeConfig = {
101101
// // https://js.electronforge.io/interfaces/_electron_forge_maker_deb.InternalOptions.MakerDebConfigOptions.html
102102
// options: { bin: 'WooCommercePOS' },
103103
// }),
104-
new MakerAppImage(
105-
{
106-
options: {
107-
icon: path.resolve(__dirname, 'icons/icon.png'),
108-
categories: ['Office'],
109-
},
110-
},
111-
['linux']
112-
),
104+
// new MakerAppImage(
105+
// {
106+
// options: {
107+
// icon: path.resolve(__dirname, 'icons/icon.png'),
108+
// categories: ['Office'],
109+
// },
110+
// },
111+
// ['linux']
112+
// ),
113113
],
114114
publishers: [
115115
new PublisherGithub({

package.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@
77
"author": "Paul Kilmurray <paul@wcpos.com>",
88
"main": ".webpack/main",
99
"scripts": {
10-
"start": "concurrently \"yarn start:expo\" \"yarn start:electron\"",
11-
"start:expo": "ELECTRON=true EXPO_NO_METRO_LAZY=true yarn workspace @wcpos/managed-expo start --port 8088",
12-
"start:electron": "yarn && NODE_ENV=\"development\" electron-forge start --enable-logging",
13-
"rebuild:all": "electron-rebuild -v 34.2.0 -f",
10+
"dev": "concurrently \"pnpm run dev:expo\" \"pnpm run dev:electron\"",
11+
"dev:expo": "ELECTRON=true EXPO_NO_METRO_LAZY=true BROWSER=none pnpm --filter @wcpos/main dev --web --port 8088",
12+
"dev:electron": "NODE_ENV=\"development\" electron-forge start --enable-logging",
13+
"rebuild:all": "electron-rebuild -v 34.1.1 -f",
1414
"package": "DEBUG=electron-osx-sign* electron-forge package",
1515
"make": "electron-forge make",
1616
"publish-app": "electron-forge publish",
@@ -19,7 +19,7 @@
1919
"ts:check": "yarn tsc --noEmit"
2020
},
2121
"dependencies": {
22-
"@sentry/electron": "^5.9.0",
22+
"@sentry/electron": "6.1.0",
2323
"@transifex/native": "^7.1.3",
2424
"axios": "^1.7.9",
2525
"better-sqlite3": "11.8.1",
@@ -44,7 +44,7 @@
4444
"@types/webpack-node-externals": "^3.0.4",
4545
"@vercel/webpack-asset-relocator-loader": "1.7.3",
4646
"concurrently": "9.1.2",
47-
"electron": "34.2.0",
47+
"electron": "34.1.1",
4848
"electron-debug": "^4.1.0",
4949
"electron-devtools-installer": "4.0.0",
5050
"electron-squirrel-startup": "^1.0.1",

src/main/database.ts

Lines changed: 82 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -1,125 +1,117 @@
11
import fs from 'fs';
22
import path from 'path';
3-
43
import Database from 'better-sqlite3';
54
import { app, ipcMain } from 'electron';
6-
75
import logger from './log';
86

97
const isDevelopment = process.env.NODE_ENV === 'development';
10-
// const sqlite = isDevelopment ? sqlite3.verbose() : sqlite3;
118
const registry = new Map();
129

1310
/**
14-
* The app.getPath() method is only available once the app is 'ready'.
15-
* Use app.on('ready' () => { ... }); to detect the 'ready' event.
16-
* See Electron's Event: 'ready' event for more information.
17-
*
18-
* https://github.com/electron/electron/blob/main/docs/api/app.md#appgetpathname
11+
* Open or retrieve an existing SQLite database.
1912
*/
2013
const openDatabase = (name: string) => {
21-
/**
22-
* Check registry
23-
*/
24-
if (registry.has(name)) {
25-
return { name };
26-
}
14+
// Check registry first
15+
if (registry.has(name)) {
16+
return { name };
17+
}
2718

28-
try {
29-
/**
30-
* Determine database folder
31-
*
32-
* @NOTE - there seems to be a weird conflict with electron-store if I use the name 'databases'
33-
* in the app's userData folder - it was deleting the directory every time the app started ??!!
34-
*/
35-
const dbFolder = isDevelopment
36-
? path.resolve('databases')
37-
: path.resolve(app.getPath('userData'), 'wcpos_dbs');
19+
try {
20+
const dbFolder = isDevelopment
21+
? path.resolve('databases')
22+
: path.resolve(app.getPath('userData'), 'wcpos_dbs');
3823

39-
/**
40-
* Create folder if it doesn't exist
41-
*/
42-
if (!fs.existsSync(dbFolder)) {
43-
try {
44-
fs.mkdirSync(dbFolder, { recursive: true });
45-
logger.info(`Created database folder: ${dbFolder}`);
46-
} catch (err) {
47-
logger.error(`Failed to create database folder: ${dbFolder}`, err);
48-
}
49-
}
24+
// Create folder if it doesn't exist
25+
if (!fs.existsSync(dbFolder)) {
26+
try {
27+
fs.mkdirSync(dbFolder, { recursive: true });
28+
logger.info(`Created database folder: ${dbFolder}`);
29+
} catch (err) {
30+
logger.error(`Failed to create database folder: ${dbFolder}`, err);
31+
}
32+
}
5033

51-
/**
52-
* Open database
53-
*/
54-
logger.info('Opening SQLite database', name);
55-
const db = new Database(path.resolve(dbFolder, `${name}.sqlite3`), { verbose: logger.debug });
56-
logger.info('Opened SQLite database', db);
34+
logger.info('Opening SQLite database', name);
35+
const db = new Database(path.resolve(dbFolder, `${name}.sqlite3`), { verbose: logger.debug });
36+
logger.info('Opened SQLite database', db);
5737

58-
registry.set(name, db);
59-
return { name };
60-
} catch (error) {
61-
logger.error('Failed to open database', error);
62-
throw error; // Re-throw the error after logging it to allow further handling upstream
63-
}
38+
registry.set(name, db);
39+
return { name };
40+
} catch (error) {
41+
logger.error('Failed to open database', error);
42+
throw error;
43+
}
6444
};
6545

6646
export const closeAll = () => {
67-
registry.forEach((db, name) => {
68-
db.close();
69-
registry.delete(name);
70-
logger.info(`Closed and removed ${name} from registry.`);
71-
});
47+
registry.forEach((db, name) => {
48+
db.close();
49+
registry.delete(name);
50+
logger.info(`Closed and removed ${name} from registry.`);
51+
});
7252
};
7353

7454
/**
75-
* RxDB sends query params as booleans, but SQLite doesn't support booleans.
55+
* Convert boolean values in parameters to numbers (SQLite doesn't support booleans).
7656
*/
7757
function convertBooleansToNumbers(params: (string | number | boolean)[]): (string | number)[] {
78-
return params.map((param) => (typeof param === 'boolean' ? (param ? 1 : 0) : param));
58+
return params.map(param => (typeof param === 'boolean' ? (param ? 1 : 0) : param));
7959
}
8060

8161
/**
62+
* Execute an SQL statement.
8263
*
64+
* - SELECT queries: use .all()
65+
* - PRAGMA assignments (e.g. PRAGMA synchronous = normal): use .run()
66+
* - Other PRAGMA queries: use .all()
67+
* - All others: use .run()
8368
*/
8469
function executeSql(db, sql, params) {
85-
if (/^\s*(SELECT|PRAGMA)/i.test(sql)) {
86-
return db.prepare(sql).all(params); // For SELECT or PRAGMA queries
87-
} else {
88-
return db.prepare(sql).run(params); // For INSERT, UPDATE, DELETE
89-
}
70+
if (/^\s*SELECT/i.test(sql)) {
71+
return db.prepare(sql).all(params);
72+
}
73+
// PRAGMA assignments like "PRAGMA synchronous = normal" do not return data.
74+
if (/^\s*PRAGMA\s+\w+\s*=\s*/i.test(sql)) {
75+
return db.prepare(sql).run(params);
76+
}
77+
if (/^\s*PRAGMA/i.test(sql)) {
78+
return db.prepare(sql).all(params);
79+
}
80+
return db.prepare(sql).run(params);
9081
}
9182

9283
/**
93-
*
84+
* Handle SQLite IPC requests.
9485
*/
9586
ipcMain.handle('sqlite', (event, obj) => {
96-
logger.silly('SQL request', JSON.stringify(obj, null, 2));
97-
try {
98-
let db;
99-
switch (obj.type) {
100-
case 'open':
101-
return openDatabase(obj.name);
102-
case 'close':
103-
db = registry.get(obj.name);
104-
if (!db) throw new Error(`Database connection "${obj.name}" not found`);
105-
db.close();
106-
registry.delete(obj.name);
107-
logger.info(`Closed and removed ${obj.name} from registry.`);
108-
return;
109-
case 'quit':
110-
closeAll();
111-
return;
112-
case 'all':
113-
case 'run': // These cases are now dynamically handled together
114-
db = registry.get(obj.name);
115-
if (!db) throw new Error(`Database connection "${obj.name}" not found`);
116-
const params = convertBooleansToNumbers(obj.sql.params);
117-
return executeSql(db, obj.sql.query, params);
118-
default:
119-
throw new Error('Unknown type');
120-
}
121-
} catch (err) {
122-
logger.error('SQLite error', err, obj);
123-
throw err;
124-
}
125-
});
87+
logger.silly('SQL request', JSON.stringify(obj, null, 2));
88+
try {
89+
let db;
90+
switch (obj.type) {
91+
case 'open':
92+
return openDatabase(obj.name);
93+
case 'close':
94+
db = registry.get(obj.name);
95+
if (!db) throw new Error(`Database connection "${obj.name}" not found`);
96+
db.close();
97+
registry.delete(obj.name);
98+
logger.info(`Closed and removed ${obj.name} from registry.`);
99+
return;
100+
case 'quit':
101+
closeAll();
102+
return;
103+
case 'all':
104+
case 'run': {
105+
db = registry.get(obj.name);
106+
if (!db) throw new Error(`Database connection "${obj.name}" not found`);
107+
const convertedParams = convertBooleansToNumbers(obj.sql.params);
108+
return executeSql(db, obj.sql.query, convertedParams);
109+
}
110+
default:
111+
throw new Error('Unknown type');
112+
}
113+
} catch (err) {
114+
logger.error('SQLite error', err, obj);
115+
throw err;
116+
}
117+
});

src/main/database.ts.bak

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { app, ipcMain } from 'electron';
2+
import path from 'path';
3+
import { getRxStorageFilesystemNode } from 'rxdb-premium/plugins/storage-filesystem-node';
4+
import logger from './log';
5+
import { isDevelopment } from './util';
6+
import fs from 'fs';
7+
import type { RxStorageAbstractFilesystem } from 'rxdb-premium/plugins/storage-abstract-filesystem';
8+
9+
// Create the storage adapter when the app is ready.
10+
let storage: RxStorageAbstractFilesystem;
11+
app.on('ready', async () => {
12+
try {
13+
const dbFolder = isDevelopment
14+
? path.resolve('databases')
15+
: path.resolve(app.getPath('userData'), 'wcpos_dbs');
16+
17+
// Create folder if it doesn't exist
18+
if (!fs.existsSync(dbFolder)) {
19+
try {
20+
fs.mkdirSync(dbFolder, { recursive: true });
21+
logger.info(`Created database folder: ${dbFolder}`);
22+
} catch (err) {
23+
logger.error(`Failed to create database folder: ${dbFolder}`, err);
24+
}
25+
}
26+
27+
logger.info('Initialising storage adapter');
28+
storage = getRxStorageFilesystemNode({
29+
basePath: dbFolder,
30+
inWorker: false
31+
});
32+
logger.info('Storage adapter initialised');
33+
} catch (error) {
34+
logger.error('Error initialising storage adapter:', error);
35+
}
36+
});
37+
38+
// Generic IPC handler for storage calls.
39+
ipcMain.handle('rxStorage', async (event, { methodPath, args }) => {
40+
try {
41+
if (!storage) {
42+
throw new Error('Storage not initialised');
43+
}
44+
// Resolve the methodPath (e.g. "createStorageInstance")
45+
const parts = methodPath.split('.');
46+
logger.info('Resolving method path:', parts);
47+
let target = storage;
48+
for (const part of parts) {
49+
target = target[part];
50+
if (target === undefined) {
51+
throw new Error(`Method ${methodPath} not found on storage`);
52+
}
53+
}
54+
if (typeof target !== 'function') {
55+
throw new Error(`Target ${methodPath} is not a function`);
56+
}
57+
const result = await target(...args);
58+
return result;
59+
} catch (error) {
60+
logger.error('Error in rxStorage remote call:', error);
61+
throw error;
62+
}
63+
});

src/preload.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const ipc = {
1818
// From main to render.
1919
on: [] as string[], // We'll handle dynamic channels separately
2020
// From render to main and back again.
21-
invoke: ['sqlite', 'axios'] as string[],
21+
invoke: ['sqlite', 'axios', 'rxStorage'] as string[],
2222
// From main to render, once
2323
once: [] as string[], // We'll handle dynamic channels separately
2424
},

0 commit comments

Comments
 (0)