@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.
Files changed (239) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +652 -0
  3. package/dist/api/logsRouter.d.ts +20 -0
  4. package/dist/api/logsRouter.d.ts.map +1 -0
  5. package/dist/api/logsRouter.js +515 -0
  6. package/dist/api/logsRouter.js.map +1 -0
  7. package/dist/cli/dev-server.d.ts +7 -0
  8. package/dist/cli/dev-server.d.ts.map +1 -0
  9. package/dist/cli/dev-server.js +640 -0
  10. package/dist/cli/dev-server.js.map +1 -0
  11. package/dist/cli/index.d.ts +7 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +26 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/core/StandardServer.d.ts +129 -0
  16. package/dist/core/StandardServer.d.ts.map +1 -0
  17. package/dist/core/StandardServer.js +453 -0
  18. package/dist/core/StandardServer.js.map +1 -0
  19. package/dist/core/apiResponse.d.ts +69 -0
  20. package/dist/core/apiResponse.d.ts.map +1 -0
  21. package/dist/core/apiResponse.js +127 -0
  22. package/dist/core/apiResponse.js.map +1 -0
  23. package/dist/core/healthCheck.d.ts +160 -0
  24. package/dist/core/healthCheck.d.ts.map +1 -0
  25. package/dist/core/healthCheck.js +398 -0
  26. package/dist/core/healthCheck.js.map +1 -0
  27. package/dist/core/index.d.ts +40 -0
  28. package/dist/core/index.d.ts.map +1 -0
  29. package/dist/core/index.js +40 -0
  30. package/dist/core/index.js.map +1 -0
  31. package/dist/core/logger.d.ts +117 -0
  32. package/dist/core/logger.d.ts.map +1 -0
  33. package/dist/core/logger.js +826 -0
  34. package/dist/core/logger.js.map +1 -0
  35. package/dist/core/portUtils.d.ts +71 -0
  36. package/dist/core/portUtils.d.ts.map +1 -0
  37. package/dist/core/portUtils.js +240 -0
  38. package/dist/core/portUtils.js.map +1 -0
  39. package/dist/core/storageService.d.ts +119 -0
  40. package/dist/core/storageService.d.ts.map +1 -0
  41. package/dist/core/storageService.js +405 -0
  42. package/dist/core/storageService.js.map +1 -0
  43. package/dist/desktop/bundler.d.ts +40 -0
  44. package/dist/desktop/bundler.d.ts.map +1 -0
  45. package/dist/desktop/bundler.js +176 -0
  46. package/dist/desktop/bundler.js.map +1 -0
  47. package/dist/desktop/index.d.ts +25 -0
  48. package/dist/desktop/index.d.ts.map +1 -0
  49. package/dist/desktop/index.js +15 -0
  50. package/dist/desktop/index.js.map +1 -0
  51. package/dist/desktop/native-modules.d.ts +66 -0
  52. package/dist/desktop/native-modules.d.ts.map +1 -0
  53. package/dist/desktop/native-modules.js +200 -0
  54. package/dist/desktop/native-modules.js.map +1 -0
  55. package/dist/index.d.ts +29 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +39 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/logging/LogCategories.d.ts +87 -0
  60. package/dist/logging/LogCategories.d.ts.map +1 -0
  61. package/dist/logging/LogCategories.js +205 -0
  62. package/dist/logging/LogCategories.js.map +1 -0
  63. package/dist/middleware/aiErrorHandler.d.ts +31 -0
  64. package/dist/middleware/aiErrorHandler.d.ts.map +1 -0
  65. package/dist/middleware/aiErrorHandler.js +181 -0
  66. package/dist/middleware/aiErrorHandler.js.map +1 -0
  67. package/dist/middleware/auth.d.ts +101 -0
  68. package/dist/middleware/auth.d.ts.map +1 -0
  69. package/dist/middleware/auth.js +230 -0
  70. package/dist/middleware/auth.js.map +1 -0
  71. package/dist/middleware/cors.d.ts +56 -0
  72. package/dist/middleware/cors.d.ts.map +1 -0
  73. package/dist/middleware/cors.js +123 -0
  74. package/dist/middleware/cors.js.map +1 -0
  75. package/dist/middleware/errorHandler.d.ts +13 -0
  76. package/dist/middleware/errorHandler.d.ts.map +1 -0
  77. package/dist/middleware/errorHandler.js +85 -0
  78. package/dist/middleware/errorHandler.js.map +1 -0
  79. package/dist/middleware/fileUpload.d.ts +62 -0
  80. package/dist/middleware/fileUpload.d.ts.map +1 -0
  81. package/dist/middleware/fileUpload.js +175 -0
  82. package/dist/middleware/fileUpload.js.map +1 -0
  83. package/dist/middleware/health.d.ts +48 -0
  84. package/dist/middleware/health.d.ts.map +1 -0
  85. package/dist/middleware/health.js +143 -0
  86. package/dist/middleware/health.js.map +1 -0
  87. package/dist/middleware/index.d.ts +20 -0
  88. package/dist/middleware/index.d.ts.map +1 -0
  89. package/dist/middleware/index.js +18 -0
  90. package/dist/middleware/index.js.map +1 -0
  91. package/dist/middleware/openapi.d.ts +64 -0
  92. package/dist/middleware/openapi.d.ts.map +1 -0
  93. package/dist/middleware/openapi.js +258 -0
  94. package/dist/middleware/openapi.js.map +1 -0
  95. package/dist/middleware/requestLogging.d.ts +22 -0
  96. package/dist/middleware/requestLogging.d.ts.map +1 -0
  97. package/dist/middleware/requestLogging.js +61 -0
  98. package/dist/middleware/requestLogging.js.map +1 -0
  99. package/dist/middleware/session.d.ts +84 -0
  100. package/dist/middleware/session.d.ts.map +1 -0
  101. package/dist/middleware/session.js +189 -0
  102. package/dist/middleware/session.js.map +1 -0
  103. package/dist/middleware/validation.d.ts +1337 -0
  104. package/dist/middleware/validation.d.ts.map +1 -0
  105. package/dist/middleware/validation.js +483 -0
  106. package/dist/middleware/validation.js.map +1 -0
  107. package/dist/services/aiService.d.ts +180 -0
  108. package/dist/services/aiService.d.ts.map +1 -0
  109. package/dist/services/aiService.js +547 -0
  110. package/dist/services/aiService.js.map +1 -0
  111. package/dist/services/conversationStorage.d.ts +38 -0
  112. package/dist/services/conversationStorage.d.ts.map +1 -0
  113. package/dist/services/conversationStorage.js +158 -0
  114. package/dist/services/conversationStorage.js.map +1 -0
  115. package/dist/services/crossPlatformBuffer.d.ts +84 -0
  116. package/dist/services/crossPlatformBuffer.d.ts.map +1 -0
  117. package/dist/services/crossPlatformBuffer.js +246 -0
  118. package/dist/services/crossPlatformBuffer.js.map +1 -0
  119. package/dist/services/index.d.ts +17 -0
  120. package/dist/services/index.d.ts.map +1 -0
  121. package/dist/services/index.js +18 -0
  122. package/dist/services/index.js.map +1 -0
  123. package/dist/services/networkService.d.ts +81 -0
  124. package/dist/services/networkService.d.ts.map +1 -0
  125. package/dist/services/networkService.js +268 -0
  126. package/dist/services/networkService.js.map +1 -0
  127. package/dist/services/queueService.d.ts +112 -0
  128. package/dist/services/queueService.d.ts.map +1 -0
  129. package/dist/services/queueService.js +338 -0
  130. package/dist/services/queueService.js.map +1 -0
  131. package/dist/services/settingsService.d.ts +135 -0
  132. package/dist/services/settingsService.d.ts.map +1 -0
  133. package/dist/services/settingsService.js +425 -0
  134. package/dist/services/settingsService.js.map +1 -0
  135. package/dist/services/systemMonitor.d.ts +208 -0
  136. package/dist/services/systemMonitor.d.ts.map +1 -0
  137. package/dist/services/systemMonitor.js +693 -0
  138. package/dist/services/systemMonitor.js.map +1 -0
  139. package/dist/services/updateService.d.ts +78 -0
  140. package/dist/services/updateService.d.ts.map +1 -0
  141. package/dist/services/updateService.js +252 -0
  142. package/dist/services/updateService.js.map +1 -0
  143. package/dist/services/websocketEvents.d.ts +372 -0
  144. package/dist/services/websocketEvents.d.ts.map +1 -0
  145. package/dist/services/websocketEvents.js +338 -0
  146. package/dist/services/websocketEvents.js.map +1 -0
  147. package/dist/services/websocketServer.d.ts +80 -0
  148. package/dist/services/websocketServer.d.ts.map +1 -0
  149. package/dist/services/websocketServer.js +299 -0
  150. package/dist/services/websocketServer.js.map +1 -0
  151. package/dist/settings/SettingsSchema.d.ts +151 -0
  152. package/dist/settings/SettingsSchema.d.ts.map +1 -0
  153. package/dist/settings/SettingsSchema.js +424 -0
  154. package/dist/settings/SettingsSchema.js.map +1 -0
  155. package/dist/testing/TestServer.d.ts +69 -0
  156. package/dist/testing/TestServer.d.ts.map +1 -0
  157. package/dist/testing/TestServer.js +250 -0
  158. package/dist/testing/TestServer.js.map +1 -0
  159. package/dist/types/index.d.ts +137 -0
  160. package/dist/types/index.d.ts.map +1 -0
  161. package/dist/types/index.js +5 -0
  162. package/dist/types/index.js.map +1 -0
  163. package/dist/utils/appPaths.d.ts +74 -0
  164. package/dist/utils/appPaths.d.ts.map +1 -0
  165. package/dist/utils/appPaths.js +162 -0
  166. package/dist/utils/appPaths.js.map +1 -0
  167. package/dist/utils/fs-utils.d.ts +50 -0
  168. package/dist/utils/fs-utils.d.ts.map +1 -0
  169. package/dist/utils/fs-utils.js +114 -0
  170. package/dist/utils/fs-utils.js.map +1 -0
  171. package/dist/utils/index.d.ts +12 -0
  172. package/dist/utils/index.d.ts.map +1 -0
  173. package/dist/utils/index.js +10 -0
  174. package/dist/utils/index.js.map +1 -0
  175. package/dist/utils/standardConfig.d.ts +61 -0
  176. package/dist/utils/standardConfig.d.ts.map +1 -0
  177. package/dist/utils/standardConfig.js +109 -0
  178. package/dist/utils/standardConfig.js.map +1 -0
  179. package/dist/utils/startupBanner.d.ts +34 -0
  180. package/dist/utils/startupBanner.d.ts.map +1 -0
  181. package/dist/utils/startupBanner.js +169 -0
  182. package/dist/utils/startupBanner.js.map +1 -0
  183. package/dist/utils/startupLogger.d.ts +45 -0
  184. package/dist/utils/startupLogger.d.ts.map +1 -0
  185. package/dist/utils/startupLogger.js +200 -0
  186. package/dist/utils/startupLogger.js.map +1 -0
  187. package/package.json +151 -0
  188. package/src/api/logsRouter.ts +600 -0
  189. package/src/cli/dev-server.ts +803 -0
  190. package/src/cli/index.ts +31 -0
  191. package/src/core/StandardServer.ts +587 -0
  192. package/src/core/apiResponse.ts +202 -0
  193. package/src/core/healthCheck.ts +565 -0
  194. package/src/core/index.ts +80 -0
  195. package/src/core/logger.ts +1092 -0
  196. package/src/core/portUtils.ts +319 -0
  197. package/src/core/storageService.ts +595 -0
  198. package/src/desktop/bundler.ts +271 -0
  199. package/src/desktop/index.ts +18 -0
  200. package/src/desktop/native-modules.ts +289 -0
  201. package/src/index.ts +142 -0
  202. package/src/logging/LogCategories.ts +302 -0
  203. package/src/middleware/aiErrorHandler.ts +278 -0
  204. package/src/middleware/auth.ts +329 -0
  205. package/src/middleware/cors.ts +187 -0
  206. package/src/middleware/errorHandler.ts +103 -0
  207. package/src/middleware/fileUpload.ts +252 -0
  208. package/src/middleware/health.ts +206 -0
  209. package/src/middleware/index.ts +71 -0
  210. package/src/middleware/openapi.ts +305 -0
  211. package/src/middleware/requestLogging.ts +92 -0
  212. package/src/middleware/session.ts +238 -0
  213. package/src/middleware/validation.ts +603 -0
  214. package/src/services/aiService.ts +789 -0
  215. package/src/services/conversationStorage.ts +232 -0
  216. package/src/services/crossPlatformBuffer.ts +341 -0
  217. package/src/services/index.ts +47 -0
  218. package/src/services/networkService.ts +351 -0
  219. package/src/services/queueService.ts +446 -0
  220. package/src/services/settingsService.ts +549 -0
  221. package/src/services/systemMonitor.ts +936 -0
  222. package/src/services/updateService.ts +334 -0
  223. package/src/services/websocketEvents.ts +409 -0
  224. package/src/services/websocketServer.ts +394 -0
  225. package/src/settings/SettingsSchema.ts +664 -0
  226. package/src/testing/TestServer.ts +312 -0
  227. package/src/types/index.ts +154 -0
  228. package/src/utils/appPaths.ts +196 -0
  229. package/src/utils/fs-utils.ts +130 -0
  230. package/src/utils/index.ts +15 -0
  231. package/src/utils/standardConfig.ts +178 -0
  232. package/src/utils/startupBanner.ts +287 -0
  233. package/src/utils/startupLogger.ts +268 -0
  234. package/ui/dist/index.d.mts +1221 -0
  235. package/ui/dist/index.d.ts +1221 -0
  236. package/ui/dist/index.js +73 -0
  237. package/ui/dist/index.js.map +1 -0
  238. package/ui/dist/index.mjs +73 -0
  239. 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";