@glassnote/client 2.4.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/INSTALACION.md +258 -0
- package/README.md +228 -0
- package/autoStart.js +608 -0
- package/autoupdate.js +473 -0
- package/autoupdate_renderer.js +371 -0
- package/bin/glassnote.js +523 -0
- package/images/demo01.png +0 -0
- package/images/dmg-background.png +0 -0
- package/images/dmg-background.svg +37628 -0
- package/images/icon-16.png +0 -0
- package/images/icon-24.png +0 -0
- package/images/icon-512.png +0 -0
- package/images/icon.ico +0 -0
- package/images/icon.png +0 -0
- package/images/splash.svg +61 -0
- package/localserver.js +297 -0
- package/logUtilities.js +128 -0
- package/main.js +745 -0
- package/npmMode.js +139 -0
- package/npmUpdate.js +152 -0
- package/package.json +141 -0
- package/preload.js +148 -0
- package/userData.js +492 -0
package/userData.js
ADDED
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { v4: uuidv4 } = require('uuid');
|
|
4
|
+
|
|
5
|
+
// Logging de diagnóstico para problema del UUID
|
|
6
|
+
|
|
7
|
+
const userDataDir = path.join(
|
|
8
|
+
process.env.APPDATA ||
|
|
9
|
+
(process.platform === 'darwin'
|
|
10
|
+
? path.join(process.env.HOME, 'Library', 'Application Support')
|
|
11
|
+
: path.join(process.env.HOME, '.config')),
|
|
12
|
+
'glassnote'
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
const userDataPath = path.join(userDataDir, '.glassnote');
|
|
16
|
+
|
|
17
|
+
// Path to Godot version's data file
|
|
18
|
+
// Get the base app data directory (parent of userDataDir)
|
|
19
|
+
const baseAppDataDir = path.dirname(userDataDir);
|
|
20
|
+
const godotDataPath = path.join(
|
|
21
|
+
userDataDir,
|
|
22
|
+
'Godot',
|
|
23
|
+
'app_userdata',
|
|
24
|
+
'glassnote',
|
|
25
|
+
'.glassnote'
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
// In-memory cache for user data
|
|
30
|
+
let userDataCache = null;
|
|
31
|
+
|
|
32
|
+
function ensureFileExists() {
|
|
33
|
+
|
|
34
|
+
if (!fs.existsSync(userDataDir)) {
|
|
35
|
+
fs.mkdirSync(userDataDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (!fs.existsSync(userDataPath)) {
|
|
39
|
+
let uuid = uuidv4(); // Default to new UUID
|
|
40
|
+
let servers = []; // Default empty servers array
|
|
41
|
+
|
|
42
|
+
// Check if Godot version's data file exists and try to migrate data
|
|
43
|
+
if (fs.existsSync(godotDataPath)) {
|
|
44
|
+
try {
|
|
45
|
+
const godotData = fs.readFileSync(godotDataPath, 'utf8');
|
|
46
|
+
const parsedData = JSON.parse(godotData);
|
|
47
|
+
|
|
48
|
+
// Migrate UUID if available
|
|
49
|
+
if (parsedData.uuid) {
|
|
50
|
+
uuid = parsedData.uuid;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Migrate server value to servers array if available
|
|
54
|
+
if (parsedData.server) {
|
|
55
|
+
servers = [parsedData.server];
|
|
56
|
+
}
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error('Error reading Godot data file:', err);
|
|
59
|
+
console.error('Generating new UUID due to error reading Godot data');
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
console.log('No Godot data file found, generating new UUID:', uuid);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const initialData = { uuid: uuid, servers: servers };
|
|
66
|
+
fs.writeFileSync(userDataPath, JSON.stringify(initialData, null, 2));
|
|
67
|
+
userDataCache = initialData;
|
|
68
|
+
return initialData;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Load data into cache if not already loaded
|
|
72
|
+
if (userDataCache === null) {
|
|
73
|
+
userDataCache = readData();
|
|
74
|
+
} else {
|
|
75
|
+
console.log('Cache already loaded, skipping readData()');
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// Validate that UUID exists and is a valid format
|
|
79
|
+
|
|
80
|
+
if (!userDataCache.uuid || typeof userDataCache.uuid !== 'string' || userDataCache.uuid.trim() === '' || !isValidUUID(userDataCache.uuid)) {
|
|
81
|
+
|
|
82
|
+
const newUUID = uuidv4();
|
|
83
|
+
userDataCache.uuid = newUUID;
|
|
84
|
+
writeData(userDataCache);
|
|
85
|
+
} else {
|
|
86
|
+
console.log('UUID validation PASSED');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return userDataCache;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function readData() {
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const data = fs.readFileSync(userDataPath, 'utf8');
|
|
96
|
+
|
|
97
|
+
const parsedData = JSON.parse(data);
|
|
98
|
+
|
|
99
|
+
// Ensure we always return an object with proper structure
|
|
100
|
+
if (typeof parsedData !== 'object' || parsedData === null) {
|
|
101
|
+
console.error('Invalid data format, returning default structure');
|
|
102
|
+
userDataCache = { uuid: null, servers: [] };
|
|
103
|
+
return userDataCache;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Ensure servers array exists
|
|
107
|
+
if (!Array.isArray(parsedData.servers)) {
|
|
108
|
+
if (typeof parsedData.servers === 'string') {
|
|
109
|
+
parsedData.servers = [parsedData.servers];
|
|
110
|
+
} else {
|
|
111
|
+
parsedData.servers = [];
|
|
112
|
+
}
|
|
113
|
+
} else {
|
|
114
|
+
console.log('servers is already array, length:', parsedData.servers.length);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
userDataCache = parsedData;
|
|
118
|
+
return userDataCache;
|
|
119
|
+
} catch (err) {
|
|
120
|
+
console.error('Error reading user data:', err.message);
|
|
121
|
+
console.error('Error stack:', err.stack);
|
|
122
|
+
// Return a properly structured object instead of empty
|
|
123
|
+
userDataCache = { uuid: null, servers: [] };
|
|
124
|
+
console.error('Returning error structure:', userDataCache);
|
|
125
|
+
console.error('=== readData() returning (error) ===');
|
|
126
|
+
return userDataCache;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function writeData(data) {
|
|
131
|
+
|
|
132
|
+
// Validate data structure before writing
|
|
133
|
+
if (!data || typeof data !== 'object') {
|
|
134
|
+
console.error('writeData() called with invalid data:', data);
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// ALWAYS preserve a valid UUID - never overwrite with invalid/null UUID
|
|
139
|
+
let originalUUID = data.uuid;
|
|
140
|
+
let needsUUIDPreservation = false;
|
|
141
|
+
|
|
142
|
+
// Check if UUID in data is valid
|
|
143
|
+
if (!data.uuid || typeof data.uuid !== 'string' || !isValidUUID(data.uuid)) {
|
|
144
|
+
console.warn('writeData(): UUID in data is invalid:', data.uuid);
|
|
145
|
+
needsUUIDPreservation = true;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
// If UUID needs preservation, read current file
|
|
149
|
+
if (needsUUIDPreservation) {
|
|
150
|
+
try {
|
|
151
|
+
if (fs.existsSync(userDataPath)) {
|
|
152
|
+
const currentContent = fs.readFileSync(userDataPath, 'utf8');
|
|
153
|
+
const currentData = JSON.parse(currentContent);
|
|
154
|
+
if (currentData.uuid && isValidUUID(currentData.uuid)) {
|
|
155
|
+
data.uuid = currentData.uuid;
|
|
156
|
+
} else {
|
|
157
|
+
console.warn('writeData(): No valid UUID in current file either');
|
|
158
|
+
// If no valid UUID exists anywhere, generate a new one
|
|
159
|
+
if (!data.uuid || !isValidUUID(data.uuid)) {
|
|
160
|
+
const newUUID = uuidv4();
|
|
161
|
+
data.uuid = newUUID;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
} else {
|
|
165
|
+
// File doesn't exist, ensure we have a valid UUID
|
|
166
|
+
if (!data.uuid || !isValidUUID(data.uuid)) {
|
|
167
|
+
const newUUID = uuidv4();
|
|
168
|
+
data.uuid = newUUID;
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
} catch (err) {
|
|
172
|
+
console.error('writeData(): Error reading current file:', err.message);
|
|
173
|
+
// On error, ensure we have a valid UUID
|
|
174
|
+
if (!data.uuid || !isValidUUID(data.uuid)) {
|
|
175
|
+
const newUUID = uuidv4();
|
|
176
|
+
console.error('writeData(): Generating new UUID after error:', newUUID);
|
|
177
|
+
data.uuid = newUUID;
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
} else {
|
|
181
|
+
console.log('writeData(): UUID in data is valid:', data.uuid);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Create backup before writing
|
|
185
|
+
try {
|
|
186
|
+
if (fs.existsSync(userDataPath)) {
|
|
187
|
+
const backupPath = userDataPath + '.backup';
|
|
188
|
+
fs.copyFileSync(userDataPath, backupPath);
|
|
189
|
+
}
|
|
190
|
+
} catch (err) {
|
|
191
|
+
console.warn('writeData(): Could not create backup:', err.message);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
try {
|
|
195
|
+
fs.writeFileSync(userDataPath, JSON.stringify(data, null, 2));
|
|
196
|
+
return true;
|
|
197
|
+
} catch (err) {
|
|
198
|
+
console.error('Error writing user data:', err.message);
|
|
199
|
+
console.error('Error stack:', err.stack);
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function get(key, nestedKey) {
|
|
205
|
+
// Handle both get(key) and get(key, nestedKey)
|
|
206
|
+
if (arguments.length === 1) {
|
|
207
|
+
nestedKey = undefined;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Ensure cache is loaded
|
|
211
|
+
if (userDataCache === null) {
|
|
212
|
+
ensureFileExists();
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
if (nestedKey !== undefined) {
|
|
216
|
+
// If nestedKey is provided, get nested value
|
|
217
|
+
if (userDataCache[key] && typeof userDataCache[key] === 'object' && userDataCache[key] !== null) {
|
|
218
|
+
return userDataCache[key][nestedKey];
|
|
219
|
+
}
|
|
220
|
+
return undefined;
|
|
221
|
+
} else {
|
|
222
|
+
// If only key is provided, get top-level value
|
|
223
|
+
return userDataCache[key];
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
function set(key, nestedKey, value) {
|
|
228
|
+
|
|
229
|
+
// Handle both set(key, value) and set(key, nestedKey, value)
|
|
230
|
+
if (arguments.length === 2) {
|
|
231
|
+
// set(key, value) - value is actually the second argument
|
|
232
|
+
value = nestedKey;
|
|
233
|
+
nestedKey = undefined;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// BLOCK ATTEMPTS TO OVERWRITE UUID FROM RENDERER
|
|
237
|
+
if (key === 'uuid' && nestedKey === undefined) {
|
|
238
|
+
console.error('SECURITY: Attempt to overwrite UUID blocked!');
|
|
239
|
+
console.error('UUID can only be set by Electron main process, not from renderer.');
|
|
240
|
+
|
|
241
|
+
// Get current UUID to return success but don't actually change it
|
|
242
|
+
if (userDataCache === null) {
|
|
243
|
+
ensureFileExists();
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// CRITICAL FIX: DO NOT update cache with invalid UUID from renderer
|
|
247
|
+
// Keep the existing UUID in cache to prevent ensureFileExists() from regenerating it
|
|
248
|
+
|
|
249
|
+
// Return true to avoid breaking renderer expectations, but UUID is not actually changed
|
|
250
|
+
return true;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// Ensure cache is loaded
|
|
254
|
+
if (userDataCache === null) {
|
|
255
|
+
ensureFileExists();
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// Validate cache structure
|
|
259
|
+
if (!userDataCache || typeof userDataCache !== 'object') {
|
|
260
|
+
console.error('set(): userDataCache is invalid, reinitializing');
|
|
261
|
+
userDataCache = { uuid: null, servers: [] };
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Preserve UUID if it exists but cache structure is incomplete
|
|
265
|
+
if (!userDataCache.uuid || typeof userDataCache.uuid !== 'string') {
|
|
266
|
+
try {
|
|
267
|
+
if (fs.existsSync(userDataPath)) {
|
|
268
|
+
const currentContent = fs.readFileSync(userDataPath, 'utf8');
|
|
269
|
+
const currentData = JSON.parse(currentContent);
|
|
270
|
+
if (currentData.uuid && typeof currentData.uuid === 'string') {
|
|
271
|
+
userDataCache.uuid = currentData.uuid;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
} catch (err) {
|
|
275
|
+
console.error('set(): Error reading file for UUID:', err.message);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
// Handle case where nestedKey is an object but should be treated as value
|
|
280
|
+
// This happens when: set(key, object, undefined) or set(key, object, null)
|
|
281
|
+
if (nestedKey !== undefined && typeof nestedKey === 'object' &&
|
|
282
|
+
(value === undefined || value === null)) {
|
|
283
|
+
// Swap: value = nestedKey, nestedKey = undefined
|
|
284
|
+
value = nestedKey;
|
|
285
|
+
nestedKey = undefined;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
// Also handle case where nestedKey is not a string (invalid for nested key)
|
|
289
|
+
if (nestedKey !== undefined && typeof nestedKey !== 'string') {
|
|
290
|
+
// If nestedKey is not a string, it can't be used as an object key
|
|
291
|
+
// Treat it as value instead
|
|
292
|
+
value = nestedKey;
|
|
293
|
+
nestedKey = undefined;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
if (nestedKey !== undefined) {
|
|
297
|
+
// If nestedKey is provided, set nested value
|
|
298
|
+
// Check if current value is an object, if not, replace it with an object
|
|
299
|
+
if (!userDataCache[key] || typeof userDataCache[key] !== 'object' || Array.isArray(userDataCache[key])) {
|
|
300
|
+
userDataCache[key] = {};
|
|
301
|
+
}
|
|
302
|
+
userDataCache[key][nestedKey] = value;
|
|
303
|
+
} else {
|
|
304
|
+
// If only key is provided, set top-level value
|
|
305
|
+
userDataCache[key] = value;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return writeData(userDataCache);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function remove(key, nestedKey) {
|
|
312
|
+
// Handle both remove(key) and remove(key, nestedKey)
|
|
313
|
+
if (arguments.length === 1) {
|
|
314
|
+
nestedKey = undefined;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Ensure cache is loaded
|
|
318
|
+
if (userDataCache === null) {
|
|
319
|
+
ensureFileExists();
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (nestedKey !== undefined) {
|
|
323
|
+
// If nestedKey is provided, remove nested value
|
|
324
|
+
if (userDataCache[key] && typeof userDataCache[key] === 'object' && userDataCache[key] !== null) {
|
|
325
|
+
delete userDataCache[key][nestedKey];
|
|
326
|
+
// If the object becomes empty, remove the entire key
|
|
327
|
+
if (Object.keys(userDataCache[key]).length === 0) {
|
|
328
|
+
delete userDataCache[key];
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
// If only key is provided, remove top-level value
|
|
333
|
+
delete userDataCache[key];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return writeData(userDataCache);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function getUUID() {
|
|
340
|
+
|
|
341
|
+
// If UUID is already in cache and valid, return it immediately
|
|
342
|
+
if (userDataCache && userDataCache.uuid && typeof userDataCache.uuid === 'string' && isValidUUID(userDataCache.uuid)) {
|
|
343
|
+
return userDataCache.uuid;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Otherwise, ensure file exists and get UUID
|
|
347
|
+
const data = ensureFileExists();
|
|
348
|
+
|
|
349
|
+
// Double-check that UUID is valid
|
|
350
|
+
if (!data.uuid || typeof data.uuid !== 'string' || !isValidUUID(data.uuid)) {
|
|
351
|
+
console.error('getUUID(): Invalid UUID returned from ensureFileExists():', data.uuid);
|
|
352
|
+
// Try to read directly from file as last resort
|
|
353
|
+
try {
|
|
354
|
+
if (fs.existsSync(userDataPath)) {
|
|
355
|
+
const fileContent = fs.readFileSync(userDataPath, 'utf8');
|
|
356
|
+
const fileData = JSON.parse(fileContent);
|
|
357
|
+
if (fileData.uuid && isValidUUID(fileData.uuid)) {
|
|
358
|
+
// Update cache
|
|
359
|
+
userDataCache.uuid = fileData.uuid;
|
|
360
|
+
writeData(userDataCache);
|
|
361
|
+
return fileData.uuid;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
} catch (err) {
|
|
365
|
+
console.error('getUUID(): Error reading UUID from file:', err.message);
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// Generate new UUID as last resort
|
|
369
|
+
const newUUID = uuidv4();
|
|
370
|
+
userDataCache.uuid = newUUID;
|
|
371
|
+
writeData(userDataCache);
|
|
372
|
+
return newUUID;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
return data.uuid;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
// Función específica para leer el lock desde el archivo (no del cache)
|
|
379
|
+
function getLockFromFile() {
|
|
380
|
+
try {
|
|
381
|
+
// Leer directamente del archivo, no del cache
|
|
382
|
+
if (!fs.existsSync(userDataPath)) {
|
|
383
|
+
return undefined;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const data = fs.readFileSync(userDataPath, 'utf8');
|
|
387
|
+
const parsedData = JSON.parse(data);
|
|
388
|
+
|
|
389
|
+
// Retornar el valor del lock si existe
|
|
390
|
+
return parsedData.lock;
|
|
391
|
+
} catch (err) {
|
|
392
|
+
console.error('Error reading lock from file:', err);
|
|
393
|
+
return undefined;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
function getUserDataPath() {
|
|
398
|
+
return userDataDir;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function getUserDataDir() {
|
|
402
|
+
return userDataDir;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
// Función auxiliar para validar formato UUID
|
|
406
|
+
function isValidUUID(uuid) {
|
|
407
|
+
if (!uuid || typeof uuid !== 'string') return false;
|
|
408
|
+
const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
409
|
+
return uuidRegex.test(uuid);
|
|
410
|
+
}
|
|
411
|
+
|
|
412
|
+
// Función para validar y reparar datos de usuario
|
|
413
|
+
function validateAndRepairUserData() {
|
|
414
|
+
|
|
415
|
+
try {
|
|
416
|
+
if (!fs.existsSync(userDataPath)) {
|
|
417
|
+
return ensureFileExists();
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Read current file
|
|
421
|
+
const fileContent = fs.readFileSync(userDataPath, 'utf8');
|
|
422
|
+
const fileData = JSON.parse(fileContent);
|
|
423
|
+
|
|
424
|
+
let needsRepair = false;
|
|
425
|
+
|
|
426
|
+
// Validate UUID
|
|
427
|
+
if (!fileData.uuid || typeof fileData.uuid !== 'string' || !isValidUUID(fileData.uuid)) {
|
|
428
|
+
console.warn('Invalid UUID in file, repairing...');
|
|
429
|
+
needsRepair = true;
|
|
430
|
+
|
|
431
|
+
// Try to preserve existing UUID if format is close
|
|
432
|
+
if (fileData.uuid && typeof fileData.uuid === 'string' && fileData.uuid.trim() !== '') {
|
|
433
|
+
// Check if it's a UUID without dashes or with wrong format
|
|
434
|
+
const cleanUUID = fileData.uuid.trim().toLowerCase();
|
|
435
|
+
if (cleanUUID.length === 32 && /^[0-9a-f]{32}$/.test(cleanUUID)) {
|
|
436
|
+
// Convert 32-char hex to UUID format
|
|
437
|
+
fileData.uuid = cleanUUID.replace(/([0-9a-f]{8})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{4})([0-9a-f]{12})/, '$1-$2-$3-$4-$5');
|
|
438
|
+
} else {
|
|
439
|
+
// Generate new UUID
|
|
440
|
+
fileData.uuid = uuidv4();
|
|
441
|
+
}
|
|
442
|
+
} else {
|
|
443
|
+
// Generate new UUID
|
|
444
|
+
fileData.uuid = uuidv4();
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// Ensure servers array exists
|
|
449
|
+
if (!Array.isArray(fileData.servers)) {
|
|
450
|
+
console.warn('Invalid servers format, repairing...');
|
|
451
|
+
needsRepair = true;
|
|
452
|
+
if (typeof fileData.servers === 'string') {
|
|
453
|
+
fileData.servers = [fileData.servers];
|
|
454
|
+
} else {
|
|
455
|
+
fileData.servers = [];
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Update cache
|
|
460
|
+
userDataCache = fileData;
|
|
461
|
+
|
|
462
|
+
if (needsRepair) {
|
|
463
|
+
writeData(fileData);
|
|
464
|
+
} else {
|
|
465
|
+
console.log('Data validation passed, no repairs needed');
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
return fileData;
|
|
469
|
+
} catch (err) {
|
|
470
|
+
console.error('Error validating user data:', err.message);
|
|
471
|
+
console.error('Falling back to ensureFileExists()');
|
|
472
|
+
return ensureFileExists();
|
|
473
|
+
}
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
// NOT calling ensureFileExists() here anymore - will be called on demand
|
|
477
|
+
// This prevents double initialization and potential UUID regeneration
|
|
478
|
+
|
|
479
|
+
module.exports = {
|
|
480
|
+
ensureFileExists,
|
|
481
|
+
readData,
|
|
482
|
+
writeData,
|
|
483
|
+
get,
|
|
484
|
+
set,
|
|
485
|
+
remove,
|
|
486
|
+
getUUID,
|
|
487
|
+
getLockFromFile,
|
|
488
|
+
getUserDataPath,
|
|
489
|
+
getUserDataDir,
|
|
490
|
+
isValidUUID,
|
|
491
|
+
validateAndRepairUserData,
|
|
492
|
+
};
|