diff --git a/changelog.md b/changelog.md index eefc243..aeedeb3 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,14 @@ # Changelog +## 2025-12-31 - 3.19.1 - fix(intellisense) +Debounce TypeScript/JavaScript IntelliSense processing and cache missing packages to reduce work and noisy logs + +- Add 500ms debounce in editor workspace to avoid parsing on every keystroke +- Introduce notFoundPackages cache to skip repeated filesystem checks for packages without types +- Clear not-found cache when scanning node_modules so newly installed packages are re-detected +- Remove noisy console logs and make file/directory read errors non-fatal (ignored) +- Simplify processContentChange signature (removed optional filePath) and remove manual diagnostic refresh logic + ## 2025-12-31 - 3.19.0 - feat(dees-editor-workspace) improve TypeScript IntelliSense, auto-run workspace init commands, and watch node_modules for new packages diff --git a/ts_web/00_commitinfo_data.ts b/ts_web/00_commitinfo_data.ts index e9899bb..84718f7 100644 --- a/ts_web/00_commitinfo_data.ts +++ b/ts_web/00_commitinfo_data.ts @@ -3,6 +3,6 @@ */ export const commitinfo = { name: '@design.estate/dees-catalog', - version: '3.19.0', + version: '3.19.1', description: 'A comprehensive library that provides dynamic web components for building sophisticated and modern web applications using JavaScript and TypeScript.' } diff --git a/ts_web/elements/00group-editor/dees-editor-workspace/dees-editor-workspace.ts b/ts_web/elements/00group-editor/dees-editor-workspace/dees-editor-workspace.ts index 8331708..67cabe5 100644 --- a/ts_web/elements/00group-editor/dees-editor-workspace/dees-editor-workspace.ts +++ b/ts_web/elements/00group-editor/dees-editor-workspace/dees-editor-workspace.ts @@ -240,6 +240,7 @@ testSmartPromise(); // node_modules watcher for auto-loading types private nodeModulesWatcher: IFileWatcher | null = null; private nodeModulesDebounceTimeout: ReturnType | null = null; + private intelliSenseDebounceTimeout: ReturnType | null = null; // Auto-save functionality @state() @@ -973,7 +974,7 @@ testSmartPromise(); // Process the initial file content for IntelliSense const language = this.getLanguageFromPath(path); if (this.intelliSenseManager && (language === 'typescript' || language === 'javascript')) { - await this.intelliSenseManager.processContentChange(content, path); + await this.intelliSenseManager.processContentChange(content); } } } catch (error) { @@ -1029,10 +1030,15 @@ testSmartPromise(); ...this.openFiles.slice(fileIndex + 1), ]; - // Process content for IntelliSense (TypeScript/JavaScript files) + // Process content for IntelliSense (debounced to avoid parsing on every keystroke) const language = this.getLanguageFromPath(this.activeFilePath); if (this.intelliSenseManager && (language === 'typescript' || language === 'javascript')) { - this.intelliSenseManager.processContentChange(newContent, this.activeFilePath); + if (this.intelliSenseDebounceTimeout) { + clearTimeout(this.intelliSenseDebounceTimeout); + } + this.intelliSenseDebounceTimeout = setTimeout(() => { + this.intelliSenseManager?.processContentChange(newContent); + }, 500); // 500ms debounce } } } diff --git a/ts_web/elements/00group-editor/dees-editor-workspace/typescript-intellisense.ts b/ts_web/elements/00group-editor/dees-editor-workspace/typescript-intellisense.ts index 290a740..41e240d 100644 --- a/ts_web/elements/00group-editor/dees-editor-workspace/typescript-intellisense.ts +++ b/ts_web/elements/00group-editor/dees-editor-workspace/typescript-intellisense.ts @@ -24,6 +24,7 @@ interface IMonacoTypeScriptAPI { */ export class TypeScriptIntelliSenseManager { private loadedLibs: Set = new Set(); + private notFoundPackages: Set = new Set(); // Packages checked but not found private monacoInstance: typeof monaco | null = null; private executionEnvironment: IExecutionEnvironment | null = null; @@ -174,17 +175,19 @@ export class TypeScriptIntelliSenseManager { public async loadTypesForPackage(packageName: string): Promise { if (!this.monacoInstance || !this.executionEnvironment) return; if (this.loadedLibs.has(packageName)) return; - - console.log(`[IntelliSense] Loading types for package: ${packageName}`); + if (this.notFoundPackages.has(packageName)) return; // Skip packages we already checked try { - const typesLoaded = await this.tryLoadPackageTypes(packageName); - console.log(`[IntelliSense] tryLoadPackageTypes result for ${packageName}: ${typesLoaded}`); + let typesLoaded = await this.tryLoadPackageTypes(packageName); if (!typesLoaded) { - const atTypesLoaded = await this.tryLoadAtTypesPackage(packageName); - console.log(`[IntelliSense] tryLoadAtTypesPackage result for ${packageName}: ${atTypesLoaded}`); + typesLoaded = await this.tryLoadAtTypesPackage(packageName); + } + if (typesLoaded) { + this.loadedLibs.add(packageName); + } else { + // Cache that this package wasn't found to avoid repeated filesystem checks + this.notFoundPackages.add(packageName); } - this.loadedLibs.add(packageName); } catch (error) { console.warn(`Failed to load types for ${packageName}:`, error); } @@ -195,13 +198,11 @@ export class TypeScriptIntelliSenseManager { if (!this.executionEnvironment || !ts) return false; const basePath = `/node_modules/${packageName}`; - console.log(`[IntelliSense] Checking package at: ${basePath}`); try { // Check package.json for types field const packageJsonPath = `${basePath}/package.json`; const packageJsonExists = await this.executionEnvironment.exists(packageJsonPath); - console.log(`[IntelliSense] package.json exists: ${packageJsonExists}`); if (packageJsonExists) { const packageJsonContent = await this.executionEnvironment.readFile(packageJsonPath); @@ -209,10 +210,8 @@ export class TypeScriptIntelliSenseManager { // Add package.json to Monaco so TypeScript can resolve the types field ts.typescriptDefaults.addExtraLib(packageJsonContent, `file://${packageJsonPath}`); - console.log(`[IntelliSense] Added package.json: ${packageJsonPath}`); const typesPath = packageJson.types || packageJson.typings; - console.log(`[IntelliSense] types field: ${typesPath}`); if (typesPath) { // Load all .d.ts files from the package, not just the entry point // Modern packages often have multiple declaration files with imports @@ -230,16 +229,14 @@ export class TypeScriptIntelliSenseManager { for (const dtsPath of commonPaths) { if (await this.executionEnvironment.exists(dtsPath)) { - console.log(`[IntelliSense] Found types at: ${dtsPath}`); await this.loadAllDtsFilesFromPackage(basePath); return true; } } - console.log(`[IntelliSense] No types found for ${packageName}`); return false; } catch (error) { - console.error(`[IntelliSense] Error loading package types:`, error); + console.error(`Failed to load package types for ${packageName}:`, error); return false; } } @@ -275,15 +272,14 @@ export class TypeScriptIntelliSenseManager { } else if (entry.type === 'file' && entry.name.endsWith('.d.ts')) { try { const content = await this.executionEnvironment.readFile(fullPath); - console.log(`[IntelliSense] Adding extra lib: ${fullPath} (${content.length} chars)`); ts.typescriptDefaults.addExtraLib(content, `file://${fullPath}`); - } catch (error) { - console.warn(`[IntelliSense] Failed to read .d.ts file: ${fullPath}`, error); + } catch { + // Ignore files that can't be read } } } - } catch (error) { - console.warn(`[IntelliSense] Failed to read directory: ${dirPath}`, error); + } catch { + // Directory might not be readable } } @@ -312,43 +308,15 @@ export class TypeScriptIntelliSenseManager { /** * Process content change and load types for any new imports - * @param content The file content to parse for imports - * @param filePath Optional file path to trigger diagnostic refresh */ - public async processContentChange(content: string, filePath?: string): Promise { + public async processContentChange(content: string): Promise { const imports = this.parseImports(content); - let typesLoaded = false; for (const packageName of imports) { if (!this.loadedLibs.has(packageName)) { await this.loadTypesForPackage(packageName); - typesLoaded = true; } } - - // If we loaded new types and have a file path, trigger diagnostic refresh - if (typesLoaded && filePath && this.monacoInstance) { - this.triggerDiagnosticRefresh(filePath); - } - } - - /** - * Force Monaco to re-validate a file by touching its model. - * This is needed because addExtraLib doesn't always trigger re-validation. - */ - private triggerDiagnosticRefresh(filePath: string): void { - if (!this.monacoInstance) return; - - const uri = this.monacoInstance.Uri.parse(`file://${filePath}`); - const model = this.monacoInstance.editor.getModel(uri); - - if (model) { - // Touch the model to trigger re-validation - // We do this by getting and re-setting the same value - const currentValue = model.getValue(); - model.setValue(currentValue); - console.log(`[IntelliSense] Triggered diagnostic refresh for: ${filePath}`); - } } /** @@ -358,6 +326,9 @@ export class TypeScriptIntelliSenseManager { public async scanAndLoadNewPackageTypes(): Promise { if (!this.executionEnvironment) return; + // Clear not-found cache so newly installed packages can be detected + this.notFoundPackages.clear(); + try { // Check if node_modules exists if (!await this.executionEnvironment.exists('/node_modules')) return;