@@ -6,6 +6,8 @@ import { Plugin } from '@remixproject/engine'
66import * as packageJson from '../../../../../package.json'
77import { PluginViewWrapper } from '@remix-ui/helper'
88
9+ import { fetchAndLoadTypes } from './type-fetcher'
10+
911const EventManager = require ( '../../lib/events' )
1012
1113const profile = {
@@ -71,12 +73,19 @@ export default class Editor extends Plugin {
7173 this . api = { }
7274 this . dispatch = null
7375 this . ref = null
76+
77+ this . monaco = null
78+ this . typeLoaderDebounce = null
7479 }
7580
7681 setDispatch ( dispatch ) {
7782 this . dispatch = dispatch
7883 }
7984
85+ setMonaco ( monaco ) {
86+ this . monaco = monaco
87+ }
88+
8089 updateComponent ( state ) {
8190 return < EditorUI
8291 editorAPI = { state . api }
@@ -86,6 +95,7 @@ export default class Editor extends Plugin {
8695 events = { state . events }
8796 plugin = { state . plugin }
8897 isDiff = { state . isDiff }
98+ setMonaco = { ( monaco ) => this . setMonaco ( monaco ) }
8999 />
90100 }
91101
@@ -128,6 +138,17 @@ export default class Editor extends Plugin {
128138
129139 async onActivation ( ) {
130140 this . activated = true
141+ this . on ( 'editor' , 'editorMounted' , ( ) => {
142+ if ( ! this . monaco ) return
143+ const tsDefaults = this . monaco . languages . typescript . typescriptDefaults
144+
145+ tsDefaults . setCompilerOptions ( {
146+ moduleResolution : this . monaco . languages . typescript . ModuleResolutionKind . NodeJs ,
147+ typeRoots : [ "file:///node_modules/@types" , "file:///node_modules" ] ,
148+ target : this . monaco . languages . typescript . ScriptTarget . ES2020 ,
149+ allowNonTsExtensions : true ,
150+ } )
151+ } )
131152 this . on ( 'sidePanel' , 'focusChanged' , ( name ) => {
132153 this . keepDecorationsFor ( name , 'sourceAnnotationsPerFile' )
133154 this . keepDecorationsFor ( name , 'markerPerFile' )
@@ -158,6 +179,30 @@ export default class Editor extends Plugin {
158179
159180 async _onChange ( file ) {
160181 this . triggerEvent ( 'didChangeFile' , [ file ] )
182+
183+ if ( this . monaco && ( file . endsWith ( '.ts' ) || file . endsWith ( '.js' ) ) ) {
184+ clearTimeout ( this . typeLoaderDebounce )
185+ this . typeLoaderDebounce = setTimeout ( async ( ) => {
186+ if ( ! this . monaco ) return
187+ const model = this . monaco . editor . getModel ( this . monaco . Uri . parse ( file ) )
188+ if ( ! model ) return
189+ const code = model . getValue ( )
190+
191+ try {
192+ const npmImports = [ ...code . matchAll ( / f r o m \s + [ ' " ] ( (? ! [ . / ] ) .+ ) [ ' " ] / g) ] . map ( match => match [ 1 ] )
193+ const uniquePackages = [ ...new Set ( npmImports ) ]
194+
195+ if ( uniquePackages . length > 0 ) {
196+ await Promise . all ( uniquePackages . map ( pkg => fetchAndLoadTypes ( pkg , this . monaco ) ) )
197+ const tsDefaults = this . monaco . languages . typescript . typescriptDefaults
198+ tsDefaults . setCompilerOptions ( tsDefaults . getCompilerOptions ( ) )
199+ }
200+ } catch ( error ) {
201+ console . error ( '[Type Loader] Error during type loading process:' , error )
202+ }
203+ } , 1500 )
204+ }
205+
161206 const currentFile = await this . call ( 'fileManager' , 'file' )
162207 if ( ! currentFile ) {
163208 return
@@ -232,7 +277,7 @@ export default class Editor extends Plugin {
232277 this . emit ( 'addModel' , contentDep , 'typescript' , pathDep , this . readOnlySessions [ path ] )
233278 }
234279 } else {
235- console . log ( "The file " , pathDep , " can't be found." )
280+ // console.log("The file ", pathDep, " can't be found.")
236281 }
237282 } catch ( e ) {
238283 console . log ( e )
0 commit comments