koffi 2.5.8 → 2.5.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -99
- package/build/{2.5.8 → koffi}/darwin_arm64/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/darwin_x64/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/freebsd_arm64/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/freebsd_ia32/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/freebsd_x64/koffi.node +0 -0
- package/build/koffi/linux_arm32hf/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/linux_arm64/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/linux_ia32/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/linux_riscv64hf64/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/linux_x64/koffi.node +0 -0
- package/build/koffi/openbsd_ia32/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/openbsd_x64/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/win32_arm64/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/win32_ia32/koffi.node +0 -0
- package/build/{2.5.8 → koffi}/win32_x64/koffi.node +0 -0
- package/doc/conf.py +2 -1
- package/doc/index.rst +1 -0
- package/doc/packaging.md +71 -0
- package/doc/start.md +1 -36
- package/package.json +2 -2
- package/src/cnoke/assets/FindCNoke.cmake +16 -0
- package/src/core/libcc/libcc.cc +13 -9
- package/src/core/libcc/libcc.hh +2 -1
- package/src/index.d.ts +4 -0
- package/src/index.js +53 -24
- package/src/koffi/CMakeLists.txt +10 -0
- package/src/koffi/examples/electron-builder/README.md +11 -0
- package/src/koffi/examples/electron-builder/package.json +21 -0
- package/src/koffi/examples/electron-builder/src/app.js +20 -0
- package/src/koffi/examples/electron-builder/src/index.html +143 -0
- package/src/koffi/examples/electron-builder/src/preload.js +5 -0
- package/src/koffi/examples/electron-forge/README.md +25 -0
- package/src/koffi/examples/electron-forge/forge.config.js +43 -0
- package/src/koffi/examples/electron-forge/package.json +37 -0
- package/src/koffi/examples/electron-forge/src/index.css +7 -0
- package/src/koffi/examples/electron-forge/src/index.html +143 -0
- package/src/koffi/examples/electron-forge/src/main.js +52 -0
- package/src/koffi/examples/electron-forge/src/preload.js +5 -0
- package/src/koffi/examples/electron-forge/src/renderer.js +31 -0
- package/src/koffi/examples/electron-forge/webpack.main.config.js +11 -0
- package/src/koffi/examples/electron-forge/webpack.renderer.config.js +13 -0
- package/src/koffi/examples/electron-forge/webpack.rules.js +35 -0
- package/src/koffi/examples/node-esbuild/README.md +19 -0
- package/src/koffi/examples/node-esbuild/index.js +2 -0
- package/src/koffi/examples/node-esbuild/package.json +16 -0
- package/src/koffi/examples/nwjs/README.md +20 -0
- package/src/koffi/examples/nwjs/package.json +11 -0
- package/src/koffi/examples/nwjs/src/index.html +145 -0
- package/src/koffi/examples/nwjs/src/package.json +10 -0
- package/src/koffi/src/ffi.cc +1 -0
- package/build/2.5.8/linux_arm32hf/koffi.node +0 -0
- package/build/2.5.8/openbsd_ia32/koffi.node +0 -0
- /package/build/{2.5.8 → koffi}/win32_arm64/koffi.exp +0 -0
- /package/build/{2.5.8 → koffi}/win32_arm64/koffi.lib +0 -0
- /package/build/{2.5.8 → koffi}/win32_ia32/koffi.exp +0 -0
- /package/build/{2.5.8 → koffi}/win32_ia32/koffi.lib +0 -0
- /package/build/{2.5.8 → koffi}/win32_x64/koffi.exp +0 -0
- /package/build/{2.5.8 → koffi}/win32_x64/koffi.lib +0 -0
package/src/index.js
CHANGED
|
@@ -21,14 +21,14 @@
|
|
|
21
21
|
|
|
22
22
|
'use strict';
|
|
23
23
|
|
|
24
|
-
const cnoke = require('./cnoke/src/index.js');
|
|
25
24
|
const util = require('util');
|
|
26
25
|
const fs = require('fs');
|
|
26
|
+
const { get_napi_version, determine_arch } = require('./cnoke/src/tools.js');
|
|
27
27
|
const pkg = require('../package.json');
|
|
28
28
|
|
|
29
29
|
if (process.versions.napi == null || process.versions.napi < pkg.cnoke.napi) {
|
|
30
30
|
let major = parseInt(process.versions.node, 10);
|
|
31
|
-
let required =
|
|
31
|
+
let required = get_napi_version(pkg.cnoke.napi, major);
|
|
32
32
|
|
|
33
33
|
if (required != null) {
|
|
34
34
|
throw new Error(`Project ${pkg.name} requires Node >= ${required} in the Node ${major}.x branch (N-API >= ${pkg.cnoke.napi})`);
|
|
@@ -37,33 +37,62 @@ if (process.versions.napi == null || process.versions.napi < pkg.cnoke.napi) {
|
|
|
37
37
|
}
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
-
let arch =
|
|
40
|
+
let arch = determine_arch();
|
|
41
|
+
let triplet = `${process.platform}_${arch}`;
|
|
41
42
|
|
|
42
|
-
let
|
|
43
|
-
__dirname + `/../build/${pkg.version}/${process.platform}_${arch}/koffi.node`,
|
|
44
|
-
__dirname + `/build/koffi/${pkg.version}/${process.platform}_${arch}/koffi.node`,
|
|
45
|
-
__dirname + `/koffi/${pkg.version}/${process.platform}_${arch}/koffi.node`,
|
|
46
|
-
__dirname + `/../build/${pkg.version}/koffi_${process.platform}_${arch}/koffi.node`,
|
|
47
|
-
__dirname + `/build/koffi/${pkg.version}/koffi_${process.platform}_${arch}/koffi.node`,
|
|
48
|
-
__dirname + `/koffi/${pkg.version}/koffi_${process.platform}_${arch}/koffi.node`
|
|
49
|
-
];
|
|
43
|
+
let native = null;
|
|
50
44
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
45
|
+
// Try an explicit list with static strings to help bundlers
|
|
46
|
+
try {
|
|
47
|
+
switch (triplet) {
|
|
48
|
+
case 'darwin_arm64': { native = require('../build/koffi/darwin_arm64/koffi.node'); } break;
|
|
49
|
+
case 'darwin_x64': { native = require('../build/koffi/darwin_x64/koffi.node'); } break;
|
|
50
|
+
case 'freebsd_arm46': { native = require('../build/koffi/freebsd_arm46/koffi.node'); } break;
|
|
51
|
+
case 'freebsd_ia32': { native = require('../build/koffi/freebsd_ia32/koffi.node'); } break;
|
|
52
|
+
case 'freebsd_x64': { native = require('../build/koffi/freebsd_x64/koffi.node'); } break;
|
|
53
|
+
case 'linux_arm32hf': { native = require('../build/koffi/linux_arm32hf/koffi.node'); } break;
|
|
54
|
+
case 'linux_arm64': { native = require('../build/koffi/linux_arm64/koffi.node'); } break;
|
|
55
|
+
case 'linux_ia32': { native = require('../build/koffi/linux_ia32/koffi.node'); } break;
|
|
56
|
+
case 'linux_risc64hf64': { native = require('../build/koffi/linux_risc64hf64/koffi.node'); } break;
|
|
57
|
+
case 'linux_x64': { native = require('../build/koffi/linux_x64/koffi.node'); } break;
|
|
58
|
+
case 'openbsd_ia32': { native = require('../build/koffi/openbsd_ia32/koffi.node'); } break;
|
|
59
|
+
case 'openbsd_x64': { native = require('../build/koffi/openbsd_x64/koffi.node'); } break;
|
|
60
|
+
case 'win32_arm64': { native = require('../build/koffi/win32_arm64/koffi.node'); } break;
|
|
61
|
+
case 'win32_ia32': { native = require('../build/koffi/win32_ia32/koffi.node'); } break;
|
|
62
|
+
case 'win32_x64': { native = require('../build/koffi/win32_x64/koffi.node'); } break;
|
|
63
|
+
}
|
|
64
|
+
} catch (err) {
|
|
65
|
+
// Go on!
|
|
60
66
|
}
|
|
61
67
|
|
|
62
|
-
|
|
63
|
-
if (
|
|
64
|
-
|
|
68
|
+
// And now, search everywhere we know
|
|
69
|
+
if (native == null) {
|
|
70
|
+
let names = [
|
|
71
|
+
`/koffi/${process.platform}_${arch}/koffi.node`,
|
|
72
|
+
`/node_modules/koffi/build/koffi/${process.platform}_${arch}/koffi.node`
|
|
73
|
+
];
|
|
74
|
+
|
|
75
|
+
for (let name of names) {
|
|
76
|
+
if (fs.existsSync(__dirname + name)) {
|
|
77
|
+
native = require(__dirname + name);
|
|
78
|
+
break;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
65
81
|
|
|
66
|
-
|
|
82
|
+
if (native == null && process.resourcesPath != null) {
|
|
83
|
+
for (let name of names) {
|
|
84
|
+
if (fs.existsSync(process.resourcesPath + name)) {
|
|
85
|
+
native = require(process.resourcesPath + name);
|
|
86
|
+
break;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (native == null)
|
|
93
|
+
throw new Error('Cannot find the native Koffi module; did you bundle it correctly?');
|
|
94
|
+
if (native.version != pkg.version)
|
|
95
|
+
throw new Error('Mismatched native Koffi modules');
|
|
67
96
|
|
|
68
97
|
module.exports = {
|
|
69
98
|
...native,
|
package/src/koffi/CMakeLists.txt
CHANGED
|
@@ -47,6 +47,16 @@ endif()
|
|
|
47
47
|
|
|
48
48
|
# ---- Koffi ----
|
|
49
49
|
|
|
50
|
+
if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/package.json)
|
|
51
|
+
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/package.json PKG)
|
|
52
|
+
else()
|
|
53
|
+
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/../../package.json PKG)
|
|
54
|
+
endif()
|
|
55
|
+
string(REGEX MATCH "\"version\": \"([^\"]+)\"" XX "${PKG}")
|
|
56
|
+
set(KOFFI_VERSION ${CMAKE_MATCH_1})
|
|
57
|
+
|
|
58
|
+
set_source_files_properties(src/ffi.cc PROPERTIES COMPILE_DEFINITIONS VERSION=${KOFFI_VERSION})
|
|
59
|
+
|
|
50
60
|
set(KOFFI_SRC
|
|
51
61
|
src/call.cc
|
|
52
62
|
src/ffi.cc
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
This is a simple example shows:
|
|
2
|
+
|
|
3
|
+
- How to communicate with Koffi from a renderer window
|
|
4
|
+
- How to use electron-builder with an application that uses Koffi
|
|
5
|
+
|
|
6
|
+
Use the following commands to package the app for your system:
|
|
7
|
+
|
|
8
|
+
```sh
|
|
9
|
+
npm install
|
|
10
|
+
npm run dist
|
|
11
|
+
```
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "KoffiConfig",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Koffi Electron Example",
|
|
5
|
+
"main": "src/app.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "electron .",
|
|
8
|
+
"pack": "electron-builder --dir",
|
|
9
|
+
"dist": "electron-builder"
|
|
10
|
+
},
|
|
11
|
+
"author": "Niels Martignène <niels.martignene@protonmail.com>",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"electron": "^25.3.2",
|
|
15
|
+
"electron-builder": "^24.6.3",
|
|
16
|
+
"esbuild": "^0.18.17"
|
|
17
|
+
},
|
|
18
|
+
"dependencies": {
|
|
19
|
+
"koffi": "^2.5.9"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
const { app, BrowserWindow, ipcMain } = require('electron');
|
|
2
|
+
const koffi = require('koffi');
|
|
3
|
+
|
|
4
|
+
app.whenReady().then(() => {
|
|
5
|
+
ipcMain.handle('koffi:config', (e, ...args) => koffi.config(...args));
|
|
6
|
+
|
|
7
|
+
createWindow();
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
function createWindow() {
|
|
11
|
+
const win = new BrowserWindow({
|
|
12
|
+
width: 800,
|
|
13
|
+
height: 600,
|
|
14
|
+
webPreferences: {
|
|
15
|
+
preload: __dirname + '/preload.js'
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
win.loadFile(__dirname + '/index.html');
|
|
20
|
+
};
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Koffi Configuration</title>
|
|
6
|
+
|
|
7
|
+
<style>
|
|
8
|
+
html {
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
body {
|
|
12
|
+
font-family: 'Open Sans', sans-serif;
|
|
13
|
+
display: flex;
|
|
14
|
+
min-height: calc(100% - 17px);
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
font-size: 14px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#error {
|
|
21
|
+
position: fixed;
|
|
22
|
+
top: 50px;
|
|
23
|
+
left: calc(50% - 200px);
|
|
24
|
+
width: 400px;
|
|
25
|
+
padding: 8px;
|
|
26
|
+
background: #db0a0a;
|
|
27
|
+
color: white;
|
|
28
|
+
box-shadow: 1px 1px rgba(0, 0, 0, 0.5);
|
|
29
|
+
text-align: center;
|
|
30
|
+
}
|
|
31
|
+
#error:empty { display: none; }
|
|
32
|
+
|
|
33
|
+
#config {
|
|
34
|
+
background: #f8f8f8;
|
|
35
|
+
border-radius: 8px;
|
|
36
|
+
padding: 1em;
|
|
37
|
+
font-size: 1.2em;
|
|
38
|
+
}
|
|
39
|
+
form {
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
gap: 0.5em;
|
|
43
|
+
}
|
|
44
|
+
label {
|
|
45
|
+
display: flex;
|
|
46
|
+
gap: 12px;
|
|
47
|
+
}
|
|
48
|
+
label > span { width: 200px; }
|
|
49
|
+
label > :not(span) { flex: 1; }
|
|
50
|
+
button {
|
|
51
|
+
margin-top: 1em;
|
|
52
|
+
background: white;
|
|
53
|
+
border: white;
|
|
54
|
+
border-radius: 6px;
|
|
55
|
+
padding: 6px;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
}
|
|
58
|
+
button:hover { background: #ededed; }
|
|
59
|
+
</style>
|
|
60
|
+
</head>
|
|
61
|
+
|
|
62
|
+
<body>
|
|
63
|
+
<div id="error"></div>
|
|
64
|
+
<div id="config"></div>
|
|
65
|
+
|
|
66
|
+
<script>
|
|
67
|
+
update();
|
|
68
|
+
|
|
69
|
+
async function update() {
|
|
70
|
+
let config = await window.koffi.config();
|
|
71
|
+
|
|
72
|
+
let container = document.querySelector('#config');
|
|
73
|
+
let form = document.createElement('form');
|
|
74
|
+
|
|
75
|
+
form.addEventListener('submit', e => { e.preventDefault(); apply(e.target.elements); });
|
|
76
|
+
|
|
77
|
+
for (let key in config) {
|
|
78
|
+
let value = config[key];
|
|
79
|
+
|
|
80
|
+
if (typeof value != 'number')
|
|
81
|
+
continue;
|
|
82
|
+
|
|
83
|
+
let label = document.createElement('label');
|
|
84
|
+
let span = document.createElement('span');
|
|
85
|
+
let input = document.createElement('input');
|
|
86
|
+
|
|
87
|
+
span.textContent = key;
|
|
88
|
+
input.name = key;
|
|
89
|
+
input.type = 'number';
|
|
90
|
+
input.value = config[key];
|
|
91
|
+
|
|
92
|
+
label.appendChild(span);
|
|
93
|
+
label.appendChild(input);
|
|
94
|
+
form.appendChild(label);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let button = document.createElement('button');
|
|
98
|
+
button.textContent = 'Modifier';
|
|
99
|
+
button.type = 'submit';
|
|
100
|
+
|
|
101
|
+
form.appendChild(button);
|
|
102
|
+
|
|
103
|
+
window.requestAnimationFrame(() => {
|
|
104
|
+
container.innerHTML = '';
|
|
105
|
+
container.appendChild(form);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function apply(elements) {
|
|
110
|
+
let config = await koffi.config();
|
|
111
|
+
|
|
112
|
+
for (let key in elements) {
|
|
113
|
+
if (!config.hasOwnProperty(key))
|
|
114
|
+
continue;
|
|
115
|
+
|
|
116
|
+
let value = elements[key].valueAsNumber;
|
|
117
|
+
|
|
118
|
+
if (typeof value == 'number')
|
|
119
|
+
config[key] = value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
await koffi.config(config);
|
|
124
|
+
} catch (err) {
|
|
125
|
+
console.error(err);
|
|
126
|
+
flashError(err.message);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
update();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function flashError(msg) {
|
|
133
|
+
let div = document.querySelector('#error');
|
|
134
|
+
|
|
135
|
+
if (flashError.timer != null)
|
|
136
|
+
clearTimeout(flashError.timer);
|
|
137
|
+
flashError.timer = setTimeout(() => { div.textContent = '' }, 4000);
|
|
138
|
+
|
|
139
|
+
div.textContent = msg;
|
|
140
|
+
}
|
|
141
|
+
</script>
|
|
142
|
+
</body>
|
|
143
|
+
</html>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
This is a simple example based on electron-forge coupled with webpack, and using Koffi.
|
|
2
|
+
|
|
3
|
+
The initial structure was generated with the following command:
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
npm init electron-app@latest my-app -- --template=webpack
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
To run the app, execute the following:
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
cd examples/electron-forge
|
|
13
|
+
npm install
|
|
14
|
+
npm start
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
You can also use electron-forge to package the app directly:
|
|
18
|
+
|
|
19
|
+
```sh
|
|
20
|
+
cd examples/electron-forge
|
|
21
|
+
npm install
|
|
22
|
+
npm run make
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Things should just work :)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
module.exports = {
|
|
2
|
+
packagerConfig: {
|
|
3
|
+
asar: true,
|
|
4
|
+
},
|
|
5
|
+
rebuildConfig: {},
|
|
6
|
+
makers: [
|
|
7
|
+
{
|
|
8
|
+
name: '@electron-forge/maker-squirrel',
|
|
9
|
+
config: {},
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
name: '@electron-forge/maker-zip',
|
|
13
|
+
config: {},
|
|
14
|
+
}
|
|
15
|
+
],
|
|
16
|
+
plugins: [
|
|
17
|
+
{
|
|
18
|
+
name: '@electron-forge/plugin-auto-unpack-natives',
|
|
19
|
+
config: {},
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
name: '@electron-forge/plugin-webpack',
|
|
23
|
+
config: {
|
|
24
|
+
mainConfig: './webpack.main.config.js',
|
|
25
|
+
renderer: {
|
|
26
|
+
config: './webpack.renderer.config.js',
|
|
27
|
+
entryPoints: [
|
|
28
|
+
{
|
|
29
|
+
html: './src/index.html',
|
|
30
|
+
js: './src/renderer.js',
|
|
31
|
+
name: 'main_window',
|
|
32
|
+
preload: {
|
|
33
|
+
js: './src/preload.js',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
"port": 3001,
|
|
39
|
+
"loggerPort": 9001
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
],
|
|
43
|
+
};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "KoffiConfig",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Koffi Electron Example",
|
|
5
|
+
"main": ".webpack/main",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"start": "electron-forge start",
|
|
8
|
+
"package": "electron-forge package",
|
|
9
|
+
"make": "electron-forge make",
|
|
10
|
+
"publish": "electron-forge publish",
|
|
11
|
+
"lint": "echo \"No linting configured\""
|
|
12
|
+
},
|
|
13
|
+
"keywords": [],
|
|
14
|
+
"author": {
|
|
15
|
+
"name": "Niels Martignène",
|
|
16
|
+
"email": "niels.martignene@protonmail.com"
|
|
17
|
+
},
|
|
18
|
+
"license": "MIT",
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@electron-forge/cli": "^6.2.1",
|
|
21
|
+
"@electron-forge/maker-deb": "^6.2.1",
|
|
22
|
+
"@electron-forge/maker-rpm": "^6.2.1",
|
|
23
|
+
"@electron-forge/maker-squirrel": "^6.2.1",
|
|
24
|
+
"@electron-forge/maker-zip": "^6.2.1",
|
|
25
|
+
"@electron-forge/plugin-auto-unpack-natives": "^6.2.1",
|
|
26
|
+
"@electron-forge/plugin-webpack": "^6.2.1",
|
|
27
|
+
"@vercel/webpack-asset-relocator-loader": "^1.7.3",
|
|
28
|
+
"css-loader": "^6.8.1",
|
|
29
|
+
"electron": "25.3.2",
|
|
30
|
+
"node-loader": "^2.0.0",
|
|
31
|
+
"style-loader": "^3.3.3"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"electron-squirrel-startup": "^1.0.0",
|
|
35
|
+
"koffi": "^2.5.9"
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<title>Koffi Configuration</title>
|
|
6
|
+
|
|
7
|
+
<style>
|
|
8
|
+
html {
|
|
9
|
+
height: 100%;
|
|
10
|
+
}
|
|
11
|
+
body {
|
|
12
|
+
font-family: 'Open Sans', sans-serif;
|
|
13
|
+
display: flex;
|
|
14
|
+
min-height: calc(100% - 17px);
|
|
15
|
+
align-items: center;
|
|
16
|
+
justify-content: center;
|
|
17
|
+
font-size: 14px;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#error {
|
|
21
|
+
position: fixed;
|
|
22
|
+
top: 50px;
|
|
23
|
+
left: calc(50% - 200px);
|
|
24
|
+
width: 400px;
|
|
25
|
+
padding: 8px;
|
|
26
|
+
background: #db0a0a;
|
|
27
|
+
color: white;
|
|
28
|
+
box-shadow: 1px 1px rgba(0, 0, 0, 0.5);
|
|
29
|
+
text-align: center;
|
|
30
|
+
}
|
|
31
|
+
#error:empty { display: none; }
|
|
32
|
+
|
|
33
|
+
#config {
|
|
34
|
+
background: #f8f8f8;
|
|
35
|
+
border-radius: 8px;
|
|
36
|
+
padding: 1em;
|
|
37
|
+
font-size: 1.2em;
|
|
38
|
+
}
|
|
39
|
+
form {
|
|
40
|
+
display: flex;
|
|
41
|
+
flex-direction: column;
|
|
42
|
+
gap: 0.5em;
|
|
43
|
+
}
|
|
44
|
+
label {
|
|
45
|
+
display: flex;
|
|
46
|
+
gap: 12px;
|
|
47
|
+
}
|
|
48
|
+
label > span { width: 200px; }
|
|
49
|
+
label > :not(span) { flex: 1; }
|
|
50
|
+
button {
|
|
51
|
+
margin-top: 1em;
|
|
52
|
+
background: white;
|
|
53
|
+
border: white;
|
|
54
|
+
border-radius: 6px;
|
|
55
|
+
padding: 6px;
|
|
56
|
+
cursor: pointer;
|
|
57
|
+
}
|
|
58
|
+
button:hover { background: #ededed; }
|
|
59
|
+
</style>
|
|
60
|
+
</head>
|
|
61
|
+
|
|
62
|
+
<body>
|
|
63
|
+
<div id="error"></div>
|
|
64
|
+
<div id="config"></div>
|
|
65
|
+
|
|
66
|
+
<script>
|
|
67
|
+
update();
|
|
68
|
+
|
|
69
|
+
async function update() {
|
|
70
|
+
let config = await window.koffi.config();
|
|
71
|
+
|
|
72
|
+
let container = document.querySelector('#config');
|
|
73
|
+
let form = document.createElement('form');
|
|
74
|
+
|
|
75
|
+
form.addEventListener('submit', e => { e.preventDefault(); apply(e.target.elements); });
|
|
76
|
+
|
|
77
|
+
for (let key in config) {
|
|
78
|
+
let value = config[key];
|
|
79
|
+
|
|
80
|
+
if (typeof value != 'number')
|
|
81
|
+
continue;
|
|
82
|
+
|
|
83
|
+
let label = document.createElement('label');
|
|
84
|
+
let span = document.createElement('span');
|
|
85
|
+
let input = document.createElement('input');
|
|
86
|
+
|
|
87
|
+
span.textContent = key;
|
|
88
|
+
input.name = key;
|
|
89
|
+
input.type = 'number';
|
|
90
|
+
input.value = config[key];
|
|
91
|
+
|
|
92
|
+
label.appendChild(span);
|
|
93
|
+
label.appendChild(input);
|
|
94
|
+
form.appendChild(label);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let button = document.createElement('button');
|
|
98
|
+
button.textContent = 'Modifier';
|
|
99
|
+
button.type = 'submit';
|
|
100
|
+
|
|
101
|
+
form.appendChild(button);
|
|
102
|
+
|
|
103
|
+
window.requestAnimationFrame(() => {
|
|
104
|
+
container.innerHTML = '';
|
|
105
|
+
container.appendChild(form);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
async function apply(elements) {
|
|
110
|
+
let config = await koffi.config();
|
|
111
|
+
|
|
112
|
+
for (let key in elements) {
|
|
113
|
+
if (!config.hasOwnProperty(key))
|
|
114
|
+
continue;
|
|
115
|
+
|
|
116
|
+
let value = elements[key].valueAsNumber;
|
|
117
|
+
|
|
118
|
+
if (typeof value == 'number')
|
|
119
|
+
config[key] = value;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
try {
|
|
123
|
+
await koffi.config(config);
|
|
124
|
+
} catch (err) {
|
|
125
|
+
console.error(err);
|
|
126
|
+
flashError(err.message);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
update();
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function flashError(msg) {
|
|
133
|
+
let div = document.querySelector('#error');
|
|
134
|
+
|
|
135
|
+
if (flashError.timer != null)
|
|
136
|
+
clearTimeout(flashError.timer);
|
|
137
|
+
flashError.timer = setTimeout(() => { div.textContent = '' }, 4000);
|
|
138
|
+
|
|
139
|
+
div.textContent = msg;
|
|
140
|
+
}
|
|
141
|
+
</script>
|
|
142
|
+
</body>
|
|
143
|
+
</html>
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
const { app, BrowserWindow, ipcMain } = require('electron');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const koffi = require('koffi');
|
|
4
|
+
|
|
5
|
+
// Handle creating/removing shortcuts on Windows when installing/uninstalling.
|
|
6
|
+
if (require('electron-squirrel-startup')) {
|
|
7
|
+
app.quit();
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
const createWindow = () => {
|
|
11
|
+
// Create the browser window.
|
|
12
|
+
const mainWindow = new BrowserWindow({
|
|
13
|
+
width: 800,
|
|
14
|
+
height: 600,
|
|
15
|
+
webPreferences: {
|
|
16
|
+
preload: MAIN_WINDOW_PRELOAD_WEBPACK_ENTRY,
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
// and load the index.html of the app.
|
|
21
|
+
mainWindow.loadURL(MAIN_WINDOW_WEBPACK_ENTRY);
|
|
22
|
+
|
|
23
|
+
// Open the DevTools.
|
|
24
|
+
// mainWindow.webContents.openDevTools();
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
// This method will be called when Electron has finished
|
|
28
|
+
// initialization and is ready to create browser windows.
|
|
29
|
+
// Some APIs can only be used after this event occurs.
|
|
30
|
+
app.on('ready', createWindow);
|
|
31
|
+
|
|
32
|
+
// Quit when all windows are closed, except on macOS. There, it's common
|
|
33
|
+
// for applications and their menu bar to stay active until the user quits
|
|
34
|
+
// explicitly with Cmd + Q.
|
|
35
|
+
app.on('window-all-closed', () => {
|
|
36
|
+
if (process.platform !== 'darwin') {
|
|
37
|
+
app.quit();
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
app.on('activate', () => {
|
|
42
|
+
// On OS X it's common to re-create a window in the app when the
|
|
43
|
+
// dock icon is clicked and there are no other windows open.
|
|
44
|
+
if (BrowserWindow.getAllWindows().length === 0) {
|
|
45
|
+
createWindow();
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
// In this file you can include the rest of your app's specific main process
|
|
50
|
+
// code. You can also put them in separate files and import them here.
|
|
51
|
+
|
|
52
|
+
ipcMain.handle('koffi:config', (e, ...args) => koffi.config(...args));
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file will automatically be loaded by webpack and run in the "renderer" context.
|
|
3
|
+
* To learn more about the differences between the "main" and the "renderer" context in
|
|
4
|
+
* Electron, visit:
|
|
5
|
+
*
|
|
6
|
+
* https://electronjs.org/docs/tutorial/application-architecture#main-and-renderer-processes
|
|
7
|
+
*
|
|
8
|
+
* By default, Node.js integration in this file is disabled. When enabling Node.js integration
|
|
9
|
+
* in a renderer process, please be aware of potential security implications. You can read
|
|
10
|
+
* more about security risks here:
|
|
11
|
+
*
|
|
12
|
+
* https://electronjs.org/docs/tutorial/security
|
|
13
|
+
*
|
|
14
|
+
* To enable Node.js integration in this file, open up `main.js` and enable the `nodeIntegration`
|
|
15
|
+
* flag:
|
|
16
|
+
*
|
|
17
|
+
* ```
|
|
18
|
+
* // Create the browser window.
|
|
19
|
+
* mainWindow = new BrowserWindow({
|
|
20
|
+
* width: 800,
|
|
21
|
+
* height: 600,
|
|
22
|
+
* webPreferences: {
|
|
23
|
+
* nodeIntegration: true
|
|
24
|
+
* }
|
|
25
|
+
* });
|
|
26
|
+
* ```
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import './index.css';
|
|
30
|
+
|
|
31
|
+
console.log('👋 This message is being logged by "renderer.js", included via webpack');
|