@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,334 @@
1
+ /**
2
+ * Update Service
3
+ * Checks for application updates via GitHub releases
4
+ */
5
+
6
+ import { createLogger } from "../core/index.js";
7
+ import { pathExists, readFile } from "../utils/fs-utils.js";
8
+ import path from "path";
9
+
10
+ let pkg: any = { version: "1.0.0", name: "@superdangerous/app-framework" };
11
+
12
+ // Initialize package info asynchronously
13
+ (async () => {
14
+ try {
15
+ const pkgPath = path.join(process.cwd(), "package.json");
16
+ if (await pathExists(pkgPath)) {
17
+ const content = await readFile(pkgPath, "utf8");
18
+ pkg = JSON.parse(content);
19
+ }
20
+ } catch {
21
+ // Use default values
22
+ }
23
+ })();
24
+
25
+ let logger: any; // Will be initialized when needed
26
+
27
+ function ensureLogger() {
28
+ if (!logger) {
29
+ logger = createLogger("UpdateService");
30
+ }
31
+ return logger;
32
+ }
33
+
34
+ interface ReleaseAsset {
35
+ name: string;
36
+ size: number;
37
+ downloadUrl: string;
38
+ }
39
+
40
+ interface LatestRelease {
41
+ version: string;
42
+ name: string;
43
+ body: string;
44
+ url: string;
45
+ publishedAt: string;
46
+ assets: ReleaseAsset[];
47
+ }
48
+
49
+ interface UpdateInfo {
50
+ currentVersion: string;
51
+ updateAvailable: boolean;
52
+ latestRelease: LatestRelease | null;
53
+ lastCheck: number | null;
54
+ }
55
+
56
+ interface Version {
57
+ major: number;
58
+ minor: number;
59
+ patch: number;
60
+ }
61
+
62
+ interface ChangelogEntry {
63
+ version: string;
64
+ name: string;
65
+ body: string;
66
+ publishedAt: string;
67
+ url: string;
68
+ }
69
+
70
+ class UpdateService {
71
+ private currentVersion: string;
72
+ private githubRepo: string;
73
+ private checkInterval: number;
74
+ private lastCheck: number | null;
75
+ private updateAvailable: boolean;
76
+ private latestRelease: LatestRelease | null;
77
+
78
+ constructor() {
79
+ this.currentVersion = pkg.version;
80
+ this.githubRepo = "SuperDangerous/app-framework"; // Update with actual repo
81
+ this.checkInterval = 24 * 60 * 60 * 1000; // Check daily
82
+ this.lastCheck = null;
83
+ this.updateAvailable = false;
84
+ this.latestRelease = null;
85
+ }
86
+
87
+ /**
88
+ * Check for updates from GitHub releases
89
+ */
90
+ async checkForUpdates(force: boolean = false): Promise<UpdateInfo> {
91
+ try {
92
+ // Skip if checked recently (unless forced)
93
+ if (!force && this.lastCheck) {
94
+ const timeSinceCheck = Date.now() - this.lastCheck;
95
+ if (timeSinceCheck < this.checkInterval) {
96
+ ensureLogger().debug("Skipping update check (too recent)");
97
+ return this.getUpdateInfo();
98
+ }
99
+ }
100
+
101
+ ensureLogger().info("Checking for updates...");
102
+
103
+ // Fetch latest release from GitHub API
104
+ const response = await fetch(
105
+ `https://api.github.com/repos/${this.githubRepo}/releases/latest`,
106
+ {
107
+ headers: {
108
+ Accept: "application/vnd.github.v3+json",
109
+ "User-Agent": `device-simulator/${this.currentVersion}`,
110
+ },
111
+ },
112
+ );
113
+
114
+ if (!response.ok) {
115
+ if (response.status === 404) {
116
+ ensureLogger().debug("No releases found");
117
+ return this.getUpdateInfo();
118
+ }
119
+ throw new Error(`GitHub API error: ${response.status}`);
120
+ }
121
+
122
+ const release = (await response.json()) as any;
123
+ this.lastCheck = Date.now();
124
+
125
+ // Parse version from tag (remove 'v' prefix if present)
126
+ const latestVersion = release.tag_name.replace(/^v/, "");
127
+
128
+ // Compare versions
129
+ this.updateAvailable = this.isNewerVersion(
130
+ latestVersion,
131
+ this.currentVersion,
132
+ );
133
+
134
+ if (this.updateAvailable) {
135
+ this.latestRelease = {
136
+ version: latestVersion,
137
+ name: release.name,
138
+ body: release.body,
139
+ url: release.html_url,
140
+ publishedAt: release.published_at,
141
+ assets: release.assets.map((asset: any) => ({
142
+ name: asset.name,
143
+ size: asset.size,
144
+ downloadUrl: asset.browser_download_url,
145
+ })),
146
+ };
147
+
148
+ ensureLogger().info(
149
+ `Update available: ${latestVersion} (current: ${this.currentVersion})`,
150
+ );
151
+ } else {
152
+ ensureLogger().info("Application is up to date");
153
+ this.latestRelease = null;
154
+ }
155
+
156
+ return this.getUpdateInfo();
157
+ } catch (_error: any) {
158
+ ensureLogger().error("Failed to check for updates:", _error);
159
+ throw _error;
160
+ }
161
+ }
162
+
163
+ /**
164
+ * Compare version strings (semantic versioning)
165
+ */
166
+ private isNewerVersion(latest: string, current: string): boolean {
167
+ const parseVersion = (v: string): Version => {
168
+ const parts = v.split(".").map((p) => parseInt(p) || 0);
169
+ return {
170
+ major: parts[0] || 0,
171
+ minor: parts[1] || 0,
172
+ patch: parts[2] || 0,
173
+ };
174
+ };
175
+
176
+ const latestParsed = parseVersion(latest);
177
+ const currentParsed = parseVersion(current);
178
+
179
+ if (latestParsed.major > currentParsed.major) return true;
180
+ if (latestParsed.major < currentParsed.major) return false;
181
+
182
+ if (latestParsed.minor > currentParsed.minor) return true;
183
+ if (latestParsed.minor < currentParsed.minor) return false;
184
+
185
+ return latestParsed.patch > currentParsed.patch;
186
+ }
187
+
188
+ /**
189
+ * Get current update information
190
+ */
191
+ getUpdateInfo(): UpdateInfo {
192
+ return {
193
+ currentVersion: this.currentVersion,
194
+ updateAvailable: this.updateAvailable,
195
+ latestRelease: this.latestRelease,
196
+ lastCheck: this.lastCheck,
197
+ };
198
+ }
199
+
200
+ /**
201
+ * Get changelog between versions
202
+ */
203
+ async getChangelog(
204
+ fromVersion: string = this.currentVersion,
205
+ ): Promise<ChangelogEntry[]> {
206
+ try {
207
+ const response = await fetch(
208
+ `https://api.github.com/repos/${this.githubRepo}/releases`,
209
+ {
210
+ headers: {
211
+ Accept: "application/vnd.github.v3+json",
212
+ "User-Agent": `device-simulator/${this.currentVersion}`,
213
+ },
214
+ },
215
+ );
216
+
217
+ if (!response.ok) {
218
+ throw new Error(`GitHub API error: ${response.status}`);
219
+ }
220
+
221
+ const releases = (await response.json()) as any;
222
+ const changelog: ChangelogEntry[] = [];
223
+
224
+ for (const release of releases) {
225
+ const version = release.tag_name.replace(/^v/, "");
226
+
227
+ // Only include versions newer than fromVersion
228
+ if (this.isNewerVersion(version, fromVersion)) {
229
+ changelog.push({
230
+ version,
231
+ name: release.name,
232
+ body: release.body,
233
+ publishedAt: release.published_at,
234
+ url: release.html_url,
235
+ });
236
+ }
237
+ }
238
+
239
+ return changelog;
240
+ } catch (_error: any) {
241
+ ensureLogger().error("Failed to fetch changelog:", _error);
242
+ throw _error;
243
+ }
244
+ }
245
+
246
+ /**
247
+ * Get download URL for current platform
248
+ */
249
+ getDownloadUrl(): string | null {
250
+ if (!this.latestRelease) return null;
251
+
252
+ const platform = process.platform;
253
+ const arch = process.arch;
254
+
255
+ // Map platform/arch to expected asset names
256
+ const assetPatterns: Record<string, RegExp> = {
257
+ "darwin-x64": /mac.*x64|darwin.*x64|osx/i,
258
+ "darwin-arm64": /mac.*arm|darwin.*arm|apple.*silicon/i,
259
+ "win32-x64": /win.*x64|windows.*64/i,
260
+ "linux-x64": /linux.*x64|linux.*amd64/i,
261
+ };
262
+
263
+ const key = `${platform}-${arch}`;
264
+ const pattern = assetPatterns[key];
265
+
266
+ if (!pattern) {
267
+ ensureLogger().warn(`No download pattern for platform: ${key}`);
268
+ return this.latestRelease.url; // Return release page URL as fallback
269
+ }
270
+
271
+ const asset = this.latestRelease.assets.find((a) => pattern.test(a.name));
272
+ return asset ? asset.downloadUrl : this.latestRelease.url;
273
+ }
274
+
275
+ /**
276
+ * Schedule automatic update checks
277
+ */
278
+ startAutoCheck(): void {
279
+ // Initial check
280
+ this.checkForUpdates().catch((err) => {
281
+ ensureLogger().error("Auto update check failed:", err);
282
+ });
283
+
284
+ // Schedule periodic checks
285
+ setInterval(() => {
286
+ this.checkForUpdates().catch((err) => {
287
+ ensureLogger().error("Auto update check failed:", err);
288
+ });
289
+ }, this.checkInterval);
290
+ }
291
+
292
+ /**
293
+ * Stop automatic update checks
294
+ */
295
+ stopAutoCheck(): void {
296
+ // Would need to store interval ID to properly clear
297
+ ensureLogger().info("Auto update checks stopped");
298
+ }
299
+
300
+ /**
301
+ * Get system information for update compatibility
302
+ */
303
+ getSystemInfo(): Record<string, any> {
304
+ return {
305
+ platform: process.platform,
306
+ arch: process.arch,
307
+ nodeVersion: process.version,
308
+ appVersion: this.currentVersion,
309
+ memory: process.memoryUsage(),
310
+ uptime: process.uptime(),
311
+ };
312
+ }
313
+
314
+ /**
315
+ * Check if update is compatible with current system
316
+ */
317
+ isUpdateCompatible(): boolean {
318
+ // Add compatibility checks here
319
+ // For now, assume all updates are compatible
320
+ return true;
321
+ }
322
+ }
323
+
324
+ // Singleton instance
325
+ let updateService: UpdateService | null = null;
326
+
327
+ export function getUpdateService(): UpdateService {
328
+ if (!updateService) {
329
+ updateService = new UpdateService();
330
+ }
331
+ return updateService;
332
+ }
333
+
334
+ export default UpdateService;