neex 0.6.83 → 0.6.85

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.
@@ -27,7 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
29
  exports.DevManager = void 0;
30
- // src/dev-manager.ts - Enhanced TypeScript development server with built-in compilation
30
+ // src/dev-manager.ts - Enhanced TypeScript development server with improved caching
31
31
  const child_process_1 = require("child_process");
32
32
  const chokidar_1 = require("chokidar");
33
33
  const logger_manager_js_1 = require("./logger-manager.js");
@@ -81,7 +81,6 @@ class DevManager {
81
81
  logger_manager_js_1.loggerManager.printLine(`Error parsing tsconfig.json: ${parsedConfig.errors[0].messageText}`, 'warn');
82
82
  return defaultOptions;
83
83
  }
84
- // Override some options for development
85
84
  const options = { ...parsedConfig.options, ...defaultOptions };
86
85
  if (this.options.verbose) {
87
86
  logger_manager_js_1.loggerManager.printLine(`Loaded TypeScript config from ${configPath}`, 'info');
@@ -122,28 +121,84 @@ class DevManager {
122
121
  }
123
122
  }
124
123
  }
125
- compileTypeScript(filePath) {
124
+ generateFileHash(content) {
125
+ // Simple hash function for content
126
+ let hash = 0;
127
+ for (let i = 0; i < content.length; i++) {
128
+ const char = content.charCodeAt(i);
129
+ hash = ((hash << 5) - hash) + char;
130
+ hash = hash & hash; // Convert to 32bit integer
131
+ }
132
+ return hash.toString(16);
133
+ }
134
+ shouldRecompile(filePath, sourceCode) {
126
135
  const absolutePath = path_1.default.resolve(filePath);
127
- // Check cache first
128
136
  const cached = this.moduleCache.get(absolutePath);
129
- if (cached && !this.options.transpileOnly) {
130
- return cached;
137
+ if (!cached) {
138
+ return true;
139
+ }
140
+ // Check if file was modified
141
+ const stat = fs_1.default.statSync(absolutePath);
142
+ if (stat.mtimeMs > cached.lastModified) {
143
+ return true;
131
144
  }
145
+ // Check if content hash changed
146
+ const currentHash = this.generateFileHash(sourceCode);
147
+ if (currentHash !== cached.hash) {
148
+ return true;
149
+ }
150
+ return false;
151
+ }
152
+ compileTypeScript(filePath) {
153
+ const absolutePath = path_1.default.resolve(filePath);
132
154
  try {
133
155
  const sourceCode = fs_1.default.readFileSync(absolutePath, 'utf8');
156
+ const currentHash = this.generateFileHash(sourceCode);
157
+ // Check if we need to recompile
158
+ if (!this.shouldRecompile(absolutePath, sourceCode)) {
159
+ const cached = this.moduleCache.get(absolutePath);
160
+ if (this.options.verbose) {
161
+ logger_manager_js_1.loggerManager.printLine(`Using cached compilation for ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
162
+ }
163
+ return cached;
164
+ }
165
+ if (this.options.verbose) {
166
+ logger_manager_js_1.loggerManager.printLine(`Compiling ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
167
+ }
134
168
  const dependencies = new Set();
135
- // Extract import/require dependencies
136
- const importRegex = /(?:import|require)\s*(?:\(.*?\)|.*?from\s+)['"`]([^'"`]+)['"`]/g;
169
+ // Extract import/require dependencies with better regex
170
+ const importRegex = /(?:import|require)\s*(?:\([^)]*\)|[^;]+from\s+)['"`]([^'"`]+)['"`]/g;
137
171
  let match;
138
172
  while ((match = importRegex.exec(sourceCode)) !== null) {
139
- if (!match[1].startsWith('.'))
140
- continue;
141
- const depPath = path_1.default.resolve(path_1.default.dirname(absolutePath), match[1]);
142
- dependencies.add(depPath);
173
+ if (match[1].startsWith('.')) {
174
+ let depPath = path_1.default.resolve(path_1.default.dirname(absolutePath), match[1]);
175
+ // Handle file extensions
176
+ if (!path_1.default.extname(depPath)) {
177
+ // Try common extensions
178
+ for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
179
+ if (fs_1.default.existsSync(depPath + ext)) {
180
+ depPath = depPath + ext;
181
+ break;
182
+ }
183
+ }
184
+ // Try index files
185
+ if (!fs_1.default.existsSync(depPath)) {
186
+ for (const ext of ['.ts', '.tsx', '.js', '.jsx']) {
187
+ const indexPath = path_1.default.join(depPath, 'index' + ext);
188
+ if (fs_1.default.existsSync(indexPath)) {
189
+ depPath = indexPath;
190
+ break;
191
+ }
192
+ }
193
+ }
194
+ }
195
+ if (fs_1.default.existsSync(depPath)) {
196
+ dependencies.add(depPath);
197
+ }
198
+ }
143
199
  }
144
200
  let result;
145
201
  if (this.options.transpileOnly) {
146
- // Fast transpile without type checking
147
202
  result = ts.transpileModule(sourceCode, {
148
203
  compilerOptions: this.tsCompilerOptions,
149
204
  fileName: absolutePath,
@@ -151,13 +206,13 @@ class DevManager {
151
206
  });
152
207
  }
153
208
  else {
154
- // Full compilation with type checking
209
+ // Create a program for better error reporting
155
210
  const program = ts.createProgram([absolutePath], this.tsCompilerOptions);
156
211
  const sourceFile = program.getSourceFile(absolutePath);
157
212
  if (!sourceFile) {
158
213
  throw new Error(`Could not load source file: ${absolutePath}`);
159
214
  }
160
- // Check for errors
215
+ // Check for compilation errors
161
216
  const diagnostics = ts.getPreEmitDiagnostics(program, sourceFile);
162
217
  if (diagnostics.length > 0) {
163
218
  const errors = diagnostics.map(diagnostic => {
@@ -168,27 +223,34 @@ class DevManager {
168
223
  }
169
224
  return message;
170
225
  });
171
- logger_manager_js_1.loggerManager.printLine(`TypeScript compilation errors:\n${errors.join('\n')}`, 'error');
226
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} TypeScript compilation errors:\n${errors.join('\n')}`, 'error');
227
+ // Don't exit in dev mode, just show errors
172
228
  if (!this.options.quiet) {
173
- process.exit(1);
229
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow(figures_1.default.warning)} Continuing with compilation errors...`, 'warn');
174
230
  }
175
231
  }
176
232
  result = ts.transpileModule(sourceCode, {
177
233
  compilerOptions: this.tsCompilerOptions,
178
234
  fileName: absolutePath,
179
- reportDiagnostics: true
235
+ reportDiagnostics: false
180
236
  });
181
237
  }
238
+ const stat = fs_1.default.statSync(absolutePath);
182
239
  const compiled = {
183
240
  code: result.outputText,
184
241
  map: result.sourceMapText,
185
- dependencies
242
+ dependencies,
243
+ lastModified: stat.mtimeMs,
244
+ hash: currentHash
186
245
  };
187
246
  this.moduleCache.set(absolutePath, compiled);
247
+ if (this.options.verbose) {
248
+ logger_manager_js_1.loggerManager.printLine(`Compiled ${path_1.default.relative(process.cwd(), filePath)} (${dependencies.size} dependencies)`, 'info');
249
+ }
188
250
  return compiled;
189
251
  }
190
252
  catch (error) {
191
- logger_manager_js_1.loggerManager.printLine(`Compilation error in ${filePath}: ${error.message}`, 'error');
253
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Compilation error in ${path_1.default.relative(process.cwd(), filePath)}: ${error.message}`, 'error');
192
254
  throw error;
193
255
  }
194
256
  }
@@ -197,7 +259,8 @@ class DevManager {
197
259
  if (!fs_1.default.existsSync(tempDir)) {
198
260
  fs_1.default.mkdirSync(tempDir, { recursive: true });
199
261
  }
200
- const tempFile = path_1.default.join(tempDir, `${path_1.default.basename(originalPath, path_1.default.extname(originalPath))}-${Date.now()}.js`);
262
+ const baseName = path_1.default.basename(originalPath, path_1.default.extname(originalPath));
263
+ const tempFile = path_1.default.join(tempDir, `${baseName}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}.js`);
201
264
  let code = compiled.code;
202
265
  // Handle source maps
203
266
  if (compiled.map && this.options.sourceMaps) {
@@ -212,18 +275,49 @@ class DevManager {
212
275
  const tempDir = path_1.default.join(process.cwd(), '.neex-temp');
213
276
  if (fs_1.default.existsSync(tempDir)) {
214
277
  try {
215
- fs_1.default.rmSync(tempDir, { recursive: true, force: true });
278
+ const files = fs_1.default.readdirSync(tempDir);
279
+ for (const file of files) {
280
+ const filePath = path_1.default.join(tempDir, file);
281
+ try {
282
+ fs_1.default.unlinkSync(filePath);
283
+ }
284
+ catch (error) {
285
+ // Ignore individual file errors
286
+ }
287
+ }
288
+ fs_1.default.rmdirSync(tempDir);
216
289
  }
217
290
  catch (error) {
218
291
  // Ignore cleanup errors
219
292
  }
220
293
  }
221
294
  }
295
+ invalidateCache(filePath) {
296
+ const absolutePath = path_1.default.resolve(filePath);
297
+ // Remove from cache
298
+ const removed = this.moduleCache.delete(absolutePath);
299
+ if (this.options.verbose && removed) {
300
+ logger_manager_js_1.loggerManager.printLine(`Invalidated cache for ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
301
+ }
302
+ // Remove dependent modules from cache
303
+ const dependents = [];
304
+ for (const [cachedPath, module] of this.moduleCache.entries()) {
305
+ if (module.dependencies.has(absolutePath)) {
306
+ this.moduleCache.delete(cachedPath);
307
+ dependents.push(cachedPath);
308
+ }
309
+ }
310
+ if (this.options.verbose && dependents.length > 0) {
311
+ logger_manager_js_1.loggerManager.printLine(`Invalidated ${dependents.length} dependent modules`, 'info');
312
+ }
313
+ }
222
314
  async getExecuteCommand() {
223
315
  if (this.options.execCommand) {
224
316
  const parts = this.options.execCommand.split(' ');
225
317
  return { command: parts[0], args: [...parts.slice(1)] };
226
318
  }
319
+ // Always recompile the main file to ensure fresh execution
320
+ this.invalidateCache(this.options.file);
227
321
  // Compile TypeScript file
228
322
  const compiled = this.compileTypeScript(this.options.file);
229
323
  const tempFile = this.createTempFile(compiled, this.options.file);
@@ -272,7 +366,7 @@ class DevManager {
272
366
  this.restartCount++;
273
367
  if (!this.options.quiet) {
274
368
  const timestamp = new Date().toLocaleTimeString();
275
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.play)} Started ${chalk_1.default.cyan(path_1.default.relative(process.cwd(), this.options.file))} ${chalk_1.default.dim(`(${timestamp})`)}`, 'info');
369
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.play)} Started ${chalk_1.default.cyan(path_1.default.relative(process.cwd(), this.options.file))} ${chalk_1.default.dim(`(#${this.restartCount} - ${timestamp})`)}`, 'info');
276
370
  }
277
371
  (_a = this.process.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
278
372
  if (!this.options.quiet) {
@@ -285,7 +379,7 @@ class DevManager {
285
379
  }
286
380
  });
287
381
  this.process.on('error', (error) => {
288
- logger_manager_js_1.loggerManager.printLine(`Process error: ${error.message}`, 'error');
382
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Process error: ${error.message}`, 'error');
289
383
  });
290
384
  this.process.on('exit', (code, signal) => {
291
385
  if (this.process) {
@@ -300,7 +394,7 @@ class DevManager {
300
394
  });
301
395
  }
302
396
  catch (error) {
303
- logger_manager_js_1.loggerManager.printLine(`Failed to start process: ${error.message}`, 'error');
397
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Failed to start process: ${error.message}`, 'error');
304
398
  throw error;
305
399
  }
306
400
  }
@@ -317,7 +411,7 @@ class DevManager {
317
411
  this.process = null;
318
412
  const cleanup = () => {
319
413
  if (!this.options.quiet) {
320
- logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow(figures_1.default.square)} Stopped process`, 'info');
414
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow(figures_1.default.square)} Process stopped`, 'info');
321
415
  }
322
416
  this.cleanupTempFiles();
323
417
  resolve();
@@ -338,7 +432,7 @@ class DevManager {
338
432
  // Ignore
339
433
  }
340
434
  }
341
- }, 3000);
435
+ }, 2000);
342
436
  }
343
437
  }
344
438
  catch (error) {
@@ -347,17 +441,6 @@ class DevManager {
347
441
  }
348
442
  });
349
443
  }
350
- invalidateCache(filePath) {
351
- const absolutePath = path_1.default.resolve(filePath);
352
- // Remove from cache
353
- this.moduleCache.delete(absolutePath);
354
- // Remove dependent modules from cache
355
- for (const [cachedPath, module] of this.moduleCache.entries()) {
356
- if (module.dependencies.has(absolutePath)) {
357
- this.moduleCache.delete(cachedPath);
358
- }
359
- }
360
- }
361
444
  async restart() {
362
445
  if (this.isRestarting) {
363
446
  return;
@@ -369,11 +452,9 @@ class DevManager {
369
452
  if (!this.options.quiet) {
370
453
  logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.yellow(figures_1.default.arrowRight)} Restarting due to changes...`, 'info');
371
454
  }
372
- // Clear module cache
373
- this.moduleCache.clear();
374
455
  await this.stopProcess();
375
456
  // Small delay to ensure cleanup
376
- await new Promise(resolve => setTimeout(resolve, 100));
457
+ await new Promise(resolve => setTimeout(resolve, 50));
377
458
  await this.startProcess();
378
459
  this.isRestarting = false;
379
460
  }
@@ -387,6 +468,7 @@ class DevManager {
387
468
  '**/.neex-temp/**',
388
469
  '**/*.log',
389
470
  '**/*.d.ts',
471
+ '**/*.map',
390
472
  ...this.options.ignore.map(pattern => `**/${pattern}/**`)
391
473
  ];
392
474
  this.watcher = (0, chokidar_1.watch)(watchPatterns, {
@@ -394,38 +476,38 @@ class DevManager {
394
476
  ignoreInitial: true,
395
477
  followSymlinks: false,
396
478
  usePolling: false,
397
- atomic: 200,
479
+ atomic: 100,
398
480
  awaitWriteFinish: {
399
- stabilityThreshold: 100,
400
- pollInterval: 50
481
+ stabilityThreshold: 50,
482
+ pollInterval: 25
401
483
  }
402
484
  });
403
485
  this.watcher.on('change', (filePath) => {
404
486
  this.invalidateCache(filePath);
405
487
  if (this.options.verbose) {
406
- logger_manager_js_1.loggerManager.printLine(`File changed: ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
488
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(figures_1.default.info)} File changed: ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
407
489
  }
408
490
  this.debouncedRestart();
409
491
  });
410
492
  this.watcher.on('add', (filePath) => {
411
493
  if (this.options.verbose) {
412
- logger_manager_js_1.loggerManager.printLine(`File added: ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
494
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green('+')} File added: ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
413
495
  }
414
496
  this.debouncedRestart();
415
497
  });
416
498
  this.watcher.on('unlink', (filePath) => {
417
499
  this.invalidateCache(filePath);
418
500
  if (this.options.verbose) {
419
- logger_manager_js_1.loggerManager.printLine(`File removed: ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
501
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red('-')} File removed: ${path_1.default.relative(process.cwd(), filePath)}`, 'info');
420
502
  }
421
503
  this.debouncedRestart();
422
504
  });
423
505
  this.watcher.on('error', (error) => {
424
- logger_manager_js_1.loggerManager.printLine(`Watcher error: ${error.message}`, 'error');
506
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.red(figures_1.default.cross)} Watcher error: ${error.message}`, 'error');
425
507
  });
426
508
  if (this.options.verbose) {
427
- logger_manager_js_1.loggerManager.printLine(`Watching: ${watchPatterns.join(', ')}`, 'info');
428
- logger_manager_js_1.loggerManager.printLine(`Ignoring: ${ignored.join(', ')}`, 'info');
509
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim(figures_1.default.info)} Watching: ${watchPatterns.join(', ')}`, 'info');
510
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim(figures_1.default.info)} Ignoring: ${ignored.join(', ')}`, 'info');
429
511
  }
430
512
  }
431
513
  async start() {
@@ -441,12 +523,14 @@ class DevManager {
441
523
  logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(figures_1.default.info)} Starting TypeScript development server...`, 'info');
442
524
  // Show configuration in verbose mode
443
525
  if (this.options.verbose) {
444
- logger_manager_js_1.loggerManager.printLine(`Target file: ${this.options.file}`, 'info');
445
- logger_manager_js_1.loggerManager.printLine(`Watch patterns: ${this.options.watch.join(', ')}`, 'info');
446
- logger_manager_js_1.loggerManager.printLine(`Restart delay: ${this.options.delay}ms`, 'info');
447
- logger_manager_js_1.loggerManager.printLine(`Transpile only: ${this.options.transpileOnly}`, 'info');
448
- logger_manager_js_1.loggerManager.printLine(`Source maps: ${this.options.sourceMaps}`, 'info');
526
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Target file:')} ${this.options.file}`, 'info');
527
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Watch patterns:')} ${this.options.watch.join(', ')}`, 'info');
528
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Restart delay:')} ${this.options.delay}ms`, 'info');
529
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Transpile only:')} ${this.options.transpileOnly}`, 'info');
530
+ logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.dim('Source maps:')} ${this.options.sourceMaps}`, 'info');
449
531
  }
532
+ // Clear any existing cache
533
+ this.moduleCache.clear();
450
534
  this.setupWatcher();
451
535
  await this.startProcess();
452
536
  logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.green(figures_1.default.tick)} TypeScript development server started. Watching for changes...`, 'info');
@@ -458,6 +542,8 @@ class DevManager {
458
542
  this.watcher = null;
459
543
  }
460
544
  await this.stopProcess();
545
+ // Clear cache on stop
546
+ this.moduleCache.clear();
461
547
  if (this.restartCount > 0) {
462
548
  logger_manager_js_1.loggerManager.printLine(`${chalk_1.default.blue(figures_1.default.info)} Development server stopped after ${this.restartCount} restart(s)`, 'info');
463
549
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "neex",
3
- "version": "0.6.83",
3
+ "version": "0.6.85",
4
4
  "description": "The Modern Build System for Polyrepo-in-Monorepo Architecture",
5
5
  "main": "dist/src/index.js",
6
6
  "types": "dist/src/index.d.ts",