@superdangerous/app-framework 4.9.0
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/LICENSE +21 -0
- package/README.md +652 -0
- package/dist/api/logsRouter.d.ts +20 -0
- package/dist/api/logsRouter.d.ts.map +1 -0
- package/dist/api/logsRouter.js +515 -0
- package/dist/api/logsRouter.js.map +1 -0
- package/dist/cli/dev-server.d.ts +7 -0
- package/dist/cli/dev-server.d.ts.map +1 -0
- package/dist/cli/dev-server.js +640 -0
- package/dist/cli/dev-server.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +26 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/core/StandardServer.d.ts +129 -0
- package/dist/core/StandardServer.d.ts.map +1 -0
- package/dist/core/StandardServer.js +453 -0
- package/dist/core/StandardServer.js.map +1 -0
- package/dist/core/apiResponse.d.ts +69 -0
- package/dist/core/apiResponse.d.ts.map +1 -0
- package/dist/core/apiResponse.js +127 -0
- package/dist/core/apiResponse.js.map +1 -0
- package/dist/core/healthCheck.d.ts +160 -0
- package/dist/core/healthCheck.d.ts.map +1 -0
- package/dist/core/healthCheck.js +398 -0
- package/dist/core/healthCheck.js.map +1 -0
- package/dist/core/index.d.ts +40 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +40 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/logger.d.ts +117 -0
- package/dist/core/logger.d.ts.map +1 -0
- package/dist/core/logger.js +826 -0
- package/dist/core/logger.js.map +1 -0
- package/dist/core/portUtils.d.ts +71 -0
- package/dist/core/portUtils.d.ts.map +1 -0
- package/dist/core/portUtils.js +240 -0
- package/dist/core/portUtils.js.map +1 -0
- package/dist/core/storageService.d.ts +119 -0
- package/dist/core/storageService.d.ts.map +1 -0
- package/dist/core/storageService.js +405 -0
- package/dist/core/storageService.js.map +1 -0
- package/dist/desktop/bundler.d.ts +40 -0
- package/dist/desktop/bundler.d.ts.map +1 -0
- package/dist/desktop/bundler.js +176 -0
- package/dist/desktop/bundler.js.map +1 -0
- package/dist/desktop/index.d.ts +25 -0
- package/dist/desktop/index.d.ts.map +1 -0
- package/dist/desktop/index.js +15 -0
- package/dist/desktop/index.js.map +1 -0
- package/dist/desktop/native-modules.d.ts +66 -0
- package/dist/desktop/native-modules.d.ts.map +1 -0
- package/dist/desktop/native-modules.js +200 -0
- package/dist/desktop/native-modules.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/logging/LogCategories.d.ts +87 -0
- package/dist/logging/LogCategories.d.ts.map +1 -0
- package/dist/logging/LogCategories.js +205 -0
- package/dist/logging/LogCategories.js.map +1 -0
- package/dist/middleware/aiErrorHandler.d.ts +31 -0
- package/dist/middleware/aiErrorHandler.d.ts.map +1 -0
- package/dist/middleware/aiErrorHandler.js +181 -0
- package/dist/middleware/aiErrorHandler.js.map +1 -0
- package/dist/middleware/auth.d.ts +101 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +230 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/cors.d.ts +56 -0
- package/dist/middleware/cors.d.ts.map +1 -0
- package/dist/middleware/cors.js +123 -0
- package/dist/middleware/cors.js.map +1 -0
- package/dist/middleware/errorHandler.d.ts +13 -0
- package/dist/middleware/errorHandler.d.ts.map +1 -0
- package/dist/middleware/errorHandler.js +85 -0
- package/dist/middleware/errorHandler.js.map +1 -0
- package/dist/middleware/fileUpload.d.ts +62 -0
- package/dist/middleware/fileUpload.d.ts.map +1 -0
- package/dist/middleware/fileUpload.js +175 -0
- package/dist/middleware/fileUpload.js.map +1 -0
- package/dist/middleware/health.d.ts +48 -0
- package/dist/middleware/health.d.ts.map +1 -0
- package/dist/middleware/health.js +143 -0
- package/dist/middleware/health.js.map +1 -0
- package/dist/middleware/index.d.ts +20 -0
- package/dist/middleware/index.d.ts.map +1 -0
- package/dist/middleware/index.js +18 -0
- package/dist/middleware/index.js.map +1 -0
- package/dist/middleware/openapi.d.ts +64 -0
- package/dist/middleware/openapi.d.ts.map +1 -0
- package/dist/middleware/openapi.js +258 -0
- package/dist/middleware/openapi.js.map +1 -0
- package/dist/middleware/requestLogging.d.ts +22 -0
- package/dist/middleware/requestLogging.d.ts.map +1 -0
- package/dist/middleware/requestLogging.js +61 -0
- package/dist/middleware/requestLogging.js.map +1 -0
- package/dist/middleware/session.d.ts +84 -0
- package/dist/middleware/session.d.ts.map +1 -0
- package/dist/middleware/session.js +189 -0
- package/dist/middleware/session.js.map +1 -0
- package/dist/middleware/validation.d.ts +1337 -0
- package/dist/middleware/validation.d.ts.map +1 -0
- package/dist/middleware/validation.js +483 -0
- package/dist/middleware/validation.js.map +1 -0
- package/dist/services/aiService.d.ts +180 -0
- package/dist/services/aiService.d.ts.map +1 -0
- package/dist/services/aiService.js +547 -0
- package/dist/services/aiService.js.map +1 -0
- package/dist/services/conversationStorage.d.ts +38 -0
- package/dist/services/conversationStorage.d.ts.map +1 -0
- package/dist/services/conversationStorage.js +158 -0
- package/dist/services/conversationStorage.js.map +1 -0
- package/dist/services/crossPlatformBuffer.d.ts +84 -0
- package/dist/services/crossPlatformBuffer.d.ts.map +1 -0
- package/dist/services/crossPlatformBuffer.js +246 -0
- package/dist/services/crossPlatformBuffer.js.map +1 -0
- package/dist/services/index.d.ts +17 -0
- package/dist/services/index.d.ts.map +1 -0
- package/dist/services/index.js +18 -0
- package/dist/services/index.js.map +1 -0
- package/dist/services/networkService.d.ts +81 -0
- package/dist/services/networkService.d.ts.map +1 -0
- package/dist/services/networkService.js +268 -0
- package/dist/services/networkService.js.map +1 -0
- package/dist/services/queueService.d.ts +112 -0
- package/dist/services/queueService.d.ts.map +1 -0
- package/dist/services/queueService.js +338 -0
- package/dist/services/queueService.js.map +1 -0
- package/dist/services/settingsService.d.ts +135 -0
- package/dist/services/settingsService.d.ts.map +1 -0
- package/dist/services/settingsService.js +425 -0
- package/dist/services/settingsService.js.map +1 -0
- package/dist/services/systemMonitor.d.ts +208 -0
- package/dist/services/systemMonitor.d.ts.map +1 -0
- package/dist/services/systemMonitor.js +693 -0
- package/dist/services/systemMonitor.js.map +1 -0
- package/dist/services/updateService.d.ts +78 -0
- package/dist/services/updateService.d.ts.map +1 -0
- package/dist/services/updateService.js +252 -0
- package/dist/services/updateService.js.map +1 -0
- package/dist/services/websocketEvents.d.ts +372 -0
- package/dist/services/websocketEvents.d.ts.map +1 -0
- package/dist/services/websocketEvents.js +338 -0
- package/dist/services/websocketEvents.js.map +1 -0
- package/dist/services/websocketServer.d.ts +80 -0
- package/dist/services/websocketServer.d.ts.map +1 -0
- package/dist/services/websocketServer.js +299 -0
- package/dist/services/websocketServer.js.map +1 -0
- package/dist/settings/SettingsSchema.d.ts +151 -0
- package/dist/settings/SettingsSchema.d.ts.map +1 -0
- package/dist/settings/SettingsSchema.js +424 -0
- package/dist/settings/SettingsSchema.js.map +1 -0
- package/dist/testing/TestServer.d.ts +69 -0
- package/dist/testing/TestServer.d.ts.map +1 -0
- package/dist/testing/TestServer.js +250 -0
- package/dist/testing/TestServer.js.map +1 -0
- package/dist/types/index.d.ts +137 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/appPaths.d.ts +74 -0
- package/dist/utils/appPaths.d.ts.map +1 -0
- package/dist/utils/appPaths.js +162 -0
- package/dist/utils/appPaths.js.map +1 -0
- package/dist/utils/fs-utils.d.ts +50 -0
- package/dist/utils/fs-utils.d.ts.map +1 -0
- package/dist/utils/fs-utils.js +114 -0
- package/dist/utils/fs-utils.js.map +1 -0
- package/dist/utils/index.d.ts +12 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +10 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/standardConfig.d.ts +61 -0
- package/dist/utils/standardConfig.d.ts.map +1 -0
- package/dist/utils/standardConfig.js +109 -0
- package/dist/utils/standardConfig.js.map +1 -0
- package/dist/utils/startupBanner.d.ts +34 -0
- package/dist/utils/startupBanner.d.ts.map +1 -0
- package/dist/utils/startupBanner.js +169 -0
- package/dist/utils/startupBanner.js.map +1 -0
- package/dist/utils/startupLogger.d.ts +45 -0
- package/dist/utils/startupLogger.d.ts.map +1 -0
- package/dist/utils/startupLogger.js +200 -0
- package/dist/utils/startupLogger.js.map +1 -0
- package/package.json +151 -0
- package/src/api/logsRouter.ts +600 -0
- package/src/cli/dev-server.ts +803 -0
- package/src/cli/index.ts +31 -0
- package/src/core/StandardServer.ts +587 -0
- package/src/core/apiResponse.ts +202 -0
- package/src/core/healthCheck.ts +565 -0
- package/src/core/index.ts +80 -0
- package/src/core/logger.ts +1092 -0
- package/src/core/portUtils.ts +319 -0
- package/src/core/storageService.ts +595 -0
- package/src/desktop/bundler.ts +271 -0
- package/src/desktop/index.ts +18 -0
- package/src/desktop/native-modules.ts +289 -0
- package/src/index.ts +142 -0
- package/src/logging/LogCategories.ts +302 -0
- package/src/middleware/aiErrorHandler.ts +278 -0
- package/src/middleware/auth.ts +329 -0
- package/src/middleware/cors.ts +187 -0
- package/src/middleware/errorHandler.ts +103 -0
- package/src/middleware/fileUpload.ts +252 -0
- package/src/middleware/health.ts +206 -0
- package/src/middleware/index.ts +71 -0
- package/src/middleware/openapi.ts +305 -0
- package/src/middleware/requestLogging.ts +92 -0
- package/src/middleware/session.ts +238 -0
- package/src/middleware/validation.ts +603 -0
- package/src/services/aiService.ts +789 -0
- package/src/services/conversationStorage.ts +232 -0
- package/src/services/crossPlatformBuffer.ts +341 -0
- package/src/services/index.ts +47 -0
- package/src/services/networkService.ts +351 -0
- package/src/services/queueService.ts +446 -0
- package/src/services/settingsService.ts +549 -0
- package/src/services/systemMonitor.ts +936 -0
- package/src/services/updateService.ts +334 -0
- package/src/services/websocketEvents.ts +409 -0
- package/src/services/websocketServer.ts +394 -0
- package/src/settings/SettingsSchema.ts +664 -0
- package/src/testing/TestServer.ts +312 -0
- package/src/types/index.ts +154 -0
- package/src/utils/appPaths.ts +196 -0
- package/src/utils/fs-utils.ts +130 -0
- package/src/utils/index.ts +15 -0
- package/src/utils/standardConfig.ts +178 -0
- package/src/utils/startupBanner.ts +287 -0
- package/src/utils/startupLogger.ts +268 -0
- package/ui/dist/index.d.mts +1221 -0
- package/ui/dist/index.d.ts +1221 -0
- package/ui/dist/index.js +73 -0
- package/ui/dist/index.js.map +1 -0
- package/ui/dist/index.mjs +73 -0
- package/ui/dist/index.mjs.map +1 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Desktop Bundler Module
|
|
3
|
+
* Handles bundling Node.js backends for Electron desktop applications
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as esbuild from "esbuild";
|
|
7
|
+
import {
|
|
8
|
+
ensureDir,
|
|
9
|
+
writeFile,
|
|
10
|
+
stat,
|
|
11
|
+
copy,
|
|
12
|
+
move,
|
|
13
|
+
remove,
|
|
14
|
+
writeJson,
|
|
15
|
+
} from "../utils/fs-utils.js";
|
|
16
|
+
import path from "path";
|
|
17
|
+
import { execSync } from "child_process";
|
|
18
|
+
import { createLogger } from "../core/index.js";
|
|
19
|
+
import {
|
|
20
|
+
detectNativeModules,
|
|
21
|
+
copyNativeModules,
|
|
22
|
+
createNativeModuleLoader,
|
|
23
|
+
} from "./native-modules.js";
|
|
24
|
+
|
|
25
|
+
const logger = createLogger("DesktopBundler");
|
|
26
|
+
|
|
27
|
+
export interface BundleOptions {
|
|
28
|
+
entryPoint: string;
|
|
29
|
+
outDir: string;
|
|
30
|
+
appName: string;
|
|
31
|
+
version: string;
|
|
32
|
+
platform?: "node" | "neutral";
|
|
33
|
+
target?: string;
|
|
34
|
+
format?: "cjs" | "esm";
|
|
35
|
+
minify?: boolean;
|
|
36
|
+
sourcemap?: boolean;
|
|
37
|
+
external?: string[];
|
|
38
|
+
env?: Record<string, string>;
|
|
39
|
+
resources?: {
|
|
40
|
+
config?: string;
|
|
41
|
+
data?: string[];
|
|
42
|
+
};
|
|
43
|
+
nativeModules?: {
|
|
44
|
+
autoDetect?: boolean;
|
|
45
|
+
modules?: string[];
|
|
46
|
+
rebuild?: boolean;
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Bundle a Node.js backend for desktop deployment
|
|
52
|
+
*/
|
|
53
|
+
export async function bundleBackend(options: BundleOptions): Promise<void> {
|
|
54
|
+
const {
|
|
55
|
+
entryPoint,
|
|
56
|
+
outDir,
|
|
57
|
+
appName,
|
|
58
|
+
version,
|
|
59
|
+
platform = "node",
|
|
60
|
+
target = "node18",
|
|
61
|
+
format = "cjs",
|
|
62
|
+
minify = false,
|
|
63
|
+
sourcemap = false,
|
|
64
|
+
external = [],
|
|
65
|
+
env = {},
|
|
66
|
+
resources = {},
|
|
67
|
+
} = options;
|
|
68
|
+
|
|
69
|
+
logger.info(`Bundling backend for ${appName} v${version}`);
|
|
70
|
+
|
|
71
|
+
// Ensure output directory exists
|
|
72
|
+
await ensureDir(outDir);
|
|
73
|
+
|
|
74
|
+
// Default externals for Node.js
|
|
75
|
+
const defaultExternals = [
|
|
76
|
+
"fsevents", // Mac-specific, optional
|
|
77
|
+
"bufferutil", // Optional WebSocket performance
|
|
78
|
+
"utf-8-validate", // Optional WebSocket validation
|
|
79
|
+
"@superdangerous/app-framework/ui", // UI components not needed in backend
|
|
80
|
+
"serialport", // Optional serial port support
|
|
81
|
+
"@serialport/bindings-cpp", // Optional serial port bindings
|
|
82
|
+
"@aws-sdk/client-s3", // Optional AWS S3 support
|
|
83
|
+
"modbus-serial", // Optional Modbus communication
|
|
84
|
+
];
|
|
85
|
+
|
|
86
|
+
// Build with esbuild
|
|
87
|
+
const result = await esbuild.build({
|
|
88
|
+
entryPoints: [entryPoint],
|
|
89
|
+
bundle: true,
|
|
90
|
+
platform,
|
|
91
|
+
target,
|
|
92
|
+
outfile: path.join(outDir, "backend.js"),
|
|
93
|
+
format,
|
|
94
|
+
minify,
|
|
95
|
+
sourcemap,
|
|
96
|
+
external: [...defaultExternals, ...external],
|
|
97
|
+
define: {
|
|
98
|
+
"process.env.NODE_ENV": '"production"',
|
|
99
|
+
"process.env.DESKTOP_MODE": '"true"',
|
|
100
|
+
...Object.entries(env).reduce(
|
|
101
|
+
(acc, [key, value]) => {
|
|
102
|
+
acc[`process.env.${key}`] = JSON.stringify(value);
|
|
103
|
+
return acc;
|
|
104
|
+
},
|
|
105
|
+
{} as Record<string, string>,
|
|
106
|
+
),
|
|
107
|
+
},
|
|
108
|
+
loader: {
|
|
109
|
+
".node": "file",
|
|
110
|
+
".json": "json",
|
|
111
|
+
},
|
|
112
|
+
metafile: true,
|
|
113
|
+
logLevel: "info",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
// Write metafile for analysis
|
|
117
|
+
await writeFile(
|
|
118
|
+
path.join(outDir, "backend-meta.json"),
|
|
119
|
+
JSON.stringify(result.metafile, null, 2),
|
|
120
|
+
);
|
|
121
|
+
|
|
122
|
+
// Create wrapper script
|
|
123
|
+
const wrapperScript = generateWrapperScript(appName, format);
|
|
124
|
+
await writeFile(path.join(outDir, "start-backend.js"), wrapperScript);
|
|
125
|
+
|
|
126
|
+
// Copy resources
|
|
127
|
+
if (resources.config) {
|
|
128
|
+
const configDest = path.join(outDir, "config");
|
|
129
|
+
await ensureDir(configDest);
|
|
130
|
+
await copy(resources.config, path.join(configDest, "app.json"));
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (resources.data) {
|
|
134
|
+
const dataDir = path.join(outDir, "data");
|
|
135
|
+
for (const dir of resources.data) {
|
|
136
|
+
await ensureDir(path.join(dataDir, dir));
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Handle native modules if configured
|
|
141
|
+
if (options.nativeModules) {
|
|
142
|
+
const projectDir = path.dirname(entryPoint);
|
|
143
|
+
|
|
144
|
+
// Detect native modules if requested
|
|
145
|
+
let nativeModulesList = options.nativeModules.modules || [];
|
|
146
|
+
if (options.nativeModules.autoDetect) {
|
|
147
|
+
const detected = await detectNativeModules(projectDir);
|
|
148
|
+
nativeModulesList = [...new Set([...nativeModulesList, ...detected])];
|
|
149
|
+
logger.info(`Detected native modules: ${nativeModulesList.join(", ")}`);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Copy native modules to output directory
|
|
153
|
+
if (nativeModulesList.length > 0) {
|
|
154
|
+
await copyNativeModules({
|
|
155
|
+
modules: nativeModulesList,
|
|
156
|
+
sourceDir: projectDir,
|
|
157
|
+
targetDir: outDir,
|
|
158
|
+
rebuild: options.nativeModules.rebuild,
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
// Create native module loader
|
|
162
|
+
await createNativeModuleLoader(
|
|
163
|
+
path.join(outDir, "native-loader.js"),
|
|
164
|
+
nativeModulesList,
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
logger.info(`Copied ${nativeModulesList.length} native modules`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Get bundle size
|
|
172
|
+
const stats = await stat(path.join(outDir, "backend.js"));
|
|
173
|
+
const sizeMB = (stats.size / (1024 * 1024)).toFixed(2);
|
|
174
|
+
|
|
175
|
+
logger.info(`✅ Backend bundled successfully!`);
|
|
176
|
+
logger.info(` Bundle size: ${sizeMB} MB`);
|
|
177
|
+
logger.info(` Location: ${outDir}/backend.js`);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Generate wrapper script for starting the bundled backend
|
|
182
|
+
*/
|
|
183
|
+
function generateWrapperScript(appName: string, format: "cjs" | "esm"): string {
|
|
184
|
+
return `#!/usr/bin/env node
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Desktop App Backend Wrapper for ${appName}
|
|
188
|
+
* Sets up environment and starts the bundled backend
|
|
189
|
+
*/
|
|
190
|
+
|
|
191
|
+
${format === "esm" ? "import { fileURLToPath } from 'url';" : ""}
|
|
192
|
+
${format === "esm" ? "import { dirname, join } from 'path';" : "const path = require('path');"}
|
|
193
|
+
|
|
194
|
+
${
|
|
195
|
+
format === "esm"
|
|
196
|
+
? `
|
|
197
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
198
|
+
const __dirname = dirname(__filename);
|
|
199
|
+
`
|
|
200
|
+
: ""
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Set environment variables
|
|
204
|
+
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
|
|
205
|
+
process.env.DESKTOP_MODE = 'true';
|
|
206
|
+
|
|
207
|
+
// Set data directory to app data location
|
|
208
|
+
if (!process.env.DATA_DIR) {
|
|
209
|
+
// In production, this will be set by Electron
|
|
210
|
+
// For testing, use a local data directory
|
|
211
|
+
process.env.DATA_DIR = ${format === "esm" ? "join" : "path.join"}(__dirname, 'data');
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Note: Using console.log in wrapper script as it runs in production without logger
|
|
215
|
+
console.log('Starting ${appName} Backend...');
|
|
216
|
+
console.log('Data directory:', process.env.DATA_DIR);
|
|
217
|
+
|
|
218
|
+
// Start the bundled backend
|
|
219
|
+
${format === "cjs" ? "require('./backend.js');" : "import('./backend.js');"}
|
|
220
|
+
`;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
/**
|
|
224
|
+
* Bundle dependencies separately for better caching
|
|
225
|
+
*/
|
|
226
|
+
export async function bundleDependencies(
|
|
227
|
+
packageJsonPath: string,
|
|
228
|
+
outDir: string,
|
|
229
|
+
): Promise<void> {
|
|
230
|
+
const fs = await import("fs");
|
|
231
|
+
const packageJson = JSON.parse(
|
|
232
|
+
await fs.promises.readFile(packageJsonPath, "utf8"),
|
|
233
|
+
);
|
|
234
|
+
const dependencies = packageJson.dependencies || {};
|
|
235
|
+
|
|
236
|
+
logger.info("Installing production dependencies...");
|
|
237
|
+
|
|
238
|
+
// Create temporary directory for dependencies
|
|
239
|
+
const tempDir = path.join(outDir, "temp");
|
|
240
|
+
await ensureDir(tempDir);
|
|
241
|
+
|
|
242
|
+
// Create minimal package.json
|
|
243
|
+
const minimalPackage = {
|
|
244
|
+
name: packageJson.name,
|
|
245
|
+
version: packageJson.version,
|
|
246
|
+
dependencies,
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
await writeJson(path.join(tempDir, "package.json"), minimalPackage);
|
|
250
|
+
|
|
251
|
+
// Install production dependencies
|
|
252
|
+
execSync("npm install --production --no-audit --no-fund", {
|
|
253
|
+
cwd: tempDir,
|
|
254
|
+
stdio: "inherit",
|
|
255
|
+
});
|
|
256
|
+
|
|
257
|
+
// Move node_modules to output directory
|
|
258
|
+
await move(
|
|
259
|
+
path.join(tempDir, "node_modules"),
|
|
260
|
+
path.join(outDir, "node_modules"),
|
|
261
|
+
{ overwrite: true },
|
|
262
|
+
);
|
|
263
|
+
|
|
264
|
+
// Clean up temp directory
|
|
265
|
+
await remove(tempDir);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export default {
|
|
269
|
+
bundleBackend,
|
|
270
|
+
bundleDependencies,
|
|
271
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Desktop Module Exports
|
|
3
|
+
* Provides all desktop-related utilities for Electron integration
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
export * from "./bundler.js";
|
|
7
|
+
export * from "./native-modules.js";
|
|
8
|
+
|
|
9
|
+
// Re-export as namespace for convenience
|
|
10
|
+
import * as bundler from "./bundler.js";
|
|
11
|
+
import * as nativeModules from "./native-modules.js";
|
|
12
|
+
|
|
13
|
+
export const Desktop = {
|
|
14
|
+
...bundler,
|
|
15
|
+
...nativeModules,
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export default Desktop;
|
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Native Module Handler for Desktop Bundling
|
|
3
|
+
* Manages native Node.js modules that can't be bundled
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
ensureDir,
|
|
8
|
+
pathExists,
|
|
9
|
+
copy,
|
|
10
|
+
writeFile,
|
|
11
|
+
readFile,
|
|
12
|
+
readdir,
|
|
13
|
+
stat,
|
|
14
|
+
} from "../utils/fs-utils.js";
|
|
15
|
+
import path from "path";
|
|
16
|
+
import { execSync } from "child_process";
|
|
17
|
+
import { createLogger } from "../core/logger.js";
|
|
18
|
+
const logger = createLogger("native-modules");
|
|
19
|
+
|
|
20
|
+
export interface NativeModuleConfig {
|
|
21
|
+
/**
|
|
22
|
+
* List of native modules to copy to resources
|
|
23
|
+
*/
|
|
24
|
+
modules: string[];
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Source node_modules directory
|
|
28
|
+
*/
|
|
29
|
+
sourceDir: string;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Target resources directory
|
|
33
|
+
*/
|
|
34
|
+
targetDir: string;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Whether to rebuild native modules for target platform
|
|
38
|
+
*/
|
|
39
|
+
rebuild?: boolean;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Electron version (if rebuilding for Electron)
|
|
43
|
+
*/
|
|
44
|
+
electronVersion?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Default native modules that commonly need special handling
|
|
49
|
+
*/
|
|
50
|
+
export const COMMON_NATIVE_MODULES = [
|
|
51
|
+
"serialport",
|
|
52
|
+
"@serialport/bindings-cpp",
|
|
53
|
+
"node-pty",
|
|
54
|
+
"bcrypt",
|
|
55
|
+
"better-sqlite3",
|
|
56
|
+
"canvas",
|
|
57
|
+
"sharp",
|
|
58
|
+
"fsevents",
|
|
59
|
+
"usb",
|
|
60
|
+
"node-hid",
|
|
61
|
+
];
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Copy native modules to resources directory
|
|
65
|
+
*/
|
|
66
|
+
export async function copyNativeModules(
|
|
67
|
+
config: NativeModuleConfig,
|
|
68
|
+
): Promise<void> {
|
|
69
|
+
const { modules, sourceDir, targetDir } = config;
|
|
70
|
+
|
|
71
|
+
// Ensure target directory exists
|
|
72
|
+
await ensureDir(path.join(targetDir, "node_modules"));
|
|
73
|
+
|
|
74
|
+
for (const moduleName of modules) {
|
|
75
|
+
const sourcePath = path.join(sourceDir, "node_modules", moduleName);
|
|
76
|
+
const targetPath = path.join(targetDir, "node_modules", moduleName);
|
|
77
|
+
|
|
78
|
+
if (await pathExists(sourcePath)) {
|
|
79
|
+
logger.info(`📦 Copying native module: ${moduleName}`);
|
|
80
|
+
await copy(sourcePath, targetPath);
|
|
81
|
+
} else {
|
|
82
|
+
logger.warn(`⚠️ Native module not found: ${moduleName}`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Rebuild native modules for target platform
|
|
89
|
+
*/
|
|
90
|
+
export async function rebuildNativeModules(
|
|
91
|
+
targetDir: string,
|
|
92
|
+
electronVersion?: string,
|
|
93
|
+
): Promise<void> {
|
|
94
|
+
logger.info("🔨 Rebuilding native modules...");
|
|
95
|
+
|
|
96
|
+
const cwd = targetDir;
|
|
97
|
+
|
|
98
|
+
if (electronVersion) {
|
|
99
|
+
// Rebuild for Electron
|
|
100
|
+
try {
|
|
101
|
+
execSync(`npx electron-rebuild -v ${electronVersion}`, {
|
|
102
|
+
cwd,
|
|
103
|
+
stdio: "inherit",
|
|
104
|
+
});
|
|
105
|
+
} catch (_error) {
|
|
106
|
+
logger.error("Failed to rebuild for Electron:", _error);
|
|
107
|
+
throw _error;
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
// Rebuild for Node.js
|
|
111
|
+
try {
|
|
112
|
+
execSync("npm rebuild", { cwd, stdio: "inherit" });
|
|
113
|
+
} catch (_error) {
|
|
114
|
+
logger.error("Failed to rebuild native modules:", _error);
|
|
115
|
+
throw _error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Create a loader script that sets up paths for native modules
|
|
122
|
+
*/
|
|
123
|
+
export async function createNativeModuleLoader(
|
|
124
|
+
outputPath: string,
|
|
125
|
+
nativeModules: string[],
|
|
126
|
+
): Promise<void> {
|
|
127
|
+
const loaderScript = `/**
|
|
128
|
+
* Native Module Loader
|
|
129
|
+
* Sets up require paths for native modules in desktop app
|
|
130
|
+
*/
|
|
131
|
+
|
|
132
|
+
const path = require('path');
|
|
133
|
+
const Module = require('module');
|
|
134
|
+
|
|
135
|
+
// Add native modules directory to Node module paths
|
|
136
|
+
const nativeModulesPath = path.join(__dirname, 'node_modules');
|
|
137
|
+
Module.globalPaths.push(nativeModulesPath);
|
|
138
|
+
|
|
139
|
+
// Patch require to handle native modules
|
|
140
|
+
const originalRequire = Module.prototype.require;
|
|
141
|
+
const nativeModules = ${JSON.stringify(nativeModules)};
|
|
142
|
+
|
|
143
|
+
Module.prototype.require = function(id) {
|
|
144
|
+
// Check if this is a native module
|
|
145
|
+
if (nativeModules.includes(id) || nativeModules.some(m => id.startsWith(m + '/'))) {
|
|
146
|
+
try {
|
|
147
|
+
// Try to load from native modules directory
|
|
148
|
+
return originalRequire.apply(this, [path.join(nativeModulesPath, id)]);
|
|
149
|
+
} catch (_error) {
|
|
150
|
+
// Fall back to original require
|
|
151
|
+
return originalRequire.apply(this, arguments);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
return originalRequire.apply(this, arguments);
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
// Export for use in main bundle
|
|
159
|
+
module.exports = { nativeModulesPath };
|
|
160
|
+
`;
|
|
161
|
+
|
|
162
|
+
await writeFile(outputPath, loaderScript, "utf8");
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Check if a module is a native module
|
|
167
|
+
*/
|
|
168
|
+
export async function isNativeModule(moduleName: string): Promise<boolean> {
|
|
169
|
+
try {
|
|
170
|
+
const packageJsonPath = require.resolve(`${moduleName}/package.json`);
|
|
171
|
+
const content = await readFile(packageJsonPath, "utf8");
|
|
172
|
+
const packageJson = JSON.parse(content);
|
|
173
|
+
|
|
174
|
+
// Check for common indicators of native modules
|
|
175
|
+
return !!(
|
|
176
|
+
packageJson.gypfile ||
|
|
177
|
+
packageJson.binary ||
|
|
178
|
+
packageJson.scripts?.install ||
|
|
179
|
+
packageJson.scripts?.postinstall?.includes("node-gyp") ||
|
|
180
|
+
packageJson.dependencies?.["node-addon-api"] ||
|
|
181
|
+
packageJson.dependencies?.["nan"]
|
|
182
|
+
);
|
|
183
|
+
} catch {
|
|
184
|
+
return false;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Detect all native modules in a project
|
|
190
|
+
*/
|
|
191
|
+
export async function detectNativeModules(
|
|
192
|
+
projectDir: string,
|
|
193
|
+
): Promise<string[]> {
|
|
194
|
+
const nodeModulesDir = path.join(projectDir, "node_modules");
|
|
195
|
+
const nativeModules: string[] = [];
|
|
196
|
+
|
|
197
|
+
if (!(await pathExists(nodeModulesDir))) {
|
|
198
|
+
return nativeModules;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const modules = await readdir(nodeModulesDir);
|
|
202
|
+
|
|
203
|
+
for (const moduleName of modules) {
|
|
204
|
+
if (moduleName.startsWith(".")) continue;
|
|
205
|
+
|
|
206
|
+
const modulePath = path.join(nodeModulesDir, moduleName);
|
|
207
|
+
const stats = await stat(modulePath);
|
|
208
|
+
|
|
209
|
+
if (stats.isDirectory()) {
|
|
210
|
+
if (moduleName.startsWith("@")) {
|
|
211
|
+
// Scoped package
|
|
212
|
+
const scopedModules = await readdir(modulePath);
|
|
213
|
+
for (const scopedModule of scopedModules) {
|
|
214
|
+
const fullName = `${moduleName}/${scopedModule}`;
|
|
215
|
+
if (await isNativeModule(fullName)) {
|
|
216
|
+
nativeModules.push(fullName);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
} else {
|
|
220
|
+
// Regular package
|
|
221
|
+
if (await isNativeModule(moduleName)) {
|
|
222
|
+
nativeModules.push(moduleName);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
return nativeModules;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Bundle configuration that handles native modules
|
|
233
|
+
*/
|
|
234
|
+
export interface BundleWithNativeModulesOptions {
|
|
235
|
+
entryPoint: string;
|
|
236
|
+
outputPath: string;
|
|
237
|
+
nativeModules?: string[];
|
|
238
|
+
autoDetect?: boolean;
|
|
239
|
+
rebuild?: boolean;
|
|
240
|
+
electronVersion?: string;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Create a bundle that properly handles native modules
|
|
245
|
+
*/
|
|
246
|
+
export async function bundleWithNativeModules(
|
|
247
|
+
options: BundleWithNativeModulesOptions,
|
|
248
|
+
): Promise<void> {
|
|
249
|
+
const {
|
|
250
|
+
entryPoint,
|
|
251
|
+
outputPath,
|
|
252
|
+
autoDetect = true,
|
|
253
|
+
rebuild = false,
|
|
254
|
+
electronVersion,
|
|
255
|
+
} = options;
|
|
256
|
+
|
|
257
|
+
const projectDir = path.dirname(entryPoint);
|
|
258
|
+
const outputDir = path.dirname(outputPath);
|
|
259
|
+
|
|
260
|
+
// Detect or use provided native modules
|
|
261
|
+
let nativeModules = options.nativeModules || [];
|
|
262
|
+
if (autoDetect) {
|
|
263
|
+
const detected = await detectNativeModules(projectDir);
|
|
264
|
+
nativeModules = [...new Set([...nativeModules, ...detected])];
|
|
265
|
+
logger.info(`🔍 Detected native modules: ${nativeModules.join(", ")}`);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Copy native modules
|
|
269
|
+
if (nativeModules.length > 0) {
|
|
270
|
+
await copyNativeModules({
|
|
271
|
+
modules: nativeModules,
|
|
272
|
+
sourceDir: projectDir,
|
|
273
|
+
targetDir: outputDir,
|
|
274
|
+
});
|
|
275
|
+
|
|
276
|
+
// Create loader script
|
|
277
|
+
await createNativeModuleLoader(
|
|
278
|
+
path.join(outputDir, "native-loader.js"),
|
|
279
|
+
nativeModules,
|
|
280
|
+
);
|
|
281
|
+
|
|
282
|
+
// Rebuild if requested
|
|
283
|
+
if (rebuild) {
|
|
284
|
+
await rebuildNativeModules(outputDir, electronVersion);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
logger.info("✅ Native modules prepared for bundling");
|
|
289
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SuperDangerous App Framework
|
|
3
|
+
* Main entry point for the TypeScript framework
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// Core exports
|
|
7
|
+
export * from "./core/index.js";
|
|
8
|
+
// API Response utilities are exported separately to avoid conflicts
|
|
9
|
+
export {
|
|
10
|
+
sendSuccess,
|
|
11
|
+
sendError,
|
|
12
|
+
sendValidationError,
|
|
13
|
+
sendNotFound,
|
|
14
|
+
sendUnauthorized,
|
|
15
|
+
sendForbidden,
|
|
16
|
+
sendBadRequest,
|
|
17
|
+
sendCreated,
|
|
18
|
+
sendNoContent,
|
|
19
|
+
asyncHandler,
|
|
20
|
+
apiErrorHandler,
|
|
21
|
+
type ApiResponse,
|
|
22
|
+
type ApiErrorResponse,
|
|
23
|
+
type ApiSuccessResponse,
|
|
24
|
+
} from "./core/apiResponse.js";
|
|
25
|
+
|
|
26
|
+
// Service exports
|
|
27
|
+
export * from "./services/index.js";
|
|
28
|
+
|
|
29
|
+
// Middleware exports
|
|
30
|
+
export * from "./middleware/index.js";
|
|
31
|
+
export * from "./middleware/auth.js";
|
|
32
|
+
export {
|
|
33
|
+
configureSession,
|
|
34
|
+
sessionUtils,
|
|
35
|
+
createRedisStore,
|
|
36
|
+
} from "./middleware/session.js";
|
|
37
|
+
export type { SessionConfig as FrameworkSessionConfig } from "./middleware/session.js";
|
|
38
|
+
|
|
39
|
+
// Utility exports
|
|
40
|
+
export * from "./utils/index.js";
|
|
41
|
+
|
|
42
|
+
// Re-export commonly used items at top level
|
|
43
|
+
export { createLogger, type Logger, type LogLevel } from "./core/index.js";
|
|
44
|
+
export { StandardServer, createStandardServer } from "./core/StandardServer.js";
|
|
45
|
+
export type { StandardServerConfig } from "./core/StandardServer.js";
|
|
46
|
+
export {
|
|
47
|
+
StorageService,
|
|
48
|
+
getStorageService,
|
|
49
|
+
SecureFileHandler,
|
|
50
|
+
getSecureFileHandler,
|
|
51
|
+
} from "./core/storageService.js";
|
|
52
|
+
export {
|
|
53
|
+
createWebSocketServer,
|
|
54
|
+
getWebSocketServer,
|
|
55
|
+
} from "./services/websocketServer.js";
|
|
56
|
+
export { validate, schemas } from "./middleware/validation.js";
|
|
57
|
+
|
|
58
|
+
// Testing utilities
|
|
59
|
+
export {
|
|
60
|
+
TestServer,
|
|
61
|
+
createTestServer,
|
|
62
|
+
setupTestServer,
|
|
63
|
+
teardownTestServer,
|
|
64
|
+
getTestServer,
|
|
65
|
+
} from "./testing/TestServer.js";
|
|
66
|
+
export type { TestServerConfig } from "./testing/TestServer.js";
|
|
67
|
+
|
|
68
|
+
// Standardized API routers
|
|
69
|
+
export { default as logsRouter } from "./api/logsRouter.js";
|
|
70
|
+
export type { LogEntry as RouterLogEntry, LogFile } from "./api/logsRouter.js";
|
|
71
|
+
|
|
72
|
+
// Desktop integration exports
|
|
73
|
+
export * from "./desktop/index.js";
|
|
74
|
+
|
|
75
|
+
// System monitoring exports
|
|
76
|
+
export { getSystemMonitor } from "./services/systemMonitor.js";
|
|
77
|
+
export type {
|
|
78
|
+
SystemHealth,
|
|
79
|
+
CPUInfo,
|
|
80
|
+
MemoryInfo,
|
|
81
|
+
DiskInfo,
|
|
82
|
+
SystemInfo,
|
|
83
|
+
ProcessInfo,
|
|
84
|
+
} from "./services/systemMonitor.js";
|
|
85
|
+
|
|
86
|
+
// Health check exports
|
|
87
|
+
export {
|
|
88
|
+
createHealthCheckRouter,
|
|
89
|
+
getHealthCheckService,
|
|
90
|
+
type SystemHealth as HealthStatus,
|
|
91
|
+
type SystemMetrics,
|
|
92
|
+
type HealthCheckOptions,
|
|
93
|
+
type CustomHealthCheck,
|
|
94
|
+
type HealthCheckResult,
|
|
95
|
+
type DependencyHealth,
|
|
96
|
+
} from "./core/healthCheck.js";
|
|
97
|
+
|
|
98
|
+
// WebSocket Manager exports
|
|
99
|
+
|
|
100
|
+
// Configuration management - use SettingsService instead
|
|
101
|
+
|
|
102
|
+
// Settings Schema exports - Consolidated implementation
|
|
103
|
+
export {
|
|
104
|
+
createSettingsSchema,
|
|
105
|
+
flattenSettings,
|
|
106
|
+
unflattenSettings,
|
|
107
|
+
flattenSettingsValues,
|
|
108
|
+
unflattenSettingsValues,
|
|
109
|
+
getRestartRequiredSettings,
|
|
110
|
+
validateSettings,
|
|
111
|
+
validateSetting,
|
|
112
|
+
validateAllSettings,
|
|
113
|
+
getSettingByKey,
|
|
114
|
+
getDefaultSettingsValues,
|
|
115
|
+
evaluateFieldVisibility,
|
|
116
|
+
groupFields,
|
|
117
|
+
applyToStorageTransform,
|
|
118
|
+
applyFromStorageTransform,
|
|
119
|
+
createSettingsFormState,
|
|
120
|
+
Validators,
|
|
121
|
+
type SettingsSchema,
|
|
122
|
+
type SettingsCategory,
|
|
123
|
+
type SettingDefinition,
|
|
124
|
+
type SettingOption,
|
|
125
|
+
type SettingsFormState,
|
|
126
|
+
type SettingsValidationResult,
|
|
127
|
+
} from "./settings/SettingsSchema.js";
|
|
128
|
+
|
|
129
|
+
// Log Categories exports
|
|
130
|
+
export {
|
|
131
|
+
LogLevels,
|
|
132
|
+
defaultLogViewerConfig,
|
|
133
|
+
parseLogEntry,
|
|
134
|
+
formatLogEntry,
|
|
135
|
+
calculateLogStats,
|
|
136
|
+
filterLogEntries,
|
|
137
|
+
type LogCategory,
|
|
138
|
+
type LogFilter,
|
|
139
|
+
type LogViewerConfig,
|
|
140
|
+
type LogEntry,
|
|
141
|
+
type LogStats,
|
|
142
|
+
} from "./logging/LogCategories.js";
|